(GLES) Ensure gles framebuffer bound at shared context 25/322625/8
authorEunki Hong <eunkiki.hong@samsung.com>
Fri, 11 Apr 2025 17:09:47 +0000 (02:09 +0900)
committerEunki, Hong <eunkiki.hong@samsung.com>
Wed, 23 Apr 2025 02:26:54 +0000 (11:26 +0900)
gles-context have framebuffer dependency cache objects.
But now, it looks that we only allow to Create/Bind the framebuffers
at shared context.

Since we cant destroy the framebuffer at another context,
we should ensure to remove the cache objects at shared conetext.

Change-Id: I4da09e30644488dcb2f217cee1fcf2d7213b1202
Signed-off-by: Eunki Hong <eunkiki.hong@samsung.com>
dali/internal/graphics/gles-impl/egl-graphics-controller.cpp
dali/internal/graphics/gles-impl/egl-graphics-controller.h
dali/internal/graphics/gles-impl/gles-context.cpp
dali/internal/graphics/gles-impl/gles-context.h
dali/internal/graphics/gles-impl/gles-framebuffer-state-cache.cpp
dali/internal/graphics/gles-impl/gles-framebuffer-state-cache.h
dali/internal/graphics/gles-impl/gles-graphics-framebuffer.cpp
dali/internal/graphics/gles-impl/gles-graphics-framebuffer.h

