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:
parent
e751a5edd7
commit
01e71bc351
1 changed files with 60 additions and 15 deletions
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue