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