ecca85d5a664190ead3a8b5ec918b713e1354a1b
[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     if( mImpl->mConsumeSurface )
86     {
87       tbm_surface_queue_release( mImpl->mTbmQueue, mImpl->mConsumeSurface );
88       mImpl->mConsumeSurface = NULL;
89     }
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   ConditionalWait::ScopedLock lock( mImpl->mTbmSurfaceCondition );
110
111   return mImpl->mConsumeSurface;
112 }
113
114 Any NativeRenderSurface::GetSurface()
115 {
116   return Any( NULL );
117 }
118
119 void NativeRenderSurface::InitializeEgl( EglInterface& egl )
120 {
121   DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
122   unsetenv( "EGL_PLATFORM" );
123
124   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
125
126   eglImpl.ChooseConfig( true, mImpl->mColorDepth );
127 }
128
129 void NativeRenderSurface::CreateEglSurface( EglInterface& egl )
130 {
131   DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
132
133   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
134
135   eglImpl.CreateSurfaceWindow( (EGLNativeWindowType)mImpl->mTbmQueue, mImpl->mColorDepth );
136 }
137
138 void NativeRenderSurface::DestroyEglSurface( EglInterface& egl )
139 {
140   DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
141
142   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
143   eglImpl.DestroySurface();
144 }
145
146 bool NativeRenderSurface::ReplaceEGLSurface( EglInterface& egl )
147 {
148   DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
149
150   if( mImpl->mConsumeSurface )
151   {
152     tbm_surface_queue_release( mImpl->mTbmQueue, mImpl->mConsumeSurface );
153     mImpl->mConsumeSurface = NULL;
154   }
155
156   if( mImpl->mTbmQueue )
157   {
158     tbm_surface_queue_destroy( mImpl->mTbmQueue );
159   }
160
161   CreateNativeRenderable();
162
163   if( !mImpl->mTbmQueue )
164   {
165     return false;
166   }
167
168   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
169
170   return eglImpl.ReplaceSurfaceWindow( (EGLNativeWindowType)mImpl->mTbmQueue ); // reinterpret_cast does not compile
171 }
172
173 void NativeRenderSurface::StartRender()
174 {
175 }
176
177 bool NativeRenderSurface::PreRender( EglInterface&, Integration::GlAbstraction& )
178 {
179   // nothing to do for pixmaps
180   return true;
181 }
182
183 void NativeRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, bool replacingSurface )
184 {
185   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
186   eglImpl.SwapBuffers();
187
188   if( mImpl->mThreadSynchronization )
189   {
190     mImpl->mThreadSynchronization->PostRenderStarted();
191   }
192
193   if( tbm_surface_queue_can_acquire( mImpl->mTbmQueue, 1 ) )
194   {
195     if( tbm_surface_queue_acquire( mImpl->mTbmQueue, &mImpl->mConsumeSurface ) != TBM_SURFACE_QUEUE_ERROR_NONE )
196     {
197       DALI_LOG_ERROR( "Failed to aquire a tbm_surface\n" );
198       return;
199     }
200   }
201
202  // create damage for client applications which wish to know the update timing
203   if( mImpl->mRenderNotification )
204   {
205     // use notification trigger
206     // Tell the event-thread to render the tbm_surface
207     mImpl->mRenderNotification->Trigger();
208   }
209
210   if( mImpl->mThreadSynchronization )
211   {
212     // wait until the event-thread completed to use the tbm_surface
213     mImpl->mThreadSynchronization->PostRenderWaitForCompletion();
214   }
215
216   // release the consumed surface after post render was completed
217   if( mImpl->mConsumeSurface )
218   {
219     tbm_surface_queue_release( mImpl->mTbmQueue, mImpl->mConsumeSurface );
220     mImpl->mConsumeSurface = NULL;
221   }
222 }
223
224 void NativeRenderSurface::StopRender()
225 {
226   ReleaseLock();
227 }
228
229 PositionSize NativeRenderSurface::GetPositionSize() const
230 {
231   return mImpl->mPosition;
232 }
233
234 void NativeRenderSurface::MoveResize( Dali::PositionSize positionSize )
235 {
236 }
237
238 void NativeRenderSurface::SetViewMode( ViewMode viewMode )
239 {
240 }
241
242 void NativeRenderSurface::SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization )
243 {
244   mImpl->mThreadSynchronization = &threadSynchronization;
245 }
246
247 RenderSurface::Type NativeRenderSurface::GetSurfaceType()
248 {
249   return RenderSurface::NATIVE_RENDER_SURFACE;
250 }
251
252 void NativeRenderSurface::CreateNativeRenderable()
253 {
254   // check we're creating one with a valid size
255   DALI_ASSERT_ALWAYS( mImpl->mPosition.width > 0 && mImpl->mPosition.height > 0 && "Pixmap size is invalid" );
256
257   mImpl->mTbmQueue = tbm_surface_queue_create( 3, mImpl->mPosition.width, mImpl->mPosition.height, mImpl->mTbmFormat, TBM_BO_DEFAULT );
258
259   if( mImpl->mTbmQueue )
260   {
261     mImpl->mOwnSurface = true;
262   }
263   else
264   {
265     mImpl->mOwnSurface = false;
266   }
267 }
268
269 void NativeRenderSurface::ReleaseLock()
270 {
271   if( mImpl->mThreadSynchronization )
272   {
273     mImpl->mThreadSynchronization->PostRenderComplete();
274   }
275 }
276
277 } // namespace Dali