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