2 * Copyright (c) 2017 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 <dali/integration-api/wayland/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>
27 #include <Ecore_Wl2.h>
29 #include <Ecore_Wayland.h>
31 #include <tbm_bufmgr.h>
32 #include <tbm_surface_queue.h>
33 #include <tbm_surface_internal.h>
36 #include <dali/internal/system/common/trigger-event.h>
37 #include <dali/internal/graphics/gles20/egl-implementation.h>
38 #include <dali/internal/window-system/common/display-connection.h>
39 #include <dali/integration-api/thread-synchronization-interface.h>
44 #if defined(DEBUG_ENABLED)
45 extern Debug::Filter* gRenderSurfaceLogFilter;
48 struct NativeRenderSurface::Impl
50 Impl( Dali::PositionSize positionSize, const std::string& name, bool isTransparent )
51 : mPosition( positionSize ),
53 mRenderNotification( NULL ),
54 mColorDepth( isTransparent ? COLOR_DEPTH_32 : COLOR_DEPTH_24 ),
55 mTbmFormat( isTransparent ? TBM_FORMAT_ARGB8888 : TBM_FORMAT_RGB888 ),
57 mDrawableCompleted( false ),
59 mConsumeSurface( NULL ),
60 mThreadSynchronization( NULL )
64 PositionSize mPosition;
66 TriggerEventInterface* mRenderNotification;
67 ColorDepth mColorDepth;
68 tbm_format mTbmFormat;
70 bool mDrawableCompleted;
72 tbm_surface_queue_h mTbmQueue;
73 tbm_surface_h mConsumeSurface;
74 ThreadSynchronizationInterface* mThreadSynchronization; ///< A pointer to the thread-synchronization
75 ConditionalWait mTbmSurfaceCondition;
78 NativeRenderSurface::NativeRenderSurface(Dali::PositionSize positionSize,
79 const std::string& name,
81 : mImpl( new Impl( positionSize, name, isTransparent ) )
88 CreateNativeRenderable();
89 setenv( "EGL_PLATFORM", "tbm", 1 );
92 NativeRenderSurface::~NativeRenderSurface()
94 // release the surface if we own one
95 if( mImpl->mOwnSurface )
99 if( mImpl->mTbmQueue )
101 tbm_surface_queue_destroy( mImpl->mTbmQueue );
106 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::General, "Own tbm surface queue destroy\n" );
110 void NativeRenderSurface::SetRenderNotification( TriggerEventInterface* renderNotification )
112 mImpl->mRenderNotification = renderNotification;
115 tbm_surface_h NativeRenderSurface::GetDrawable()
117 return mImpl->mConsumeSurface;
120 Any NativeRenderSurface::GetSurface()
125 void NativeRenderSurface::InitializeEgl( EglInterface& egl )
127 DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
128 unsetenv( "EGL_PLATFORM" );
130 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
132 eglImpl.ChooseConfig( true, mImpl->mColorDepth );
135 void NativeRenderSurface::CreateEglSurface( EglInterface& egl )
137 DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
139 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
141 eglImpl.CreateSurfaceWindow( reinterpret_cast< EGLNativeWindowType >( mImpl->mTbmQueue ), mImpl->mColorDepth );
144 void NativeRenderSurface::DestroyEglSurface( EglInterface& egl )
146 DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
148 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
149 eglImpl.DestroySurface();
152 bool NativeRenderSurface::ReplaceEGLSurface( EglInterface& egl )
154 DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
156 if( !mImpl->mTbmQueue )
161 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
163 return eglImpl.ReplaceSurfaceWindow( reinterpret_cast< EGLNativeWindowType >( mImpl->mTbmQueue ) );
166 void NativeRenderSurface::StartRender()
170 bool NativeRenderSurface::PreRender( EglInterface&, Integration::GlAbstraction&, bool )
172 // nothing to do for pixmaps
176 void NativeRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, bool replacingSurface, bool resizingSurface )
178 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
179 eglImpl.SwapBuffers();
181 if( mImpl->mThreadSynchronization )
183 mImpl->mThreadSynchronization->PostRenderStarted();
186 if( tbm_surface_queue_can_acquire( mImpl->mTbmQueue, 1 ) )
188 if( tbm_surface_queue_acquire( mImpl->mTbmQueue, &mImpl->mConsumeSurface ) != TBM_SURFACE_QUEUE_ERROR_NONE )
190 DALI_LOG_ERROR( "Failed to aquire a tbm_surface\n" );
195 tbm_surface_internal_ref( mImpl->mConsumeSurface );
197 if( replacingSurface )
199 ConditionalWait::ScopedLock lock( mImpl->mTbmSurfaceCondition );
200 mImpl->mDrawableCompleted = true;
201 mImpl->mTbmSurfaceCondition.Notify( lock );
204 // create damage for client applications which wish to know the update timing
205 if( !replacingSurface && mImpl->mRenderNotification )
207 // use notification trigger
208 // Tell the event-thread to render the tbm_surface
209 mImpl->mRenderNotification->Trigger();
212 if( mImpl->mThreadSynchronization )
214 // wait until the event-thread completed to use the tbm_surface
215 mImpl->mThreadSynchronization->PostRenderWaitForCompletion();
218 // release the consumed surface after post render was completed
222 void NativeRenderSurface::StopRender()
227 PositionSize NativeRenderSurface::GetPositionSize() const
229 return mImpl->mPosition;
232 void NativeRenderSurface::MoveResize( Dali::PositionSize positionSize )
236 void NativeRenderSurface::SetViewMode( ViewMode viewMode )
240 void NativeRenderSurface::SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization )
242 mImpl->mThreadSynchronization = &threadSynchronization;
245 RenderSurface::Type NativeRenderSurface::GetSurfaceType()
247 return RenderSurface::NATIVE_RENDER_SURFACE;
250 void NativeRenderSurface::CreateNativeRenderable()
252 // check we're creating one with a valid size
253 DALI_ASSERT_ALWAYS( mImpl->mPosition.width > 0 && mImpl->mPosition.height > 0 && "tbm_surface size is invalid" );
255 mImpl->mTbmQueue = tbm_surface_queue_create( 3, mImpl->mPosition.width, mImpl->mPosition.height, mImpl->mTbmFormat, TBM_BO_DEFAULT );
257 if( mImpl->mTbmQueue )
259 mImpl->mOwnSurface = true;
263 mImpl->mOwnSurface = false;
267 void NativeRenderSurface::ReleaseLock()
269 if( mImpl->mThreadSynchronization )
271 mImpl->mThreadSynchronization->PostRenderComplete();
275 void NativeRenderSurface::WaitUntilSurfaceReplaced()
277 ConditionalWait::ScopedLock lock( mImpl->mTbmSurfaceCondition );
278 while( !mImpl->mDrawableCompleted )
280 mImpl->mTbmSurfaceCondition.Wait( lock );
283 mImpl->mDrawableCompleted = false;
286 void NativeRenderSurface::ReleaseDrawable()
288 if( mImpl->mConsumeSurface )
290 tbm_surface_internal_unref( mImpl->mConsumeSurface );
292 if( tbm_surface_internal_is_valid( mImpl->mConsumeSurface ) )
294 tbm_surface_queue_release( mImpl->mTbmQueue, mImpl->mConsumeSurface );
296 mImpl->mConsumeSurface = NULL;