From b23e5c4515403316e61fc0e02946cabe33e60f06 Mon Sep 17 00:00:00 2001 From: jules Date: Wed, 19 Oct 2011 10:26:26 +0100 Subject: [PATCH] ImageButton fix. OpenGL refactoring. --- .../juce_core/native/juce_posix_SharedCode.h | 2 +- .../native/juce_RenderingHelpers.h | 4 +- .../buttons/juce_ImageButton.cpp | 14 +- .../native/juce_android_OpenGLComponent.cpp | 5 + .../native/juce_ios_OpenGLComponent.mm | 6 + .../native/juce_linux_OpenGLComponent.cpp | 7 + .../native/juce_mac_OpenGLComponent.mm | 6 + .../native/juce_win32_OpenGLComponent.cpp | 6 + .../opengl/juce_OpenGLFrameBuffer.cpp | 73 ++--- .../opengl/juce_OpenGLFrameBuffer.h | 13 - .../juce_opengl/opengl/juce_OpenGLHelpers.cpp | 278 ++++-------------- .../juce_opengl/opengl/juce_OpenGLHelpers.h | 13 +- .../opengl/juce_OpenGLRenderingTarget.h | 5 - .../juce_opengl/opengl/juce_OpenGLTexture.cpp | 4 + 14 files changed, 136 insertions(+), 300 deletions(-) diff --git a/modules/juce_core/native/juce_posix_SharedCode.h b/modules/juce_core/native/juce_posix_SharedCode.h index 4a9395ed0e..6a049bc398 100644 --- a/modules/juce_core/native/juce_posix_SharedCode.h +++ b/modules/juce_core/native/juce_posix_SharedCode.h @@ -771,7 +771,7 @@ void InterProcessLock::exit() //============================================================================== void JUCE_API juce_threadEntryPoint (void*); -void* threadEntryProc (void* userData) +extern "C" void* threadEntryProc (void* userData) { JUCE_AUTORELEASEPOOL diff --git a/modules/juce_graphics/native/juce_RenderingHelpers.h b/modules/juce_graphics/native/juce_RenderingHelpers.h index f230db2f47..c1e96948dd 100644 --- a/modules/juce_graphics/native/juce_RenderingHelpers.h +++ b/modules/juce_graphics/native/juce_RenderingHelpers.h @@ -77,7 +77,7 @@ public: { if (isOnlyTranslated && t.isOnlyTranslation() - && isIntegerTranlation (t)) + && isIntegerTranslation (t)) { xOffset += (int) t.getTranslationX(); yOffset += (int) t.getTranslationY(); @@ -126,7 +126,7 @@ public: bool isOnlyTranslated; private: - static inline bool isIntegerTranlation (const AffineTransform& t) noexcept + static inline bool isIntegerTranslation (const AffineTransform& t) noexcept { const int tx = (int) (t.getTranslationX() * 256.0f); const int ty = (int) (t.getTranslationY() * 256.0f); diff --git a/modules/juce_gui_basics/buttons/juce_ImageButton.cpp b/modules/juce_gui_basics/buttons/juce_ImageButton.cpp index 356cf823c6..3501f0de26 100644 --- a/modules/juce_gui_basics/buttons/juce_ImageButton.cpp +++ b/modules/juce_gui_basics/buttons/juce_ImageButton.cpp @@ -129,16 +129,16 @@ void ImageButton::paintButton (Graphics& g, const int ih = im.getHeight(); imageW = getWidth(); imageH = getHeight(); - imageX = (imageW - iw) >> 1; - imageY = (imageH - ih) >> 1; + imageX = (imageW - iw) / 2; + imageY = (imageH - ih) / 2; if (scaleImageToFit) { if (preserveProportions) { int newW, newH; - const float imRatio = ih / (float)iw; - const float destRatio = imageH / (float)imageW; + const float imRatio = ih / (float) iw; + const float destRatio = imageH / (float) imageW; if (imRatio > destRatio) { @@ -169,11 +169,13 @@ void ImageButton::paintButton (Graphics& g, imageH = ih; } + const bool useDownImage = isButtonDown || getToggleState(); + getLookAndFeel().drawImageButton (g, &im, imageX, imageY, imageW, imageH, - isButtonDown ? downOverlay + useDownImage ? downOverlay : (isMouseOverButton ? overOverlay : normalOverlay), - isButtonDown ? downOpacity + useDownImage ? downOpacity : (isMouseOverButton ? overOpacity : normalOpacity), *this); diff --git a/modules/juce_opengl/native/juce_android_OpenGLComponent.cpp b/modules/juce_opengl/native/juce_android_OpenGLComponent.cpp index 55057665f3..ecac95a7b2 100644 --- a/modules/juce_opengl/native/juce_android_OpenGLComponent.cpp +++ b/modules/juce_opengl/native/juce_android_OpenGLComponent.cpp @@ -39,3 +39,8 @@ void OpenGLPixelFormat::getAvailablePixelFormats (Component* component, { } + +bool OpenGLHelpers::isContextActive() +{ + return false; +} diff --git a/modules/juce_opengl/native/juce_ios_OpenGLComponent.mm b/modules/juce_opengl/native/juce_ios_OpenGLComponent.mm index b78ada4d02..29681bffd5 100644 --- a/modules/juce_opengl/native/juce_ios_OpenGLComponent.mm +++ b/modules/juce_opengl/native/juce_ios_OpenGLComponent.mm @@ -234,3 +234,9 @@ void OpenGLPixelFormat::getAvailablePixelFormats (Component* /*component*/, OwnedArray & /*results*/) { } + +//============================================================================== +bool OpenGLHelpers::isContextActive() +{ + return [EAGLContext currentContext] != nil; +} diff --git a/modules/juce_opengl/native/juce_linux_OpenGLComponent.cpp b/modules/juce_opengl/native/juce_linux_OpenGLComponent.cpp index b8dcd93c70..8934762259 100644 --- a/modules/juce_opengl/native/juce_linux_OpenGLComponent.cpp +++ b/modules/juce_opengl/native/juce_linux_OpenGLComponent.cpp @@ -200,3 +200,10 @@ void OpenGLPixelFormat::getAvailablePixelFormats (Component* component, OwnedArr { results.add (new OpenGLPixelFormat()); // xxx } + +//============================================================================== +bool OpenGLHelpers::isContextActive() +{ + ScopedXLock xlock; + return glXGetCurrentContext() != 0; +} diff --git a/modules/juce_opengl/native/juce_mac_OpenGLComponent.mm b/modules/juce_opengl/native/juce_mac_OpenGLComponent.mm index 193085e18c..cc4e374627 100644 --- a/modules/juce_opengl/native/juce_mac_OpenGLComponent.mm +++ b/modules/juce_opengl/native/juce_mac_OpenGLComponent.mm @@ -312,3 +312,9 @@ void OpenGLPixelFormat::getAvailablePixelFormats (Component* /*component*/, results.add (pf); } } + +//============================================================================== +bool OpenGLHelpers::isContextActive() +{ + return [NSOpenGLContext currentContext] != nil; +} diff --git a/modules/juce_opengl/native/juce_win32_OpenGLComponent.cpp b/modules/juce_opengl/native/juce_win32_OpenGLComponent.cpp index 020704ecad..ba14dc1df4 100644 --- a/modules/juce_opengl/native/juce_win32_OpenGLComponent.cpp +++ b/modules/juce_opengl/native/juce_win32_OpenGLComponent.cpp @@ -509,3 +509,9 @@ void OpenGLPixelFormat::getAvailablePixelFormats (Component* component, wc.findAlternativeOpenGLPixelFormats (results); } } + +//============================================================================== +bool OpenGLHelpers::isContextActive() +{ + return wglGetCurrentContext() != 0; +} diff --git a/modules/juce_opengl/opengl/juce_OpenGLFrameBuffer.cpp b/modules/juce_opengl/opengl/juce_OpenGLFrameBuffer.cpp index 0cf7dce8b5..e64a4fb409 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLFrameBuffer.cpp +++ b/modules/juce_opengl/opengl/juce_OpenGLFrameBuffer.cpp @@ -145,6 +145,10 @@ public: hasStencilBuffer (false), ok (false) { + // Framebuffer objects can only be created when the current thread has an active OpenGL + // context. You'll need to make an OpenGLComponent active before calling this. + jassert (OpenGLHelpers::isContextActive()); + #if JUCE_WINDOWS || JUCE_LINUX initialiseFrameBufferFunctions(); @@ -155,17 +159,13 @@ public: OpenGLHelpers::resetErrorState(); glGenFramebuffersEXT (1, &frameBufferHandle); + glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, frameBufferHandle); glGenTextures (1, &textureID); glBindTexture (textureType, textureID); glTexImage2D (textureType, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - glTexParameterf (textureType, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf (textureType, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameterf (textureType, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf (textureType, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, textureType, textureID, 0); if (wantsDepthBuffer || wantsStencilBuffer) @@ -174,37 +174,33 @@ public: glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, depthOrStencilBuffer); jassert (glIsRenderbufferEXT (depthOrStencilBuffer)); - if (wantsDepthBuffer && wantsStencilBuffer) - { - glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, width, height); + glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, + (wantsDepthBuffer && wantsStencilBuffer) ? GL_DEPTH24_STENCIL8_EXT + #if JUCE_OPENGL_ES + : GL_DEPTH_COMPONENT16, + #else + : GL_DEPTH_COMPONENT, + #endif + width, height); - GLint params = 0; - glGetRenderbufferParameterivEXT (GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_DEPTH_SIZE_EXT, ¶ms); + GLint params = 0; + glGetRenderbufferParameterivEXT (GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_DEPTH_SIZE_EXT, ¶ms); + glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthOrStencilBuffer); - glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthOrStencilBuffer); + if (wantsStencilBuffer) glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthOrStencilBuffer); - hasDepthBuffer = true; - hasStencilBuffer = true; - } - else - { - #if JUCE_OPENGL_ES - glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16, width, height); - #else - glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, height); - #endif - - GLint params = 0; - glGetRenderbufferParameterivEXT (GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_DEPTH_SIZE_EXT, ¶ms); - glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthOrStencilBuffer); - - hasDepthBuffer = true; - } + hasDepthBuffer = wantsDepthBuffer; + hasStencilBuffer = wantsStencilBuffer; } ok = checkStatus(); + glTexParameterf (textureType, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf (textureType, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterf (textureType, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf (textureType, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0); } @@ -438,7 +434,7 @@ bool OpenGLFrameBuffer::writePixels (const void* data, int pixelStride, const Re glBindTexture (GL_TEXTURE_2D, temporaryTexture); glPixelStorei (GL_UNPACK_ALIGNMENT, pixelStride); - glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, area.getWidth(), area.getHeight(), 0, + glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, area.getWidth(), area.getHeight(), 0, format, GL_UNSIGNED_BYTE, data); glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -522,24 +518,5 @@ void OpenGLFrameBuffer::drawAt (float x1, float y1) const } } -//============================================================================== -void OpenGLFrameBuffer::createAlphaChannelFromPath (const Path& path, const AffineTransform& transform, - const int oversamplingLevel) -{ - makeCurrentRenderingTarget(); - - glEnableClientState (GL_VERTEX_ARRAY); - glEnableClientState (GL_TEXTURE_COORD_ARRAY); - glDisableClientState (GL_COLOR_ARRAY); - glDisableClientState (GL_NORMAL_ARRAY); - glDisable (GL_TEXTURE_2D); - glDisable (GL_DEPTH_TEST); - glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glEnable (GL_BLEND); - glBlendFunc (GL_ONE, GL_ONE); - - prepareFor2D(); - TriangulatedPath (path, transform).draw (oversamplingLevel); -} END_JUCE_NAMESPACE diff --git a/modules/juce_opengl/opengl/juce_OpenGLFrameBuffer.h b/modules/juce_opengl/opengl/juce_OpenGLFrameBuffer.h index 41c72aeb25..f9f047d866 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLFrameBuffer.h +++ b/modules/juce_opengl/opengl/juce_OpenGLFrameBuffer.h @@ -134,19 +134,6 @@ public: bool writePixels (const void* srcData, int srcPixelStride, const Rectangle& targetArea); - /** This will render an anti-aliased path into just the alpha channel of this framebuffer. - - The idea here is that you can clear a framebuffer, use this to set its alpha channel, then - fill the RGB channels with some kind of fill-pattern, and then copy the whole thing onto - a target, to produce a filled path with some kind of texture. - - Calling this will make changes to a lot of openGL state, including colour masks, blend - functions, etc - */ - void createAlphaChannelFromPath (const Path& path, - const AffineTransform& transform, - int oversamplingLevel = 4); - private: class Pimpl; friend class ScopedPointer; diff --git a/modules/juce_opengl/opengl/juce_OpenGLHelpers.cpp b/modules/juce_opengl/opengl/juce_OpenGLHelpers.cpp index ed94e09eaf..62bf2ea230 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLHelpers.cpp +++ b/modules/juce_opengl/opengl/juce_OpenGLHelpers.cpp @@ -51,7 +51,7 @@ void OpenGLHelpers::prepareFor2D (const int width, const int height) glLoadIdentity(); #if JUCE_OPENGL_ES - glOrthof (0.0f, (float) width, 0.0f, (float) height, 0.0f, 1.0f); + glOrthof (0.0f, (GLfloat) width, 0.0f, (GLfloat) height, 0.0f, 1.0f); #else glOrtho (0.0, width, 0.0, height, 0, 1); #endif @@ -64,10 +64,10 @@ void OpenGLHelpers::setPerspective (double fovy, double aspect, double zNear, do glLoadIdentity(); #if JUCE_OPENGL_ES - const float ymax = (float) (zNear * tan (fovy * double_Pi / 360.0)); - const float ymin = -ymax; + const GLfloat ymax = (GLfloat) (zNear * tan (fovy * double_Pi / 360.0)); + const GLfloat ymin = -ymax; - glFrustumf (ymin * (float) aspect, ymax * (float) aspect, ymin, ymax, (float) zNear, (float) zFar); + glFrustumf (ymin * (GLfloat) aspect, ymax * (GLfloat) aspect, ymin, ymax, (GLfloat) zNear, (GLfloat) zFar); #else const double ymax = zNear * tan (fovy * double_Pi / 360.0); const double ymin = -ymax; @@ -136,7 +136,6 @@ namespace OpenGLGradientHelpers { void drawTriangles (GLenum mode, const GLfloat* vertices, const GLfloat* textureCoords, const int numElements) { - glEnable (GL_BLEND); glEnable (GL_TEXTURE_2D); glEnableClientState (GL_VERTEX_ARRAY); glEnableClientState (GL_TEXTURE_COORD_ARRAY); @@ -164,10 +163,10 @@ namespace OpenGLGradientHelpers p2.getX(), p2.getY(), 1.0f, 0.0f, p3.getX(), p3.getY(), 0.0f, 1.0f)); - const float l = (float) rect.getX(); - const float r = (float) rect.getRight(); - const float t = (float) rect.getY(); - const float b = (float) rect.getBottom(); + const GLfloat l = (GLfloat) rect.getX(); + const GLfloat r = (GLfloat) rect.getRight(); + const GLfloat t = (GLfloat) rect.getY(); + const GLfloat b = (GLfloat) rect.getBottom(); const GLfloat vertices[] = { l, t, r, t, l, b, r, b }; GLfloat textureCoords[] = { l, t, r, t, l, b, r, b }; @@ -202,8 +201,7 @@ namespace OpenGLGradientHelpers *t++ = 0.0f; *t++ = 0.0f; - const float originalRadius = grad.point1.getDistanceFrom (grad.point2); - const float texturePos = sourceRadius / originalRadius; + const GLfloat texturePos = sourceRadius / grad.point1.getDistanceFrom (grad.point2); for (int i = numDivisions + 1; --i >= 0;) { @@ -280,15 +278,54 @@ void OpenGLHelpers::fillRectWithColour (const Rectangle& rect, const Colour void OpenGLHelpers::fillRect (const Rectangle& rect) { - const GLfloat vertices[] = { (float) rect.getX(), (float) rect.getY(), - (float) rect.getRight(), (float) rect.getY(), - (float) rect.getX(), (float) rect.getBottom(), - (float) rect.getRight(), (float) rect.getBottom() }; + const GLfloat vertices[] = { (GLfloat) rect.getX(), (GLfloat) rect.getY(), + (GLfloat) rect.getRight(), (GLfloat) rect.getY(), + (GLfloat) rect.getX(), (GLfloat) rect.getBottom(), + (GLfloat) rect.getRight(), (GLfloat) rect.getBottom() }; glVertexPointer (2, GL_FLOAT, 0, vertices); glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); } +void OpenGLHelpers::fillRectWithTiledTexture (int textureWidth, int textureHeight, + const Rectangle& clip, + const AffineTransform& transform, + float alpha) +{ + glEnable (GL_TEXTURE_2D); + glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glEnableClientState (GL_VERTEX_ARRAY); + glEnableClientState (GL_TEXTURE_COORD_ARRAY); + glDisableClientState (GL_COLOR_ARRAY); + glDisableClientState (GL_NORMAL_ARRAY); + glColor4f (1.0f, 1.0f, 1.0f, alpha); + + glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + + const GLfloat clipX = (GLfloat) clip.getX(); + const GLfloat clipY = (GLfloat) clip.getY(); + const GLfloat clipR = (GLfloat) clip.getRight(); + const GLfloat clipB = (GLfloat) clip.getBottom(); + + const GLfloat vertices[] = { clipX, clipY, clipR, clipY, clipX, clipB, clipR, clipB }; + GLfloat textureCoords[] = { clipX, clipY, clipR, clipY, clipX, clipB, clipR, clipB }; + + { + const AffineTransform t (transform.inverted().scaled (1.0f / textureWidth, + 1.0f / textureHeight)); + t.transformPoints (textureCoords[0], textureCoords[1], textureCoords[2], textureCoords[3]); + t.transformPoints (textureCoords[4], textureCoords[5], textureCoords[6], textureCoords[7]); + } + + glVertexPointer (2, GL_FLOAT, 0, vertices); + glTexCoordPointer (2, GL_FLOAT, 0, textureCoords); + + glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); +} + + //============================================================================== // This breaks down a path into a series of horizontal strips of trapezoids.. class TriangulatedPath::TrapezoidedPath @@ -575,6 +612,8 @@ TriangulatedPath::TriangulatedPath (const Path& path, const AffineTransform& tra TrapezoidedPath (path, transform).iterate (*this); } +TriangulatedPath::~TriangulatedPath() {} + void TriangulatedPath::draw (const int oversamplingLevel) const { glColor4f (1.0f, 1.0f, 1.0f, 1.0f / (oversamplingLevel * oversamplingLevel)); @@ -670,214 +709,5 @@ void OpenGLRenderingTarget::prepareFor2D() getRenderingTargetHeight()); } -namespace GLPathRendering -{ - void clipToPath (OpenGLRenderingTarget& target, - const Path& path, const AffineTransform& transform) - { - const int w = target.getRenderingTargetWidth(); - const int h = target.getRenderingTargetHeight(); - - OpenGLFrameBuffer fb; - fb.initialise (w, h); - fb.makeCurrentAndClear(); - fb.createAlphaChannelFromPath (path, transform); - - target.makeCurrentRenderingTarget(); - target.prepareFor2D(); - - glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); - glBlendFunc (GL_DST_ALPHA, GL_ZERO); - - glColor4f (1.0f, 1.0f, 1.0f, 1.0f); - fb.drawAt (0, 0); - } - - void fillPathWithColour (OpenGLRenderingTarget& target, - const Rectangle& clip, const Path& path, - const AffineTransform& pathTransform, - const Colour& colour) - { - OpenGLFrameBuffer f; - f.initialise (clip.getWidth(), clip.getHeight()); - f.makeCurrentAndClear(); - - f.createAlphaChannelFromPath (path, pathTransform.translated ((float) -clip.getX(), (float) -clip.getY()) - .followedBy (AffineTransform::verticalFlip ((float) clip.getHeight()))); - f.releaseAsRenderingTarget(); - - target.makeCurrentRenderingTarget(); - - glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - OpenGLHelpers::setColour (colour); - target.prepareFor2D(); - - f.drawAt ((float) clip.getX(), (float) (target.getRenderingTargetHeight() - clip.getBottom())); - } - - void fillPathWithGradient (OpenGLRenderingTarget& target, - const Rectangle& clip, const Path& path, - const AffineTransform& pathTransform, - const ColourGradient& grad, - const AffineTransform& gradientTransform, - const GLfloat alpha) - { - const int targetHeight = target.getRenderingTargetHeight(); - - OpenGLFrameBuffer f; - f.initialise (clip.getWidth(), clip.getHeight()); - f.makeCurrentAndClear(); - - const AffineTransform correction (AffineTransform::translation ((float) -clip.getX(), (float) -clip.getY()) - .followedBy (AffineTransform::verticalFlip ((float) clip.getHeight()))); - - f.createAlphaChannelFromPath (path, pathTransform.followedBy (correction)); - - f.makeCurrentRenderingTarget(); - f.prepareFor2D(); - - glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glBlendFunc (GL_DST_ALPHA, GL_ZERO); - - OpenGLHelpers::fillRectWithColourGradient (Rectangle (0, 0, clip.getWidth(), clip.getHeight()), - grad, gradientTransform.followedBy (correction)); - f.releaseAsRenderingTarget(); - target.makeCurrentRenderingTarget(); - - glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - glColor4f (alpha, alpha, alpha, alpha); - target.prepareFor2D(); - - f.drawAt ((float) clip.getX(), (float) (targetHeight - clip.getBottom())); - } - - void fillPathWithImage (OpenGLRenderingTarget& target, - const Rectangle& clip, const Path& path, - const AffineTransform& transform, - GLuint textureID, GLfloat textureWidth, GLfloat textureHeight, - const AffineTransform& textureTransform, - const bool tiled, - const GLfloat alpha) - { - const int targetHeight = target.getRenderingTargetHeight(); - - OpenGLFrameBuffer f; - f.initialise (clip.getWidth(), clip.getHeight()); - f.makeCurrentRenderingTarget(); - f.prepareFor2D(); - - glDisable (GL_BLEND); - glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glColor4f (1.0f, 1.0f, 1.0f, 1.0f); - - const GLfloat clipX = (GLfloat) clip.getX(); - const GLfloat clipY = (GLfloat) clip.getY(); - const GLfloat clipH = (GLfloat) clip.getHeight(); - const GLfloat clipB = (GLfloat) clip.getBottom(); - - const AffineTransform correction (AffineTransform::translation (-clipX, -clipY) - .followedBy (AffineTransform::verticalFlip (clipH))); - - glBindTexture (GL_TEXTURE_2D, textureID); - glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glEnableClientState (GL_VERTEX_ARRAY); - glEnableClientState (GL_TEXTURE_COORD_ARRAY); - glDisableClientState (GL_COLOR_ARRAY); - glDisableClientState (GL_NORMAL_ARRAY); - glColor4f (1.0f, 1.0f, 1.0f, 1.0f); - - if (tiled) - { - glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - - const GLfloat clipW = (GLfloat) clip.getWidth(); - const GLfloat clipR = (GLfloat) clip.getRight(); - - const GLfloat vertices[] = { 0, clipH, clipW, clipH, 0, 0, clipW, 0 }; - GLfloat textureCoords[] = { clipX, clipY, clipR, clipY, clipX, clipB, clipR, clipB }; - - { - const AffineTransform t (textureTransform.inverted().scaled (1.0f / textureWidth, - 1.0f / textureHeight)); - t.transformPoints (textureCoords[0], textureCoords[1], textureCoords[2], textureCoords[3]); - t.transformPoints (textureCoords[4], textureCoords[5], textureCoords[6], textureCoords[7]); - } - - glVertexPointer (2, GL_FLOAT, 0, vertices); - glTexCoordPointer (2, GL_FLOAT, 0, textureCoords); - - glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); - } - else - { - glClearColor (0, 0, 0, 0); - glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - - glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - GLfloat vertices[] = { 0, 0, textureWidth, 0, 0, textureHeight, textureWidth, textureHeight }; - const GLfloat textureCoords[] = { 0, 0, 1.0f, 0, 0, 1.0f, 1.0f, 1.0f }; - - { - const AffineTransform t (textureTransform.followedBy (correction)); - t.transformPoints (vertices[0], vertices[1], vertices[2], vertices[3]); - t.transformPoints (vertices[4], vertices[5], vertices[6], vertices[7]); - } - - glVertexPointer (2, GL_FLOAT, 0, vertices); - glTexCoordPointer (2, GL_FLOAT, 0, textureCoords); - - glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); - } - - glBindTexture (GL_TEXTURE_2D, 0); - - clipToPath (f, path, transform.followedBy (correction)); - - f.releaseAsRenderingTarget(); - target.makeCurrentRenderingTarget(); - - glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glColor4f (1.0f, 1.0f, 1.0f, alpha); - target.prepareFor2D(); - - f.drawAt (clipX, targetHeight - clipB); - } -} - -void OpenGLRenderingTarget::fillPath (const Rectangle& clip, - const Path& path, const AffineTransform& transform, - const FillType& fill) -{ - if (! fill.isInvisible()) - { - if (fill.isColour()) - { - GLPathRendering::fillPathWithColour (*this, clip, path, transform, fill.colour); - } - else if (fill.isGradient()) - { - GLPathRendering::fillPathWithGradient (*this, clip, path, transform, - *(fill.gradient), fill.transform, - fill.colour.getFloatAlpha()); - } - else if (fill.isTiledImage()) - { - OpenGLTextureFromImage t (fill.image); - - GLPathRendering::fillPathWithImage (*this, clip, path, transform, - t.textureID, (GLfloat) t.width, (GLfloat) t.height, - fill.transform, true, - fill.colour.getFloatAlpha()); - } - } -} END_JUCE_NAMESPACE diff --git a/modules/juce_opengl/opengl/juce_OpenGLHelpers.h b/modules/juce_opengl/opengl/juce_OpenGLHelpers.h index 35597fe2d7..ee96916b75 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLHelpers.h +++ b/modules/juce_opengl/opengl/juce_OpenGLHelpers.h @@ -40,6 +40,9 @@ public: /** Clears the GL error state. */ static void resetErrorState(); + /** Returns true if the current thread has an active OpenGL context. */ + static bool isContextActive(); + /** Clears the current context using the given colour. */ static void clear (const Colour& colour); @@ -78,6 +81,11 @@ public: static void fillRectWithColourGradient (const Rectangle& rect, const ColourGradient& gradient, const AffineTransform& transform); + + static void fillRectWithTiledTexture (int textureWidth, int textureHeight, + const Rectangle& targetArea, + const AffineTransform& transform, + float alpha); }; //============================================================================== @@ -88,6 +96,9 @@ class JUCE_API TriangulatedPath public: TriangulatedPath (const Path& path, const AffineTransform& transform); + /** Destructor. */ + ~TriangulatedPath(); + /** Renders the path, using a jittered oversampling method. The oversampling level is the square root of the number of times it should be oversampled, so 3 or 4 might be reasonable. @@ -102,7 +113,7 @@ private: friend class TrapezoidedPath; void startNewBlock(); - void addTriangle (GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2, GLfloat x3, GLfloat y3); + void addTriangle (GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2, GLfloat x3, GLfloat y3); void addTrapezoid (GLfloat y1, GLfloat y2, GLfloat x1, GLfloat x2, GLfloat x3, GLfloat x4); struct TriangleBlock; diff --git a/modules/juce_opengl/opengl/juce_OpenGLRenderingTarget.h b/modules/juce_opengl/opengl/juce_OpenGLRenderingTarget.h index 8f57ce43d5..24fd7f5076 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLRenderingTarget.h +++ b/modules/juce_opengl/opengl/juce_OpenGLRenderingTarget.h @@ -51,11 +51,6 @@ public: @see OpenGLHelpers::prepareFor2D */ void prepareFor2D(); - - /** Fills a path with a custom FillType. */ - void fillPath (const Rectangle& clipArea, - const Path& path, const AffineTransform& pathTransform, - const FillType& fill); }; diff --git a/modules/juce_opengl/opengl/juce_OpenGLTexture.cpp b/modules/juce_opengl/opengl/juce_OpenGLTexture.cpp index f9e2516194..7ad981ae42 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLTexture.cpp +++ b/modules/juce_opengl/opengl/juce_OpenGLTexture.cpp @@ -49,6 +49,10 @@ bool OpenGLTexture::isValidSize (int width, int height) void OpenGLTexture::create (const int w, const int h) { + // Texture objects can only be created when the current thread has an active OpenGL + // context. You'll need to make an OpenGLComponent active before calling this. + jassert (OpenGLHelpers::isContextActive()); + jassert (isValidSize (w, h)); // Perhaps these dimensions must be a power-of-two? release();