2 * Copyright (c) 2021 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include "gles-graphics-framebuffer.h"
22 #include <dali/integration-api/gl-abstraction.h>
23 #include <dali/integration-api/gl-defines.h>
26 #include <dali/internal/graphics/gles-impl/gles-graphics-texture.h>
27 #include "egl-graphics-controller.h"
29 namespace Dali::Graphics::GLES
33 const GLenum COLOR_ATTACHMENTS[] =
45 struct DEPTH_STENCIL_ATTACHMENT_TYPE
47 constexpr explicit DEPTH_STENCIL_ATTACHMENT_TYPE(Graphics::Format textureFormat)
51 case Graphics::Format::D16_UNORM:
52 case Graphics::Format::D32_SFLOAT:
53 case Graphics::Format::X8_D24_UNORM_PACK32:
55 attachment = GL_DEPTH_ATTACHMENT;
59 case Graphics::Format::S8_UINT: // Probably won't work as a standalone texture.
61 attachment = GL_STENCIL_ATTACHMENT;
65 case Graphics::Format::D16_UNORM_S8_UINT:
66 case Graphics::Format::D24_UNORM_S8_UINT:
67 case Graphics::Format::D32_SFLOAT_S8_UINT:
69 attachment = GL_DEPTH_STENCIL_ATTACHMENT;
79 Dali::GLenum attachment{GL_NONE};
82 } // anonymous namespace
84 Framebuffer::Framebuffer(const Graphics::FramebufferCreateInfo& createInfo, Graphics::EglGraphicsController& controller)
85 : FramebufferResource(createInfo, controller)
87 // Add framebuffer to the Resource queue
88 mController.AddFramebuffer(*this);
91 Framebuffer::~Framebuffer() = default;
93 bool Framebuffer::InitializeResource()
95 auto context = mController.GetCurrentContext();
96 auto gl = mController.GetGL();
97 if(gl && context && !mInitialized)
101 context->GenFramebuffers(1, &mFramebufferId);
102 context->BindFrameBuffer(GL_FRAMEBUFFER, mFramebufferId);
104 for(Graphics::ColorAttachment& attachment : mCreateInfo.colorAttachments)
106 AttachTexture(attachment.texture, COLOR_ATTACHMENTS[attachment.attachmentId], attachment.layerId, attachment.levelId);
109 // @todo is this per framebuffer, or more immediate state that needs setting when framebuffer changed?
110 context->DrawBuffers(mCreateInfo.colorAttachments.size(), COLOR_ATTACHMENTS);
112 if(mCreateInfo.depthStencilAttachment.depthTexture)
114 // Create a depth or depth/stencil render target.
115 auto depthTexture = static_cast<const GLES::Texture*>(mCreateInfo.depthStencilAttachment.depthTexture);
116 auto attachmentId = DEPTH_STENCIL_ATTACHMENT_TYPE(depthTexture->GetCreateInfo().format).attachment;
118 AttachTexture(depthTexture, attachmentId, 0, mCreateInfo.depthStencilAttachment.depthLevel);
120 else if(mCreateInfo.depthStencilAttachment.depthUsage == Graphics::DepthStencilAttachment::Usage::WRITE)
122 gl->GenRenderbuffers(1, &mDepthBufferId);
123 gl->BindRenderbuffer(GL_RENDERBUFFER, mDepthBufferId);
124 gl->RenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, mCreateInfo.size.width, mCreateInfo.size.height);
125 gl->FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepthBufferId);
128 if(mCreateInfo.depthStencilAttachment.stencilTexture)
130 auto stencilTexture = static_cast<const GLES::Texture*>(mCreateInfo.depthStencilAttachment.stencilTexture);
131 auto attachmentId = DEPTH_STENCIL_ATTACHMENT_TYPE(stencilTexture->GetCreateInfo().format).attachment;
133 AttachTexture(stencilTexture, attachmentId, 0, mCreateInfo.depthStencilAttachment.stencilLevel);
135 else if(mCreateInfo.depthStencilAttachment.stencilUsage == Graphics::DepthStencilAttachment::Usage::WRITE)
137 gl->GenRenderbuffers(1, &mStencilBufferId);
138 gl->BindRenderbuffer(GL_RENDERBUFFER, mStencilBufferId);
139 gl->RenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, mCreateInfo.size.width, mCreateInfo.size.height);
140 gl->FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mStencilBufferId);
143 context->BindFrameBuffer(GL_FRAMEBUFFER, 0);
149 void Framebuffer::DestroyResource()
151 auto context = mController.GetCurrentContext();
152 auto gl = mController.GetGL();
153 if(gl && context && mInitialized)
157 gl->DeleteRenderbuffers(1, &mDepthBufferId);
161 gl->DeleteRenderbuffers(1, &mStencilBufferId);
164 context->DeleteFramebuffers(1, &mFramebufferId);
167 mInitialized = false;
171 void Framebuffer::DiscardResource()
173 mController.DiscardResource(this);
176 void Framebuffer::Bind() const
178 auto context = mController.GetCurrentContext();
179 auto gl = mController.GetGL();
183 context->BindFrameBuffer(GL_FRAMEBUFFER, mFramebufferId);
187 void Framebuffer::AttachTexture(const Graphics::Texture* texture, uint32_t attachmentId, uint32_t layerId, uint32_t levelId)
189 auto gl = mController.GetGL();
192 auto graphicsTexture = static_cast<const GLES::Texture*>(texture);
193 if(graphicsTexture->GetCreateInfo().textureType == Graphics::TextureType::TEXTURE_2D)
195 gl->FramebufferTexture2D(GL_FRAMEBUFFER, attachmentId, graphicsTexture->GetGlTarget(), graphicsTexture->GetGLTexture(), levelId);
199 gl->FramebufferTexture2D(GL_FRAMEBUFFER, attachmentId, GL_TEXTURE_CUBE_MAP_POSITIVE_X + layerId, graphicsTexture->GetGLTexture(), levelId);
204 uint32_t Framebuffer::GetGlFramebufferId() const
206 return mFramebufferId;
209 uint32_t Framebuffer::GetGlDepthBufferId() const
211 return mDepthBufferId;
214 uint32_t Framebuffer::GetGlStencilBufferId() const
216 return mStencilBufferId;
219 } //namespace Dali::Graphics::GLES