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