[dali_2.3.38] Merge branch 'devel/master'
[platform/core/uifw/dali-core.git] / dali / internal / render / renderers / render-frame-buffer.cpp
1 /*
2  * Copyright (c) 2024 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 // CLASS HEADER
18 #include <dali/internal/render/renderers/render-frame-buffer.h>
19
20 // INTERNAL INCLUDES
21 #include <dali/integration-api/debug.h>
22 #include <dali/internal/render/renderers/render-texture.h>
23
24 namespace Dali
25 {
26 namespace Internal
27 {
28 namespace Render
29 {
30 FrameBuffer::FrameBuffer(uint32_t width, uint32_t height, Mask attachments)
31 : mWidth(width),
32   mHeight(height),
33   mDepthBuffer(attachments & Dali::FrameBuffer::Attachment::DEPTH),
34   mStencilBuffer(attachments & Dali::FrameBuffer::Attachment::STENCIL)
35 {
36   mCreateInfo.size.width  = width;
37   mCreateInfo.size.height = height;
38   if(mDepthBuffer)
39   {
40     mCreateInfo.depthStencilAttachment.depthUsage = Graphics::DepthStencilAttachment::Usage::WRITE;
41   }
42   if(mStencilBuffer)
43   {
44     mCreateInfo.depthStencilAttachment.stencilUsage = Graphics::DepthStencilAttachment::Usage::WRITE;
45   }
46 }
47
48 FrameBuffer::~FrameBuffer() = default;
49
50 void FrameBuffer::Destroy()
51 {
52   mGraphicsObject.reset();
53 }
54
55 void FrameBuffer::Initialize(Graphics::Controller& graphicsController)
56 {
57   mGraphicsController = &graphicsController;
58 }
59
60 void FrameBuffer::AttachColorTexture(Render::Texture* texture, uint32_t mipmapLevel, uint32_t layer)
61 {
62   if(texture)
63   {
64     if(!texture->GetGraphicsObject())
65     {
66       texture->Create(0 | Graphics::TextureUsageFlagBits::COLOR_ATTACHMENT | Graphics::TextureUsageFlagBits::SAMPLE);
67     }
68
69     uint32_t                  attachmentId = mCreateInfo.colorAttachments.size();
70     Graphics::ColorAttachment colorAttachment{attachmentId, texture->GetGraphicsObject(), layer, mipmapLevel};
71     mCreateInfo.colorAttachments.push_back(colorAttachment);
72   }
73 }
74
75 void FrameBuffer::AttachDepthTexture(Render::Texture* texture, uint32_t mipmapLevel)
76 {
77   if(texture)
78   {
79     if(!texture->GetGraphicsObject())
80     {
81       texture->Create(0 | Graphics::TextureUsageFlagBits::DEPTH_STENCIL_ATTACHMENT | Graphics::TextureUsageFlagBits::SAMPLE);
82     }
83
84     mCreateInfo.depthStencilAttachment.depthTexture = texture->GetGraphicsObject();
85     mCreateInfo.depthStencilAttachment.depthUsage   = Graphics::DepthStencilAttachment::Usage::WRITE;
86     mCreateInfo.depthStencilAttachment.depthLevel   = mipmapLevel;
87   }
88 }
89
90 void FrameBuffer::AttachDepthStencilTexture(Render::Texture* texture, uint32_t mipmapLevel)
91 {
92   if(texture)
93   {
94     if(!texture->GetGraphicsObject())
95     {
96       texture->Create(0 | Graphics::TextureUsageFlagBits::DEPTH_STENCIL_ATTACHMENT | Graphics::TextureUsageFlagBits::SAMPLE);
97     }
98     mCreateInfo.depthStencilAttachment.stencilTexture = texture->GetGraphicsObject();
99     mCreateInfo.depthStencilAttachment.stencilUsage   = Graphics::DepthStencilAttachment::Usage::WRITE;
100     mCreateInfo.depthStencilAttachment.stencilLevel   = mipmapLevel;
101   }
102 }
103
104 void FrameBuffer::SetMultiSamplingLevel(uint8_t multiSamplingLevel)
105 {
106   mCreateInfo.multiSamplingLevel = multiSamplingLevel;
107 }
108
109 bool FrameBuffer::CreateGraphicsObjects()
110 {
111   bool created = false;
112
113   if(!mGraphicsObject)
114   {
115     // Only create a graphics object if there are attachments for it to render into
116     if(mCreateInfo.colorAttachments.empty() &&
117        mCreateInfo.depthStencilAttachment.depthTexture == nullptr &&
118        mCreateInfo.depthStencilAttachment.stencilTexture == nullptr &&
119        !mDepthBuffer && !mStencilBuffer)
120     {
121       DALI_LOG_ERROR("Attempting to bind a framebuffer with no attachments\n");
122     }
123     else
124     {
125       std::vector<Graphics::AttachmentDescription> attachmentDescriptions;
126
127       // Default behaviour for color attachments is to CLEAR and STORE
128       mClearValues.clear();
129       for(auto& attachments : mCreateInfo.colorAttachments)
130       {
131         if(attachments.texture)
132         {
133           Graphics::AttachmentDescription desc{};
134           desc.SetLoadOp(Graphics::AttachmentLoadOp::CLEAR);
135           desc.SetStoreOp(Graphics::AttachmentStoreOp::STORE);
136           attachmentDescriptions.push_back(desc);
137           mClearValues.emplace_back();
138         }
139       }
140
141       if(mCreateInfo.depthStencilAttachment.depthTexture || mCreateInfo.depthStencilAttachment.stencilTexture ||
142          mDepthBuffer || mStencilBuffer)
143       {
144         Graphics::AttachmentDescription depthStencilDesc{};
145         depthStencilDesc.SetLoadOp(Graphics::AttachmentLoadOp::CLEAR)
146           .SetStoreOp(Graphics::AttachmentStoreOp::DONT_CARE);
147
148         if(mCreateInfo.depthStencilAttachment.stencilTexture || mStencilBuffer)
149         {
150           depthStencilDesc.SetStencilLoadOp(Graphics::AttachmentLoadOp::CLEAR)
151             .SetStencilStoreOp(Graphics::AttachmentStoreOp::DONT_CARE);
152         }
153         mClearValues.emplace_back();
154         attachmentDescriptions.push_back(depthStencilDesc);
155       }
156
157       Graphics::RenderPassCreateInfo rpInfo{};
158       rpInfo.SetAttachments(attachmentDescriptions);
159
160       // Add default render pass (loadOp = clear)
161       mRenderPass.emplace_back(mGraphicsController->CreateRenderPass(rpInfo, nullptr));
162
163       // Add default render pass (loadOp = dontcare)
164       attachmentDescriptions[0].SetLoadOp(Graphics::AttachmentLoadOp::DONT_CARE);
165       mRenderPass.emplace_back(mGraphicsController->CreateRenderPass(rpInfo, nullptr));
166
167       std::vector<Graphics::RenderPass*> renderPasses;
168       renderPasses.push_back(mRenderPass[0].get());
169       renderPasses.push_back(mRenderPass[1].get());
170       mCreateInfo.SetRenderPasses(std::move(renderPasses));
171
172       mGraphicsObject = mGraphicsController->CreateFramebuffer(mCreateInfo, std::move(mGraphicsObject));
173
174       // Create render target
175       Graphics::RenderTargetCreateInfo rtInfo{};
176       rtInfo
177         .SetFramebuffer(mGraphicsObject.get())
178         .SetExtent({mWidth, mHeight})
179         .SetPreTransform(0 | Graphics::RenderTargetTransformFlagBits::TRANSFORM_IDENTITY_BIT);
180
181       mRenderTarget = mGraphicsController->CreateRenderTarget(rtInfo, std::move(mRenderTarget));
182       created       = true;
183     }
184   }
185   return created;
186 }
187
188 uint32_t FrameBuffer::GetWidth() const
189 {
190   return mWidth;
191 }
192
193 uint32_t FrameBuffer::GetHeight() const
194 {
195   return mHeight;
196 }
197
198 [[nodiscard]] Graphics::RenderPass* FrameBuffer::GetGraphicsRenderPass(Graphics::AttachmentLoadOp  colorLoadOp,
199                                                                        Graphics::AttachmentStoreOp colorStoreOp) const
200 {
201   // clear only when requested
202   if(colorLoadOp == Graphics::AttachmentLoadOp::CLEAR)
203   {
204     return mRenderPass[0].get();
205   }
206   else
207   {
208     return mRenderPass[1].get();
209   }
210 }
211
212 } // namespace Render
213
214 } // namespace Internal
215
216 } // namespace Dali