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