index ae2d3e61f749ee2794fde05136edaa215fb3da39..222e1c71c062a56056b0301c3dd44cf95f2b8d55 100644 (file)
@@ -207,8 +207,11 @@ void EglGraphicsController::InitializeGLES(Integration::GlAbstraction& glAbstrac
   mContext        = std::make_unique<GLES::Context>(*this, mGlAbstraction);
   mCurrentContext = mContext.get();
 
+  // Register shared context for framebuffers
+  GLES::Framebuffer::SetSharedContext(mCurrentContext);
+
   static auto enableShaderUseProgramBinaryString = Dali::EnvironmentVariable::GetEnvironmentVariable(DALI_ENV_SHADER_USE_PROGRAM_BINARY);
-  mUseProgramBinary = enableShaderUseProgramBinaryString ? std::atoi(enableShaderUseProgramBinaryString) : false;
+  mUseProgramBinary                              = enableShaderUseProgramBinaryString ? std::atoi(enableShaderUseProgramBinaryString) : false;
 }
 
 void EglGraphicsController::Initialize(Integration::GraphicsSyncAbstraction& syncImplementation,
@@ -270,6 +273,9 @@ void EglGraphicsController::Shutdown()
   // Final flush
   Flush();
 
+  // Invalidate shared context for framebuffers
+  GLES::Framebuffer::SetSharedContext(nullptr);
+
   if(mContext)
   {
     mContext->GlContextDestroyed();
index 58611c6ed6e52950a427de37565aaba2fbb90d30..8f14276c9feb4d3cd41ea6107dd2d4904dff68b1 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_EGL_GRAPHICS_CONTROLLER_H
 
 /*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -507,6 +507,7 @@ public:
        !mTextureUpdateRequests.empty() ||
        !mTextureMipmapGenerationRequests.empty())
     {
+      // Must be ResourceContext as current if we have any resource creation.
       mGraphics->ActivateResourceContext();
     }
 
@@ -529,6 +530,7 @@ public:
     ResetBufferCache();
 
     // Process discards
+    // Note : we don't need to be ResourceContext when we destroy resources.
     ProcessDiscardQueues();
 
     // Flush pipeline cache to remove unused pipelines
index eed36755a963f7963ff2559de8eacbbc70f0b60c..6b766025fa858a10794e17d832b5994dba051114 100644 (file)
@@ -823,7 +823,8 @@ void Context::BeginRenderPass(const BeginRenderPassDescriptor& renderPassBegin)
   if(targetInfo.surface)
   {
     // Bind surface FB
-    BindFrameBuffer(GL_FRAMEBUFFER, 0);
+    gl->BindFramebuffer(GL_FRAMEBUFFER, 0);
+    mImpl->mGlStateCache.mFrameBufferStateCache.SetCurrentFrameBuffer(0);
   }
   else if(targetInfo.framebuffer)
   {
@@ -1213,47 +1214,6 @@ bool Context::BindBuffer(GLenum target, uint32_t bufferId)
   return false;
 }
 
-void Context::DrawBuffers(uint32_t count, const GLenum* buffers)
-{
-  if(auto* gl = mImpl->GetGL())
-  {
-    mImpl->mGlStateCache.mFrameBufferStateCache.DrawOperation(mImpl->mGlStateCache.mColorMask,
-                                                              mImpl->mGlStateCache.DepthBufferWriteEnabled(),
-                                                              mImpl->mGlStateCache.StencilBufferWriteEnabled());
-
-    gl->DrawBuffers(count, buffers);
-  }
-}
-
-void Context::BindFrameBuffer(GLenum target, uint32_t bufferId)
-{
-  if(auto* gl = mImpl->GetGL())
-  {
-    mImpl->mGlStateCache.mFrameBufferStateCache.SetCurrentFrameBuffer(bufferId);
-
-    gl->BindFramebuffer(target, bufferId);
-  }
-}
-
-void Context::GenFramebuffers(uint32_t count, uint32_t* framebuffers)
-{
-  if(auto* gl = mImpl->GetGL())
-  {
-    gl->GenFramebuffers(count, framebuffers);
-    mImpl->mGlStateCache.mFrameBufferStateCache.FrameBuffersCreated(count, framebuffers);
-  }
-}
-
-void Context::DeleteFramebuffers(uint32_t count, uint32_t* framebuffers)
-{
-  if(auto* gl = mImpl->GetGL())
-  {
-    mImpl->mGlStateCache.mFrameBufferStateCache.FrameBuffersDeleted(count, framebuffers);
-
-    gl->DeleteFramebuffers(count, framebuffers);
-  }
-}
-
 GLStateCache& Context::GetGLStateCache()
 {
   return mImpl->mGlStateCache;
index 7532772372544eedeef9482f94ab35dfbf6519e2..ca63593a0a433feb32af63722577569da8100a58 100644 (file)
@@ -207,10 +207,6 @@ public:
    */
   bool BindBuffer(GLenum target, uint32_t bufferId);
 
-  void DrawBuffers(uint32_t count, const GLenum* buffers);
-  void BindFrameBuffer(GLenum target, uint32_t bufferId);
-  void GenFramebuffers(uint32_t count, uint32_t* framebuffers);
-  void DeleteFramebuffers(uint32_t count, uint32_t* framebuffers);
   void ColorMask(bool enabled);
   void ClearStencilBuffer();
   void ClearDepthBuffer();
index 2fbb32e72b089d32b0dcbe729cc109590310e528..e545b9af4ccb0a2185369bf693fffd01845d0ed6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -97,37 +97,41 @@ GLbitfield FrameBufferStateCache::GetClearMask(GLbitfield mask, bool forceClear,
   return mask;
 }
 
-void FrameBufferStateCache::SetCurrentFrameBuffer(GLuint frameBufferId)
+void FrameBufferStateCache::SetCurrentFrameBuffer(const GLuint framebufferId)
 {
-  mCurrentFrameBufferId = frameBufferId;
+  mCurrentFrameBufferId = framebufferId;
 }
 
-void FrameBufferStateCache::FrameBuffersDeleted(GLsizei count, const GLuint* const frameBuffers)
+void FrameBufferStateCache::FrameBufferCreated(const GLuint framebufferId)
 {
-  for(GLsizei i = 0; i < count; ++i)
+  // check the frame buffer doesn't exist already
+  FrameBufferState* state = GetFrameBufferState(framebufferId);
+  if(state)
   {
-    DeleteFrameBuffer(frameBuffers[i]);
+    DALI_LOG_ERROR("FrameBuffer already exists%d \n", framebufferId);
+    // reset its state
+    state->mState = INITIAL_FRAMEBUFFER_STATE;
+    return;
   }
+
+  FrameBufferState newFrameBuffer(framebufferId);
+  mFrameBufferStates.PushBack(newFrameBuffer);
 }
-void FrameBufferStateCache::FrameBuffersCreated(GLsizei count, const GLuint* const frameBuffers)
+
+void FrameBufferStateCache::FrameBufferDeleted(const GLuint framebufferId)
 {
-  for(GLsizei i = 0; i < count; ++i)
-  {
-    // check the frame buffer doesn't exist already
-    GLuint id = frameBuffers[i];
+  FrameBufferStateVector::Iterator iter    = mFrameBufferStates.Begin();
+  FrameBufferStateVector::Iterator endIter = mFrameBufferStates.End();
 
-    FrameBufferState* state = GetFrameBufferState(id);
-    if(state)
+  for(; iter != endIter; ++iter)
+  {
+    if((*iter).mId == framebufferId)
     {
-      DALI_LOG_ERROR("FrameBuffer already exists%d \n", id);
-      // reset its state
-      state->mState = INITIAL_FRAMEBUFFER_STATE;
-      continue;
+      mFrameBufferStates.Erase(iter);
+      return;
     }
-
-    FrameBufferState newFrameBuffer(frameBuffers[i]);
-    mFrameBufferStates.PushBack(newFrameBuffer);
   }
+  DALI_LOG_ERROR("FrameBuffer not found %d \n", framebufferId);
 }
 
 void FrameBufferStateCache::DrawOperation(bool colorBuffer, bool depthBuffer, bool stencilBuffer)
@@ -161,8 +165,7 @@ void FrameBufferStateCache::Reset()
   mFrameBufferStates.Clear();
 
   // create the default frame buffer
-  GLuint id = 0; // 0 == default frame buffer id
-  FrameBuffersCreated(1, &id);
+  FrameBufferCreated(0);
 }
 
 void FrameBufferStateCache::SetClearState(FrameBufferState* state, GLbitfield mask)
@@ -184,12 +187,12 @@ void FrameBufferStateCache::SetClearState(FrameBufferState* state, GLbitfield ma
   }
 }
 
-FrameBufferStateCache::FrameBufferState* FrameBufferStateCache::GetFrameBufferState(GLuint frameBufferId)
+FrameBufferStateCache::FrameBufferState* FrameBufferStateCache::GetFrameBufferState(GLuint framebufferId)
 {
   for(FrameBufferStateVector::SizeType i = 0; i < mFrameBufferStates.Count(); ++i)
   {
     FrameBufferState& state = mFrameBufferStates[i];
-    if(state.mId == frameBufferId)
+    if(state.mId == framebufferId)
     {
       return &state;
     }
@@ -197,22 +200,6 @@ FrameBufferStateCache::FrameBufferState* FrameBufferStateCache::GetFrameBufferSt
   return nullptr;
 }
 
-void FrameBufferStateCache::DeleteFrameBuffer(GLuint frameBufferId)
-{
-  FrameBufferStateVector::Iterator iter    = mFrameBufferStates.Begin();
-  FrameBufferStateVector::Iterator endIter = mFrameBufferStates.End();
-
-  for(; iter != endIter; ++iter)
-  {
-    if((*iter).mId == frameBufferId)
-    {
-      mFrameBufferStates.Erase(iter);
-      return;
-    }
-  }
-  DALI_LOG_ERROR("FrameBuffer not found %d \n", frameBufferId);
-}
-
 } // namespace GLES
 
 } // namespace Dali::Graphics
