return *mGlContextHelperAbstraction;
}
-Graphics::UniquePtr<CommandBuffer>
-EglGraphicsController::CreateCommandBuffer(const CommandBufferCreateInfo& commandBufferCreateInfo,
- Graphics::UniquePtr<CommandBuffer>&& oldCommandBuffer)
+Graphics::UniquePtr<CommandBuffer> EglGraphicsController::CreateCommandBuffer(
+ const CommandBufferCreateInfo& commandBufferCreateInfo,
+ Graphics::UniquePtr<CommandBuffer>&& oldCommandBuffer)
{
return NewObject<GLES::CommandBuffer>(commandBufferCreateInfo, *this, std::move(oldCommandBuffer));
}
-Graphics::UniquePtr<Texture>
-EglGraphicsController::CreateTexture(const TextureCreateInfo& textureCreateInfo, Graphics::UniquePtr<Texture>&& oldTexture)
+Graphics::UniquePtr<Texture> EglGraphicsController::CreateTexture(
+ const TextureCreateInfo& textureCreateInfo, Graphics::UniquePtr<Texture>&& oldTexture)
{
return NewObject<GLES::Texture>(textureCreateInfo, *this, std::move(oldTexture));
}
-Graphics::UniquePtr<Buffer>
-EglGraphicsController::CreateBuffer(const BufferCreateInfo& bufferCreateInfo, Graphics::UniquePtr<Buffer>&& oldBuffer)
+Graphics::UniquePtr<Buffer> EglGraphicsController::CreateBuffer(
+ const BufferCreateInfo& bufferCreateInfo, Graphics::UniquePtr<Buffer>&& oldBuffer)
{
return NewObject<GLES::Buffer>(bufferCreateInfo, *this, std::move(oldBuffer));
}
-Graphics::UniquePtr<Pipeline> EglGraphicsController::CreatePipeline(const PipelineCreateInfo& pipelineCreateInfo, Graphics::UniquePtr<Graphics::Pipeline>&& oldPipeline)
+Graphics::UniquePtr<Framebuffer> EglGraphicsController::CreateFramebuffer(
+ const FramebufferCreateInfo& framebufferCreateInfo, Graphics::UniquePtr<Framebuffer>&& oldFramebuffer)
+{
+ return NewObject<GLES::Framebuffer>(framebufferCreateInfo, *this, std::move(oldFramebuffer));
+}
+
+Graphics::UniquePtr<Pipeline> EglGraphicsController::CreatePipeline(
+ const PipelineCreateInfo& pipelineCreateInfo, Graphics::UniquePtr<Graphics::Pipeline>&& oldPipeline)
{
// Create pipeline cache if needed
if(!mPipelineCache)
return mPipelineCache->GetPipeline(pipelineCreateInfo, std::move(oldPipeline));
}
-Graphics::UniquePtr<Program> EglGraphicsController::CreateProgram(const ProgramCreateInfo& programCreateInfo, UniquePtr<Program>&& oldProgram)
+Graphics::UniquePtr<Program> EglGraphicsController::CreateProgram(
+ const ProgramCreateInfo& programCreateInfo, UniquePtr<Program>&& oldProgram)
{
// Create program cache if needed
if(!mPipelineCache)
mCreateBufferQueue.push(&buffer);
}
+void EglGraphicsController::AddFramebuffer(GLES::Framebuffer& framebuffer)
+{
+ // Assuming we are on the correct context
+ mCreateFramebufferQueue.push(&framebuffer);
+}
+
void EglGraphicsController::ProcessDiscardQueues()
{
// Process textures
// Process buffers
ProcessDiscardQueue<GLES::Buffer>(mDiscardBufferQueue);
+ // Process Framebuffers
+ ProcessDiscardQueue<GLES::Framebuffer>(mDiscardFramebufferQueue);
+
// Process pipelines
ProcessDiscardQueue<GLES::Pipeline>(mDiscardPipelineQueue);
// Process buffers
ProcessCreateQueue(mCreateBufferQueue);
+
+ // Process framebuffers
+ ProcessCreateQueue(mCreateFramebufferQueue);
}
void EglGraphicsController::ProcessCommandQueues()
{
// TODO: command queue per context, sync between queues should be
// done externally
+ const Graphics::Framebuffer* currentFramebuffer{nullptr};
while(!mCommandQueue.empty())
{
}
case GLES::CommandType::BIND_PIPELINE:
{
- mContext->BindPipeline(cmd.bindPipeline.pipeline);
+ auto pipeline = static_cast<const GLES::Pipeline*>(cmd.bindPipeline.pipeline);
+
+ // Bind framebuffer if different. @todo Move to RenderPass
+ auto fbState = pipeline->GetCreateInfo().framebufferState;
+ if(fbState && fbState->framebuffer != currentFramebuffer)
+ {
+ currentFramebuffer = fbState->framebuffer;
+ static_cast<const GLES::Framebuffer*>(currentFramebuffer)->Bind();
+ }
+
+ mContext->BindPipeline(pipeline);
break;
}
case GLES::CommandType::DRAW:
#include "gles-context.h"
#include "gles-graphics-buffer.h"
#include "gles-graphics-command-buffer.h"
+#include "gles-graphics-framebuffer.h"
#include "gles-graphics-pipeline-cache.h"
#include "gles-graphics-pipeline.h"
#include "gles-graphics-reflection.h"
/**
* @copydoc Dali::Graphics::CreateFramebuffer()
*/
- Graphics::UniquePtr<Framebuffer> CreateFramebuffer(const FramebufferCreateInfo& framebufferCreateInfo, Graphics::UniquePtr<Framebuffer>&& oldFramebuffer) override
- {
- return nullptr;
- }
+ Graphics::UniquePtr<Framebuffer> CreateFramebuffer(const FramebufferCreateInfo& framebufferCreateInfo, Graphics::UniquePtr<Framebuffer>&& oldFramebuffer) override;
/**
* @copydoc Dali::Graphics::CreatePipeline()
void AddBuffer(GLES::Buffer& buffer);
/**
+ * @brief Adds framebuffer to the creation queue
+ * @param buffer
+ */
+ void AddFramebuffer(GLES::Framebuffer& framebuffer);
+
+ /**
* @brief Pushes Bufer to the discard queue
*
* Function is called from the UniquePtr custom deleter.
*
* Function is called from the UniquePtr custom deleter.
*
- * @param[in] texture Pointer to the texture
+ * @param[in] buffer Pointer to the buffer object
*/
void DiscardResource(GLES::Buffer* buffer)
{
}
/**
+ * @brief Pushes framebuffer to the discard queue
+ *
+ * Function is called from the UniquePtr custom deleter.
+ *
+ * @param[in] framebuffer Pointer to the framebuffer object
+ */
+ void DiscardResource(GLES::Framebuffer* framebuffer)
+ {
+ mDiscardFramebufferQueue.push(framebuffer);
+ }
+
+ /**
* @brief Pushes Program to the discard queue
*
* Function is called from the UniquePtr custom deleter.
std::queue<GLES::Shader*> mDiscardShaderQueue; ///< Discard queue of shaders
std::queue<GLES::Sampler*> mDiscardSamplerQueue; ///< Discard queue of samplers
std::queue<GLES::CommandBuffer*> mDiscardCommandBufferQueue; ///< Discard queue of command buffers
+ std::queue<GLES::Framebuffer*> mCreateFramebufferQueue; ///< Create queue for framebuffer resource
+ std::queue<GLES::Framebuffer*> mDiscardFramebufferQueue; ///< Discard queue for framebuffer resource
std::queue<GLES::CommandBuffer*> mCommandQueue; ///< we may have more in the future
// CLASS HEADER
#include "gles-graphics-framebuffer.h"
+
+// external headers
+#include <dali/integration-api/gl-abstraction.h>
+#include <dali/integration-api/gl-defines.h>
+
+// Internal headers
+#include <dali/internal/graphics/gles-impl/gles-graphics-texture.h>
+#include "egl-graphics-controller.h"
+
+namespace Dali::Graphics::GLES
+{
+namespace
+{
+const GLenum COLOR_ATTACHMENTS[] =
+ {
+ GL_COLOR_ATTACHMENT0,
+ GL_COLOR_ATTACHMENT1,
+ GL_COLOR_ATTACHMENT2,
+ GL_COLOR_ATTACHMENT3,
+ GL_COLOR_ATTACHMENT4,
+ GL_COLOR_ATTACHMENT5,
+ GL_COLOR_ATTACHMENT6,
+ GL_COLOR_ATTACHMENT7,
+};
+
+struct DEPTH_STENCIL_ATTACHMENT_TYPE
+{
+ constexpr explicit DEPTH_STENCIL_ATTACHMENT_TYPE(Graphics::Format textureFormat)
+ {
+ switch(textureFormat)
+ {
+ case Graphics::Format::D16_UNORM:
+ case Graphics::Format::D32_SFLOAT:
+ case Graphics::Format::X8_D24_UNORM_PACK32:
+ {
+ attachment = GL_DEPTH_ATTACHMENT;
+ break;
+ }
+
+ case Graphics::Format::S8_UINT: // Probably won't work as a standalone texture.
+ {
+ attachment = GL_STENCIL_ATTACHMENT;
+ break;
+ }
+
+ case Graphics::Format::D16_UNORM_S8_UINT:
+ case Graphics::Format::D24_UNORM_S8_UINT:
+ case Graphics::Format::D32_SFLOAT_S8_UINT:
+ {
+ attachment = GL_DEPTH_STENCIL_ATTACHMENT;
+ break;
+ }
+ default:
+ {
+ attachment = GL_NONE;
+ break;
+ }
+ }
+ }
+ Dali::GLenum attachment{GL_NONE};
+};
+
+} // anonymous namespace
+
+Framebuffer::Framebuffer(const Graphics::FramebufferCreateInfo& createInfo, Graphics::EglGraphicsController& controller)
+: FramebufferResource(createInfo, controller)
+{
+ // Add framebuffer to the Resource queue
+ mController.AddFramebuffer(*this);
+}
+
+bool Framebuffer::InitializeResource()
+{
+ if(!mInitialized)
+ {
+ mInitialized = true;
+ auto gl = mController.GetGL();
+
+ gl->GenFramebuffers(1, &mFramebufferId);
+ gl->BindFramebuffer(GL_FRAMEBUFFER, mFramebufferId);
+
+ for(Graphics::ColorAttachment& attachment : mCreateInfo.colorAttachments)
+ {
+ AttachTexture(attachment.texture, COLOR_ATTACHMENTS[attachment.attachmentId], attachment.layerId, attachment.levelId);
+ }
+
+ // @todo is this per framebuffer, or more immediate state that needs setting when framebuffer changed?
+ gl->DrawBuffers(mCreateInfo.colorAttachments.size(), COLOR_ATTACHMENTS);
+
+ if(mCreateInfo.depthStencilAttachment.depthTexture)
+ {
+ // Create a depth or depth/stencil render target.
+ auto depthTexture = static_cast<const GLES::Texture*>(mCreateInfo.depthStencilAttachment.depthTexture);
+ auto attachmentId = DEPTH_STENCIL_ATTACHMENT_TYPE(depthTexture->GetCreateInfo().format).attachment;
+
+ gl->GenRenderbuffers(1, &mDepthBufferId);
+ gl->BindRenderbuffer(GL_RENDERBUFFER, mDepthBufferId);
+ gl->RenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, mCreateInfo.size.width, mCreateInfo.size.height);
+ gl->FramebufferRenderbuffer(GL_FRAMEBUFFER, attachmentId, GL_RENDERBUFFER, mDepthBufferId);
+
+ AttachTexture(depthTexture, attachmentId, 0, mCreateInfo.depthStencilAttachment.depthLevel);
+ }
+
+ if(mCreateInfo.depthStencilAttachment.stencilTexture)
+ {
+ auto stencilTexture = static_cast<const GLES::Texture*>(mCreateInfo.depthStencilAttachment.stencilTexture);
+ auto attachmentId = DEPTH_STENCIL_ATTACHMENT_TYPE(stencilTexture->GetCreateInfo().format).attachment;
+
+ // Create a stencil render target.
+ gl->GenRenderbuffers(1, &mStencilBufferId);
+ gl->BindRenderbuffer(GL_RENDERBUFFER, mStencilBufferId);
+ gl->RenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, mCreateInfo.size.width, mCreateInfo.size.height);
+ gl->FramebufferRenderbuffer(GL_FRAMEBUFFER, attachmentId, GL_RENDERBUFFER, mStencilBufferId);
+
+ AttachTexture(stencilTexture, attachmentId, 0, mCreateInfo.depthStencilAttachment.stencilLevel);
+ }
+ gl->BindFramebuffer(GL_FRAMEBUFFER, 0);
+ }
+
+ return mInitialized;
+}
+
+void Framebuffer::DestroyResource()
+{
+ auto gl = mController.GetGL();
+ if(mInitialized)
+ {
+ if(mDepthBufferId)
+ {
+ gl->DeleteRenderbuffers(1, &mDepthBufferId);
+ }
+ if(mStencilBufferId)
+ {
+ gl->DeleteRenderbuffers(1, &mStencilBufferId);
+ }
+
+ gl->DeleteFramebuffers(1, &mFramebufferId);
+ mFramebufferId = 0u;
+ mInitialized = false;
+ }
+}
+
+void Framebuffer::DiscardResource()
+{
+ mController.DiscardResource(this);
+}
+
+void Framebuffer::Bind() const
+{
+ auto gl = mController.GetGL();
+ gl->BindFramebuffer(GL_FRAMEBUFFER, mFramebufferId);
+}
+
+void Framebuffer::AttachTexture(const Graphics::Texture* texture, uint32_t attachmentId, uint32_t layerId, uint32_t levelId)
+{
+ auto gl = mController.GetGL();
+ auto graphicsTexture = static_cast<const GLES::Texture*>(texture);
+ if(graphicsTexture->GetCreateInfo().textureType == Graphics::TextureType::TEXTURE_2D)
+ {
+ gl->FramebufferTexture2D(GL_FRAMEBUFFER, attachmentId, graphicsTexture->GetGlTarget(), graphicsTexture->GetGLTexture(), levelId);
+ }
+ else
+ {
+ gl->FramebufferTexture2D(GL_FRAMEBUFFER, attachmentId, GL_TEXTURE_CUBE_MAP_POSITIVE_X + layerId, graphicsTexture->GetGLTexture(), levelId);
+ }
+}
+
+} //namespace Dali::Graphics::GLES
* @param[in] createInfo Valid createInfo structure
* @param[in] controller Reference to the controller
*/
- Framebuffer(const Graphics::FramebufferCreateInfo& createInfo, Graphics::EglGraphicsController& controller)
- : FramebufferResource(createInfo, controller)
- {
- }
+ Framebuffer(const Graphics::FramebufferCreateInfo& createInfo, Graphics::EglGraphicsController& controller);
/**
* @brief Destructor
/**
* @brief Called when GL resources are destroyed
*/
- void DestroyResource() override
- {
- // TODO: Implement destroying the resource
- }
+ void DestroyResource() override;
/**
* @brief Called when initializing the resource
*
* @return True on success
*/
- bool InitializeResource() override
- {
- // TODO: Implement initializing resource
- return {};
- }
+ bool InitializeResource() override;
/**
* @brief Called when UniquePtr<> on client-side dies
*/
- void DiscardResource() override
- {
- // TODO: Implement moving to the discard queue
- }
+ void DiscardResource() override;
+
+ /**
+ * Used to bind the framebuffer, e.g. when offscreen changes
+ */
+ void Bind() const;
+
+private:
+ /**
+ * Attach a texture to the specified attachment point
+ * @param[in] texture The texture to bind
+ * @param[in] attachmentId The attachment point to bind it to
+ * @param[in] layerId The texture layer (e.g. for cubemap)
+ * @param[in] levelId The texture mipmap level
+ */
+ void AttachTexture(const Graphics::Texture* texture, uint32_t attachmentId, uint32_t layerId, uint32_t levelId);
+
+private:
+ uint32_t mFramebufferId{0u};
+ uint32_t mDepthBufferId{0u};
+ uint32_t mStencilBufferId{0u};
+ bool mInitialized{false};
};
} // namespace Dali::Graphics::GLES
-#endif
\ No newline at end of file
+#endif
*/
void Prepare();
+ /**
+ * @brief Returns the GL Target
+ * @return the Gl target
+ */
+ [[nodiscard]] GLenum GetGlTarget() const
+ {
+ return mGlTarget;
+ }
+
protected:
private:
std::vector<char> mStagingBuffer;