Multi-level context caching
[platform/core/uifw/dali-adaptor.git] / dali / internal / graphics / gles-impl / gles-graphics-framebuffer.cpp
index 6869bd9..d909146 100644 (file)
 
 // 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);
+}
+
+Framebuffer::~Framebuffer() = default;
+
+bool Framebuffer::InitializeResource()
+{
+  auto context = mController.GetCurrentContext();
+  auto gl      = mController.GetGL();
+  if(gl && context && !mInitialized)
+  {
+    mInitialized = true;
+
+    context->GenFramebuffers(1, &mFramebufferId);
+    context->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?
+    context->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);
+    }
+
+    context->BindFrameBuffer(GL_FRAMEBUFFER, 0);
+  }
+
+  return mInitialized;
+}
+
+void Framebuffer::DestroyResource()
+{
+  auto context = mController.GetCurrentContext();
+  auto gl      = mController.GetGL();
+  if(gl && context && mInitialized)
+  {
+    if(mDepthBufferId)
+    {
+      gl->DeleteRenderbuffers(1, &mDepthBufferId);
+    }
+    if(mStencilBufferId)
+    {
+      gl->DeleteRenderbuffers(1, &mStencilBufferId);
+    }
+
+    context->DeleteFramebuffers(1, &mFramebufferId);
+
+    mFramebufferId = 0u;
+    mInitialized   = false;
+  }
+}
+
+void Framebuffer::DiscardResource()
+{
+  mController.DiscardResource(this);
+}
+
+void Framebuffer::Bind() const
+{
+  auto context = mController.GetCurrentContext();
+  auto gl      = mController.GetGL();
+
+  if(gl && context)
+  {
+    context->BindFrameBuffer(GL_FRAMEBUFFER, mFramebufferId);
+  }
+}
+
+void Framebuffer::AttachTexture(const Graphics::Texture* texture, uint32_t attachmentId, uint32_t layerId, uint32_t levelId)
+{
+  auto gl = mController.GetGL();
+  if(gl)
+  {
+    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);
+    }
+  }
+}
+
+uint32_t Framebuffer::GetGlFramebufferId() const
+{
+  return mFramebufferId;
+}
+
+uint32_t Framebuffer::GetGlDepthBufferId() const
+{
+  return mDepthBufferId;
+}
+
+uint32_t Framebuffer::GetGlStencilBufferId() const
+{
+  return mStencilBufferId;
+}
+
+} //namespace Dali::Graphics::GLES