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