Browse Source

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.

tags/2021-05-28
jules 13 years ago
parent
commit
b338698e34
11 changed files with 425 additions and 1471 deletions
  1. +3
    -2
      extras/JuceDemo/Source/demos/OpenGLDemo.cpp
  2. +1
    -1
      modules/juce_gui_basics/windows/juce_ResizableWindow.h
  3. +64
    -25
      modules/juce_opengl/opengl/juce_OpenGLComponent.cpp
  4. +1
    -1
      modules/juce_opengl/opengl/juce_OpenGLComponent.h
  5. +15
    -13
      modules/juce_opengl/opengl/juce_OpenGLContext.cpp
  6. +6
    -1
      modules/juce_opengl/opengl/juce_OpenGLContext.h
  7. +14
    -9
      modules/juce_opengl/opengl/juce_OpenGLFrameBuffer.cpp
  8. +3
    -0
      modules/juce_opengl/opengl/juce_OpenGLFrameBuffer.h
  9. +302
    -1367
      modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp
  10. +14
    -50
      modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.h
  11. +2
    -2
      modules/juce_opengl/opengl/juce_OpenGLImage.cpp

+ 3
- 2
extras/JuceDemo/Source/demos/OpenGLDemo.cpp View File

@@ -157,8 +157,9 @@ public:
void drawBackground2DStuff() 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.. // This stuff just creates a spinning star shape and fills it..
Path p; Path p;


+ 1
- 1
modules/juce_gui_basics/windows/juce_ResizableWindow.h View File

@@ -322,7 +322,7 @@ protected:
//============================================================================== //==============================================================================
/** @internal */ /** @internal */
void paint (Graphics& g); 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(); void moved();
/** (if overriding this, make sure you call ResizableWindow::resized() in your subclass) */ /** (if overriding this, make sure you call ResizableWindow::resized() in your subclass) */
void resized(); void resized();


+ 64
- 25
modules/juce_opengl/opengl/juce_OpenGLComponent.cpp View File

