[dali_2.3.25] Merge branch 'devel/master'
[platform/core/uifw/dali-adaptor.git] / dali / internal / window-system / tizen-wayland / native-render-surface-ecore-wl.cpp
1 /*
2  * Copyright (c) 2023 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/internal/window-system/tizen-wayland/native-render-surface-ecore-wl.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/integration-api/debug.h>
23 #include <dali/integration-api/gl-abstraction.h>
24
25 #include <tbm_bufmgr.h>
26 #include <tbm_surface_internal.h>
27
28 // INTERNAL INCLUDES
29 #include <dali/integration-api/adaptor-framework/thread-synchronization-interface.h>
30 #include <dali/internal/adaptor/common/adaptor-impl.h>
31 #include <dali/internal/adaptor/common/adaptor-internal-services.h>
32 #include <dali/internal/graphics/gles/egl-graphics.h>
33 #include <dali/internal/graphics/gles/egl-implementation.h>
34 #include <dali/internal/system/common/trigger-event.h>
35 #include <dali/internal/window-system/common/display-connection.h>
36
37 namespace Dali
38 {
39 namespace
40 {
41 #if defined(DEBUG_ENABLED)
42 Debug::Filter* gNativeSurfaceLogFilter = Debug::Filter::New(Debug::Verbose, false, "LOG_NATIVE_RENDER_SURFACE");
43 #endif
44
45 // The callback of tbm_surface_queue_add_acquirable_cb()
46 static void TbmAcquirableCallback(tbm_surface_queue_h queue, void* data)
47 {
48   NativeRenderSurfaceEcoreWl* surface = static_cast<NativeRenderSurfaceEcoreWl*>(data);
49   if(surface)
50   {
51     surface->TriggerFrameRenderedCallback();
52   }
53 }
54
55 } // unnamed namespace
56
57 NativeRenderSurfaceEcoreWl::NativeRenderSurfaceEcoreWl(SurfaceSize surfaceSize, Any surface, bool isTransparent)
58 : mRenderNotification(NULL),
59   mGraphics(NULL),
60   mEGL(nullptr),
61   mEGLSurface(nullptr),
62   mEGLContext(nullptr),
63   mOwnSurface(false),
64   mTbmQueue(NULL),
65   mThreadSynchronization(NULL)
66 {
67   if(surface.Empty())
68   {
69     mSurfaceSize = surfaceSize;
70     mColorDepth  = isTransparent ? COLOR_DEPTH_32 : COLOR_DEPTH_24;
71     mTbmFormat   = isTransparent ? TBM_FORMAT_ARGB8888 : TBM_FORMAT_RGB888;
72     CreateNativeRenderable();
73   }
74   else
75   {
76     mTbmQueue = AnyCast<tbm_surface_queue_h>(surface);
77
78     uint16_t width  = static_cast<uint16_t>(tbm_surface_queue_get_width(mTbmQueue));
79     uint16_t height = static_cast<uint16_t>(tbm_surface_queue_get_height(mTbmQueue));
80     mSurfaceSize    = SurfaceSize(width, height);
81
82     mTbmFormat = tbm_surface_queue_get_format(mTbmQueue);
83
84     mColorDepth = (mTbmFormat == TBM_FORMAT_ARGB8888) ? COLOR_DEPTH_32 : COLOR_DEPTH_24;
85   }
86 }
87
88 NativeRenderSurfaceEcoreWl::~NativeRenderSurfaceEcoreWl()
89 {
90   if(mEGLSurface)
91   {
92     DestroySurface();
93   }
94
95   // release the surface if we own one
96   if(mOwnSurface)
97   {
98     if(mTbmQueue)
99     {
100       tbm_surface_queue_destroy(mTbmQueue);
101     }
102
103     DALI_LOG_INFO(gNativeSurfaceLogFilter, Debug::General, "Own tbm surface queue destroy\n");
104   }
105 }
106
107 void NativeRenderSurfaceEcoreWl::SetRenderNotification(TriggerEventInterface* renderNotification)
108 {
109   mRenderNotification = renderNotification;
110 }
111
112 Any NativeRenderSurfaceEcoreWl::GetNativeRenderable()
113 {
114   return mTbmQueue;
115 }
116
117 void NativeRenderSurfaceEcoreWl::TriggerFrameRenderedCallback()
118 {
119   if(mFrameRenderedCallback)
120   {
121     mFrameRenderedCallback->Trigger();
122   }
123 }
124
125 void NativeRenderSurfaceEcoreWl::SetFrameRenderedCallback(CallbackBase* callback)
126 {
127   mFrameRenderedCallback = std::unique_ptr<EventThreadCallback>(new EventThreadCallback(callback));
128
129   tbm_surface_queue_error_e result = tbm_surface_queue_add_acquirable_cb(mTbmQueue, TbmAcquirableCallback, this);
130   if(result != TBM_ERROR_NONE)
131   {
132     DALI_LOG_ERROR("Failed calling tbm_surface_queue_add_acquirable_cb(), error : %x", result);
133   }
134 }
135
136 PositionSize NativeRenderSurfaceEcoreWl::GetPositionSize() const
137 {
138   return PositionSize(0, 0, static_cast<int>(mSurfaceSize.GetWidth()), static_cast<int>(mSurfaceSize.GetHeight()));
139 }
140
141 void NativeRenderSurfaceEcoreWl::GetDpi(unsigned int& dpiHorizontal, unsigned int& dpiVertical)
142 {
143   // calculate DPI
144   float xres, yres;
145
146   // 1 inch = 25.4 millimeters
147   xres = 96;
148   yres = 96;
149
150   dpiHorizontal = int(xres + 0.5f); // rounding
151   dpiVertical   = int(yres + 0.5f);
152 }
153
154 int NativeRenderSurfaceEcoreWl::GetSurfaceOrientation() const
155 {
156   return 0;
157 }
158
159 int NativeRenderSurfaceEcoreWl::GetScreenOrientation() const
160 {
161   return 0;
162 }
163
164 void NativeRenderSurfaceEcoreWl::InitializeGraphics()
165 {
166   DALI_LOG_TRACE_METHOD(gNativeSurfaceLogFilter);
167
168   mGraphics        = &mAdaptor->GetGraphicsInterface();
169   auto eglGraphics = static_cast<Internal::Adaptor::EglGraphics*>(mGraphics);
170
171   mEGL = &eglGraphics->GetEglInterface();
172
173   if(mEGLContext == NULL)
174   {
175     // Create the OpenGL context for this window
176     Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>(*mEGL);
177     eglImpl.CreateWindowContext(mEGLContext);
178
179     // Create the OpenGL surface
180     CreateSurface();
181   }
182 }
183
184 void NativeRenderSurfaceEcoreWl::CreateSurface()
185 {
186   DALI_LOG_TRACE_METHOD(gNativeSurfaceLogFilter);
187
188   auto                                  eglGraphics = static_cast<Internal::Adaptor::EglGraphics*>(mGraphics);
189   Internal::Adaptor::EglImplementation& eglImpl     = eglGraphics->GetEglImplementation();
190
191   mEGLSurface = eglImpl.CreateSurfaceWindow(reinterpret_cast<EGLNativeWindowType>(mTbmQueue), mColorDepth);
192 }
193
194 void NativeRenderSurfaceEcoreWl::DestroySurface()
195 {
196   DALI_LOG_TRACE_METHOD(gNativeSurfaceLogFilter);
197
198   auto                                  eglGraphics = static_cast<Internal::Adaptor::EglGraphics*>(mGraphics);
199   Internal::Adaptor::EglImplementation& eglImpl     = eglGraphics->GetEglImplementation();
200
201   eglImpl.DestroySurface(mEGLSurface);
202 }
203
204 bool NativeRenderSurfaceEcoreWl::ReplaceGraphicsSurface()
205 {
206   DALI_LOG_TRACE_METHOD(gNativeSurfaceLogFilter);
207
208   if(!mTbmQueue)
209   {
210     return false;
211   }
212
213   auto                                  eglGraphics = static_cast<Internal::Adaptor::EglGraphics*>(mGraphics);
214   Internal::Adaptor::EglImplementation& eglImpl     = eglGraphics->GetEglImplementation();
215
216   return eglImpl.ReplaceSurfaceWindow(reinterpret_cast<EGLNativeWindowType>(mTbmQueue), mEGLSurface, mEGLContext);
217 }
218
219 void NativeRenderSurfaceEcoreWl::MoveResize(Dali::PositionSize positionSize)
220 {
221   tbm_surface_queue_error_e error = TBM_SURFACE_QUEUE_ERROR_NONE;
222
223   error = tbm_surface_queue_reset(mTbmQueue, positionSize.width, positionSize.height, mTbmFormat);
224
225   if(error != TBM_SURFACE_QUEUE_ERROR_NONE)
226   {
227     DALI_LOG_ERROR("Failed to resize tbm_surface_queue");
228   }
229
230   mSurfaceSize.SetWidth(static_cast<uint16_t>(positionSize.width));
231   mSurfaceSize.SetHeight(static_cast<uint16_t>(positionSize.height));
232 }
233
234 void NativeRenderSurfaceEcoreWl::StartRender()
235 {
236 }
237
238 bool NativeRenderSurfaceEcoreWl::PreRender(bool resizingSurface, const std::vector<Rect<int>>& damagedRects, Rect<int>& clippingRect)
239 {
240   // Not support partial update
241   clippingRect = Rect<int32_t>(0, 0, mSurfaceSize.GetWidth(), mSurfaceSize.GetHeight());
242   return true;
243 }
244
245 void NativeRenderSurfaceEcoreWl::PostRender()
246 {
247   auto eglGraphics = static_cast<Internal::Adaptor::EglGraphics*>(mGraphics);
248   if(eglGraphics)
249   {
250     Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
251     eglImpl.SwapBuffers(mEGLSurface);
252   }
253
254   if(mRenderNotification)
255   {
256     if(mThreadSynchronization)
257     {
258       mThreadSynchronization->PostRenderStarted();
259     }
260
261     // Tell the event-thread to render the tbm_surface
262     mRenderNotification->Trigger();
263
264     if(mThreadSynchronization)
265     {
266       // wait until the event-thread completed to use the tbm_surface
267       mThreadSynchronization->PostRenderWaitForCompletion();
268     }
269   }
270 }
271
272 void NativeRenderSurfaceEcoreWl::StopRender()
273 {
274   ReleaseLock();
275 }
276
277 void NativeRenderSurfaceEcoreWl::SetThreadSynchronization(ThreadSynchronizationInterface& threadSynchronization)
278 {
279   mThreadSynchronization = &threadSynchronization;
280 }
281
282 Dali::RenderSurfaceInterface::Type NativeRenderSurfaceEcoreWl::GetSurfaceType()
283 {
284   return Dali::RenderSurfaceInterface::NATIVE_RENDER_SURFACE;
285 }
286
287 void NativeRenderSurfaceEcoreWl::MakeContextCurrent()
288 {
289   if(mEGL != nullptr)
290   {
291     mEGL->MakeContextCurrent(mEGLSurface, mEGLContext);
292   }
293 }
294
295 Integration::DepthBufferAvailable NativeRenderSurfaceEcoreWl::GetDepthBufferRequired()
296 {
297   return mGraphics ? mGraphics->GetDepthBufferRequired() : Integration::DepthBufferAvailable::FALSE;
298 }
299
300 Integration::StencilBufferAvailable NativeRenderSurfaceEcoreWl::GetStencilBufferRequired()
301 {
302   return mGraphics ? mGraphics->GetStencilBufferRequired() : Integration::StencilBufferAvailable::FALSE;
303 }
304
305 void NativeRenderSurfaceEcoreWl::ReleaseLock()
306 {
307   if(mThreadSynchronization)
308   {
309     mThreadSynchronization->PostRenderComplete();
310   }
311 }
312
313 void NativeRenderSurfaceEcoreWl::CreateNativeRenderable()
314 {
315   int width  = static_cast<int>(mSurfaceSize.GetWidth());
316   int height = static_cast<int>(mSurfaceSize.GetHeight());
317
318   // check we're creating one with a valid size
319   DALI_ASSERT_ALWAYS(width > 0 && height > 0 && "tbm_surface size is invalid");
320
321   mTbmQueue = tbm_surface_queue_create(3, width, height, mTbmFormat, TBM_BO_DEFAULT);
322
323   if(mTbmQueue)
324   {
325     mOwnSurface = true;
326   }
327   else
328   {
329     mOwnSurface = false;
330   }
331 }
332
333 } // namespace Dali