064b6a621df85904c037a287513b9ec9e0f1bfda
[platform/core/uifw/dali-adaptor.git] / dali / internal / window-system / tizen-wayland / native-render-surface-ecore-wl.cpp
1 /*
2  * Copyright (c) 2020 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/gl-abstraction.h>
23 #include <dali/integration-api/debug.h>
24
25 #ifdef ECORE_WAYLAND2
26 #include <Ecore_Wl2.h>
27 #else
28 #include <Ecore_Wayland.h>
29 #endif
30
31 #include <tbm_bufmgr.h>
32 #include <tbm_surface_internal.h>
33
34 // INTERNAL INCLUDES
35 #include <dali/integration-api/adaptor-framework/thread-synchronization-interface.h>
36 #include <dali/internal/adaptor/common/adaptor-impl.h>
37 #include <dali/internal/adaptor/common/adaptor-internal-services.h>
38 #include <dali/internal/graphics/gles/egl-graphics.h>
39 #include <dali/internal/graphics/gles/egl-implementation.h>
40 #include <dali/internal/system/common/trigger-event.h>
41 #include <dali/internal/window-system/common/display-connection.h>
42 #include <dali/internal/window-system/common/window-system.h>
43
44 namespace Dali
45 {
46
47 namespace
48 {
49
50 #if defined(DEBUG_ENABLED)
51 Debug::Filter* gNativeSurfaceLogFilter = Debug::Filter::New(Debug::Verbose, false, "LOG_NATIVE_RENDER_SURFACE");
52 #endif
53
54 } // unnamed namespace
55
56 NativeRenderSurfaceEcoreWl::NativeRenderSurfaceEcoreWl( SurfaceSize surfaceSize, Any surface, bool isTransparent )
57 : mRenderNotification( NULL ),
58   mGraphics( NULL ),
59   mEGL( nullptr ),
60   mEGLSurface( nullptr ),
61   mEGLContext( nullptr ),
62   mOwnSurface( false ),
63   mDrawableCompleted( false ),
64   mTbmQueue( NULL ),
65   mConsumeSurface( NULL ),
66   mThreadSynchronization( NULL )
67 {
68   Dali::Internal::Adaptor::WindowSystem::Initialize();
69
70   if( surface.Empty() )
71   {
72     mSurfaceSize = surfaceSize;
73     mColorDepth = isTransparent ? COLOR_DEPTH_32 : COLOR_DEPTH_24;
74     mTbmFormat = isTransparent ? TBM_FORMAT_ARGB8888 : TBM_FORMAT_RGB888;
75     CreateNativeRenderable();
76   }
77   else
78   {
79     mTbmQueue = AnyCast< tbm_surface_queue_h >( surface );
80
81     uint16_t width = static_cast<uint16_t>( tbm_surface_queue_get_width( mTbmQueue ) );
82     uint16_t height = static_cast<uint16_t>( tbm_surface_queue_get_height( mTbmQueue ) );
83     mSurfaceSize = SurfaceSize( width, height );
84
85     mTbmFormat = tbm_surface_queue_get_format( mTbmQueue );
86
87     mColorDepth = ( mTbmFormat == TBM_FORMAT_ARGB8888 ) ? COLOR_DEPTH_32 : COLOR_DEPTH_24;
88   }
89 }
90
91 NativeRenderSurfaceEcoreWl::~NativeRenderSurfaceEcoreWl()
92 {
93   if ( mEGLSurface )
94   {
95     DestroySurface();
96   }
97
98   // release the surface if we own one
99   if( mOwnSurface )
100   {
101     ReleaseDrawable();
102
103     if( mTbmQueue )
104     {
105       tbm_surface_queue_destroy( mTbmQueue );
106     }
107
108     DALI_LOG_INFO( gNativeSurfaceLogFilter, Debug::General, "Own tbm surface queue destroy\n" );
109   }
110
111   Dali::Internal::Adaptor::WindowSystem::Shutdown();
112 }
113
114 Any NativeRenderSurfaceEcoreWl::GetDrawable()
115 {
116   return mConsumeSurface;
117 }
118
119 void NativeRenderSurfaceEcoreWl::SetRenderNotification( TriggerEventInterface* renderNotification )
120 {
121   mRenderNotification = renderNotification;
122 }
123
124 void NativeRenderSurfaceEcoreWl::WaitUntilSurfaceReplaced()
125 {
126   ConditionalWait::ScopedLock lock( mTbmSurfaceCondition );
127   while( !mDrawableCompleted )
128   {
129     mTbmSurfaceCondition.Wait( lock );
130   }
131
132   mDrawableCompleted = false;
133 }
134
135 Any NativeRenderSurfaceEcoreWl::GetNativeRenderable()
136 {
137   return mTbmQueue;
138 }
139
140 PositionSize NativeRenderSurfaceEcoreWl::GetPositionSize() const
141 {
142   return PositionSize( 0, 0, static_cast<int>( mSurfaceSize.GetWidth() ), static_cast<int>( mSurfaceSize.GetHeight() ) );
143 }
144
145 void NativeRenderSurfaceEcoreWl::GetDpi( unsigned int& dpiHorizontal, unsigned int& dpiVertical )
146 {
147   // calculate DPI
148   float xres, yres;
149
150   // 1 inch = 25.4 millimeters
151 #ifdef ECORE_WAYLAND2
152   // TODO: Application should set dpi value in wayland2
153   xres = 96;
154   yres = 96;
155 #else
156   xres = ecore_wl_dpi_get();
157   yres = ecore_wl_dpi_get();
158 #endif
159
160   dpiHorizontal = int( xres + 0.5f );  // rounding
161   dpiVertical   = int( yres + 0.5f );
162 }
163
164 int NativeRenderSurfaceEcoreWl::GetOrientation() const
165 {
166   return 0;
167 }
168
169 void NativeRenderSurfaceEcoreWl::InitializeGraphics()
170 {
171   DALI_LOG_TRACE_METHOD( gNativeSurfaceLogFilter );
172
173   mGraphics = &mAdaptor->GetGraphicsInterface();
174   auto eglGraphics = static_cast<Internal::Adaptor::EglGraphics *>(mGraphics);
175
176   mEGL = &eglGraphics->GetEglInterface();
177
178   if ( mEGLContext == NULL )
179   {
180     // Create the OpenGL context for this window
181     Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>(*mEGL);
182     eglImpl.CreateWindowContext( mEGLContext );
183
184     // Create the OpenGL surface
185     CreateSurface();
186   }
187 }
188
189 void NativeRenderSurfaceEcoreWl::CreateSurface()
190 {
191   DALI_LOG_TRACE_METHOD( gNativeSurfaceLogFilter );
192
193   auto eglGraphics = static_cast<Internal::Adaptor::EglGraphics *>(mGraphics);
194   Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
195
196   mEGLSurface = eglImpl.CreateSurfaceWindow( reinterpret_cast< EGLNativeWindowType >( mTbmQueue ), mColorDepth );
197 }
198
199 void NativeRenderSurfaceEcoreWl::DestroySurface()
200 {
201   DALI_LOG_TRACE_METHOD( gNativeSurfaceLogFilter );
202
203   auto eglGraphics = static_cast<Internal::Adaptor::EglGraphics *>(mGraphics);
204   Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
205
206   eglImpl.DestroySurface( mEGLSurface );
207 }
208
209 bool NativeRenderSurfaceEcoreWl::ReplaceGraphicsSurface()
210 {
211   DALI_LOG_TRACE_METHOD( gNativeSurfaceLogFilter );
212
213   if( !mTbmQueue )
214   {
215     return false;
216   }
217
218   auto eglGraphics = static_cast<Internal::Adaptor::EglGraphics *>(mGraphics);
219   Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
220
221   return eglImpl.ReplaceSurfaceWindow( reinterpret_cast< EGLNativeWindowType >( mTbmQueue ), mEGLSurface, mEGLContext );
222 }
223
224 void NativeRenderSurfaceEcoreWl::MoveResize( Dali::PositionSize positionSize )
225 {
226   tbm_surface_queue_error_e error = TBM_SURFACE_QUEUE_ERROR_NONE;
227
228   error = tbm_surface_queue_reset( mTbmQueue, positionSize.width, positionSize.height, mTbmFormat );
229
230   if( error != TBM_SURFACE_QUEUE_ERROR_NONE )
231   {
232     DALI_LOG_ERROR( "Failed to resize tbm_surface_queue" );
233   }
234
235   mSurfaceSize.SetWidth( static_cast<uint16_t>( positionSize.width ) );
236   mSurfaceSize.SetHeight( static_cast<uint16_t>( positionSize.height ) );
237 }
238
239 void NativeRenderSurfaceEcoreWl::StartRender()
240 {
241 }
242
243 bool NativeRenderSurfaceEcoreWl::PreRender( bool resizingSurface, const std::vector<Rect<int>>& damagedRects, Rect<int>& clippingRect )
244 {
245   //TODO: Need to support partial update
246   return true;
247 }
248
249 void NativeRenderSurfaceEcoreWl::PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface, const std::vector<Rect<int>>& damagedRects )
250 {
251   auto eglGraphics = static_cast<Internal::Adaptor::EglGraphics *>(mGraphics);
252   if (eglGraphics)
253   {
254     Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
255     eglImpl.SwapBuffers( mEGLSurface, damagedRects );
256   }
257
258   if ( mOwnSurface )
259   {
260     if( mThreadSynchronization )
261     {
262       mThreadSynchronization->PostRenderStarted();
263     }
264
265     if( tbm_surface_queue_can_acquire( mTbmQueue, 1 ) )
266     {
267       if( tbm_surface_queue_acquire( mTbmQueue, &mConsumeSurface ) != TBM_SURFACE_QUEUE_ERROR_NONE )
268       {
269         DALI_LOG_ERROR( "Failed to acquire a tbm_surface\n" );
270         return;
271       }
272     }
273
274     if ( mConsumeSurface )
275     {
276       tbm_surface_internal_ref( mConsumeSurface );
277     }
278
279     if( replacingSurface )
280     {
281       ConditionalWait::ScopedLock lock( mTbmSurfaceCondition );
282       mDrawableCompleted = true;
283       mTbmSurfaceCondition.Notify( lock );
284     }
285
286    // create damage for client applications which wish to know the update timing
287     if( !replacingSurface && mRenderNotification )
288     {
289       // use notification trigger
290       // Tell the event-thread to render the tbm_surface
291       mRenderNotification->Trigger();
292     }
293
294     if( mThreadSynchronization )
295     {
296       // wait until the event-thread completed to use the tbm_surface
297       mThreadSynchronization->PostRenderWaitForCompletion();
298     }
299
300     // release the consumed surface after post render was completed
301     ReleaseDrawable();
302   }
303   else
304   {
305     // create damage for client applications which wish to know the update timing
306     if( !replacingSurface && mRenderNotification )
307     {
308       // use notification trigger
309       // Tell the event-thread to render the tbm_surface
310       mRenderNotification->Trigger();
311     }
312   }
313 }
314
315 void NativeRenderSurfaceEcoreWl::StopRender()
316 {
317   ReleaseLock();
318 }
319
320 void NativeRenderSurfaceEcoreWl::SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization )
321 {
322   mThreadSynchronization = &threadSynchronization;
323 }
324
325 Dali::RenderSurfaceInterface::Type NativeRenderSurfaceEcoreWl::GetSurfaceType()
326 {
327   return Dali::RenderSurfaceInterface::NATIVE_RENDER_SURFACE;
328 }
329
330 void NativeRenderSurfaceEcoreWl::MakeContextCurrent()
331 {
332   if ( mEGL != nullptr )
333   {
334     mEGL->MakeContextCurrent( mEGLSurface, mEGLContext );
335   }
336 }
337
338 Integration::DepthBufferAvailable NativeRenderSurfaceEcoreWl::GetDepthBufferRequired()
339 {
340   return mGraphics ? mGraphics->GetDepthBufferRequired() : Integration::DepthBufferAvailable::FALSE;
341 }
342
343 Integration::StencilBufferAvailable NativeRenderSurfaceEcoreWl::GetStencilBufferRequired()
344 {
345   return mGraphics ? mGraphics->GetStencilBufferRequired() : Integration::StencilBufferAvailable::FALSE;
346 }
347
348 void NativeRenderSurfaceEcoreWl::ReleaseLock()
349 {
350   if( mThreadSynchronization )
351   {
352     mThreadSynchronization->PostRenderComplete();
353   }
354 }
355
356 void NativeRenderSurfaceEcoreWl::CreateNativeRenderable()
357 {
358   int width = static_cast<int>( mSurfaceSize.GetWidth() );
359   int height = static_cast<int>( mSurfaceSize.GetHeight() );
360
361   // check we're creating one with a valid size
362   DALI_ASSERT_ALWAYS( width > 0 && height > 0 && "tbm_surface size is invalid" );
363
364   mTbmQueue = tbm_surface_queue_create( 3, width, height, mTbmFormat, TBM_BO_DEFAULT );
365
366   if( mTbmQueue )
367   {
368     mOwnSurface = true;
369   }
370   else
371   {
372     mOwnSurface = false;
373   }
374 }
375
376 void NativeRenderSurfaceEcoreWl::ReleaseDrawable()
377 {
378   if( mConsumeSurface )
379   {
380     tbm_surface_internal_unref( mConsumeSurface );
381
382     if( tbm_surface_internal_is_valid( mConsumeSurface ) )
383     {
384       tbm_surface_queue_release( mTbmQueue, mConsumeSurface );
385     }
386     mConsumeSurface = NULL;
387   }
388 }
389
390 } // namespace Dali