Facial animation support
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / gl-view / drawable-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/drawable-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/rendering/renderer.h>
27
28 namespace Dali::Toolkit::Internal
29 {
30 Dali::Toolkit::GlView DrawableView::New()
31 {
32   auto* impl   = new DrawableView();
33   Dali::Toolkit::GlView handle = Dali::Toolkit::GlView(*impl);
34   impl->Initialize();
35   return handle;
36 }
37
38 DrawableView::DrawableView()
39 : Dali::Toolkit::Internal::GlViewImpl( GlView::BackendMode::DIRECT_RENDERING ),
40   mRenderingMode(Toolkit::GlView::RenderingMode::CONTINUOUS),
41   mDepth(false),
42   mStencil(false),
43   mMSAA(0)
44 {
45   mRenderCallback = RenderCallback::New( this, &DrawableView::OnRenderCallback);
46 }
47
48 DrawableView::~DrawableView() = default;
49
50 void DrawableView::RegisterGlCallbacks(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback)
51 {
52   mOnInitCallback.reset( initCallback );
53   mOnRenderCallback.reset(renderFrameCallback );
54   mOnTerminateCallback. reset( terminateCallback );
55 }
56
57 void DrawableView::SetResizeCallback(CallbackBase* resizeCallback)
58 {
59   mOnResizeCallback.reset( resizeCallback );
60 }
61
62 bool DrawableView::SetGraphicsConfig(bool depth, bool stencil, int msaa, Dali::Toolkit::GlView::GraphicsApiVersion version)
63 {
64   DALI_LOG_ERROR( "DrawableView::SetGraphicsConfig() is currently not implemented");
65
66   return true;
67 }
68
69 void DrawableView::SetRenderingMode(Dali::Toolkit::GlView::RenderingMode mode)
70 {
71   mRenderingMode    = mode;
72   Renderer renderer = Self().GetRendererAt(0);
73
74   if(mRenderingMode == Dali::Toolkit::GlView::RenderingMode::ON_DEMAND)
75   {
76     renderer.SetProperty(DevelRenderer::Property::RENDERING_BEHAVIOR, DevelRenderer::Rendering::IF_REQUIRED);
77   }
78   else
79   {
80     renderer.SetProperty(DevelRenderer::Property::RENDERING_BEHAVIOR, DevelRenderer::Rendering::CONTINUOUSLY);
81   }
82 }
83
84 Dali::Toolkit::GlView::RenderingMode DrawableView::GetRenderingMode() const
85 {
86   return mRenderingMode;
87 }
88
89 void DrawableView::RenderOnce()
90 {
91   // Ignored.
92   // TODO: without rendering on the separate thread the RenderOnce won't
93   // work as expected. Potential implementation of threading may enable that
94   // feature.
95 }
96
97 void DrawableView::OnInitialize()
98 {
99   AddRenderer();
100
101   // Adding VisibilityChange Signal.
102   Actor self = Self();
103   Dali::DevelActor::VisibilityChangedSignal(self).Connect(this, &DrawableView::OnControlVisibilityChanged);
104 }
105
106 void DrawableView::OnSizeSet(const Vector3& targetSize)
107 {
108   Control::OnSizeSet(targetSize);
109
110   mSurfaceSize = targetSize;
111
112   // If the callbacks are set then schedule execution of resize callback
113   if(mRenderCallback && mOnResizeCallback)
114   {
115     mSurfaceResized = true;
116   }
117 }
118
119 void DrawableView::OnControlVisibilityChanged(Dali::Actor actor, bool visible, Dali::DevelActor::VisibilityChange::Type type)
120 {
121   // Ignored due to lack dedicated rendering thread
122 }
123
124 void DrawableView::OnWindowVisibilityChanged(Window window, bool visible)
125 {
126   // Ignored due to lack dedicated rendering thread
127 }
128
129 void DrawableView::OnSceneConnection(int depth)
130 {
131   Control::OnSceneConnection(depth);
132
133   Actor  self   = Self();
134   Window window = DevelWindow::Get(self);
135
136   // Despite OnWindowVisibilityChanged() is ignored it still should follow
137   // the designed behaviour of GlView so signal is connected regardless
138   if(window)
139   {
140     DevelWindow::VisibilityChangedSignal(window).Connect(this, &DrawableView::OnWindowVisibilityChanged);
141   }
142 }
143
144 void DrawableView::OnSceneDisconnection()
145 {
146   Control::OnSceneDisconnection();
147 }
148
149 void DrawableView::AddRenderer()
150 {
151   Actor    self     = Self();
152   Renderer renderer = Renderer::New( *mRenderCallback );
153   self.AddRenderer(renderer);
154 }
155
156 bool DrawableView::OnRenderCallback( const RenderCallbackInput& renderCallbackInput )
157 {
158   // Init state
159   if( mCurrentViewState == ViewState::INIT )
160   {
161     if(mOnInitCallback)
162     {
163       CallbackBase::Execute(*mOnInitCallback);
164     }
165     mCurrentViewState = ViewState::RENDER;
166   }
167
168   int renderFrameResult = 0;
169   if( mCurrentViewState == ViewState::RENDER )
170   {
171     // The mSurfaceResized is set by another thread so atomic check must be provided
172     bool expected{ true };
173     if(mSurfaceResized.compare_exchange_weak( expected, false,
174                                              std::memory_order_release,
175                                              std::memory_order_relaxed
176                                              ) && mOnResizeCallback)
177     {
178       CallbackBase::Execute(*mOnResizeCallback, static_cast<int>(mSurfaceSize.x), static_cast<int>(mSurfaceSize.y));
179     }
180
181     if(mOnRenderCallback)
182     {
183       renderFrameResult = CallbackBase::ExecuteReturn<int>(*mOnRenderCallback);
184       if(renderFrameResult)
185       {
186         // TODO: may be utilized for RenderOnce feature
187       }
188     }
189   }
190
191   // The terminate callback isn't easy to implement for DR. The NativeImage backend
192   // calls it when the GlView is being destroyed. For DrawableView it means that
193   // the RenderCallback won't be executed (as it is a part of graphics pipeline).
194   // We don't have currenty no way to know whether the View will be destroyed and
195   // to execute last native draw command in the pipeline.
196   //
197   // else if( mCurrentViewState == ViewState::TERMINATE )
198   // {
199   //    CallbackBase::Execute(*mOnTerminateCallback);
200   // }
201
202   return true;
203 }
204
205 } // namespace Dali