[Tizen] Support Ecore-Wayland2
[platform/core/uifw/dali-adaptor.git] / dali / internal / window-system / tizen-wayland / native-render-surface-ecore-wl.cpp
1 /*
2  * Copyright (c) 2018 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/internal/system/common/trigger-event.h>
36 #include <dali/internal/graphics/gles20/egl-implementation.h>
37 #include <dali/internal/window-system/common/display-connection.h>
38 #include <dali/integration-api/thread-synchronization-interface.h>
39
40 namespace Dali
41 {
42
43 namespace
44 {
45
46 #if defined(DEBUG_ENABLED)
47 Debug::Filter* gNativeSurfaceLogFilter = Debug::Filter::New(Debug::Verbose, false, "LOG_NATIVE_RENDER_SURFACE");
48 #endif
49
50 } // unnamed namespace
51
52 NativeRenderSurfaceEcoreWl::NativeRenderSurfaceEcoreWl( Dali::PositionSize positionSize, const std::string& name, bool isTransparent )
53 : mPosition( positionSize ),
54   mTitle( name ),
55   mRenderNotification( NULL ),
56   mColorDepth( isTransparent ? COLOR_DEPTH_32 : COLOR_DEPTH_24 ),
57   mTbmFormat( isTransparent ? TBM_FORMAT_ARGB8888 : TBM_FORMAT_RGB888 ),
58   mOwnSurface( false ),
59   mDrawableCompleted( false ),
60   mTbmQueue( NULL ),
61   mConsumeSurface( NULL ),
62   mThreadSynchronization( NULL )
63 {
64 #ifdef ECORE_WAYLAND2
65   ecore_wl2_init();
66 #else
67   ecore_wl_init( NULL );
68 #endif
69
70   CreateNativeRenderable();
71   setenv( "EGL_PLATFORM", "tbm", 1 );
72 }
73
74 NativeRenderSurfaceEcoreWl::~NativeRenderSurfaceEcoreWl()
75 {
76   // release the surface if we own one
77   if( mOwnSurface )
78   {
79     ReleaseDrawable();
80
81     if( mTbmQueue )
82     {
83       tbm_surface_queue_destroy( mTbmQueue );
84     }
85
86     DALI_LOG_INFO( gNativeSurfaceLogFilter, Debug::General, "Own tbm surface queue destroy\n" );
87   }
88
89 #ifdef ECORE_WAYLAND2
90   ecore_wl2_shutdown();
91 #else
92   ecore_wl_shutdown();
93 #endif
94 }
95
96 Any NativeRenderSurfaceEcoreWl::GetDrawable()
97 {
98   return mConsumeSurface;
99 }
100
101 void NativeRenderSurfaceEcoreWl::SetRenderNotification( TriggerEventInterface* renderNotification )
102 {
103   mRenderNotification = renderNotification;
104 }
105
106 void NativeRenderSurfaceEcoreWl::WaitUntilSurfaceReplaced()
107 {
108   ConditionalWait::ScopedLock lock( mTbmSurfaceCondition );
109   while( !mDrawableCompleted )
110   {
111     mTbmSurfaceCondition.Wait( lock );
112   }
113
114   mDrawableCompleted = false;
115 }
116
117 PositionSize NativeRenderSurfaceEcoreWl::GetPositionSize() const
118 {
119   return mPosition;
120 }
121
122 void NativeRenderSurfaceEcoreWl::GetDpi( unsigned int& dpiHorizontal, unsigned int& dpiVertical )
123 {
124   // calculate DPI
125   float xres, yres;
126
127   // 1 inch = 25.4 millimeters
128 #ifdef ECORE_WAYLAND2
129   // TODO: Application should set dpi value in wayland2
130   xres = 96;
131   yres = 96;
132 #else
133   xres = ecore_wl_dpi_get();
134   yres = ecore_wl_dpi_get();
135 #endif
136
137   dpiHorizontal = int( xres + 0.5f );  // rounding
138   dpiVertical   = int( yres + 0.5f );
139 }
140
141 void NativeRenderSurfaceEcoreWl::InitializeEgl( EglInterface& egl )
142 {
143   DALI_LOG_TRACE_METHOD( gNativeSurfaceLogFilter );
144   unsetenv( "EGL_PLATFORM" );
145
146   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
147
148   eglImpl.ChooseConfig( true, mColorDepth );
149 }
150
151 void NativeRenderSurfaceEcoreWl::CreateEglSurface( EglInterface& egl )
152 {
153   DALI_LOG_TRACE_METHOD( gNativeSurfaceLogFilter );
154
155   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
156
157   eglImpl.CreateSurfaceWindow( reinterpret_cast< EGLNativeWindowType >( mTbmQueue ), mColorDepth );
158 }
159
160 void NativeRenderSurfaceEcoreWl::DestroyEglSurface( EglInterface& egl )
161 {
162   DALI_LOG_TRACE_METHOD( gNativeSurfaceLogFilter );
163
164   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
165   eglImpl.DestroySurface();
166 }
167
168 bool NativeRenderSurfaceEcoreWl::ReplaceEGLSurface( EglInterface& egl )
169 {
170   DALI_LOG_TRACE_METHOD( gNativeSurfaceLogFilter );
171
172   if( !mTbmQueue )
173   {
174     return false;
175   }
176
177   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
178
179   return eglImpl.ReplaceSurfaceWindow( reinterpret_cast< EGLNativeWindowType >( mTbmQueue ) );
180 }
181
182 void NativeRenderSurfaceEcoreWl::MoveResize( Dali::PositionSize positionSize )
183 {
184 }
185
186 void NativeRenderSurfaceEcoreWl::SetViewMode( ViewMode viewMode )
187 {
188 }
189
190 void NativeRenderSurfaceEcoreWl::StartRender()
191 {
192 }
193
194 bool NativeRenderSurfaceEcoreWl::PreRender( EglInterface&, Integration::GlAbstraction&, bool )
195 {
196   // nothing to do for pixmaps
197   return true;
198 }
199
200 void NativeRenderSurfaceEcoreWl::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, bool replacingSurface, bool resizingSurface )
201 {
202   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
203   eglImpl.SwapBuffers();
204
205   if( mThreadSynchronization )
206   {
207     mThreadSynchronization->PostRenderStarted();
208   }
209
210   if( tbm_surface_queue_can_acquire( mTbmQueue, 1 ) )
211   {
212     if( tbm_surface_queue_acquire( mTbmQueue, &mConsumeSurface ) != TBM_SURFACE_QUEUE_ERROR_NONE )
213     {
214       DALI_LOG_ERROR( "Failed to aquire a tbm_surface\n" );
215       return;
216     }
217   }
218
219   tbm_surface_internal_ref( mConsumeSurface );
220
221   if( replacingSurface )
222   {
223     ConditionalWait::ScopedLock lock( mTbmSurfaceCondition );
224     mDrawableCompleted = true;
225     mTbmSurfaceCondition.Notify( lock );
226   }
227
228  // create damage for client applications which wish to know the update timing
229   if( !replacingSurface && mRenderNotification )
230   {
231     // use notification trigger
232     // Tell the event-thread to render the tbm_surface
233     mRenderNotification->Trigger();
234   }
235
236   if( mThreadSynchronization )
237   {
238     // wait until the event-thread completed to use the tbm_surface
239     mThreadSynchronization->PostRenderWaitForCompletion();
240   }
241
242   // release the consumed surface after post render was completed
243   ReleaseDrawable();
244 }
245
246 void NativeRenderSurfaceEcoreWl::StopRender()
247 {
248   ReleaseLock();
249 }
250
251 void NativeRenderSurfaceEcoreWl::SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization )
252 {
253   mThreadSynchronization = &threadSynchronization;
254 }
255
256 RenderSurface::Type NativeRenderSurfaceEcoreWl::GetSurfaceType()
257 {
258   return RenderSurface::NATIVE_RENDER_SURFACE;
259 }
260
261 void NativeRenderSurfaceEcoreWl::ReleaseLock()
262 {
263   if( mThreadSynchronization )
264   {
265     mThreadSynchronization->PostRenderComplete();
266   }
267 }
268
269 void NativeRenderSurfaceEcoreWl::CreateNativeRenderable()
270 {
271   // check we're creating one with a valid size
272   DALI_ASSERT_ALWAYS( mPosition.width > 0 && mPosition.height > 0 && "tbm_surface size is invalid" );
273
274   mTbmQueue = tbm_surface_queue_create( 3, mPosition.width, mPosition.height, mTbmFormat, TBM_BO_DEFAULT );
275
276   if( mTbmQueue )
277   {
278     mOwnSurface = true;
279   }
280   else
281   {
282     mOwnSurface = false;
283   }
284 }
285
286 void NativeRenderSurfaceEcoreWl::ReleaseDrawable()
287 {
288   if( mConsumeSurface )
289   {
290     tbm_surface_internal_unref( mConsumeSurface );
291
292     if( tbm_surface_internal_is_valid( mConsumeSurface ) )
293     {
294       tbm_surface_queue_release( mTbmQueue, mConsumeSurface );
295     }
296     mConsumeSurface = NULL;
297   }
298 }
299
300 } // namespace Dali