2 * Copyright (c) 2021 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali-toolkit/internal/controls/gl-view/drawable-view-impl.h>
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>
28 namespace Dali::Toolkit::Internal
30 Dali::Toolkit::GlView DrawableView::New()
32 auto* impl = new DrawableView();
33 Dali::Toolkit::GlView handle = Dali::Toolkit::GlView(*impl);
38 DrawableView::DrawableView()
39 : Dali::Toolkit::Internal::GlViewImpl( GlView::BackendMode::DIRECT_RENDERING ),
40 mRenderingMode(Toolkit::GlView::RenderingMode::CONTINUOUS),
45 mRenderCallback = RenderCallback::New( this, &DrawableView::OnRenderCallback);
48 DrawableView::~DrawableView() = default;
50 void DrawableView::RegisterGlCallbacks(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback)
52 mOnInitCallback.reset( initCallback );
53 mOnRenderCallback.reset(renderFrameCallback );
54 mOnTerminateCallback. reset( terminateCallback );
57 void DrawableView::SetResizeCallback(CallbackBase* resizeCallback)
59 mOnResizeCallback.reset( resizeCallback );
62 bool DrawableView::SetGraphicsConfig(bool depth, bool stencil, int msaa, Dali::Toolkit::GlView::GraphicsApiVersion version)
64 DALI_LOG_ERROR( "DrawableView::SetGraphicsConfig() is currently not implemented");
69 void DrawableView::SetRenderingMode(Dali::Toolkit::GlView::RenderingMode mode)
71 mRenderingMode = mode;
72 Renderer renderer = Self().GetRendererAt(0);
74 if(mRenderingMode == Dali::Toolkit::GlView::RenderingMode::ON_DEMAND)
76 renderer.SetProperty(DevelRenderer::Property::RENDERING_BEHAVIOR, DevelRenderer::Rendering::IF_REQUIRED);
80 renderer.SetProperty(DevelRenderer::Property::RENDERING_BEHAVIOR, DevelRenderer::Rendering::CONTINUOUSLY);
84 Dali::Toolkit::GlView::RenderingMode DrawableView::GetRenderingMode() const
86 return mRenderingMode;
89 void DrawableView::RenderOnce()
92 // TODO: without rendering on the separate thread the RenderOnce won't
93 // work as expected. Potential implementation of threading may enable that
97 void DrawableView::OnInitialize()
101 // Adding VisibilityChange Signal.
103 Dali::DevelActor::VisibilityChangedSignal(self).Connect(this, &DrawableView::OnControlVisibilityChanged);
106 void DrawableView::OnSizeSet(const Vector3& targetSize)
108 Control::OnSizeSet(targetSize);
110 mSurfaceSize = targetSize;
112 // If the callbacks are set then schedule execution of resize callback
113 if(mRenderCallback && mOnResizeCallback)
115 mSurfaceResized = true;
119 void DrawableView::OnControlVisibilityChanged(Dali::Actor actor, bool visible, Dali::DevelActor::VisibilityChange::Type type)
121 // Ignored due to lack dedicated rendering thread
124 void DrawableView::OnWindowVisibilityChanged(Window window, bool visible)
126 // Ignored due to lack dedicated rendering thread
129 void DrawableView::OnSceneConnection(int depth)
131 Control::OnSceneConnection(depth);
134 Window window = DevelWindow::Get(self);
136 // Despite OnWindowVisibilityChanged() is ignored it still should follow
137 // the designed behaviour of GlView so signal is connected regardless
140 DevelWindow::VisibilityChangedSignal(window).Connect(this, &DrawableView::OnWindowVisibilityChanged);
144 void DrawableView::OnSceneDisconnection()
146 Control::OnSceneDisconnection();
149 void DrawableView::AddRenderer()
152 Renderer renderer = Renderer::New( *mRenderCallback );
153 self.AddRenderer(renderer);
156 bool DrawableView::OnRenderCallback( const RenderCallbackInput& renderCallbackInput )
159 if( mCurrentViewState == ViewState::INIT )
163 CallbackBase::Execute(*mOnInitCallback);
165 mCurrentViewState = ViewState::RENDER;
168 int renderFrameResult = 0;
169 if( mCurrentViewState == ViewState::RENDER )
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)
178 CallbackBase::Execute(*mOnResizeCallback, static_cast<int>(mSurfaceSize.x), static_cast<int>(mSurfaceSize.y));
181 if(mOnRenderCallback)
183 renderFrameResult = CallbackBase::ExecuteReturn<int>(*mOnRenderCallback);
184 if(renderFrameResult)
186 // TODO: may be utilized for RenderOnce feature
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.
197 // else if( mCurrentViewState == ViewState::TERMINATE )
199 // CallbackBase::Execute(*mOnTerminateCallback);