index 02442b85e4333538bb47ec156a3b13b5b764ea96..4610b43f618ac00429f1dba8729697925ec50b1c 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_GRAPHICS_GLES_CONTEXT_FRAMEBUFFER_STATE_CACHE_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -56,23 +56,21 @@ public:
 
   /**
    * @brief Set the current bound frame buffer
-   * @param[in] frameBufferId frame buffer id
+   * @param[in] framebufferId frame buffer id
    */
-  void SetCurrentFrameBuffer(GLuint frameBufferId);
+  void SetCurrentFrameBuffer(const GLuint framebufferId);
 
   /**
-   * @brief Called when frame buffers are deleted
-   * @param[in] count number of frame buffers
-   * @param[in] framebuffers array of frame buffer ids
+   * @brief Called when frame buffer is deleted
+   * @param[in] framebufferId frame buffer ids
    */
-  void FrameBuffersDeleted(GLsizei count, const GLuint* const frameBuffers);
+  void FrameBufferDeleted(const GLuint framebufferId);
 
   /**
-   * @brief Called when frame buffers are created
-   * @param[in] count number of frame buffers
-   * @param[in] framebuffers array of frame buffer ids
+   * @brief Called when frame buffer is created
+   * @param[in] framebufferId frame buffer id
    */
-  void FrameBuffersCreated(GLsizei count, const GLuint* const frameBuffers);
+  void FrameBufferCreated(const GLuint framebufferId);
 
   /**
    * @brief Draw operation performed on the current frame buffer
@@ -126,23 +124,17 @@ private:
 
   /**
    * @brief Helper
-   * @param[in] frameBufferId frame buffer id
+   * @param[in] framebufferId frame buffer id
    * @return pointer to  frame buffer state object ( NULL if it doesn't exist)
    */