@@ -121,6 +121,26 @@ public:
return frameBuffer; 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; RectangleList validArea;
private: private:
@@ -152,7 +172,9 @@ public:
void componentVisibilityChanged() void componentVisibilityChanged()
{ {
if (! owner.isShowing())
if (owner.isShowing())
owner.triggerRepaint();
else
owner.stopRenderThread(); owner.stopRenderThread();
} }
@@ -172,34 +194,54 @@ public:
{ {
} }
void run()
virtual void initialise()
{ {
#if JUCE_LINUX #if JUCE_LINUX
{
MessageManagerLock mml (this);
if (! mml.lockWasGained())
return;
MessageManagerLock mml (this);
if (mml.lockWasGained())
{
owner.updateContext(); owner.updateContext();
owner.updateContextPosition(); owner.updateContextPosition();
} }
#endif #endif
}
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()) while (! threadShouldExit())
{ {
const uint32 startOfRendering = Time::getMillisecondCounter();
const uint32 frameRenderStartTime = Time::getMillisecondCounter();
if (! owner.performRender())
if (! renderFrame())
break; break;
const int elapsed = (int) (Time::getMillisecondCounter() - startOfRendering);
Thread::sleep (jmax (1, (1000 / 60) - elapsed));
waitForNextFrame (frameRenderStartTime);
} }
#if JUCE_LINUX
owner.deleteContext();
#endif
shutdown();
} }
private: private:
@@ -458,17 +500,14 @@ bool OpenGLComponent::performRender()
{ {
jassert (getCurrentContext() != nullptr); jassert (getCurrentContext() != nullptr);
cachedImage->clearRegionInFrameBuffer (invalid);
{ {
OpenGLGraphicsContext g (*getCurrentContext(), frameBuffer);
ScopedPointer<LowLevelGraphicsContext> g (createOpenGLGraphicsContext (*getCurrentContext(), frameBuffer));
JUCE_CHECK_OPENGL_ERROR 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 JUCE_CHECK_OPENGL_ERROR
} }
@@ -484,7 +523,7 @@ bool OpenGLComponent::performRender()
glBindTexture (GL_TEXTURE_2D, frameBuffer.getTextureID()); glBindTexture (GL_TEXTURE_2D, frameBuffer.getTextureID());
jassert (bounds.getPosition() == Point<int>()); jassert (bounds.getPosition() == Point<int>());
context->copyTexture (bounds, bounds);
context->copyTexture (bounds, bounds, context->getWidth(), context->getHeight());
glBindTexture (GL_TEXTURE_2D, 0); glBindTexture (GL_TEXTURE_2D, 0);
JUCE_CHECK_OPENGL_ERROR JUCE_CHECK_OPENGL_ERROR
} }
@@ -495,9 +534,9 @@ bool OpenGLComponent::performRender()
return true; return true;
} }
void OpenGLComponent::paintSelf (OpenGLGraphicsContext& glRenderer)
void OpenGLComponent::paintSelf (LowLevelGraphicsContext& context)
{ {
Graphics g (&glRenderer);
Graphics g (&context);
#if JUCE_ENABLE_REPAINT_DEBUGGING #if JUCE_ENABLE_REPAINT_DEBUGGING
g.saveState(); g.saveState();


+ 1
- 1
modules/juce_opengl/opengl/juce_OpenGLComponent.h View File

@@ -289,7 +289,7 @@ private:
void updateEmbeddedPosition (const Rectangle<int>&); void updateEmbeddedPosition (const Rectangle<int>&);
void startRenderThread(); void startRenderThread();
bool performRender(); bool performRender();
void paintSelf (OpenGLGraphicsContext&);
void paintSelf (LowLevelGraphicsContext&);
int renderAndSwapBuffers(); // (This method has been deprecated) int renderAndSwapBuffers(); // (This method has been deprecated)


+ 15
- 13
modules/juce_opengl/opengl/juce_OpenGLContext.cpp View File

@@ -127,7 +127,8 @@ bool OpenGLContext::areShadersAvailable() const
} }
void OpenGLContext::copyTexture (const Rectangle<int>& targetClipArea, 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); glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glEnable (GL_BLEND); glEnable (GL_BLEND);
@@ -138,9 +139,7 @@ void OpenGLContext::copyTexture (const Rectangle<int>& targetClipArea,
struct OverlayShaderProgram : public ReferenceCountedObject struct OverlayShaderProgram : public ReferenceCountedObject
{ {
OverlayShaderProgram (OpenGLContext& context) OverlayShaderProgram (OpenGLContext& context)
: program (context),
builder (program),
params (program)
: program (context), builder (program), params (program)
{} {}
static const OverlayShaderProgram& select (OpenGLContext& context) 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 GLshort vertices[] = { left, bottom, right, bottom, left, top, right, top };
const OverlayShaderProgram& program = OverlayShaderProgram::select (*this); 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.glVertexAttribPointer (program.params.positionAttribute.attributeID, 2, GL_SHORT, GL_FALSE, 4, vertices);
extensions.glEnableVertexAttribArray (program.params.positionAttribute.attributeID); extensions.glEnableVertexAttribArray (program.params.positionAttribute.attributeID);
@@ -241,26 +240,29 @@ void OpenGLContext::copyTexture (const Rectangle<int>& targetClipArea,
#if JUCE_USE_OPENGL_FIXED_FUNCTION #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); glColor4f (1.0f, 1.0f, 1.0f, 1.0f);
glDisableClientState (GL_COLOR_ARRAY); glDisableClientState (GL_COLOR_ARRAY);
glDisableClientState (GL_NORMAL_ARRAY); glDisableClientState (GL_NORMAL_ARRAY);
glEnableClientState (GL_VERTEX_ARRAY); glEnableClientState (GL_VERTEX_ARRAY);
glEnableClientState (GL_TEXTURE_COORD_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 }; const GLfloat textureCoords[] = { 0, 0, 1.0f, 0, 0, 1.0f, 1.0f, 1.0f };
glTexCoordPointer (2, GL_FLOAT, 0, textureCoords); 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); glVertexPointer (2, GL_SHORT, 0, vertices);
glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
glDisable (GL_SCISSOR_TEST);
} }
#endif #endif
} }

+ 6
- 1
modules/juce_opengl/opengl/juce_OpenGLContext.h View File

@@ -112,9 +112,14 @@ public:
@param anchorPosAndTextureSize the position of this rectangle is the texture's top-left @param anchorPosAndTextureSize the position of this rectangle is the texture's top-left
anchor position in the target space, and the size must be anchor position in the target space, and the size must be
the total size of the texture. 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, void copyTexture (const Rectangle<int>& targetClipArea,
const Rectangle<int>& anchorPosAndTextureSize);
const Rectangle<int>& anchorPosAndTextureSize,
int contextWidth, int contextHeight);
protected: protected:
//============================================================================== //==============================================================================


+ 14
- 9
modules/juce_opengl/opengl/juce_OpenGLFrameBuffer.cpp View File

