diff --git a/modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm b/modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm index 9e7a824c51..46512b893b 100644 --- a/modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm +++ b/modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm @@ -51,8 +51,6 @@ END_JUCE_NAMESPACE - (BOOL) resignFirstResponder; - (BOOL) canBecomeFirstResponder; -- (void) asyncRepaint: (id) rect; - - (BOOL) textView: (UITextView*) textView shouldChangeTextInRange: (NSRange) range replacementText: (NSString*) text; @end @@ -343,12 +341,6 @@ juce::Point juce_lastMousePos; return owner != nullptr && owner->canBecomeKeyWindow(); } -- (void) asyncRepaint: (id) rect -{ - CGRect* r = (CGRect*) [((NSData*) rect) bytes]; - [self setNeedsDisplayInRect: *r]; -} - - (BOOL) textView: (UITextView*) textView shouldChangeTextInRange: (NSRange) range replacementText: (NSString*) text { return owner->textViewReplaceCharacters (Range (range.location, range.location + range.length), diff --git a/modules/juce_opengl/native/juce_mac_OpenGLComponent.mm b/modules/juce_opengl/native/juce_mac_OpenGLComponent.mm index dd0eef191e..305ca63836 100644 --- a/modules/juce_opengl/native/juce_mac_OpenGLComponent.mm +++ b/modules/juce_opengl/native/juce_mac_OpenGLComponent.mm @@ -69,7 +69,7 @@ END_JUCE_NAMESPACE { const ScopedLock sl (*contextLock); - if ([self openGLContext] == 0) + if ([self openGLContext] == nil) return false; [[self openGLContext] makeCurrentContext]; @@ -108,15 +108,8 @@ END_JUCE_NAMESPACE needsUpdate = true; } -- (void) rightMouseDown: (NSEvent*) ev -{ - [[self superview] rightMouseDown: ev]; -} - -- (void) rightMouseUp: (NSEvent*) ev -{ - [[self superview] rightMouseUp: ev]; -} +- (void) rightMouseDown: (NSEvent*) ev { [[self superview] rightMouseDown: ev]; } +- (void) rightMouseUp: (NSEvent*) ev { [[self superview] rightMouseUp: ev]; } @end BEGIN_JUCE_NAMESPACE @@ -275,5 +268,5 @@ void OpenGLComponent::updateEmbeddedPosition (const Rectangle&) //============================================================================== bool OpenGLHelpers::isContextActive() { - return [NSOpenGLContext currentContext] != nil; + return CGLGetCurrentContext() != 0; } diff --git a/modules/juce_opengl/opengl/juce_OpenGLFrameBuffer.cpp b/modules/juce_opengl/opengl/juce_OpenGLFrameBuffer.cpp index 6171702307..c2066e3827 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLFrameBuffer.cpp +++ b/modules/juce_opengl/opengl/juce_OpenGLFrameBuffer.cpp @@ -126,7 +126,7 @@ public: depthOrStencilBuffer (0), hasDepthBuffer (false), hasStencilBuffer (false), - ok (false) + ok (true) { // 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. @@ -180,8 +180,6 @@ public: hasStencilBuffer = wantsStencilBuffer; } - ok = checkStatus(); - glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0); } @@ -197,25 +195,14 @@ public: glDeleteFramebuffersEXT (1, &frameBufferHandle); } - bool bind() { return bind (frameBufferHandle); } - bool unbind() { return bind (0); } + void bind() { glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, frameBufferHandle); } + void unbind() { glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0); } const int width, height; GLuint textureID, frameBufferHandle, depthOrStencilBuffer; bool hasDepthBuffer, hasStencilBuffer, ok; private: - bool bind (GLuint buffer) - { - if (ok) - { - glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, buffer); - ok = checkStatus(); - } - - return ok; - } - static bool checkStatus() noexcept { const GLenum status = glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT); @@ -347,7 +334,11 @@ bool OpenGLFrameBuffer::makeCurrentRenderingTarget() // reloadSavedCopy() to put it back into GPU memory before using it.. jassert (savedState == nullptr); - return pimpl != nullptr && pimpl->bind(); + if (pimpl == nullptr) + return false; + + pimpl->bind(); + return true; } void OpenGLFrameBuffer::setCurrentFrameBufferTarget (GLuint frameBufferID) @@ -355,6 +346,13 @@ void OpenGLFrameBuffer::setCurrentFrameBufferTarget (GLuint frameBufferID) glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, frameBufferID); } +GLuint OpenGLFrameBuffer::getCurrentFrameBufferTarget() +{ + GLint fb; + glGetIntegerv (GL_FRAMEBUFFER_BINDING_EXT, &fb); + return (GLuint) fb; +} + void OpenGLFrameBuffer::releaseAsRenderingTarget() { setCurrentFrameBufferTarget (0); @@ -397,16 +395,16 @@ bool OpenGLFrameBuffer::writePixels (const PixelARGB* data, const Rectangle OpenGLHelpers::prepareFor2D (pimpl->width, pimpl->height); glDisable (GL_DEPTH_TEST); glDisable (GL_BLEND); - glColor4f (1.0f, 1.0f, 1.0f, 1.0f); #if JUCE_OPENGL_ES { // GLES has no glDrawPixels function, so we have to create a texture and draw it.. glEnable (GL_TEXTURE_2D); + glColor4f (1.0f, 1.0f, 1.0f, 1.0f); - OpenGLTexture temp; - temp.load (data, area.getWidth(), area.getHeight()); - temp.bind(); + OpenGLTexture tex; + tex.load (data, area.getWidth(), area.getHeight()); + tex.bind(); const GLint cropRect[4] = { 0, 0, area.getWidth(), area.getHeight() }; glTexParameteriv (GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, cropRect); @@ -415,10 +413,12 @@ bool OpenGLFrameBuffer::writePixels (const PixelARGB* data, const Rectangle glBindTexture (GL_TEXTURE_2D, 0); } #else - glRasterPos2i (area.getX(), area.getY()); - glBindTexture (GL_TEXTURE_2D, 0); - glPixelStorei (GL_UNPACK_ALIGNMENT, 4); - glDrawPixels (area.getWidth(), area.getHeight(), GL_BGRA_EXT, GL_UNSIGNED_BYTE, data); + { + OpenGLTexture tex; + tex.load (data, area.getWidth(), area.getHeight()); + + OpenGLHelpers::fillRectWithTexture (area.withSize (tex.getWidth(), tex.getHeight()), tex.getTextureID(), 1.0f); + } #endif glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0); diff --git a/modules/juce_opengl/opengl/juce_OpenGLFrameBuffer.h b/modules/juce_opengl/opengl/juce_OpenGLFrameBuffer.h index ca96357fa8..0fb6030c92 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLFrameBuffer.h +++ b/modules/juce_opengl/opengl/juce_OpenGLFrameBuffer.h @@ -103,6 +103,9 @@ public: */ static void setCurrentFrameBufferTarget (GLuint frameBufferID); + /** Returns the ID of the currently-bound framebuffer. */ + static GLuint getCurrentFrameBufferTarget(); + /** Clears the framebuffer with the specified colour. */ void clear (const Colour& colour); diff --git a/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp b/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp index 19cc784ccd..2ab26e5325 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp +++ b/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp @@ -103,67 +103,14 @@ namespace glColor4f (alpha, alpha, alpha, alpha); } - void drawTriangleStrip (const GLfloat* const vertices, const GLfloat* const textureCoords, const int numVertices) noexcept - { - glEnable (GL_TEXTURE_2D); - glDisableClientState (GL_COLOR_ARRAY); - glDisableClientState (GL_NORMAL_ARRAY); - glEnableClientState (GL_VERTEX_ARRAY); - glVertexPointer (2, GL_FLOAT, 0, vertices); - glEnableClientState (GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer (2, GL_FLOAT, 0, textureCoords); - glDrawArrays (GL_TRIANGLE_STRIP, 0, numVertices); - } - - void drawTriangleStrip (const GLfloat* const vertices, const GLfloat* const textureCoords, - const int numVertices, const GLuint textureID) noexcept - { - jassert (textureID != 0); - glBindTexture (GL_TEXTURE_2D, textureID); - drawTriangleStrip (vertices, textureCoords, numVertices); - glBindTexture (GL_TEXTURE_2D, 0); - } - - void drawTextureQuad (GLuint textureID, int x, int y, int w, int h) - { - const GLfloat l = (GLfloat) x; - const GLfloat t = (GLfloat) y; - const GLfloat r = (GLfloat) (x + w); - const GLfloat b = (GLfloat) (y + h); - - const GLfloat vertices[] = { l, t, r, t, l, b, r, b }; - const GLfloat textureCoords[] = { 0, 1.0f, 1.0f, 1.0f, 0, 0, 1.0f, 0 }; - - drawTriangleStrip (vertices, textureCoords, 4, textureID); - } - - void fillRectWithTexture (const Rectangle& rect, GLuint textureID, const float alpha) - { - glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glColor4f (1.0f, 1.0f, 1.0f, alpha); - - drawTextureQuad (textureID, rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight()); - } - - void clipFrameBuffers (const OpenGLTarget& dest, OpenGLFrameBuffer& source, - const Point sourceOrigin, const bool shouldMaskRGB) + void clipFrameBuffers (const OpenGLTarget& dest, OpenGLFrameBuffer& source, const Point sourceOrigin) { dest.makeActiveFor2D(); glEnable (GL_BLEND); glBlendFunc (GL_ZERO, GL_SRC_ALPHA); setColour (1.0f); - - if (shouldMaskRGB) - glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); - - drawTextureQuad (source.getTextureID(), sourceOrigin.getX(), sourceOrigin.getY(), - source.getWidth(), source.getHeight()); - - if (shouldMaskRGB) - glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + OpenGLHelpers::drawTextureQuad (source.getTextureID(), sourceOrigin.getX(), sourceOrigin.getY(), + source.getWidth(), source.getHeight()); } void renderPath (const Path& path, const AffineTransform& transform, int oversamplingLevel) @@ -177,10 +124,10 @@ namespace TriangulatedPath (path, transform).draw (oversamplingLevel); } - void setNormalBlendingMode() noexcept + void setPremultipliedBlendingMode() noexcept { glEnable (GL_BLEND); - glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA); } void setBlendMode (const bool replaceExistingContents) noexcept @@ -188,7 +135,7 @@ namespace if (replaceExistingContents) glDisable (GL_BLEND); else - setNormalBlendingMode(); + setPremultipliedBlendingMode(); } void fillRectWithTiledTexture (const OpenGLTarget& target, int textureWidth, int textureHeight, @@ -295,7 +242,8 @@ namespace textureTransform.transformPoints (textureCoords[0], textureCoords[1], textureCoords[2], textureCoords[3]); textureTransform.transformPoints (textureCoords[4], textureCoords[5], textureCoords[6], textureCoords[7]); - drawTriangleStrip (vertices, textureCoords, 4); + setColour (1.0f); + OpenGLHelpers::drawTriangleStrip (vertices, textureCoords, 4); } void fillWithRadialGradient (const OpenGLTarget& target, const Rectangle& rect, @@ -442,7 +390,6 @@ public: virtual Ptr clipToEdgeTable (const EdgeTable&) = 0; virtual Ptr clipToImageAlpha (const OpenGLTextureFromImage&, const AffineTransform&) = 0; virtual Ptr clipToMask (ClipRegion_Mask*) = 0; - virtual void translate (const Point& delta) = 0; virtual const Rectangle& getClipBounds() const = 0; virtual void fillAll (const OpenGLTarget&, const FillType& fill, bool replaceContents) = 0; virtual void fillRect (const OpenGLTarget&, const Rectangle& area, const FillType& fill, bool replaceContents) = 0; @@ -489,7 +436,7 @@ public: maskOrigin (clip.getPosition()) { initialiseClear(); - OpenGLHelpers::fillEdgeTable (e, 0, 0, 0); + OpenGLHelpers::fillEdgeTable (e); } ClipRegion_Mask (const Rectangle& bounds, const Path& p, const AffineTransform& transform, int oversamplingLevel) @@ -511,12 +458,6 @@ public: const Rectangle& getClipBounds() const { return clip; } Ptr applyClipTo (const Ptr& target) { return target->clipToMask (this); } - void translate (const Point& delta) - { - maskOrigin += delta; - clip += delta; - } - Ptr clipToRectangle (const Rectangle& r) { clip = clip.getIntersection (r); @@ -579,7 +520,7 @@ public: if (clip.isEmpty()) return nullptr; - clipFrameBuffers (OpenGLTarget (mask, maskOrigin), m->mask, m->maskOrigin, true); + clipFrameBuffers (OpenGLTarget (mask, maskOrigin), m->mask, m->maskOrigin); return this; } @@ -645,7 +586,7 @@ public: OpenGLTarget bufferTarget (buffer, bufferArea.getPosition()); bufferTarget.makeActiveFor2D(); glDisable (GL_BLEND); - fillRectWithTexture (targetArea, source.textureID, alpha); + OpenGLHelpers::fillRectWithTexture (targetArea, source.textureID, alpha); clipAndDraw (target, bufferTarget); } @@ -703,7 +644,7 @@ private: const GLfloat b = (GLfloat) (y + h); const GLfloat vertices[] = { l, t, r, t, l, b, r, b }; - glColor4f (1.0f, 1.0f, 1.0f, alpha / 255.0f); + setColour (alpha / 255.0f); glVertexPointer (2, GL_FLOAT, 0, vertices); glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); } @@ -711,7 +652,7 @@ private: void clipAndDraw (const OpenGLTarget& target, const OpenGLTarget& buffer) { - clipFrameBuffers (buffer, mask, maskOrigin, false); + clipFrameBuffers (buffer, mask, maskOrigin); target.makeActiveFor2D(); glEnable (GL_BLEND); @@ -723,8 +664,8 @@ private: void drawFrameBuffer (const OpenGLFrameBuffer& buffer, const Point& topLeft) { - drawTextureQuad (buffer.getTextureID(), topLeft.getX(), topLeft.getY(), - buffer.getWidth(), buffer.getHeight()); + OpenGLHelpers::drawTextureQuad (buffer.getTextureID(), topLeft.getX(), topLeft.getY(), + buffer.getWidth(), buffer.getHeight()); } void fillMaskWithSourceImage (const OpenGLTextureFromImage& image, const AffineTransform& transform) const @@ -749,7 +690,12 @@ private: inv.transformPoints (textureCoords[0], textureCoords[1], textureCoords[2], textureCoords[3]); inv.transformPoints (textureCoords[4], textureCoords[5], textureCoords[6], textureCoords[7]); - drawTriangleStrip (vertices, textureCoords, 4); + textureCoords[1] = 1.0f - textureCoords[1]; + textureCoords[3] = 1.0f - textureCoords[3]; + textureCoords[5] = 1.0f - textureCoords[5]; + textureCoords[7] = 1.0f - textureCoords[7]; + + OpenGLHelpers::drawTriangleStrip (vertices, textureCoords, 4); } ClipRegion_Mask& operator= (const ClipRegion_Mask&); @@ -767,7 +713,6 @@ public: Ptr clone() const { return new ClipRegion_Rectangle (clip); } const Rectangle& getClipBounds() const { return clip; } Ptr applyClipTo (const Ptr& target) { return target->clipToRectangle (clip); } - void translate (const Point& delta) { clip += delta; } Ptr clipToRectangle (const Rectangle& r) { @@ -814,8 +759,8 @@ public: { target.makeActiveFor2D(); target.scissor (clip); - setNormalBlendingMode(); - fillRectWithTexture (targetArea, source.textureID, alpha); + setPremultipliedBlendingMode(); + OpenGLHelpers::fillRectWithTexture (targetArea, source.textureID, alpha); glDisable (GL_SCISSOR_TEST); } @@ -977,12 +922,11 @@ public: OpenGLFrameBufferImage* fbi = new OpenGLFrameBufferImage (clipBounds.getWidth(), clipBounds.getHeight()); fbi->frameBuffer.clear (Colours::transparentBlack); + s->transparencyLayer = Image (fbi); - s->target = OpenGLTarget (fbi->frameBuffer, Point()); + s->target = OpenGLTarget (fbi->frameBuffer, clipBounds.getPosition()); s->transparencyLayerAlpha = opacity; - s->transform.moveOriginInDeviceSpace (-clipBounds.getX(), -clipBounds.getY()); s->cloneClipIfMultiplyReferenced(); - s->clip->translate (-clipBounds.getPosition()); } return s; @@ -1048,17 +992,34 @@ public: { if (clip != nullptr) { - const float fontHeight = font.getHeight(); + if (transform.isOnlyTranslated && t.isOnlyTranslation()) + { + RenderingHelpers::GlyphCache ::getInstance() + .drawGlyph (*this, font, glyphNumber, + transform.xOffset + t.getTranslationX(), + transform.yOffset + t.getTranslationY()); + } + else + { + const float fontHeight = font.getHeight(); - const ScopedPointer et (font.getTypeface()->getEdgeTableForGlyph - (glyphNumber, transform.getTransformWith (AffineTransform::scale (fontHeight * font.getHorizontalScale(), fontHeight) - .followedBy (t)))); + const ScopedPointer et (font.getTypeface()->getEdgeTableForGlyph + (glyphNumber, transform.getTransformWith (AffineTransform::scale (fontHeight * font.getHorizontalScale(), fontHeight) + .followedBy (t)))); - if (et != nullptr) - fillShape (new ClipRegion_Mask (*et), false); + if (et != nullptr) + fillShape (new ClipRegion_Mask (*et), false); + } } } + void fillEdgeTable (const EdgeTable& et, float x, int y) + { + EdgeTable et2 (et); + et2.translate (x, y); + fillShape (new ClipRegion_Mask (et2), false); + } + void drawLine (const Line & line) { Path p; @@ -1147,10 +1108,48 @@ private: return fillType.transformed (transform.getTransform()); } + class CachedGlyphEdgeTable + { + public: + CachedGlyphEdgeTable() : glyph (0), lastAccessCount (0) {} + + void draw (OpenGLRenderer::SavedState& state, float x, const float y) const + { + if (snapToIntegerCoordinate) + x = std::floor (x + 0.5f); + + if (edgeTable != nullptr) + state.fillEdgeTable (*edgeTable, x, roundToInt (y)); + } + + void generate (const Font& newFont, const int glyphNumber) + { + font = newFont; + snapToIntegerCoordinate = newFont.getTypeface()->isHinted(); + glyph = glyphNumber; + + const float fontHeight = font.getHeight(); + edgeTable = font.getTypeface()->getEdgeTableForGlyph (glyphNumber, + AffineTransform::scale (fontHeight * font.getHorizontalScale(), fontHeight) + #if JUCE_MAC || JUCE_IOS + .translated (0.0f, -0.5f) + #endif + ); + } + + Font font; + int glyph, lastAccessCount; + bool snapToIntegerCoordinate; + + private: + ScopedPointer edgeTable; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CachedGlyphEdgeTable); + }; + SavedState& operator= (const SavedState&); }; - //============================================================================== OpenGLRenderer::OpenGLRenderer (OpenGLComponent& target) : stack (new SavedState (OpenGLTarget (target.getFrameBufferID(), target.getWidth(), target.getHeight()))) @@ -1165,6 +1164,13 @@ OpenGLRenderer::OpenGLRenderer (OpenGLFrameBuffer& target) jassert (OpenGLHelpers::isContextActive()); } +OpenGLRenderer::OpenGLRenderer (unsigned int frameBufferID, int width, int height) + : stack (new SavedState (OpenGLTarget (frameBufferID, width, height))) +{ + // This object can only be created and used when the current thread has an active OpenGL context. + jassert (OpenGLHelpers::isContextActive()); +} + OpenGLRenderer::~OpenGLRenderer() {} bool OpenGLRenderer::isVectorDevice() const { return false; } diff --git a/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.h b/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.h index d7d796e620..e4b8bbfb33 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.h +++ b/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.h @@ -35,6 +35,7 @@ class JUCE_API OpenGLRenderer : public LowLevelGraphicsContext public: explicit OpenGLRenderer (OpenGLComponent& target); explicit OpenGLRenderer (OpenGLFrameBuffer& target); + OpenGLRenderer (unsigned int frameBufferID, int width, int height); ~OpenGLRenderer(); bool isVectorDevice() const; diff --git a/modules/juce_opengl/opengl/juce_OpenGLHelpers.cpp b/modules/juce_opengl/opengl/juce_OpenGLHelpers.cpp index 923595ca47..6e6757960b 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLHelpers.cpp +++ b/modules/juce_opengl/opengl/juce_OpenGLHelpers.cpp @@ -213,6 +213,51 @@ void OpenGLHelpers::drawQuad3D (float x1, float y1, float z1, glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); } +void OpenGLHelpers::drawTriangleStrip (const GLfloat* const vertices, const GLfloat* const textureCoords, const int numVertices) noexcept +{ + glEnable (GL_TEXTURE_2D); + glDisableClientState (GL_COLOR_ARRAY); + glDisableClientState (GL_NORMAL_ARRAY); + glEnableClientState (GL_VERTEX_ARRAY); + glVertexPointer (2, GL_FLOAT, 0, vertices); + glEnableClientState (GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer (2, GL_FLOAT, 0, textureCoords); + glDrawArrays (GL_TRIANGLE_STRIP, 0, numVertices); +} + +void OpenGLHelpers::drawTriangleStrip (const GLfloat* const vertices, const GLfloat* const textureCoords, + const int numVertices, const GLuint textureID) noexcept +{ + jassert (textureID != 0); + glBindTexture (GL_TEXTURE_2D, textureID); + drawTriangleStrip (vertices, textureCoords, numVertices); + glBindTexture (GL_TEXTURE_2D, 0); +} + +void OpenGLHelpers::drawTextureQuad (GLuint textureID, int x, int y, int w, int h) +{ + const GLfloat l = (GLfloat) x; + const GLfloat t = (GLfloat) y; + const GLfloat r = (GLfloat) (x + w); + const GLfloat b = (GLfloat) (y + h); + + const GLfloat vertices[] = { l, t, r, t, l, b, r, b }; + const GLfloat textureCoords[] = { 0, 1.0f, 1.0f, 1.0f, 0, 0, 1.0f, 0 }; + + drawTriangleStrip (vertices, textureCoords, 4, textureID); +} + +void OpenGLHelpers::fillRectWithTexture (const Rectangle& rect, GLuint textureID, const float alpha) +{ + glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glColor4f (alpha, alpha, alpha, alpha); + + drawTextureQuad (textureID, rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight()); +} + //============================================================================== void OpenGLHelpers::fillRectWithColour (const Rectangle& rect, const Colour& colour) { @@ -238,8 +283,8 @@ void OpenGLHelpers::fillRect (const Rectangle& rect) //============================================================================== struct OpenGLEdgeTableRenderer { - OpenGLEdgeTableRenderer (float r_, float g_, float b_) noexcept - : r (r_), g (g_), b (b_), lastAlpha (-1) + OpenGLEdgeTableRenderer() noexcept + : lastAlpha (-1) { } @@ -280,7 +325,6 @@ struct OpenGLEdgeTableRenderer private: GLfloat vertices[8]; - const float r, g, b; int lastAlpha; void drawHorizontal (int x, const int w, const int alphaLevel) noexcept @@ -291,7 +335,8 @@ private: if (lastAlpha != alphaLevel) { lastAlpha = alphaLevel; - glColor4f (r, g, b, alphaLevel / 255.0f); + const float a = alphaLevel / 255.0f; + glColor4f (a, a, a, a); } glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); @@ -300,10 +345,9 @@ private: JUCE_DECLARE_NON_COPYABLE (OpenGLEdgeTableRenderer); }; -void OpenGLHelpers::fillEdgeTable (const EdgeTable& edgeTable, - float red, float green, float blue) +void OpenGLHelpers::fillEdgeTable (const EdgeTable& edgeTable) { - OpenGLEdgeTableRenderer etr (red, green, blue); + OpenGLEdgeTableRenderer etr; etr.draw (edgeTable); } @@ -597,7 +641,8 @@ TriangulatedPath::~TriangulatedPath() {} void TriangulatedPath::draw (const int oversamplingLevel) const { - glColor4f (1.0f, 1.0f, 1.0f, 1.0f / (oversamplingLevel * oversamplingLevel)); + const float a = 1.0f / (oversamplingLevel * oversamplingLevel); + glColor4f (a, a, a, a); glPushMatrix(); glTranslatef (-0.5f, -0.5f, 0.0f); diff --git a/modules/juce_opengl/opengl/juce_OpenGLHelpers.h b/modules/juce_opengl/opengl/juce_OpenGLHelpers.h index e1e6aef962..1287b70eb4 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLHelpers.h +++ b/modules/juce_opengl/opengl/juce_OpenGLHelpers.h @@ -73,14 +73,23 @@ public: float x4, float y4, float z4, const Colour& colour); + static void drawTriangleStrip (const GLfloat* const vertices, const GLfloat* const textureCoords, const int numVertices) noexcept; + + static void drawTriangleStrip (const GLfloat* const vertices, const GLfloat* const textureCoords, + const int numVertices, const GLuint textureID) noexcept; + + static void drawTextureQuad (GLuint textureID, int x, int y, int w, int h); + + static void fillRectWithTexture (const Rectangle& rect, GLuint textureID, const float alpha); + static void fillRect (const Rectangle& rect); /** Fills a rectangle with the specified colour. */ static void fillRectWithColour (const Rectangle& rect, const Colour& colour); + /** Renders an edge-table into the current context. */ - static void fillEdgeTable (const EdgeTable& edgeTable, - float red, float green, float blue); + static void fillEdgeTable (const EdgeTable& edgeTable); /** Checks whether the current context supports the specified extension. */ static bool isExtensionSupported (const char* extensionName); diff --git a/modules/juce_opengl/opengl/juce_OpenGLTexture.cpp b/modules/juce_opengl/opengl/juce_OpenGLTexture.cpp index aeff6ba370..4891a613f6 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLTexture.cpp +++ b/modules/juce_opengl/opengl/juce_OpenGLTexture.cpp @@ -94,13 +94,14 @@ void OpenGLTexture::load (const Image& image) const int srcLineStride = (srcData.pixelStride * imageW + 3) & ~3; dataCopy.malloc (textureW * textureH); data = dataCopy; + const int yOffset = textureH - imageH; if (srcData.pixelFormat == Image::RGB) { for (int y = 0; y < imageH; ++y) { const PixelRGB* const src = (const PixelRGB*) addBytesToPointer (srcData.data, srcLineStride * y); - PixelARGB* const dst = (PixelARGB*) (dataCopy + textureW * y); + PixelARGB* const dst = (PixelARGB*) (dataCopy + textureW * (y + yOffset)); for (int x = 0; x < imageW; ++x) dst[x].set (src[x]); @@ -109,7 +110,7 @@ void OpenGLTexture::load (const Image& image) else if (srcData.pixelFormat == Image::ARGB) { for (int y = 0; y < imageH; ++y) - memcpy (dataCopy + textureW * y, addBytesToPointer (srcData.data, srcLineStride * y), srcLineStride); + memcpy (dataCopy + textureW * (y + yOffset), addBytesToPointer (srcData.data, srcLineStride * y), srcLineStride); } } @@ -128,7 +129,7 @@ void OpenGLTexture::load (const PixelARGB* pixels, const int w, const int h) dataCopy.malloc (textureW * textureH); for (int y = 0; y < h; ++y) - memcpy (dataCopy + textureW * y, pixels + w * y, w * 4); + memcpy (dataCopy + textureW * (y + textureH - h), pixels + w * y, w * 4); pixels = dataCopy; }