a205f2eb1d90da7e8f11d9b1f04c033bfc35ec33
[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   // flush gl instruction queue
190   glAbstraction.Flush();
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 aquire consume tbm_surface\n" );
198         return;
199       }
200     }
201   }
202
203  // create damage for client applications which wish to know the update timing
204   if( mImpl->mRenderNotification )
205   {
206     // use notification trigger
207     // Tell the event-thread to render the pixmap
208     mImpl->mRenderNotification->Trigger();
209   }
210   else
211   {
212     // FIXME
213   }
214
215 }
216
217 void NativeRenderSurface::StopRender()
218 {
219   ReleaseLock();
220 }
221
222 PositionSize NativeRenderSurface::GetPositionSize() const
223 {
224   return mImpl->mPosition;
225 }
226
227 void NativeRenderSurface::MoveResize( Dali::PositionSize positionSize )
228 {
229 }
230
231 void NativeRenderSurface::SetViewMode( ViewMode viewMode )
232 {
233 }
234
235 void NativeRenderSurface::SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization )
236 {
237   mImpl->mThreadSynchronization = &threadSynchronization;
238 }
239
240 RenderSurface::Type NativeRenderSurface::GetSurfaceType()
241 {
242   return RenderSurface::NATIVE_RENDER_SURFACE;
243 }
244
245 void NativeRenderSurface::CreateNativeRenderable()
246 {
247   // check we're creating one with a valid size
248   DALI_ASSERT_ALWAYS( mImpl->mPosition.width > 0 && mImpl->mPosition.height > 0 && "Pixmap size is invalid" );
249
250   mImpl->mTbmQueue = tbm_surface_queue_create( 3, mImpl->mPosition.width, mImpl->mPosition.height, mImpl->mTbmFormat, TBM_BO_DEFAULT );
251
252   if( mImpl->mTbmQueue )
253   {
254     mImpl->mOwnSurface = true;
255   }
256   else
257   {
258     mImpl->mOwnSurface = false;
259   }
260 }
261
262 void NativeRenderSurface::ReleaseSurface()
263 {
264   if( mImpl->mConsumeSurface )
265   {
266     tbm_surface_queue_release( mImpl->mTbmQueue, mImpl->mConsumeSurface );
267     mImpl->mConsumeSurface = NULL;
268   }
269 }
270
271 void NativeRenderSurface::ReleaseLock()
272 {
273   if( mImpl->mThreadSynchronization )
274   {
275     mImpl->mThreadSynchronization->PostRenderComplete();
276   }
277 }
278
279 } // namespace Dali