mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
OpenGL: removed the fixed-function rendering code, replacing it with a simple software renderer that blits its results to the GL context. Removed the public OpenGLGraphicsContext class, replacing it with a createOpenGLGraphicsContext() function which returns an appropriate shader-based or software-based renderer object.
This commit is contained in:
parent
8ed15bd9f0
commit
b338698e34
11 changed files with 307 additions and 1353 deletions
|
|
@ -157,8 +157,9 @@ public:
|
|||
|
||||
void drawBackground2DStuff()
|
||||
{
|
||||
OpenGLGraphicsContext glRenderer (*this); // Create an OpenGLGraphicsContext that will draw into this GL window..
|
||||
Graphics g (&glRenderer); // ..and then wrap it in a normal Graphics object so we can draw with it.
|
||||
// Create an OpenGLGraphicsContext that will draw into this GL window..
|
||||
ScopedPointer<LowLevelGraphicsContext> glRenderer (createOpenGLGraphicsContext (*this));
|
||||
Graphics g (glRenderer);
|
||||
|
||||
// This stuff just creates a spinning star shape and fills it..
|
||||
Path p;
|
||||
|
|
|
|||
|
|
@ -322,7 +322,7 @@ protected:
|
|||
//==============================================================================
|
||||
/** @internal */
|
||||
void paint (Graphics& g);
|
||||
/** (if overriding this, make sure you call ResizableWindow::resized() in your subclass) */
|
||||
/** (if overriding this, make sure you call ResizableWindow::moved() in your subclass) */
|
||||
void moved();
|
||||
/** (if overriding this, make sure you call ResizableWindow::resized() in your subclass) */
|
||||
void resized();
|
||||
|
|
|
|||
|
|
@ -121,6 +121,26 @@ public:
|
|||
return frameBuffer;
|
||||
}
|
||||
|
||||
void clearRegionInFrameBuffer (const RectangleList& list)
|
||||
{
|
||||
glClearColor (0, 0, 0, 0);
|
||||
glEnable (GL_SCISSOR_TEST);
|
||||
|
||||
const GLuint previousFrameBufferTarget = OpenGLFrameBuffer::getCurrentFrameBufferTarget();
|
||||
frameBuffer.makeCurrentRenderingTarget();
|
||||
|
||||
for (RectangleList::Iterator i (list); i.next();)
|
||||
{
|
||||
const Rectangle<int>& r = *i.getRectangle();
|
||||
glScissor (r.getX(), owner.getHeight() - r.getBottom(), r.getWidth(), r.getHeight());
|
||||
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
}
|
||||
|
||||
glDisable (GL_SCISSOR_TEST);
|
||||
owner.getCurrentContext()->extensions.glBindFramebuffer (GL_FRAMEBUFFER, previousFrameBufferTarget);
|
||||
JUCE_CHECK_OPENGL_ERROR
|
||||
}
|
||||
|
||||
RectangleList validArea;
|
||||
|
||||
private:
|
||||
|
|
@ -152,7 +172,9 @@ public:
|
|||
|
||||
void componentVisibilityChanged()
|
||||
{
|
||||
if (! owner.isShowing())
|
||||
if (owner.isShowing())
|
||||
owner.triggerRepaint();
|
||||
else
|
||||
owner.stopRenderThread();
|
||||
}
|
||||
|
||||
|
|
@ -172,36 +194,56 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
void run()
|
||||
virtual void initialise()
|
||||
{
|
||||
#if JUCE_LINUX
|
||||
MessageManagerLock mml (this);
|
||||
|
||||
if (mml.lockWasGained())
|
||||
{
|
||||
MessageManagerLock mml (this);
|
||||
|
||||
if (! mml.lockWasGained())
|
||||
return;
|
||||
|
||||
owner.updateContext();
|
||||
owner.updateContextPosition();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
while (! threadShouldExit())
|
||||
{
|
||||
const uint32 startOfRendering = Time::getMillisecondCounter();
|
||||
|
||||
if (! owner.performRender())
|
||||
break;
|
||||
|
||||
const int elapsed = (int) (Time::getMillisecondCounter() - startOfRendering);
|
||||
Thread::sleep (jmax (1, (1000 / 60) - elapsed));
|
||||
}
|
||||
|
||||
virtual void shutdown()
|
||||
{
|
||||
#if JUCE_LINUX
|
||||
owner.deleteContext();
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual bool renderFrame()
|
||||
{
|
||||
return owner.performRender();
|
||||
}
|
||||
|
||||
virtual void waitForNextFrame (const uint32 frameRenderStartTime)
|
||||
{
|
||||
const int defaultFPS = 60;
|
||||
|
||||
const int elapsed = (int) (Time::getMillisecondCounter() - frameRenderStartTime);
|
||||
Thread::sleep (jmax (1, (1000 / defaultFPS) - elapsed));
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
initialise();
|
||||
|
||||
while (! threadShouldExit())
|
||||
{
|
||||
const uint32 frameRenderStartTime = Time::getMillisecondCounter();
|
||||
|
||||
if (! renderFrame())
|
||||
break;
|
||||
|
||||
waitForNextFrame (frameRenderStartTime);
|
||||
}
|
||||
|
||||
shutdown();
|
||||
}
|
||||
|
||||
private:
|
||||
OpenGLComponent& owner;
|
||||
|
||||
|
|
@ -458,17 +500,14 @@ bool OpenGLComponent::performRender()
|
|||
{
|
||||
jassert (getCurrentContext() != nullptr);
|
||||
|
||||
cachedImage->clearRegionInFrameBuffer (invalid);
|
||||
|
||||
{
|
||||
OpenGLGraphicsContext g (*getCurrentContext(), frameBuffer);
|
||||
ScopedPointer<LowLevelGraphicsContext> g (createOpenGLGraphicsContext (*getCurrentContext(), frameBuffer));
|
||||
JUCE_CHECK_OPENGL_ERROR
|
||||
g.clipToRectangleList (invalid);
|
||||
|
||||
g.setFill (Colours::transparentBlack);
|
||||
g.fillRect (bounds, true);
|
||||
g.setFill (Colours::black);
|
||||
|
||||
JUCE_CHECK_OPENGL_ERROR
|
||||
paintSelf (g);
|
||||
g->clipToRectangleList (invalid);
|
||||
paintSelf (*g);
|
||||
JUCE_CHECK_OPENGL_ERROR
|
||||
}
|
||||
|
||||
|
|
@ -484,7 +523,7 @@ bool OpenGLComponent::performRender()
|
|||
glBindTexture (GL_TEXTURE_2D, frameBuffer.getTextureID());
|
||||
|
||||
jassert (bounds.getPosition() == Point<int>());
|
||||
context->copyTexture (bounds, bounds);
|
||||
context->copyTexture (bounds, bounds, context->getWidth(), context->getHeight());
|
||||
glBindTexture (GL_TEXTURE_2D, 0);
|
||||
JUCE_CHECK_OPENGL_ERROR
|
||||
}
|
||||
|
|
@ -495,9 +534,9 @@ bool OpenGLComponent::performRender()
|
|||
return true;
|
||||
}
|
||||
|
||||
void OpenGLComponent::paintSelf (OpenGLGraphicsContext& glRenderer)
|
||||
void OpenGLComponent::paintSelf (LowLevelGraphicsContext& context)
|
||||
{
|
||||
Graphics g (&glRenderer);
|
||||
Graphics g (&context);
|
||||
|
||||
#if JUCE_ENABLE_REPAINT_DEBUGGING
|
||||
g.saveState();
|
||||
|
|
|
|||
|
|
@ -289,7 +289,7 @@ private:
|
|||
void updateEmbeddedPosition (const Rectangle<int>&);
|
||||
void startRenderThread();
|
||||
bool performRender();
|
||||
void paintSelf (OpenGLGraphicsContext&);
|
||||
void paintSelf (LowLevelGraphicsContext&);
|
||||
|
||||
int renderAndSwapBuffers(); // (This method has been deprecated)
|
||||
|
||||
|
|
|
|||
|
|
@ -127,7 +127,8 @@ bool OpenGLContext::areShadersAvailable() const
|
|||
}
|
||||
|
||||
void OpenGLContext::copyTexture (const Rectangle<int>& targetClipArea,
|
||||
const Rectangle<int>& anchorPosAndTextureSize)
|
||||
const Rectangle<int>& anchorPosAndTextureSize,
|
||||
int contextWidth, int contextHeight)
|
||||
{
|
||||
glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glEnable (GL_BLEND);
|
||||
|
|
@ -138,9 +139,7 @@ void OpenGLContext::copyTexture (const Rectangle<int>& targetClipArea,
|
|||
struct OverlayShaderProgram : public ReferenceCountedObject
|
||||
{
|
||||
OverlayShaderProgram (OpenGLContext& context)
|
||||
: program (context),
|
||||
builder (program),
|
||||
params (program)
|
||||
: program (context), builder (program), params (program)
|
||||
{}
|
||||
|
||||
static const OverlayShaderProgram& select (OpenGLContext& context)
|
||||
|
|
@ -225,7 +224,7 @@ void OpenGLContext::copyTexture (const Rectangle<int>& targetClipArea,
|
|||
const GLshort vertices[] = { left, bottom, right, bottom, left, top, right, top };
|
||||
|
||||
const OverlayShaderProgram& program = OverlayShaderProgram::select (*this);
|
||||
program.params.set ((float) getWidth(), (float) getHeight(), anchorPosAndTextureSize.toFloat());
|
||||
program.params.set ((float) contextWidth, (float) contextHeight, anchorPosAndTextureSize.toFloat());
|
||||
|
||||
extensions.glVertexAttribPointer (program.params.positionAttribute.attributeID, 2, GL_SHORT, GL_FALSE, 4, vertices);
|
||||
extensions.glEnableVertexAttribArray (program.params.positionAttribute.attributeID);
|
||||
|
|
@ -241,26 +240,29 @@ void OpenGLContext::copyTexture (const Rectangle<int>& targetClipArea,
|
|||
|
||||
#if JUCE_USE_OPENGL_FIXED_FUNCTION
|
||||
{
|
||||
(void) anchorPosAndTextureSize; // xxx need to scissor
|
||||
const GLshort left = (GLshort) targetClipArea.getX();
|
||||
const GLshort right = (GLshort) targetClipArea.getRight();
|
||||
const GLshort top = (GLshort) (getHeight() - targetClipArea.getY());
|
||||
const GLshort bottom = (GLshort) (getHeight() - targetClipArea.getBottom());
|
||||
const GLshort vertices[] = { left, bottom, right, bottom, left, top, right, top };
|
||||
|
||||
OpenGLHelpers::prepareFor2D (getWidth(), getHeight());
|
||||
glEnable (GL_SCISSOR_TEST);
|
||||
glScissor (targetClipArea.getX(), contextHeight - targetClipArea.getBottom(),
|
||||
targetClipArea.getWidth(), targetClipArea.getHeight());
|
||||
|
||||
glColor4f (1.0f, 1.0f, 1.0f, 1.0f);
|
||||
glDisableClientState (GL_COLOR_ARRAY);
|
||||
glDisableClientState (GL_NORMAL_ARRAY);
|
||||
glEnableClientState (GL_VERTEX_ARRAY);
|
||||
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
|
||||
OpenGLHelpers::prepareFor2D (contextWidth, contextHeight);
|
||||
|
||||
const GLfloat textureCoords[] = { 0, 0, 1.0f, 0, 0, 1.0f, 1.0f, 1.0f };
|
||||
glTexCoordPointer (2, GL_FLOAT, 0, textureCoords);
|
||||
|
||||
const GLshort left = (GLshort) anchorPosAndTextureSize.getX();
|
||||
const GLshort right = (GLshort) anchorPosAndTextureSize.getRight();
|
||||
const GLshort top = (GLshort) (contextHeight - anchorPosAndTextureSize.getY());
|
||||
const GLshort bottom = (GLshort) (contextHeight - anchorPosAndTextureSize.getBottom());
|
||||
const GLshort vertices[] = { left, bottom, right, bottom, left, top, right, top };
|
||||
glVertexPointer (2, GL_SHORT, 0, vertices);
|
||||
|
||||
glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
|
||||
glDisable (GL_SCISSOR_TEST);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,9 +112,14 @@ public:
|
|||
@param anchorPosAndTextureSize the position of this rectangle is the texture's top-left
|
||||
anchor position in the target space, and the size must be
|
||||
the total size of the texture.
|
||||
@param contextWidth the width of the context or framebuffer that is being drawn into,
|
||||
used for scaling of the coordinates.
|
||||
@param contextHeight the height of the context or framebuffer that is being drawn into,
|
||||
used for vertical flipping of the y coordinates.
|
||||
*/
|
||||
void copyTexture (const Rectangle<int>& targetClipArea,
|
||||
const Rectangle<int>& anchorPosAndTextureSize);
|
||||
const Rectangle<int>& anchorPosAndTextureSize,
|
||||
int contextWidth, int contextHeight);
|
||||
|
||||
protected:
|
||||
//==============================================================================
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ public:
|
|||
width (width_),
|
||||
height (height_),
|
||||
textureID (0),
|
||||
frameBufferHandle (0),
|
||||
frameBufferID (0),
|
||||
depthOrStencilBuffer (0),
|
||||
hasDepthBuffer (false),
|
||||
hasStencilBuffer (false),
|
||||
|
|
@ -47,8 +47,8 @@ public:
|
|||
return;
|
||||
#endif
|
||||
|
||||
context.extensions.glGenFramebuffers (1, &frameBufferHandle);
|
||||
context.extensions.glBindFramebuffer (GL_FRAMEBUFFER, frameBufferHandle);
|
||||
context.extensions.glGenFramebuffers (1, &frameBufferID);
|
||||
context.extensions.glBindFramebuffer (GL_FRAMEBUFFER, frameBufferID);
|
||||
JUCE_CHECK_OPENGL_ERROR
|
||||
|
||||
glGenTextures (1, &textureID);
|
||||
|
|
@ -102,15 +102,15 @@ public:
|
|||
if (depthOrStencilBuffer != 0)
|
||||
context.extensions.glDeleteRenderbuffers (1, &depthOrStencilBuffer);
|
||||
|
||||
if (frameBufferHandle != 0)
|
||||
context.extensions.glDeleteFramebuffers (1, &frameBufferHandle);
|
||||
if (frameBufferID != 0)
|
||||
context.extensions.glDeleteFramebuffers (1, &frameBufferID);
|
||||
|
||||
JUCE_CHECK_OPENGL_ERROR
|
||||
}
|
||||
|
||||
void bind()
|
||||
{
|
||||
context.extensions.glBindFramebuffer (GL_FRAMEBUFFER, frameBufferHandle);
|
||||
context.extensions.glBindFramebuffer (GL_FRAMEBUFFER, frameBufferID);
|
||||
JUCE_CHECK_OPENGL_ERROR
|
||||
}
|
||||
|
||||
|
|
@ -122,7 +122,7 @@ public:
|
|||
|
||||
OpenGLContext& context;
|
||||
const int width, height;
|
||||
GLuint textureID, frameBufferHandle, depthOrStencilBuffer;
|
||||
GLuint textureID, frameBufferID, depthOrStencilBuffer;
|
||||
bool hasDepthBuffer, hasStencilBuffer, ok;
|
||||
|
||||
private:
|
||||
|
|
@ -214,7 +214,7 @@ bool OpenGLFrameBuffer::initialise (OpenGLFrameBuffer& other)
|
|||
glEnable (GL_TEXTURE_2D);
|
||||
#endif
|
||||
glBindTexture (GL_TEXTURE_2D, p->textureID);
|
||||
pimpl->context.copyTexture (area, area);
|
||||
pimpl->context.copyTexture (area, area, area.getWidth(), area.getHeight());
|
||||
glBindTexture (GL_TEXTURE_2D, 0);
|
||||
JUCE_CHECK_OPENGL_ERROR
|
||||
|
||||
|
|
@ -272,6 +272,11 @@ bool OpenGLFrameBuffer::makeCurrentRenderingTarget()
|
|||
return true;
|
||||
}
|
||||
|
||||
GLuint OpenGLFrameBuffer::getFrameBufferID() const
|
||||
{
|
||||
return pimpl != nullptr ? pimpl->frameBufferID : 0;
|
||||
}
|
||||
|
||||
GLuint OpenGLFrameBuffer::getCurrentFrameBufferTarget()
|
||||
{
|
||||
GLint fb;
|
||||
|
|
@ -339,7 +344,7 @@ bool OpenGLFrameBuffer::writePixels (const PixelARGB* data, const Rectangle<int>
|
|||
glDrawTexiOES (area.getX(), area.getY(), 1, area.getWidth(), area.getHeight());
|
||||
glBindTexture (GL_TEXTURE_2D, 0);
|
||||
#else
|
||||
pimpl->context.copyTexture (area, area);
|
||||
pimpl->context.copyTexture (area, area, pimpl->width, pimpl->height);
|
||||
#endif
|
||||
|
||||
pimpl->context.extensions.glBindFramebuffer (GL_FRAMEBUFFER, 0);
|
||||
|
|
|
|||
|
|
@ -95,6 +95,9 @@ public:
|
|||
/** Deselects this buffer as the current OpenGL rendering target. */
|
||||
void releaseAsRenderingTarget();
|
||||
|
||||
/** Returns the ID of this framebuffer, or 0 if it isn't initialised. */
|
||||
GLuint getFrameBufferID() const;
|
||||
|
||||
/** Returns the current frame buffer ID for the current context. */
|
||||
static GLuint getCurrentFrameBufferTarget();
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -28,59 +28,23 @@
|
|||
|
||||
|
||||
//==============================================================================
|
||||
/** A LowLevelGraphicsContext for rendering into an OpenGL framebuffer or window.
|
||||
/** Creates a graphics context object that will render into the given OpenGL target.
|
||||
The caller is responsible for deleting this object when no longer needed.
|
||||
*/
|
||||
class JUCE_API OpenGLGraphicsContext : public LowLevelGraphicsContext
|
||||
{
|
||||
public:
|
||||
explicit OpenGLGraphicsContext (OpenGLComponent& target);
|
||||
OpenGLGraphicsContext (OpenGLContext& context, OpenGLFrameBuffer& target);
|
||||
OpenGLGraphicsContext (OpenGLContext& context, unsigned int frameBufferID, int width, int height);
|
||||
~OpenGLGraphicsContext();
|
||||
LowLevelGraphicsContext* createOpenGLGraphicsContext (OpenGLComponent& target);
|
||||
|
||||
bool isVectorDevice() const;
|
||||
void setOrigin (int x, int y);
|
||||
void addTransform (const AffineTransform&);
|
||||
float getScaleFactor();
|
||||
bool clipToRectangle (const Rectangle<int>&);
|
||||
bool clipToRectangleList (const RectangleList&);
|
||||
void excludeClipRectangle (const Rectangle<int>&);
|
||||
void clipToPath (const Path& path, const AffineTransform&);
|
||||
void clipToImageAlpha (const Image& sourceImage, const AffineTransform&);
|
||||
bool clipRegionIntersects (const Rectangle<int>&);
|
||||
Rectangle<int> getClipBounds() const;
|
||||
bool isClipEmpty() const;
|
||||
/** Creates a graphics context object that will render into the given OpenGL target.
|
||||
The caller is responsible for deleting this object when no longer needed.
|
||||
*/
|
||||
LowLevelGraphicsContext* createOpenGLGraphicsContext (OpenGLContext& context,
|
||||
OpenGLFrameBuffer& target);
|
||||
|
||||
void saveState();
|
||||
void restoreState();
|
||||
/** Creates a graphics context object that will render into the given OpenGL target.
|
||||
The caller is responsible for deleting this object when no longer needed.
|
||||
*/
|
||||
LowLevelGraphicsContext* createOpenGLGraphicsContext (OpenGLContext& context,
|
||||
unsigned int frameBufferID,
|
||||
int width, int height);
|
||||
|
||||
void beginTransparencyLayer (float opacity);
|
||||
void endTransparencyLayer();
|
||||
|
||||
void setFill (const FillType& fillType);
|
||||
void setOpacity (float newOpacity);
|
||||
void setInterpolationQuality (Graphics::ResamplingQuality);
|
||||
|
||||
void fillRect (const Rectangle<int>& r, bool replaceExistingContents);
|
||||
void fillPath (const Path& path, const AffineTransform& transform);
|
||||
void drawImage (const Image& sourceImage, const AffineTransform& transform);
|
||||
void drawLine (const Line <float>& line);
|
||||
void drawVerticalLine (int x, float top, float bottom);
|
||||
void drawHorizontalLine (int y, float left, float right);
|
||||
|
||||
void setFont (const Font&);
|
||||
const Font& getFont();
|
||||
|
||||
void drawGlyph (int glyphNumber, const AffineTransform&);
|
||||
|
||||
#ifndef DOXYGEN
|
||||
class SavedState;
|
||||
class GLState;
|
||||
#endif
|
||||
|
||||
private:
|
||||
ScopedPointer<GLState> glState;
|
||||
RenderingHelpers::SavedStateStack<SavedState> stack;
|
||||
};
|
||||
|
||||
#endif // __JUCE_OPENGLGRAPHICSCONTEXT_JUCEHEADER__
|
||||
|
|
|
|||
|
|
@ -38,10 +38,10 @@ public:
|
|||
|
||||
LowLevelGraphicsContext* createLowLevelContext()
|
||||
{
|
||||
return new OpenGLGraphicsContext (context, frameBuffer);
|
||||
return createOpenGLGraphicsContext (context, frameBuffer);
|
||||
}
|
||||
|
||||
ImageType* createType() const { return new OpenGLImageType(); }
|
||||
ImageType* createType() const { return new OpenGLImageType(); }
|
||||
|
||||
ImagePixelData* clone()
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue