void EglGraphicsController::InitializeGLES(Integration::GlAbstraction& glAbstraction)
{
DALI_LOG_RELEASE_INFO("Initializing New Graphics Controller #1\n");
- mGlAbstraction = &glAbstraction;
- mContext = std::make_unique<GLES::Context>(*this);
+ mGlAbstraction = &glAbstraction;
+ mContext = std::make_unique<GLES::Context>(*this);
+ mCurrentContext = mContext.get();
}
void EglGraphicsController::Initialize(Integration::GlSyncAbstraction& glSyncAbstraction,
return static_cast<const Graphics::GLES::Program*>(&program)->GetReflection();
}
+void EglGraphicsController::CreateSurfaceContext(Dali::RenderSurfaceInterface* surface)
+{
+ std::unique_ptr<GLES::Context> context = std::make_unique<GLES::Context>(*this);
+ mSurfaceContexts.push_back(std::move(std::make_pair(surface, std::move(context))));
+}
+
+void EglGraphicsController::DeleteSurfaceContext(Dali::RenderSurfaceInterface* surface)
+{
+ mSurfaceContexts.erase(std::remove_if(
+ mSurfaceContexts.begin(), mSurfaceContexts.end(), [surface](SurfaceContextPair& iter) { return surface == iter.first; }),
+ mSurfaceContexts.end());
+}
+
+void EglGraphicsController::ActivateResourceContext()
+{
+ mCurrentContext = mContext.get();
+}
+
+void EglGraphicsController::ActivateSurfaceContext(Dali::RenderSurfaceInterface* surface)
+{
+ if(surface && mGraphics->IsResourceContextSupported())
+ {
+ auto iter = std::find_if(mSurfaceContexts.begin(), mSurfaceContexts.end(), [surface](SurfaceContextPair& iter) {
+ return (iter.first == surface);
+ });
+
+ if(iter != mSurfaceContexts.end())
+ {
+ mCurrentContext = iter->second.get();
+ }
+ }
+}
+
void EglGraphicsController::AddTexture(GLES::Texture& texture)
{
// Assuming we are on the correct context
}
case GLES::CommandType::BIND_TEXTURES:
{
- mContext->BindTextures(cmd.bindTextures.textureBindings);
+ mCurrentContext->BindTextures(cmd.bindTextures.textureBindings);
break;
}
case GLES::CommandType::BIND_VERTEX_BUFFERS:
{
auto& bindings = cmd.bindVertexBuffers.vertexBufferBindings;
- mContext->BindVertexBuffers(bindings);
+ mCurrentContext->BindVertexBuffers(bindings);
break;
}
case GLES::CommandType::BIND_UNIFORM_BUFFER:
{
auto& bindings = cmd.bindUniformBuffers;
- mContext->BindUniformBuffers(bindings.uniformBufferBindings, bindings.standaloneUniformsBufferBinding);
+ mCurrentContext->BindUniformBuffers(bindings.uniformBufferBindings, bindings.standaloneUniformsBufferBinding);
break;
}
case GLES::CommandType::BIND_INDEX_BUFFER:
{
- mContext->BindIndexBuffer(cmd.bindIndexBuffer);
+ mCurrentContext->BindIndexBuffer(cmd.bindIndexBuffer);
break;
}
case GLES::CommandType::BIND_SAMPLERS:
case GLES::CommandType::BIND_PIPELINE:
{
auto pipeline = static_cast<const GLES::Pipeline*>(cmd.bindPipeline.pipeline);
- mContext->BindPipeline(pipeline);
+ mCurrentContext->BindPipeline(pipeline);
break;
}
case GLES::CommandType::DRAW:
{
- mContext->Flush(false, cmd.draw);
+ mCurrentContext->Flush(false, cmd.draw);
break;
}
case GLES::CommandType::DRAW_INDEXED:
{
- mContext->Flush(false, cmd.draw);
+ mCurrentContext->Flush(false, cmd.draw);
break;
}
case GLES::CommandType::DRAW_INDEXED_INDIRECT:
{
- mContext->Flush(false, cmd.draw);
+ mCurrentContext->Flush(false, cmd.draw);
break;
}
case GLES::CommandType::SET_SCISSOR: // @todo Consider correcting for orientation here?
}
case GLES::CommandType::BEGIN_RENDERPASS:
{
- mContext->BeginRenderPass(cmd.beginRenderPass);
+ auto& renderTarget = *cmd.beginRenderPass.renderTarget;
+ const auto& targetInfo = renderTarget.GetCreateInfo();
+
+ if(targetInfo.surface)
+ {
+ // switch to surface context
+ mGraphics->ActivateSurfaceContext(static_cast<Dali::RenderSurfaceInterface*>(targetInfo.surface));
+ }
+ else if(targetInfo.framebuffer)
+ {
+ // switch to resource context
+ mGraphics->ActivateResourceContext();
+ }
+
+ mCurrentContext->BeginRenderPass(cmd.beginRenderPass);
break;
}
case GLES::CommandType::END_RENDERPASS:
{
- mContext->EndRenderPass();
+ mCurrentContext->EndRenderPass();
break;
}
case GLES::CommandType::PRESENT_RENDER_TARGET:
// Resolves presentation
void ResolvePresentRenderTarget(GLES::RenderTarget* renderTarget);
+ /**
+ * Creates a GLES context for the given render surface
+ *
+ * @param[in] surface The surface whose GLES context to be created.
+ */
+ void CreateSurfaceContext(Dali::RenderSurfaceInterface* surface);
+
+ /**
+ * Deletes a GLES context
+ *
+ * @param[in] surface The surface whose GLES context to be deleted.
+ */
+ void DeleteSurfaceContext(Dali::RenderSurfaceInterface* surface);
+
+ /**
+ * Activate the resource context (shared surfaceless context)
+ */
+ void ActivateResourceContext();
+
+ /**
+ * Activate the surface context
+ *
+ * @param[in] surface The surface whose context to be switched to.
+ */
+ void ActivateSurfaceContext(Dali::RenderSurfaceInterface* surface);
+
private:
Integration::GlAbstraction* mGlAbstraction{nullptr};
Integration::GlSyncAbstraction* mGlSyncAbstraction{nullptr};
using TextureUpdateRequest = std::pair<TextureUpdateInfo, TextureUpdateSourceInfo>;
std::queue<TextureUpdateRequest> mTextureUpdateRequests;
- std::unique_ptr<GLES::Context> mContext{nullptr}; ///< Context object handling command buffers execution
+ GLES::Context* mCurrentContext{nullptr}; ///< The current context
+ std::unique_ptr<GLES::Context> mContext{nullptr}; ///< Context object handling command buffers execution
+ using SurfaceContextPair = std::pair<Dali::RenderSurfaceInterface*, std::unique_ptr<GLES::Context>>;
+ std::vector<SurfaceContextPair> mSurfaceContexts; ///< Vector of surface context objects handling command buffers execution
std::unique_ptr<GLES::PipelineCache> mPipelineCache{nullptr}; ///< Internal pipeline cache
auto& renderPass = *renderPassBegin.renderPass;
auto& renderTarget = *renderPassBegin.renderTarget;
- const auto& passInfo = renderPass.GetCreateInfo();
const auto& targetInfo = renderTarget.GetCreateInfo();
auto& gl = *mImpl->mController.GetGL();
if(targetInfo.surface)
{
- // switch context to surface bound
- graphics.ActivateSurfaceContext(static_cast<Dali::RenderSurfaceInterface*>(targetInfo.surface));
-
// Bind surface FB
gl.BindFramebuffer(GL_FRAMEBUFFER, 0);
}
else if(targetInfo.framebuffer)
{
- // if needed, switch to shared context.
- graphics.ActivateResourceContext();
-
// bind framebuffer and swap.
renderTarget.GetFramebuffer()->Bind();
}
// CLASS HEADER
#include "gles-graphics-render-target.h"
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/adaptor-framework/render-surface-interface.h>
+#include "egl-graphics-controller.h"
#include "gles-graphics-framebuffer.h"
namespace Dali::Graphics::GLES
{
+struct RenderTarget::Impl
+{
+ Impl(EglGraphicsController& controller)
+ : controller(controller){};
+
+ ~Impl() = default;
+
+ EglGraphicsController& controller;
+};
+
RenderTarget::RenderTarget(const Graphics::RenderTargetCreateInfo& createInfo, Graphics::EglGraphicsController& controller)
: RenderTargetResource(createInfo, controller)
{
+ mImpl = std::make_unique<Impl>(controller);
+
+ if(createInfo.surface)
+ {
+ controller.CreateSurfaceContext(static_cast<Dali::RenderSurfaceInterface*>(createInfo.surface));
+ }
+}
+
+RenderTarget::~RenderTarget()
+{
+ if(mCreateInfo.surface)
+ {
+ mImpl->controller.DeleteSurfaceContext(static_cast<Dali::RenderSurfaceInterface*>(mCreateInfo.surface));
+ }
}
GLES::Framebuffer* RenderTarget::GetFramebuffer() const
/**
* @brief Destructor
*/
- ~RenderTarget() override = default;
+ ~RenderTarget() override;
/**
* @brief Called when GL resources are destroyed
* @brief Returns surface associated with the render target
*/
Surface* GetSurface() const;
+
+private:
+ struct Impl;
+ std::unique_ptr<Impl> mImpl{nullptr};
};
} // namespace Dali::Graphics::GLES
auto buffer = static_cast<GLES::Buffer*>(mMapBufferInfo.buffer);
if(!buffer->IsCPUAllocated())
{
- // switch to the shared context if necessary
- auto graphics = mController.GetGraphicsInterface();
- graphics->ActivateResourceContext();
buffer->Bind(BufferUsage::VERTEX_BUFFER);
gl->BufferSubData(GL_ARRAY_BUFFER, mMapBufferInfo.offset, mMapBufferInfo.size, mMappedPointer);
}
else
{
- // switch to the shared context if necessary
- auto graphics = mController.GetGraphicsInterface();
- graphics->ActivateResourceContext();
-
// @TODO: trashing vertex binding, better find target that is rarely used
buffer->Bind(Graphics::BufferUsage::VERTEX_BUFFER);
void* ptr = nullptr;
auto buffer = static_cast<GLES::Buffer*>(mMapBufferInfo.buffer);
if(!buffer->IsCPUAllocated())
{
- // switch to the shared context if necessary
- auto graphics = mController.GetGraphicsInterface();
- graphics->ActivateResourceContext();
-
buffer->Bind(Graphics::BufferUsage::VERTEX_BUFFER);
gl->UnmapBuffer(GL_ARRAY_BUFFER);
}
void EglGraphics::ActivateResourceContext()
{
+ mGraphicsController.ActivateResourceContext();
+
if(mEglImplementation && mEglImplementation->IsSurfacelessContextSupported())
{
// Make the shared surfaceless context as current before rendering
void EglGraphics::ActivateSurfaceContext(Dali::RenderSurfaceInterface* surface)
{
+ mGraphicsController.ActivateSurfaceContext(surface);
+
if(surface)
{
surface->InitializeGraphics();
void ActivateResourceContext() override;
/**
- * Activate the resource context
+ * Activate the surface context
*
* @param[in] surface The surface whose context to be switched to.
*/
void NativeRenderSurfaceEcoreWl::PostRender()
{
- // @todo: Check why did we always pass false into here previously?
- bool replacingSurface = false;
-
auto eglGraphics = static_cast<Internal::Adaptor::EglGraphics*>(mGraphics);
if(eglGraphics)
{