[dali_2.3.24] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / gl-view / gl-view-impl.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
18 // CLASS HEADER
19 #include <dali-toolkit/internal/controls/gl-view/gl-view-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/devel-api/adaptor-framework/lifecycle-controller.h>
23 #include <dali/devel-api/adaptor-framework/window-devel.h>
24 #include <dali/devel-api/rendering/renderer-devel.h>
25 #include <dali/integration-api/debug.h>
26 #include <dali/public-api/object/any.h>
27 #include <dali/public-api/rendering/renderer.h>
28 #include <dali/public-api/rendering/texture-set.h>
29 #include <dali/public-api/rendering/texture.h>
30
31 // INTERNAL INCLUDES
32 #include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
33 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
34
35 namespace Dali
36 {
37 namespace Toolkit
38 {
39 namespace Internal
40 {
41 Dali::Toolkit::GlView GlView::New(Dali::Toolkit::GlView::ColorFormat colorFormat)
42 {
43   auto*                 impl   = new Dali::Toolkit::Internal::GlView(colorFormat);
44   Dali::Toolkit::GlView handle = Dali::Toolkit::GlView(*impl);
45   impl->Initialize();
46   return handle;
47 }
48
49 GlView::GlView(Dali::Toolkit::GlView::ColorFormat colorFormat)
50 : Dali::Toolkit::Internal::GlViewImpl(Toolkit::GlView::BackendMode::EGL_IMAGE_OFFSCREEN_RENDERING),
51   mRenderThread(nullptr),
52   mNativeImageQueue(nullptr),
53   mRenderingMode(Toolkit::GlView::RenderingMode::CONTINUOUS),
54   mColorFormat(colorFormat),
55   mDepth(false),
56   mStencil(false),
57   mMSAA(0)
58 {
59 }
60
61 GlView::~GlView()
62 {
63   if(mRenderThread)
64   {
65     mRenderThread->Stop();
66     mRenderThread->Join();
67   }
68 }
69
70 void GlView::RegisterGlCallbacks(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback)
71 {
72   if(mRenderThread)
73   {
74     mRenderThread->RegisterGlCallbacks(initCallback, renderFrameCallback, terminateCallback);
75   }
76 }
77
78 void GlView::SetResizeCallback(CallbackBase* resizeCallback)
79 {
80   if(mRenderThread)
81   {
82     mRenderThread->SetResizeCallback(resizeCallback);
83   }
84 }
85
86 bool GlView::SetGraphicsConfig(bool depth, bool stencil, int msaa, Dali::Toolkit::GlView::GraphicsApiVersion version)
87 {
88   // Init Graphics
89   mDepth   = depth;
90   mStencil = stencil;
91   mMSAA    = msaa;
92
93   int rVersion;
94
95   if(version == Dali::Toolkit::GlView::GraphicsApiVersion::GLES_VERSION_2_0)
96   {
97     rVersion = 20;
98   }
99   else
100   {
101     rVersion = 30;
102   }
103
104   if(mRenderThread)
105   {
106     return mRenderThread->SetGraphicsConfig(depth, stencil, msaa, rVersion);
107   }
108
109   return false;
110 }
111
112 void GlView::SetRenderingMode(Dali::Toolkit::GlView::RenderingMode mode)
113 {
114   mRenderingMode    = mode;
115   Renderer renderer = Self().GetRendererAt(0);
116
117   if(mRenderingMode == Dali::Toolkit::GlView::RenderingMode::ON_DEMAND)
118   {
119     renderer.SetProperty(DevelRenderer::Property::RENDERING_BEHAVIOR, DevelRenderer::Rendering::IF_REQUIRED);
120
121     if(mRenderThread)
122     {
123       mRenderThread->SetOnDemandRenderMode(true);
124     }
125   }
126   else
127   {
128     renderer.SetProperty(DevelRenderer::Property::RENDERING_BEHAVIOR, DevelRenderer::Rendering::CONTINUOUSLY);
129
130     if(mRenderThread)
131     {
132       mRenderThread->SetOnDemandRenderMode(false);
133     }
134   }
135 }
136
137 Dali::Toolkit::GlView::RenderingMode GlView::GetRenderingMode() const
138 {
139   return mRenderingMode;
140 }
141
142 void GlView::RenderOnce()
143 {
144   if(mRenderThread)
145   {
146     mRenderThread->RenderOnce();
147   }
148 }
149
150 void GlView::BindTextureResources(std::vector<Dali::Texture> textures)
151 {
152   // Not supported in the indirect mode
153 }
154
155 void GlView::OnInitialize()
156 {
157   //Create NativeImageSourceQueue with the size of 1,1
158   mNativeImageQueue = Dali::NativeImageSourceQueue::New(1, 1, GetColorFormat(mColorFormat));
159
160   if(!mNativeImageQueue)
161   {
162     DALI_LOG_ERROR("NativeImageSourceQueue is NULL");
163     return;
164   }
165
166   AddRenderer();
167
168   Actor self = Self();
169
170   //Create a RenderThread
171   mRenderThread = std::unique_ptr<GlViewRenderThread>(new GlViewRenderThread(mNativeImageQueue));
172   if(!mRenderThread)
173   {
174     DALI_LOG_ERROR("Fail to create GlView Render Thread!!!!\n");
175     return;
176   }
177
178   //Adding VisibilityChange Signal.
179   self.InheritedVisibilityChangedSignal().Connect(this, &GlView::OnControlInheritedVisibilityChanged);
180 }
181
182 void GlView::OnSizeSet(const Vector3& targetSize)
183 {
184   Control::OnSizeSet(targetSize);
185
186   if(mRenderThread)
187   {
188     if(mNativeImageQueue)
189     {
190       mRenderThread->AcquireSurface();
191       mNativeImageQueue->SetSize(static_cast<uint32_t>(targetSize.x), static_cast<uint32_t>(targetSize.y));
192       mRenderThread->SetSurfaceSize(Vector2(targetSize.x, targetSize.y));
193       mRenderThread->ReleaseSurface();
194     }
195   }
196 }
197
198 Shader GlView::CreateShader()
199 {
200   std::string fragmentShader = std::string(SHADER_GL_VIEW_FRAG);
201
202   if(mNativeImageQueue)
203   {
204     mNativeImageQueue->ApplyNativeFragmentShader(fragmentShader);
205   }
206
207   return Shader::New(SHADER_GL_VIEW_VERT, fragmentShader, Shader::Hint::NONE, "GL_VIEW");
208 }
209
210 void GlView::OnControlInheritedVisibilityChanged(Dali::Actor actor, bool visible)
211 {
212   Actor self = Self();
213   if(mRenderThread)
214   {
215     if(visible && DevelWindow::Get(self).IsVisible())
216     {
217       mRenderThread->Resume();
218     }
219     else
220     {
221       mRenderThread->Pause();
222     }
223   }
224 }
225
226 void GlView::OnWindowVisibilityChanged(Window window, bool visible)
227 {
228   if(mRenderThread)
229   {
230     if(visible && Self().GetProperty<bool>(Actor::Property::VISIBLE))
231     {
232       mRenderThread->Resume();
233     }
234     else
235     {
236       mRenderThread->Pause();
237     }
238   }
239 }
240
241 void GlView::OnSceneConnection(int depth)
242 {
243   Control::OnSceneConnection(depth);
244
245   Actor  self   = Self();
246   Window window = DevelWindow::Get(self);
247
248   if(window)
249   {
250     mPlacementWindow = window;
251     DevelWindow::VisibilityChangedSignal(window).Connect(this, &GlView::OnWindowVisibilityChanged);
252   }
253 }
254
255 void GlView::OnSceneDisconnection()
256 {
257   Control::OnSceneDisconnection();
258   Window window = mPlacementWindow.GetHandle();
259   if(window)
260   {
261     DevelWindow::VisibilityChangedSignal(window).Disconnect(this, &GlView::OnWindowVisibilityChanged);
262     mPlacementWindow.Reset();
263   }
264 }
265
266 Dali::Geometry GlView::CreateTexturedQuad()
267 {
268   struct Vertex
269   {
270     Dali::Vector2 position;
271   };
272
273   static const Vertex data[] = {{Dali::Vector2(-0.5f, -0.5f)},
274                                 {Dali::Vector2(0.5f, -0.5f)},
275                                 {Dali::Vector2(-0.5f, 0.5f)},
276                                 {Dali::Vector2(0.5f, 0.5f)}};
277
278   uint32_t numberOfVertices = sizeof(data) / sizeof(Vertex);
279
280   Dali::VertexBuffer  vertexBuffer;
281   Dali::Property::Map vertexFormat;
282   vertexFormat["aPosition"] = Dali::Property::VECTOR2;
283
284   //Create a vertex buffer for vertex positions and texture coordinates
285   vertexBuffer = Dali::VertexBuffer::New(vertexFormat);
286   vertexBuffer.SetData(data, numberOfVertices);
287
288   //Create the geometry
289   Dali::Geometry geometry = Dali::Geometry::New();
290   geometry.AddVertexBuffer(vertexBuffer);
291   geometry.SetType(Dali::Geometry::TRIANGLE_STRIP);
292
293   return geometry;
294 }
295
296 void GlView::AddRenderer()
297 {
298   if(!mNativeImageQueue)
299   {
300     DALI_LOG_ERROR("Target Surface is NULL");
301     return;
302   }
303
304   Actor    self     = Self();
305   Geometry geometry = CreateTexturedQuad();
306   Shader   shader   = CreateShader();
307   Renderer renderer = Renderer::New(geometry, shader);
308
309   Texture    nativeTexture = Texture::New(*mNativeImageQueue);
310   TextureSet textureSet    = TextureSet::New();
311   textureSet.SetTexture(0u, nativeTexture);
312
313   renderer.SetTextures(textureSet);
314
315   self.AddRenderer(renderer);
316 }
317
318 Dali::NativeImageSourceQueue::ColorFormat GlView::GetColorFormat(Dali::Toolkit::GlView::ColorFormat format)
319 {
320   switch(format)
321   {
322     case Toolkit::GlView::ColorFormat::RGBA8888:
323     {
324       return Dali::NativeImageSourceQueue::ColorFormat::RGBA8888;
325     }
326
327     case Toolkit::GlView::ColorFormat::RGB888:
328     default:
329     {
330       return Dali::NativeImageSourceQueue::ColorFormat::RGBX8888;
331     }
332   }
333 }
334
335 } // namespace Internal
336
337 } // namespace Toolkit
338
339 } // namespace Dali