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>
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,
// Final flush
Flush();
+ // Invalidate shared context for framebuffers
+ GLES::Framebuffer::SetSharedContext(nullptr);
+
if(mContext)
{
mContext->GlContextDestroyed();
#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.
!mTextureUpdateRequests.empty() ||
!mTextureMipmapGenerationRequests.empty())
{
+ // Must be ResourceContext as current if we have any resource creation.
mGraphics->ActivateResourceContext();
}
ResetBufferCache();
// Process discards
+ // Note : we don't need to be ResourceContext when we destroy resources.
ProcessDiscardQueues();
// Flush pipeline cache to remove unused pipelines
if(targetInfo.surface)
{
// Bind surface FB
- BindFrameBuffer(GL_FRAMEBUFFER, 0);
+ gl->BindFramebuffer(GL_FRAMEBUFFER, 0);
+ mImpl->mGlStateCache.mFrameBufferStateCache.SetCurrentFrameBuffer(0);
}
else if(targetInfo.framebuffer)
{
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;
*/
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();
/*
- * 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.
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)
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)
}
}
-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;
}
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
#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.
/**
* @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
/**
* @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
};
/*
- * 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.
// 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
{
} // 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)
{
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)
{
}
// @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.
}
}
- 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;
{
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)
{
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;
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);
}
}
#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
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