Initialize framebuffer before render pass used
[platform/core/uifw/dali-core.git] / dali / internal / render / renderers / render-frame-buffer.cpp
1 /*
2  * Copyright (c) 2021 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 }
37
38 FrameBuffer::~FrameBuffer() = default;
39
40 void FrameBuffer::Destroy()
41 {
42   mGraphicsObject.reset();
43 }
44
45 void FrameBuffer::Initialize(Graphics::Controller& graphicsController)
46 {
47   mGraphicsController = &graphicsController;
48 }
49
50 void FrameBuffer::AttachColorTexture(Render::Texture* texture, uint32_t mipmapLevel, uint32_t layer)
51 {
52   if(texture)
53   {
54     if(!texture->GetGraphicsObject())
55     {
56       texture->Create(0 | Graphics::TextureUsageFlagBits::COLOR_ATTACHMENT | Graphics::TextureUsageFlagBits::SAMPLE);
57     }
58
59     uint32_t                  attachmentId = mCreateInfo.colorAttachments.size();
60     Graphics::ColorAttachment colorAttachment{attachmentId, texture->GetGraphicsObject(), layer, mipmapLevel};
61     mCreateInfo.colorAttachments.push_back(colorAttachment);
62   }
63 }
64
65 void FrameBuffer::AttachDepthTexture(Render::Texture* texture, uint32_t mipmapLevel)
66 {
67   if(texture && mDepthBuffer)
68   {
69     if(!texture->GetGraphicsObject())
70     {
71       texture->Create(0 | Graphics::TextureUsageFlagBits::DEPTH_STENCIL_ATTACHMENT | Graphics::TextureUsageFlagBits::SAMPLE);
72     }
73
74     mCreateInfo.depthStencilAttachment.depthTexture = texture->GetGraphicsObject();
75     mCreateInfo.depthStencilAttachment.depthLevel   = mipmapLevel;
76   }
77 }
78
79 void FrameBuffer::AttachDepthStencilTexture(Render::Texture* texture, uint32_t mipmapLevel)
80 {
81   if(texture && mStencilBuffer)
82   {
83     if(!texture->GetGraphicsObject())
84     {
85       texture->Create(0 | Graphics::TextureUsageFlagBits::DEPTH_STENCIL_ATTACHMENT | Graphics::TextureUsageFlagBits::SAMPLE);
86     }
87     mCreateInfo.depthStencilAttachment.stencilTexture = texture->GetGraphicsObject();
88     mCreateInfo.depthStencilAttachment.stencilLevel   = mipmapLevel;
89   }
90 }
91
92 bool FrameBuffer::CreateGraphicsObjects()
93 {
94   bool created = false;
95
96   if(!mGraphicsObject)
97   {
98     // Only create a graphics object if there are attachments for it to render into
99     if(mCreateInfo.colorAttachments.empty() &&
100        mCreateInfo.depthStencilAttachment.depthTexture == nullptr &&
101        mCreateInfo.depthStencilAttachment.stencilTexture == nullptr)
102     {
103       DALI_LOG_ERROR("Attempting to bind a framebuffer with no attachments\n");
104     }
105     else
106     {
107       mGraphicsObject = mGraphicsController->CreateFramebuffer(mCreateInfo, std::move(mGraphicsObject));
108
109       // Create render target
110       Graphics::RenderTargetCreateInfo rtInfo{};
111       rtInfo
112         .SetFramebuffer(mGraphicsObject.get())
113         .SetExtent({mWidth, mHeight})
114         .SetPreTransform(0 | Graphics::RenderTargetTransformFlagBits::TRANSFORM_IDENTITY_BIT);
115       mRenderTarget = mGraphicsController->CreateRenderTarget(rtInfo, std::move(mRenderTarget));
116
117       std::vector<Graphics::AttachmentDescription> attachmentDescriptions;
118
119       // Default behaviour for color attachments is to CLEAR and STORE
120       //@todo Ideally, we should create new render pass whenever
121       //      the loadop, storeop changes and the list of such renderpasses
122       //      should be managed accordingly (as in Vulkan)
123       mClearValues.clear();
124       for(auto& attachments : mCreateInfo.colorAttachments)
125       {
126         if(attachments.texture)
127         {
128           Graphics::AttachmentDescription desc{};
129           desc.SetLoadOp(Graphics::AttachmentLoadOp::CLEAR);
130           desc.SetStoreOp(Graphics::AttachmentStoreOp::STORE);
131           attachmentDescriptions.push_back(desc);
132           mClearValues.emplace_back();
133         }
134       }
135
136       if(mCreateInfo.depthStencilAttachment.depthTexture || mCreateInfo.depthStencilAttachment.stencilTexture)
137       {
138         Graphics::AttachmentDescription depthStencilDesc{};
139         depthStencilDesc.SetStencilLoadOp(Graphics::AttachmentLoadOp::CLEAR)
140           .SetStoreOp(Graphics::AttachmentStoreOp::DONT_CARE);
141
142         if(mCreateInfo.depthStencilAttachment.stencilTexture)
143         {
144           depthStencilDesc.SetStencilLoadOp(Graphics::AttachmentLoadOp::CLEAR)
145             .SetStoreOp(Graphics::AttachmentStoreOp::DONT_CARE);
146         }
147         mClearValues.emplace_back();
148         attachmentDescriptions.push_back(depthStencilDesc);
149       }
150
151       Graphics::RenderPassCreateInfo rpInfo{};
152       rpInfo.SetAttachments(attachmentDescriptions);
153
154       // Add default render pass (loadOp = clear)
155       mRenderPass.emplace_back(mGraphicsController->CreateRenderPass(rpInfo, nullptr));
156
157       // Add default render pass (loadOp = dontcare)
158       attachmentDescriptions[0].SetLoadOp(Graphics::AttachmentLoadOp::DONT_CARE);
159       mRenderPass.emplace_back(mGraphicsController->CreateRenderPass(rpInfo, nullptr));
160
161       created = true;
162     }
163   }
164   return created;
165 }
166
167 uint32_t FrameBuffer::GetWidth() const
168 {
169   return mWidth;
170 }
171
172 uint32_t FrameBuffer::GetHeight() const
173 {
174   return mHeight;
175 }
176
177 [[nodiscard]] Graphics::RenderPass* FrameBuffer::GetGraphicsRenderPass(Graphics::AttachmentLoadOp  colorLoadOp,
178                                                                        Graphics::AttachmentStoreOp colorStoreOp) const
179 {
180   // clear only when requested
181   if(colorLoadOp == Graphics::AttachmentLoadOp::CLEAR)
182   {
183     return mRenderPass[0].get();
184   }
185   else
186   {
187     return mRenderPass[1].get();
188   }
189 }
190
191 } // namespace Render
192
193 } // namespace Internal
194
195 } // namespace Dali