@@ -32,7 +32,7 @@ public:
width (width_), width (width_),
height (height_), height (height_),
textureID (0), textureID (0),
frameBufferHandle (0),
frameBufferID (0),
depthOrStencilBuffer (0), depthOrStencilBuffer (0),
hasDepthBuffer (false), hasDepthBuffer (false),
hasStencilBuffer (false), hasStencilBuffer (false),
@@ -47,8 +47,8 @@ public:
return; return;
#endif #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 JUCE_CHECK_OPENGL_ERROR
glGenTextures (1, &textureID); glGenTextures (1, &textureID);
@@ -102,15 +102,15 @@ public:
if (depthOrStencilBuffer != 0) if (depthOrStencilBuffer != 0)
context.extensions.glDeleteRenderbuffers (1, &depthOrStencilBuffer); 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 JUCE_CHECK_OPENGL_ERROR
} }
void bind() void bind()
{ {
context.extensions.glBindFramebuffer (GL_FRAMEBUFFER, frameBufferHandle);
context.extensions.glBindFramebuffer (GL_FRAMEBUFFER, frameBufferID);
JUCE_CHECK_OPENGL_ERROR JUCE_CHECK_OPENGL_ERROR
} }
@@ -122,7 +122,7 @@ public:
OpenGLContext& context; OpenGLContext& context;
const int width, height; const int width, height;
GLuint textureID, frameBufferHandle, depthOrStencilBuffer;
GLuint textureID, frameBufferID, depthOrStencilBuffer;
bool hasDepthBuffer, hasStencilBuffer, ok; bool hasDepthBuffer, hasStencilBuffer, ok;
private: private:
@@ -214,7 +214,7 @@ bool OpenGLFrameBuffer::initialise (OpenGLFrameBuffer& other)
glEnable (GL_TEXTURE_2D); glEnable (GL_TEXTURE_2D);
#endif #endif
glBindTexture (GL_TEXTURE_2D, p->textureID); 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); glBindTexture (GL_TEXTURE_2D, 0);
JUCE_CHECK_OPENGL_ERROR JUCE_CHECK_OPENGL_ERROR
@@ -272,6 +272,11 @@ bool OpenGLFrameBuffer::makeCurrentRenderingTarget()
return true; return true;
} }
GLuint OpenGLFrameBuffer::getFrameBufferID() const
{
return pimpl != nullptr ? pimpl->frameBufferID : 0;
}
GLuint OpenGLFrameBuffer::getCurrentFrameBufferTarget() GLuint OpenGLFrameBuffer::getCurrentFrameBufferTarget()
{ {
GLint fb; 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()); glDrawTexiOES (area.getX(), area.getY(), 1, area.getWidth(), area.getHeight());
glBindTexture (GL_TEXTURE_2D, 0); glBindTexture (GL_TEXTURE_2D, 0);
#else #else
pimpl->context.copyTexture (area, area);
pimpl->context.copyTexture (area, area, pimpl->width, pimpl->height);
#endif #endif
pimpl->context.extensions.glBindFramebuffer (GL_FRAMEBUFFER, 0); pimpl->context.extensions.glBindFramebuffer (GL_FRAMEBUFFER, 0);


+ 3
- 0
modules/juce_opengl/opengl/juce_OpenGLFrameBuffer.h View File

@@ -95,6 +95,9 @@ public:
/** Deselects this buffer as the current OpenGL rendering target. */ /** Deselects this buffer as the current OpenGL rendering target. */
void releaseAsRenderingTarget(); 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. */ /** Returns the current frame buffer ID for the current context. */
static GLuint getCurrentFrameBufferTarget(); static GLuint getCurrentFrameBufferTarget();


+ 302
- 1367
modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp
File diff suppressed because it is too large
View File


+ 14
- 50
modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.h View File

@@ -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;
void saveState();
void restoreState();
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&);
/** 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);
#ifndef DOXYGEN
class SavedState;
class GLState;
#endif
/** 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);
private:
ScopedPointer<GLState> glState;
RenderingHelpers::SavedStateStack<SavedState> stack;
};
#endif // __JUCE_OPENGLGRAPHICSCONTEXT_JUCEHEADER__ #endif // __JUCE_OPENGLGRAPHICSCONTEXT_JUCEHEADER__

+ 2
- 2
modules/juce_opengl/opengl/juce_OpenGLImage.cpp View File

@@ -38,10 +38,10 @@ public:
LowLevelGraphicsContext* createLowLevelContext() 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() ImagePixelData* clone()
{ {


Loading…
Cancel
Save