2 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <native-render-surface.h>
22 #include <dali/integration-api/gl-abstraction.h>
23 #include <dali/integration-api/debug.h>
24 #include <dali/devel-api/threading/conditional-wait.h>
26 #include <Ecore_Wayland.h>
27 #include <tbm_bufmgr.h>
28 #include <tbm_surface_queue.h>
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>
39 #if defined(DEBUG_ENABLED)
40 extern Debug::Filter* gRenderSurfaceLogFilter;
43 struct NativeRenderSurface::Impl
45 Impl( Dali::PositionSize positionSize, const std::string& name, bool isTransparent )
46 : mPosition( positionSize ),
48 mRenderNotification( NULL ),
49 mColorDepth( isTransparent ? COLOR_DEPTH_32 : COLOR_DEPTH_24 ),
50 mTbmFormat( isTransparent ? TBM_FORMAT_ARGB8888 : TBM_FORMAT_RGB888 ),
52 mConsumeSurface( NULL ),
53 mThreadSynchronization( NULL )
57 PositionSize mPosition;
59 TriggerEventInterface* mRenderNotification;
60 ColorDepth mColorDepth;
61 tbm_format mTbmFormat;
64 tbm_surface_queue_h mTbmQueue;
65 tbm_surface_h mConsumeSurface;
66 ThreadSynchronizationInterface* mThreadSynchronization; ///< A pointer to the thread-synchronization
67 ConditionalWait mTbmSurfaceCondition;
70 NativeRenderSurface::NativeRenderSurface(Dali::PositionSize positionSize,
71 const std::string& name,
73 : mImpl( new Impl( positionSize, name, isTransparent ) )
76 CreateNativeRenderable();
77 setenv( "EGL_PLATFORM", "tbm", 1 );
80 NativeRenderSurface::~NativeRenderSurface()
82 // release the surface if we own one
83 if( mImpl->mOwnSurface )
86 if( mImpl->mConsumeSurface )
88 tbm_surface_queue_release( mImpl->mTbmQueue, mImpl->mConsumeSurface );
89 mImpl->mConsumeSurface = NULL;
92 if( mImpl->mTbmQueue )
94 tbm_surface_queue_destroy( mImpl->mTbmQueue );
99 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::General, "Own tbm surface queue destroy\n" );
103 void NativeRenderSurface::SetRenderNotification( TriggerEventInterface* renderNotification )
105 mImpl->mRenderNotification = renderNotification;
108 tbm_surface_h NativeRenderSurface::GetDrawable()
110 ConditionalWait::ScopedLock lock( mImpl->mTbmSurfaceCondition );
112 return mImpl->mConsumeSurface;
115 Any NativeRenderSurface::GetSurface()
120 void NativeRenderSurface::InitializeEgl( EglInterface& egl )
122 DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
123 unsetenv( "EGL_PLATFORM" );
125 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
127 eglImpl.ChooseConfig( true, mImpl->mColorDepth );
130 void NativeRenderSurface::CreateEglSurface( EglInterface& egl )
132 DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
134 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
136 eglImpl.CreateSurfaceWindow( (EGLNativeWindowType)mImpl->mTbmQueue, mImpl->mColorDepth );
139 void NativeRenderSurface::DestroyEglSurface( EglInterface& egl )
141 DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
143 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
144 eglImpl.DestroySurface();
147 bool NativeRenderSurface::ReplaceEGLSurface( EglInterface& egl )
149 DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
151 if( mImpl->mConsumeSurface )
153 tbm_surface_queue_release( mImpl->mTbmQueue, mImpl->mConsumeSurface );
154 mImpl->mConsumeSurface = NULL;
157 if( mImpl->mTbmQueue )
159 tbm_surface_queue_destroy( mImpl->mTbmQueue );
162 CreateNativeRenderable();
164 if( !mImpl->mTbmQueue )
169 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
171 return eglImpl.ReplaceSurfaceWindow( (EGLNativeWindowType)mImpl->mTbmQueue ); // reinterpret_cast does not compile
174 void NativeRenderSurface::StartRender()
178 bool NativeRenderSurface::PreRender( EglInterface&, Integration::GlAbstraction& )
180 // nothing to do for pixmaps
184 void NativeRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, bool replacingSurface )
186 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
187 eglImpl.SwapBuffers();
190 ConditionalWait::ScopedLock lock( mImpl->mTbmSurfaceCondition );
192 if( tbm_surface_queue_can_acquire( mImpl->mTbmQueue, 1 ) )
194 if( tbm_surface_queue_acquire( mImpl->mTbmQueue, &mImpl->mConsumeSurface ) != TBM_SURFACE_QUEUE_ERROR_NONE )
196 DALI_LOG_ERROR( "Failed aquire consume tbm_surface\n" );
202 // create damage for client applications which wish to know the update timing
203 if( mImpl->mRenderNotification )
205 // use notification trigger
206 // Tell the event-thread to render the tbm_surface
207 mImpl->mRenderNotification->Trigger();
211 void NativeRenderSurface::StopRender()
216 PositionSize NativeRenderSurface::GetPositionSize() const
218 return mImpl->mPosition;
221 void NativeRenderSurface::MoveResize( Dali::PositionSize positionSize )
225 void NativeRenderSurface::SetViewMode( ViewMode viewMode )
229 void NativeRenderSurface::SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization )
231 mImpl->mThreadSynchronization = &threadSynchronization;
234 RenderSurface::Type NativeRenderSurface::GetSurfaceType()
236 return RenderSurface::NATIVE_RENDER_SURFACE;
239 void NativeRenderSurface::CreateNativeRenderable()
241 // check we're creating one with a valid size
242 DALI_ASSERT_ALWAYS( mImpl->mPosition.width > 0 && mImpl->mPosition.height > 0 && "Pixmap size is invalid" );
244 mImpl->mTbmQueue = tbm_surface_queue_create( 3, mImpl->mPosition.width, mImpl->mPosition.height, mImpl->mTbmFormat, TBM_BO_DEFAULT );
246 if( mImpl->mTbmQueue )
248 mImpl->mOwnSurface = true;
252 mImpl->mOwnSurface = false;
256 void NativeRenderSurface::ReleaseSurface()
258 ConditionalWait::ScopedLock lock( mImpl->mTbmSurfaceCondition );
259 if( mImpl->mConsumeSurface )
261 tbm_surface_queue_release( mImpl->mTbmQueue, mImpl->mConsumeSurface );
262 mImpl->mConsumeSurface = NULL;
266 void NativeRenderSurface::ReleaseLock()
268 if( mImpl->mThreadSynchronization )
270 mImpl->mThreadSynchronization->PostRenderComplete();