-  FrameBufferState* GetFrameBufferState(GLuint frameBufferId);
-
-  /**
-   * @brief Helper to delete a frame buffer state object
-   * @param[in] frameBufferId frame buffer id
-   */
-  void DeleteFrameBuffer(GLuint frameBufferId);
+  FrameBufferState* GetFrameBufferState(GLuint framebufferId);
 
   FrameBufferStateCache(const FrameBufferStateCache&); ///< undefined copy constructor
 
   FrameBufferStateCache& operator=(const FrameBufferStateCache&); ///< undefined assignment operator
 
-private:                                        // data
-  FrameBufferStateVector mFrameBufferStates{};    ///< state of the frame buffers
+private:                                           // data
+  FrameBufferStateVector mFrameBufferStates{};     ///< state of the frame buffers
   GLuint                 mCurrentFrameBufferId{0}; ///< currently bound frame buffer
 };
 
index e7b83313887947eba79987c03b1d7f9fc1d78e96..c1e7e114bd181fd83320e2c214a4a9eb7481274a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
 // Internal headers
 #include <dali/internal/graphics/gles-impl/gles-graphics-texture.h>
 #include "egl-graphics-controller.h"
+#include "gles-context.h"
 
 namespace Dali::Graphics::GLES
 {
@@ -81,6 +82,13 @@ struct DEPTH_STENCIL_ATTACHMENT_TYPE
 
 } // anonymous namespace
 
+Context* Framebuffer::mSharedContext = nullptr;
+
+void Framebuffer::SetSharedContext(Context* context)
+{
+  mSharedContext = context;
+}
+
 Framebuffer::Framebuffer(const Graphics::FramebufferCreateInfo& createInfo, Graphics::EglGraphicsController& controller)
 : FramebufferResource(createInfo, controller)
 {
@@ -98,14 +106,16 @@ Framebuffer::~Framebuffer() = default;
 
 bool Framebuffer::InitializeResource()
 {
-  auto context = mController.GetCurrentContext();
-  auto gl      = mController.GetGL();
-  if(gl && context && !mInitialized)
+  auto gl = mController.GetGL();
+  if(gl && mSharedContext && !mInitialized)
   {
+    DALI_ASSERT_DEBUG(mSharedContext == mController.GetCurrentContext() && "Framebuffer is create at another context!");
     mInitialized = true;
 
-    context->GenFramebuffers(1, &mFramebufferId);
-    context->BindFrameBuffer(GL_FRAMEBUFFER, mFramebufferId);
+    gl->GenFramebuffers(1, &mFramebufferId);
+    // @todo: Error check if FramebufferId is 0
+
+    gl->BindFramebuffer(GL_FRAMEBUFFER, mFramebufferId);
 
     for(Graphics::ColorAttachment& attachment : mCreateInfo.colorAttachments)
     {
@@ -113,7 +123,7 @@ bool Framebuffer::InitializeResource()
     }
 
     // @todo is this per framebuffer, or more immediate state that needs setting when framebuffer changed?
-    context->DrawBuffers(mCreateInfo.colorAttachments.size(), COLOR_ATTACHMENTS);
+    gl->DrawBuffers(mCreateInfo.colorAttachments.size(), COLOR_ATTACHMENTS);
 
     // @todo Currently, we don't assume that GL_EXT_PACKED_DEPTH_STENCIL valid.
     // We will assume that stencilTexture / stencilBufferId always mean depth-stencil.
@@ -171,7 +181,18 @@ bool Framebuffer::InitializeResource()
       }
     }
 
-    context->BindFrameBuffer(GL_FRAMEBUFFER, 0);
+    gl->BindFramebuffer(GL_FRAMEBUFFER, 0);
+
+    // Update framebuffer state cache here.
+    auto& glStateCache          = mSharedContext->GetGLStateCache();
+    auto& framebufferStateCache = glStateCache.mFrameBufferStateCache;
+
+    framebufferStateCache.FrameBufferCreated(mFramebufferId);
+    framebufferStateCache.SetCurrentFrameBuffer(mFramebufferId);
+    framebufferStateCache.DrawOperation(glStateCache.mColorMask,
+                                        glStateCache.DepthBufferWriteEnabled(),
+                                        glStateCache.StencilBufferWriteEnabled());
+    framebufferStateCache.SetCurrentFrameBuffer(0);
   }
 
   return mInitialized;
