From 5e795134fcbe84bdb5c689616f1f2349b183467c Mon Sep 17 00:00:00 2001 From: jules Date: Wed, 21 Dec 2011 11:15:22 +0000 Subject: [PATCH] Added a read/write lock to the glyph cache. OpenGL shader fix. --- .../native/juce_RenderingHelpers.h | 76 ++++++++++++------- .../opengl/juce_OpenGLGraphicsContext.cpp | 37 ++++----- 2 files changed, 65 insertions(+), 48 deletions(-) diff --git a/modules/juce_graphics/native/juce_RenderingHelpers.h b/modules/juce_graphics/native/juce_RenderingHelpers.h index 0e6777cf1a..a6d391d006 100644 --- a/modules/juce_graphics/native/juce_RenderingHelpers.h +++ b/modules/juce_graphics/native/juce_RenderingHelpers.h @@ -140,7 +140,6 @@ class GlyphCache : private DeletedAtShutdown { public: GlyphCache() - : accessCounter (0), hits (0), misses (0) { addNewGlyphSlots (120); } @@ -163,51 +162,55 @@ public: //============================================================================== void drawGlyph (RenderTargetType& target, const Font& font, const int glyphNumber, float x, float y) { - const ScopedLock sl (lock); - ++accessCounter; - int oldestCounter = std::numeric_limits::max(); - CachedGlyphType* oldest = nullptr; + CachedGlyphType* glyph = nullptr; + + const ScopedReadLock srl (lock); for (int i = glyphs.size(); --i >= 0;) { - CachedGlyphType* const glyph = glyphs.getUnchecked (i); + CachedGlyphType* const g = glyphs.getUnchecked (i); - if (glyph->glyph == glyphNumber && glyph->font == font) + if (g->glyph == glyphNumber && g->font == font) { + glyph = g; ++hits; - glyph->lastAccessCount = accessCounter; - glyph->draw (target, x, y); - return; - } - - if (glyph->lastAccessCount <= oldestCounter) - { - oldestCounter = glyph->lastAccessCount; - oldest = glyph; + break; } } - if (hits + ++misses > glyphs.size() * 16) + if (glyph == nullptr) { - if (misses * 2 > hits) - addNewGlyphSlots (32); + ++misses; + const ScopedWriteLock swl (lock); + + if (hits.value + misses.value > glyphs.size() * 16) + { + if (misses.value * 2 > hits.value) + addNewGlyphSlots (32); + + hits.set (0); + misses.set (0); + glyph = glyphs.getLast(); + } + else + { + glyph = findLeastRecentlyUsedGlyph(); + } - hits = misses = 0; - oldest = glyphs.getLast(); + jassert (glyph != nullptr); + glyph->generate (font, glyphNumber); } - jassert (oldest != nullptr); - oldest->lastAccessCount = accessCounter; - oldest->generate (font, glyphNumber); - oldest->draw (target, x, y); + glyph->lastAccessCount = accessCounter.value; + glyph->draw (target, x, y); } private: friend class OwnedArray ; OwnedArray glyphs; - int accessCounter, hits, misses; - CriticalSection lock; + Atomic accessCounter, hits, misses; + ReadWriteLock lock; void addNewGlyphSlots (int num) { @@ -215,6 +218,25 @@ private: glyphs.add (new CachedGlyphType()); } + CachedGlyphType* findLeastRecentlyUsedGlyph() const noexcept + { + CachedGlyphType* oldest = glyphs.getLast(); + int oldestCounter = oldest->lastAccessCount; + + for (int i = glyphs.size() - 1; --i >= 0;) + { + CachedGlyphType* const glyph = glyphs.getUnchecked(i); + + if (glyph->lastAccessCount <= oldestCounter) + { + oldestCounter = glyph->lastAccessCount; + oldest = glyph; + } + } + + return oldest; + } + static GlyphCache*& getSingletonPointer() noexcept { static GlyphCache* g = nullptr; diff --git a/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp b/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp index fb00852754..91361cc56e 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp +++ b/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp @@ -206,12 +206,7 @@ private: class ShaderPrograms : public ReferenceCountedObject { public: - ShaderPrograms() - : areShadersSupported (OpenGLShaderProgram::getLanguageVersion() >= 1.199) - { - } - - const bool areShadersSupported; + ShaderPrograms() {} typedef ReferenceCountedObjectPtr Ptr; @@ -341,7 +336,7 @@ public: #define JUCE_MATRIX_TIMES_FRAGCOORD "(vec2 (matrix[0], matrix[3]) * gl_FragCoord.x" \ " + vec2 (matrix[1], matrix[4]) * gl_FragCoord.y " \ " + vec2 (matrix[2], matrix[5]))" - #define JUCE_GET_TEXTURE_COLOUR "(gl_Color.w * texture2D (gradientTexture, vec2 (gradientPos, 0.5)))" + #define JUCE_GET_TEXTURE_COLOUR "(gl_Color.a * texture2D (gradientTexture, vec2 (gradientPos, 0.5)))" struct RadialGradientProgram : public ShaderBase { @@ -391,6 +386,8 @@ public: #define JUCE_DECLARE_LINEAR_UNIFORMS "uniform sampler2D gradientTexture;" \ "uniform vec4 gradientInfo;" + #define JUCE_CALC_LINEAR_GRAD_POS1 "float gradientPos = (gl_FragCoord.y - (gradientInfo.y + (gradientInfo.z * (gl_FragCoord.x - gradientInfo.x)))) / gradientInfo.w;" + #define JUCE_CALC_LINEAR_GRAD_POS2 "float gradientPos = (gl_FragCoord.x - (gradientInfo.x + (gradientInfo.z * (gl_FragCoord.y - gradientInfo.y)))) / gradientInfo.w;" struct LinearGradient1Program : public ShaderBase { @@ -399,7 +396,7 @@ public: JUCE_DECLARE_LINEAR_UNIFORMS // gradientInfo: x = x1, y = y1, z = (y2 - y1) / (x2 - x1), w = length "void main()" "{" - "float gradientPos = (gl_FragCoord.y - (gradientInfo.y + (gradientInfo.z * (gl_FragCoord.x - gradientInfo.x)))) / gradientInfo.w;" + JUCE_CALC_LINEAR_GRAD_POS1 "gl_FragColor = " JUCE_GET_TEXTURE_COLOUR ";" "}"), gradientParams (program) @@ -416,7 +413,7 @@ public: JUCE_DECLARE_MASK_UNIFORMS "void main()" "{" - "float gradientPos = (gl_FragCoord.y - (gradientInfo.y + (gradientInfo.z * (gl_FragCoord.x - gradientInfo.x)))) / gradientInfo.w;" + JUCE_CALC_LINEAR_GRAD_POS1 "gl_FragColor = " JUCE_GET_TEXTURE_COLOUR " * " JUCE_GET_MASK_ALPHA ";" "}"), gradientParams (program), @@ -434,7 +431,7 @@ public: JUCE_DECLARE_LINEAR_UNIFORMS // gradientInfo: x = x1, y = y1, z = (x2 - x1) / (y2 - y1), y = y1, w = length "void main()" "{" - "float gradientPos = (gl_FragCoord.x - (gradientInfo.x + (gradientInfo.z * (gl_FragCoord.y - gradientInfo.y)))) / gradientInfo.w;" + JUCE_CALC_LINEAR_GRAD_POS2 "gl_FragColor = " JUCE_GET_TEXTURE_COLOUR ";" "}"), gradientParams (program) @@ -451,7 +448,7 @@ public: JUCE_DECLARE_MASK_UNIFORMS "void main()" "{" - "float gradientPos = (gl_FragCoord.x - (gradientInfo.x + (gradientInfo.z * (gl_FragCoord.y - gradientInfo.y)))) / gradientInfo.w;" + JUCE_CALC_LINEAR_GRAD_POS2 "gl_FragColor = " JUCE_GET_TEXTURE_COLOUR " * " JUCE_GET_MASK_ALPHA ";" "}"), gradientParams (program), @@ -511,7 +508,7 @@ public: "void main()" "{" "vec2 texturePos = clamp (" JUCE_MATRIX_TIMES_FRAGCOORD ", vec2 (0, 0), imageRepeatSize);" - "gl_FragColor = gl_Color.w * " JUCE_GET_IMAGE_PIXEL ";" + "gl_FragColor = gl_Color.a * " JUCE_GET_IMAGE_PIXEL ";" "}"), imageParams (program) {} @@ -528,7 +525,7 @@ public: "void main()" "{" "vec2 texturePos = clamp (" JUCE_MATRIX_TIMES_FRAGCOORD ", vec2 (0, 0), imageRepeatSize);" - "gl_FragColor = gl_Color.w * " JUCE_GET_IMAGE_PIXEL " * " JUCE_GET_MASK_ALPHA ";" + "gl_FragColor = gl_Color.a * " JUCE_GET_IMAGE_PIXEL " * " JUCE_GET_MASK_ALPHA ";" "}"), imageParams (program), maskParams (program) @@ -546,7 +543,7 @@ public: "void main()" "{" "vec2 texturePos = mod (" JUCE_MATRIX_TIMES_FRAGCOORD ", imageRepeatSize);" - "gl_FragColor = gl_Color.w * " JUCE_GET_IMAGE_PIXEL ";" + "gl_FragColor = gl_Color.a * " JUCE_GET_IMAGE_PIXEL ";" "}"), imageParams (program) {} @@ -563,7 +560,7 @@ public: "void main()" "{" "vec2 texturePos = mod (" JUCE_MATRIX_TIMES_FRAGCOORD ", imageRepeatSize);" - "gl_FragColor = gl_Color.w * " JUCE_GET_IMAGE_PIXEL " * " JUCE_GET_MASK_ALPHA ";" + "gl_FragColor = gl_Color.a * " JUCE_GET_IMAGE_PIXEL " * " JUCE_GET_MASK_ALPHA ";" "}"), imageParams (program), maskParams (program) @@ -581,7 +578,7 @@ public: "void main()" "{" "vec2 texturePos = mod (" JUCE_MATRIX_TIMES_FRAGCOORD ", imageRepeatSize);" - "gl_FragColor = " JUCE_GET_IMAGE_PIXEL ";" + "gl_FragColor = gl_Color.a * " JUCE_GET_IMAGE_PIXEL ";" "}"), imageParams (program) {} @@ -1204,7 +1201,7 @@ struct StateHelpers struct CurrentShader { CurrentShader() noexcept - : canUseShaders (false), activeShader (nullptr) + : canUseShaders (OpenGLShaderProgram::getLanguageVersion() >= 1.199), activeShader (nullptr) { OpenGLContext* context = OpenGLContext::getCurrentContext(); jassert (context != nullptr); // You can only use this class when you have an active GL context! @@ -1212,13 +1209,11 @@ struct StateHelpers const Identifier programValueID ("GraphicsContextPrograms"); programs = dynamic_cast (context->properties [programValueID].getObject()); - if (programs == nullptr) + if (programs == nullptr && canUseShaders) { programs = new ShaderPrograms(); context->properties.set (programValueID, var (programs)); } - - canUseShaders = programs->areShadersSupported; } void setShader (const Rectangle& bounds, ShaderQuadQueue& quadQueue, ShaderPrograms::ShaderBase& shader) @@ -2417,7 +2412,7 @@ public: state.activeTextures.bindTexture (other.mask.getTextureID()); state.currentShader.setShader (maskArea, state.shaderQuadQueue, state.currentShader.programs->copyTexture); - state.currentShader.programs->maskTexture.imageParams.imageTexture.set (0); + state.currentShader.programs->copyTexture.imageParams.imageTexture.set (0); state.currentShader.programs->copyTexture.imageParams .setMatrix (AffineTransform::translation ((float) other.maskArea.getX(), (float) other.maskArea.getY()), other.maskArea.getWidth(), other.maskArea.getHeight(), 1.0f, 1.0f,