From fc2caf0a4dfa8caf186c5728658d21aaa50af600 Mon Sep 17 00:00:00 2001 From: reuk Date: Wed, 25 Jun 2025 15:49:17 +0100 Subject: [PATCH] OpenGLFrameBuffer: Refactor to move stored OpenGLContext out of TransientState --- modules/juce_opengl/juce_opengl.cpp | 12 +-- .../opengl/juce_OpenGLFrameBuffer.cpp | 88 ++++++++++--------- 2 files changed, 54 insertions(+), 46 deletions(-) diff --git a/modules/juce_opengl/juce_opengl.cpp b/modules/juce_opengl/juce_opengl.cpp index 9023896a08..8916e4f58d 100644 --- a/modules/juce_opengl/juce_opengl.cpp +++ b/modules/juce_opengl/juce_opengl.cpp @@ -229,24 +229,24 @@ static void clearGLError() noexcept struct OpenGLTargetSaver { - OpenGLTargetSaver (const OpenGLContext& c) noexcept - : context (c), oldFramebuffer (OpenGLFrameBuffer::getCurrentFrameBufferTarget()) + OpenGLTargetSaver() noexcept + : oldFramebuffer (OpenGLFrameBuffer::getCurrentFrameBufferTarget()) { glGetIntegerv (GL_VIEWPORT, oldViewport); } ~OpenGLTargetSaver() noexcept { - context.extensions.glBindFramebuffer (GL_FRAMEBUFFER, oldFramebuffer); + gl::glBindFramebuffer (GL_FRAMEBUFFER, oldFramebuffer); glViewport (oldViewport[0], oldViewport[1], oldViewport[2], oldViewport[3]); } + JUCE_DECLARE_NON_COPYABLE (OpenGLTargetSaver) + JUCE_DECLARE_NON_MOVEABLE (OpenGLTargetSaver) + private: - const OpenGLContext& context; GLuint oldFramebuffer; GLint oldViewport[4]; - - OpenGLTargetSaver& operator= (const OpenGLTargetSaver&); }; } // namespace juce diff --git a/modules/juce_opengl/opengl/juce_OpenGLFrameBuffer.cpp b/modules/juce_opengl/opengl/juce_OpenGLFrameBuffer.cpp index 7f1f879aa8..cdecace517 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLFrameBuffer.cpp +++ b/modules/juce_opengl/opengl/juce_OpenGLFrameBuffer.cpp @@ -54,12 +54,16 @@ public: jassert (context.isActive()); // The context must be active when creating a framebuffer! release(); - auto& transientState = state.emplace (context, width, height, false, false); + auto& transientState = state.emplace (width, height, false, false); if (! transientState.createdOk()) release(); - return isValid(); + if (! isValid()) + return false; + + associatedContext = &context; + return true; } bool initialise (OpenGLContext& context, const Image& image) @@ -77,7 +81,7 @@ public: { auto* p = std::get_if (&other.pimpl->state); - if (p == nullptr) + if (p == nullptr || other.pimpl->associatedContext == nullptr) { release(); return true; @@ -85,14 +89,16 @@ public: const Rectangle area (p->width, p->height); - if (! initialise (p->context, area.getWidth(), area.getHeight())) + if (! initialise (*other.pimpl->associatedContext, area.getWidth(), area.getHeight())) return false; + jassert (associatedContext != nullptr); + auto* transientState = std::get_if (&state); transientState->bind(); #if ! JUCE_ANDROID - if (! transientState->context.isCoreProfile()) + if (! associatedContext->isCoreProfile()) glEnable (GL_TEXTURE_2D); clearGLError(); @@ -100,7 +106,7 @@ public: { const ScopedTextureBinding scopedTextureBinding; glBindTexture (GL_TEXTURE_2D, p->textureID); - transientState->context.copyTexture (area, area, area.getWidth(), area.getHeight(), false); + associatedContext->copyTexture (area, area, area.getWidth(), area.getHeight(), false); } transientState->unbind(); @@ -109,6 +115,7 @@ public: void release() { + associatedContext = nullptr; state.emplace(); } @@ -218,13 +225,15 @@ public: bool writePixels (const PixelARGB* data, const Rectangle& area) { + if (associatedContext == nullptr) + return false; + + const OpenGLTargetSaver ts; auto* transientState = makeAndGetCurrentRenderingTarget(); if (transientState == nullptr) return false; - OpenGLTargetSaver ts (transientState->context); - glDisable (GL_DEPTH_TEST); glDisable (GL_BLEND); JUCE_CHECK_OPENGL_ERROR @@ -233,15 +242,15 @@ public: tex.loadARGB (data, area.getWidth(), area.getHeight()); glViewport (0, 0, transientState->width, transientState->height); - transientState->context.copyTexture (area, - Rectangle (area.getX(), - area.getY(), - tex.getWidth(), - tex.getHeight()), - transientState->width, - transientState->height, - true, - false); + associatedContext->copyTexture (area, + Rectangle (area.getX(), + area.getY(), + tex.getWidth(), + tex.getHeight()), + transientState->width, + transientState->height, + true, + false); JUCE_CHECK_OPENGL_ERROR return true; @@ -269,13 +278,11 @@ private: class TransientState { public: - TransientState (OpenGLContext& c, - const int w, + TransientState (const int w, const int h, const bool wantsDepthBuffer, const bool wantsStencilBuffer) - : context (c), - width (w), + : width (w), height (h), textureID (0), frameBufferID (0), @@ -286,11 +293,11 @@ private: jassert (OpenGLHelpers::isContextActive()); #if JUCE_WINDOWS || JUCE_LINUX || JUCE_BSD - if (context.extensions.glGenFramebuffers == nullptr) - return; + if (gl::glGenFramebuffers == nullptr) + return; #endif - context.extensions.glGenFramebuffers (1, &frameBufferID); + gl::glGenFramebuffers (1, &frameBufferID); bind(); { @@ -310,13 +317,13 @@ private: JUCE_CHECK_OPENGL_ERROR } - context.extensions.glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureID, 0); + gl::glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureID, 0); if (wantsDepthBuffer || wantsStencilBuffer) { - context.extensions.glGenRenderbuffers (1, &depthOrStencilBuffer); - context.extensions.glBindRenderbuffer (GL_RENDERBUFFER, depthOrStencilBuffer); - jassert (context.extensions.glIsRenderbuffer (depthOrStencilBuffer)); + gl::glGenRenderbuffers (1, &depthOrStencilBuffer); + gl::glBindRenderbuffer (GL_RENDERBUFFER, depthOrStencilBuffer); + jassert (gl::glIsRenderbuffer (depthOrStencilBuffer)); #if JUCE_OPENGL_ES constexpr auto depthComponentConstant = (GLenum) GL_DEPTH_COMPONENT16; @@ -324,17 +331,18 @@ private: constexpr auto depthComponentConstant = (GLenum) GL_DEPTH_COMPONENT; #endif - context.extensions.glRenderbufferStorage (GL_RENDERBUFFER, - (wantsDepthBuffer && wantsStencilBuffer) ? (GLenum) GL_DEPTH24_STENCIL8 - : depthComponentConstant, - width, height); + gl::glRenderbufferStorage (GL_RENDERBUFFER, + (wantsDepthBuffer && wantsStencilBuffer) ? (GLenum) GL_DEPTH24_STENCIL8 + : depthComponentConstant, + width, + height); GLint params = 0; - context.extensions.glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_DEPTH_SIZE, ¶ms); - context.extensions.glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthOrStencilBuffer); + gl::glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_DEPTH_SIZE, ¶ms); + gl::glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthOrStencilBuffer); if (wantsStencilBuffer) - context.extensions.glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthOrStencilBuffer); + gl::glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthOrStencilBuffer); } unbind(); @@ -348,10 +356,10 @@ private: glDeleteTextures (1, &textureID); if (depthOrStencilBuffer != 0) - context.extensions.glDeleteRenderbuffers (1, &depthOrStencilBuffer); + gl::glDeleteRenderbuffers (1, &depthOrStencilBuffer); if (frameBufferID != 0) - context.extensions.glDeleteFramebuffers (1, &frameBufferID); + gl::glDeleteFramebuffers (1, &frameBufferID); JUCE_CHECK_OPENGL_ERROR } @@ -365,17 +373,16 @@ private: void bind() { glGetIntegerv (GL_FRAMEBUFFER_BINDING, &prevFramebuffer); - context.extensions.glBindFramebuffer (GL_FRAMEBUFFER, frameBufferID); + gl::glBindFramebuffer (GL_FRAMEBUFFER, frameBufferID); JUCE_CHECK_OPENGL_ERROR } void unbind() { - context.extensions.glBindFramebuffer (GL_FRAMEBUFFER, (GLuint) prevFramebuffer); + gl::glBindFramebuffer (GL_FRAMEBUFFER, (GLuint) prevFramebuffer); JUCE_CHECK_OPENGL_ERROR } - OpenGLContext& context; const int width, height; GLuint textureID, frameBufferID, depthOrStencilBuffer; @@ -421,6 +428,7 @@ private: return nullptr; } + OpenGLContext* associatedContext = nullptr; std::variant state; };