Merge "Change RegisterGlCallback function name of GlView" into devel/master
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / gl-view / gl-view-impl.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
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   GlView*               impl   = new 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 : Control(ControlBehaviour(ACTOR_BEHAVIOUR_DEFAULT | DISABLE_STYLE_CHANGE_SIGNALS)),
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::OnInitialize()
151 {
152   //Create NativeImageSourceQueue with the size of 1,1
153   mNativeImageQueue = Dali::NativeImageSourceQueue::New(1, 1, GetColorFormat(mColorFormat));
154
155   if(!mNativeImageQueue)
156   {
157     DALI_LOG_ERROR("NativeImageSourceQueue is NULL");
158     return;
159   }
160
161   AddRenderer();
162
163   Actor self = Self();
164
165   //Create a RenderThread
166   mRenderThread = std::unique_ptr<GlViewRenderThread>(new GlViewRenderThread(mNativeImageQueue));
167   if(!mRenderThread)
168   {
169     DALI_LOG_ERROR("Fail to create GlView Render Thread!!!!\n");
170     return;
171   }
172
173   //Adding VisibilityChange Signal.
174   Dali::DevelActor::VisibilityChangedSignal(self).Connect(this, &GlView::OnControlVisibilityChanged);
175 }
176
177 void GlView::OnSizeSet(const Vector3& targetSize)
178 {
179   Control::OnSizeSet(targetSize);
180
181   if(mRenderThread)
182   {
183     if(mNativeImageQueue)
184     {
185       mRenderThread->AcquireSurface();
186       mNativeImageQueue->SetSize(static_cast<uint32_t>(targetSize.x), static_cast<uint32_t>(targetSize.y));
187       mRenderThread->SetSurfaceSize(Vector2(targetSize.x, targetSize.y));
188       mRenderThread->ReleaseSurface();
189     }
190   }
191 }
192
193 Shader GlView::CreateShader()
194 {
195   std::string fragmentShader = std::string(SHADER_GL_VIEW_FRAG);
196
197   if(mNativeImageQueue)
198   {
199     mNativeImageQueue->ApplyNativeFragmentShader(fragmentShader);
200   }
201
202   return Shader::New(SHADER_GL_VIEW_VERT, fragmentShader);
203 }
204
205 void GlView::OnControlVisibilityChanged(Dali::Actor actor, bool visible, Dali::DevelActor::VisibilityChange::Type type)
206 {
207   Actor self = Self();
208   if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
209   {
210     if(mRenderThread)
211     {
212       if(visible && DevelWindow::Get(self).IsVisible())
213       {
214         mRenderThread->Resume();
215       }
216       else
217       {
218         mRenderThread->Pause();
219       }
220     }
221   }
222 }
223
224 void GlView::OnWindowVisibilityChanged(Window window, bool visible)
225 {
226   if(mRenderThread)
227   {
228     if(visible && Self().GetProperty<bool>(Actor::Property::VISIBLE))
229     {
230       mRenderThread->Resume();
231     }
232     else
233     {
234       mRenderThread->Pause();
235     }
236   }
237 }
238
239 void GlView::OnSceneConnection(int depth)
240 {
241   Control::OnSceneConnection(depth);
242
243   Actor  self   = Self();
244   Window window = DevelWindow::Get(self);
245
246   if(window)
247   {
248     DevelWindow::VisibilityChangedSignal(window).Connect(this, &GlView::OnWindowVisibilityChanged);
249   }
250
251   if(mRenderThread)
252   {
253     if(self.GetProperty<bool>(Actor::Property::VISIBLE) && window.IsVisible())
254     {
255       mRenderThread->Resume();
256     }
257   }
258 }
259
260 void GlView::OnSceneDisconnection()
261 {
262   Control::OnSceneDisconnection();
263   if(mRenderThread)
264   {
265     mRenderThread->Pause();
266   }
267 }
268
269 Dali::Geometry GlView::CreateTexturedQuad()
270 {
271   struct Vertex
272   {
273     Dali::Vector2 position;
274   };
275
276   static const Vertex data[] = {{Dali::Vector2(-0.5f, -0.5f)},
277                                 {Dali::Vector2(0.5f, -0.5f)},
278                                 {Dali::Vector2(-0.5f, 0.5f)},
279                                 {Dali::Vector2(0.5f, 0.5f)}};
280
281   uint32_t numberOfVertices = sizeof(data) / sizeof(Vertex);
282
283   Dali::VertexBuffer  vertexBuffer;
284   Dali::Property::Map vertexFormat;
285   vertexFormat["aPosition"] = Dali::Property::VECTOR2;
286
287   //Create a vertex buffer for vertex positions and texture coordinates
288   vertexBuffer = Dali::VertexBuffer::New(vertexFormat);
289   vertexBuffer.SetData(data, numberOfVertices);
290
291   //Create the geometry
292   Dali::Geometry geometry = Dali::Geometry::New();
293   geometry.AddVertexBuffer(vertexBuffer);
294   geometry.SetType(Dali::Geometry::TRIANGLE_STRIP);
295
296   return geometry;
297 }
298
299 void GlView::AddRenderer()
300 {
301   if(!mNativeImageQueue)
302   {
303     DALI_LOG_ERROR("Target Surface is NULL");
304     return;
305   }
306
307   Actor    self     = Self();
308   Geometry geometry = CreateTexturedQuad();
309   Shader   shader   = CreateShader();
310   Renderer renderer = Renderer::New(geometry, shader);
311
312   Texture    nativeTexture = Texture::New(*mNativeImageQueue);
313   TextureSet textureSet    = TextureSet::New();
314   textureSet.SetTexture(0u, nativeTexture);
315
316   renderer.SetTextures(textureSet);
317
318   self.AddRenderer(renderer);
319 }
320
321 Dali::NativeImageSourceQueue::ColorFormat GlView::GetColorFormat(Dali::Toolkit::GlView::ColorFormat format)
322 {
323   switch(format)
324   {
325     case Toolkit::GlView::ColorFormat::RGBA8888:
326     {
327       return Dali::NativeImageSourceQueue::ColorFormat::RGBA8888;
328     }
329
330     case Toolkit::GlView::ColorFormat::RGB888:
331     default:
332     {
333       return Dali::NativeImageSourceQueue::ColorFormat::RGBX8888;
334     }
335   }
336 }
337
338 } // namespace Internal
339
340 } // namespace Toolkit
341
342 } // namespace Dali