@@ -181,9 +202,8 @@ void Framebuffer::DestroyResource()
 {
   if(DALI_LIKELY(!EglGraphicsController::IsShuttingDown()))
   {
-    auto context = mController.GetCurrentContext();
-    auto gl      = mController.GetGL();
-    if(gl && context && mInitialized)
+    auto gl = mController.GetGL();
+    if(gl && mInitialized)
     {
       if(mDepthBufferId)
       {
@@ -194,7 +214,17 @@ void Framebuffer::DestroyResource()
         gl->DeleteRenderbuffers(1, &mStencilBufferId);
       }
 
-      context->DeleteFramebuffers(1, &mFramebufferId);
+      if(mFramebufferId != 0u)
+      {
+        gl->DeleteFramebuffers(1, &mFramebufferId);
+      }
+
+      if(mSharedContext)
+      {
+        // Update framebuffer state cache here.
+        auto& framebufferStateCache = mSharedContext->GetGLStateCache().mFrameBufferStateCache;
+        framebufferStateCache.FrameBufferDeleted(mFramebufferId);
+      }
 
       mFramebufferId = 0u;
       mInitialized   = false;
@@ -209,12 +239,15 @@ void Framebuffer::DiscardResource()
 
 void Framebuffer::Bind() const
 {
-  auto context = mController.GetCurrentContext();
-  auto gl      = mController.GetGL();
-
-  if(gl && context)
+  auto gl = mController.GetGL();
+  if(gl && mSharedContext)
   {
-    context->BindFrameBuffer(GL_FRAMEBUFFER, mFramebufferId);
+    DALI_ASSERT_DEBUG(mSharedContext == mController.GetCurrentContext() && "Framebuffer is bound to another context!");
+    gl->BindFramebuffer(GL_FRAMEBUFFER, mFramebufferId);
+
+    // Update framebuffer state cache here.
+    auto& framebufferStateCache = mSharedContext->GetGLStateCache().mFrameBufferStateCache;
+    framebufferStateCache.SetCurrentFrameBuffer(mFramebufferId);
   }
 }
 
index 430b395f53c8990aaea2b18f20392522841fcaf3..4bcc885b2c62d1a8d043e035d4ce7e5db945bf05 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_GRAPHICS_GLES_FRAMEBUFFER_H
 
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 
 namespace Dali::Graphics::GLES
 {
+class Context;
 using FramebufferResource = Resource<Graphics::Framebuffer, Graphics::FramebufferCreateInfo>;
 
 class Framebuffer : public FramebufferResource
 {
 public:
+  /**
+   * @brief Set the shared context. All GLES::Framebuffer class will use given context.
+   */
+  static void SetSharedContext(Context* context);
+
   /**
    * @brief Constructor
    * @param[in] createInfo Valid createInfo structure
@@ -83,11 +89,14 @@ private:
   void AttachTexture(const Graphics::Texture* texture, uint32_t attachmentId, uint32_t layerId, uint32_t levelId);
 
 private:
+  static Context* mSharedContext; ///< The bind available context
+
   uint32_t mFramebufferId{0u};
   uint32_t mDepthBufferId{0u};
   uint32_t mStencilBufferId{0u};
   uint32_t mMultisamples{1u};
-  bool     mInitialized{false};
+
+  bool mInitialized{false};
 };
 
 } // namespace Dali::Graphics::GLES