1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-13 00:04:19 +00:00

OpenGL: Avoid races on viewportArea and scale data members

This commit is contained in:
reuk 2022-01-20 13:16:47 +00:00
parent e751a5edd7
commit 01e71bc351
No known key found for this signature in database
GPG key ID: FCB43929F012EE5C

View file

@ -91,6 +91,44 @@ static bool contextHasTextureNpotFeature()
class OpenGLContext::CachedImage : public CachedComponentImage,
private ThreadPoolJob
{
struct AreaAndScale
{
Rectangle<int> area;
double scale;
auto tie() const { return std::tie (area, scale); }
auto operator== (const AreaAndScale& other) const { return tie() == other.tie(); }
auto operator!= (const AreaAndScale& other) const { return tie() != other.tie(); }
};
class LockedAreaAndScale
{
public:
auto get() const
{
const ScopedLock lock (mutex);
return data;
}
template <typename Fn>
void set (const AreaAndScale& d, Fn&& ifDifferent)
{
const auto old = [&]
{
const ScopedLock lock (mutex);
return std::exchange (data, d);
}();
if (old != d)
ifDifferent();
}
private:
CriticalSection mutex;
AreaAndScale data { {}, 1.0 };
};
public:
CachedImage (OpenGLContext& c, Component& comp,
const OpenGLPixelFormat& pixFormat, void* contextToShare)
@ -205,8 +243,10 @@ public:
}
//==============================================================================
bool ensureFrameBufferSize()
bool ensureFrameBufferSize (Rectangle<int> viewportArea)
{
JUCE_ASSERT_MESSAGE_MANAGER_IS_LOCKED
auto fbW = cachedImageFrameBuffer.getWidth();
auto fbH = cachedImageFrameBuffer.getHeight();
@ -276,10 +316,13 @@ public:
doWorkWhileWaitingForLock (true);
const auto currentAreaAndScale = areaAndScale.get();
const auto viewportArea = currentAreaAndScale.area;
if (context.renderer != nullptr)
{
glViewport (0, 0, viewportArea.getWidth(), viewportArea.getHeight());
context.currentRenderScale = scale;
context.currentRenderScale = currentAreaAndScale.scale;
context.renderer->renderOpenGL();
clearGLError();
@ -290,7 +333,7 @@ public:
{
if (isUpdating)
{
paintComponent();
paintComponent (currentAreaAndScale);
if (! hasInitialised)
return false;
@ -331,7 +374,7 @@ public:
return [window backingScaleFactor];
}
return scale;
return areaAndScale.get().scale;
}();
#else
const auto displayScale = Desktop::getInstance().getDisplays().getDisplayForRect (component.getTopLevelComponent()->getScreenBounds())->scale;
@ -350,10 +393,9 @@ public:
auto newScale = displayScale;
#endif
if (scale != newScale || viewportArea != newArea)
areaAndScale.set ({ newArea, newScale }, [&]
{
scale = newScale;
viewportArea = newArea;
// Transform is only accessed when the message manager is locked
transform = AffineTransform::scale ((float) newArea.getWidth() / (float) localBounds.getWidth(),
(float) newArea.getHeight() / (float) localBounds.getHeight());
@ -361,7 +403,7 @@ public:
if (canTriggerUpdate)
invalidateAll();
}
});
}
}
@ -383,17 +425,19 @@ public:
}
}
void paintComponent()
void paintComponent (const AreaAndScale& currentAreaAndScale)
{
JUCE_ASSERT_MESSAGE_MANAGER_IS_LOCKED
// you mustn't set your own cached image object when attaching a GL context!
jassert (get (component) == this);
if (! ensureFrameBufferSize())
if (! ensureFrameBufferSize (currentAreaAndScale.area))
return;
RectangleList<int> invalid (viewportArea);
RectangleList<int> invalid (currentAreaAndScale.area);
invalid.subtract (validArea);
validArea = viewportArea;
validArea = currentAreaAndScale.area;
if (! invalid.isEmpty())
{
@ -580,7 +624,8 @@ public:
bindVertexArray();
}
glViewport (0, 0, viewportArea.getWidth(), viewportArea.getHeight());
const auto currentViewportArea = areaAndScale.get().area;
glViewport (0, 0, currentViewportArea.getWidth(), currentViewportArea.getHeight());
nativeContext->setSwapInterval (1);
@ -710,10 +755,10 @@ public:
Version openGLVersion;
OpenGLFrameBuffer cachedImageFrameBuffer;
RectangleList<int> validArea;
Rectangle<int> viewportArea, lastScreenBounds;
double scale = 1.0;
Rectangle<int> lastScreenBounds;
AffineTransform transform;
GLuint vertexArrayObject = 0;
LockedAreaAndScale areaAndScale;
StringArray associatedObjectNames;
ReferenceCountedArray<ReferenceCountedObject> associatedObjects;