2 * Copyright (c) 2018 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/internal/window-system/tizen-wayland/window-render-surface-ecore-wl.h>
22 #include <dali/integration-api/gl-abstraction.h>
23 #include <dali/integration-api/debug.h>
26 #include <dali/internal/window-system/tizen-wayland/wl-types.h>
27 #include <dali/internal/graphics/gles20/egl-implementation.h>
28 #include <dali/internal/adaptor/common/adaptor-impl.h>
29 #include <dali/integration-api/trigger-event-factory-interface.h>
41 const int MINIMUM_DIMENSION_CHANGE( 1 ); ///< Minimum change for window to be considered to have moved
43 #if defined(DEBUG_ENABLED)
44 Debug::Filter* gWindowRenderSurfaceLogFilter = Debug::Filter::New(Debug::Verbose, false, "LOG_WINDOW_RENDER_SURFACE_ECORE_WL");
47 } // unnamed namespace
49 WindowRenderSurfaceEcoreWl::WindowRenderSurfaceEcoreWl( Dali::PositionSize positionSize,
51 const std::string& name,
54 mPositionSize( positionSize ),
58 mThreadSynchronization( NULL ),
59 mRenderNotification( NULL ),
60 mRotationTrigger( NULL ),
61 mColorDepth( isTransparent ? COLOR_DEPTH_32 : COLOR_DEPTH_24 ),
63 mScreenRotationAngle( 0 ),
65 mRotationSupported( false ),
66 mRotationFinished( true ),
67 mScreenRotationFinished( true ),
68 mResizeFinished( true )
70 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "Creating Window\n" );
71 Initialize( surface );
74 WindowRenderSurfaceEcoreWl::~WindowRenderSurfaceEcoreWl()
76 if( mEglWindow != NULL )
78 wl_egl_window_destroy(mEglWindow);
84 ecore_wl_window_free( mWlWindow );
87 if( mRotationTrigger )
89 delete mRotationTrigger;
98 void WindowRenderSurfaceEcoreWl::Initialize( Any surface )
100 // see if there is a surface in Any surface
101 unsigned int surfaceId = GetSurfaceId( surface );
103 // if the surface is empty, create a new one.
106 // we own the surface about to created
107 ecore_wl_init( NULL );
113 // XLib should already be initialized so no point in calling XInitThreads
114 UseExistingRenderable( surfaceId );
118 Ecore_Wl_Window* WindowRenderSurfaceEcoreWl::GetWlWindow()
123 void WindowRenderSurfaceEcoreWl::OutputTransformed()
127 if( ecore_wl_window_ignore_output_transform_get( mWlWindow ) )
133 transform = ecore_wl_output_transform_get( ecore_wl_window_output_find( mWlWindow ) );
136 mScreenRotationAngle = transform * 90;
137 mScreenRotationFinished = false;
139 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurfaceEcoreWl::OutputTransformed: angle = %d screen rotation = %d\n", mRotationAngle, mScreenRotationAngle );
142 Any WindowRenderSurfaceEcoreWl::GetWindow()
147 void WindowRenderSurfaceEcoreWl::Map()
149 ecore_wl_window_show( mWlWindow );
152 void WindowRenderSurfaceEcoreWl::SetRenderNotification( TriggerEventInterface* renderNotification )
154 mRenderNotification = renderNotification;
157 void WindowRenderSurfaceEcoreWl::SetTransparency( bool transparent )
159 ecore_wl_window_alpha_set( mWlWindow, transparent );
162 void WindowRenderSurfaceEcoreWl::RequestRotation( int angle, int width, int height )
164 if( !mRotationSupported )
166 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurfaceEcoreWl::Rotate: Rotation is not supported!\n" );
170 if( !mRotationTrigger )
172 TriggerEventFactoryInterface& triggerFactory = Internal::Adaptor::Adaptor::GetImplementation( Adaptor::Get() ).GetTriggerEventFactoryInterface();
173 mRotationTrigger = triggerFactory.CreateTriggerEvent( MakeCallback( this, &WindowRenderSurfaceEcoreWl::ProcessRotationRequest ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER );
176 mPositionSize.width = width;
177 mPositionSize.height = height;
179 mRotationAngle = angle;
180 mRotationFinished = false;
182 ecore_wl_window_rotation_set( mWlWindow, mRotationAngle );
184 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurfaceEcoreWl::Rotate: angle = %d screen rotation = %d\n", mRotationAngle, mScreenRotationAngle );
187 PositionSize WindowRenderSurfaceEcoreWl::GetPositionSize() const
189 return mPositionSize;
192 void WindowRenderSurfaceEcoreWl::InitializeEgl( EglInterface& eglIf )
194 DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
196 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
198 eglImpl.ChooseConfig(true, mColorDepth);
201 void WindowRenderSurfaceEcoreWl::CreateEglSurface( EglInterface& eglIf )
203 DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
205 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
207 // create the EGL window
208 if( mScreenRotationAngle == 0 || mScreenRotationAngle == 180 )
210 mEglWindow = wl_egl_window_create( mWlSurface, mPositionSize.width, mPositionSize.height );
214 mEglWindow = wl_egl_window_create( mWlSurface, mPositionSize.height, mPositionSize.width );
217 EGLNativeWindowType windowType( mEglWindow );
218 eglImpl.CreateSurfaceWindow( windowType, mColorDepth );
221 wl_egl_window_capability capability = static_cast< wl_egl_window_capability >( wl_egl_window_get_capabilities( mEglWindow ) );
222 if( capability == WL_EGL_WINDOW_CAPABILITY_ROTATION_SUPPORTED )
224 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurfaceEcoreWl::CreateEglSurface: capability = %d\n", capability );
225 mRotationSupported = true;
228 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurfaceEcoreWl::CreateEglSurface: w = %d h = %d angle = %d screen rotation = %d\n", mPositionSize.width, mPositionSize.height, mRotationAngle, mScreenRotationAngle );
231 void WindowRenderSurfaceEcoreWl::DestroyEglSurface( EglInterface& eglIf )
233 DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
235 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
236 eglImpl.DestroySurface();
238 if( mEglWindow != NULL )
240 wl_egl_window_destroy(mEglWindow);
245 bool WindowRenderSurfaceEcoreWl::ReplaceEGLSurface( EglInterface& egl )
247 DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
249 if( mEglWindow != NULL )
251 wl_egl_window_destroy(mEglWindow);
255 if( mScreenRotationAngle == 0 || mScreenRotationAngle == 180 )
257 mEglWindow = wl_egl_window_create( mWlSurface, mPositionSize.width, mPositionSize.height );
261 mEglWindow = wl_egl_window_create( mWlSurface, mPositionSize.height, mPositionSize.width );
264 // Set screen rotation
265 mScreenRotationFinished = false;
267 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
268 EGLNativeWindowType windowType( mEglWindow );
269 return eglImpl.ReplaceSurfaceWindow( windowType );
272 void WindowRenderSurfaceEcoreWl::MoveResize( Dali::PositionSize positionSize )
274 bool needToMove = false;
275 bool needToResize = false;
278 if( (fabs(positionSize.x - mPositionSize.x) > MINIMUM_DIMENSION_CHANGE) ||
279 (fabs(positionSize.y - mPositionSize.y) > MINIMUM_DIMENSION_CHANGE) )
285 if( (fabs(positionSize.width - mPositionSize.width) > MINIMUM_DIMENSION_CHANGE) ||
286 (fabs(positionSize.height - mPositionSize.height) > MINIMUM_DIMENSION_CHANGE) )
293 ecore_wl_window_position_set( mWlWindow, positionSize.x, positionSize.y );
297 ecore_wl_window_update_size( mWlWindow, positionSize.width, positionSize.height );
298 mResizeFinished = false;
301 mPositionSize = positionSize;
303 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurfaceEcoreWl::MoveResize: %d, %d, %d, %d\n", mPositionSize.x, mPositionSize.y, mPositionSize.width, mPositionSize.height );
306 void WindowRenderSurfaceEcoreWl::SetViewMode( ViewMode viewMode )
310 void WindowRenderSurfaceEcoreWl::StartRender()
314 bool WindowRenderSurfaceEcoreWl::PreRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, bool resizingSurface )
316 if( resizingSurface )
318 #ifdef OVER_TIZEN_VERSION_4
319 // Window rotate or screen rotate
320 if( !mRotationFinished || !mScreenRotationFinished )
322 wl_egl_window_rotation rotation;
323 wl_output_transform bufferTransform;
324 int totalAngle = (mRotationAngle + mScreenRotationAngle) % 360;
330 rotation = ROTATION_0;
331 bufferTransform = WL_OUTPUT_TRANSFORM_NORMAL;
336 rotation = ROTATION_270;
337 bufferTransform = WL_OUTPUT_TRANSFORM_90;
342 rotation = ROTATION_180;
343 bufferTransform = WL_OUTPUT_TRANSFORM_180;
348 rotation = ROTATION_90;
349 bufferTransform = WL_OUTPUT_TRANSFORM_270;
354 rotation = ROTATION_0;
355 bufferTransform = WL_OUTPUT_TRANSFORM_NORMAL;
360 wl_egl_window_set_rotation( mEglWindow, rotation );
362 wl_egl_window_set_buffer_transform( mEglWindow, bufferTransform );
364 // Reset only screen rotation flag
365 mScreenRotationFinished = true;
367 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurfaceEcoreWl::PreRender: Set rotation [%d] [%d]\n", mRotationAngle, mScreenRotationAngle );
370 // Only window rotate
371 if( !mRotationFinished )
373 wl_output_transform windowTransform;
375 switch( mRotationAngle )
379 windowTransform = WL_OUTPUT_TRANSFORM_NORMAL;
384 windowTransform = WL_OUTPUT_TRANSFORM_90;
389 windowTransform = WL_OUTPUT_TRANSFORM_180;
394 windowTransform = WL_OUTPUT_TRANSFORM_270;
399 windowTransform = WL_OUTPUT_TRANSFORM_NORMAL;
404 wl_egl_window_set_window_transform( mEglWindow, windowTransform );
409 if( !mResizeFinished )
411 wl_egl_window_resize( mEglWindow, mPositionSize.width, mPositionSize.height, mPositionSize.x, mPositionSize.y );
412 mResizeFinished = true;
414 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurfaceEcoreWl::PreRender: Set resize\n" );
421 void WindowRenderSurfaceEcoreWl::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, bool replacingSurface, bool resizingSurface )
423 if( resizingSurface )
425 if( !mRotationFinished )
427 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurfaceEcoreWl::PostRender: Trigger rotation event\n" );
429 mRotationTrigger->Trigger();
431 if( mThreadSynchronization )
433 // Wait until the event-thread complete the rotation event processing
434 mThreadSynchronization->PostRenderWaitForCompletion();
439 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
440 eglImpl.SwapBuffers();
442 if( mRenderNotification )
444 mRenderNotification->Trigger();
448 void WindowRenderSurfaceEcoreWl::StopRender()
452 void WindowRenderSurfaceEcoreWl::SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization )
454 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurfaceEcoreWl::SetThreadSynchronization: called\n" );
456 mThreadSynchronization = &threadSynchronization;
459 void WindowRenderSurfaceEcoreWl::ReleaseLock()
464 RenderSurface::Type WindowRenderSurfaceEcoreWl::GetSurfaceType()
466 return RenderSurface::WINDOW_RENDER_SURFACE;
469 void WindowRenderSurfaceEcoreWl::CreateRenderable()
471 // if width or height are zero, go full screen.
472 if ( (mPositionSize.width == 0) || (mPositionSize.height == 0) )
474 // Default window size == screen size
478 ecore_wl_screen_size_get( &mPositionSize.width, &mPositionSize.height );
481 mWlWindow = ecore_wl_window_new( 0, mPositionSize.x, mPositionSize.y, mPositionSize.width, mPositionSize.height, ECORE_WL_WINDOW_BUFFER_TYPE_EGL_WINDOW );
483 if ( mWlWindow == 0 )
485 DALI_ASSERT_ALWAYS(0 && "Failed to create Wayland window");
488 mWlSurface = ecore_wl_window_surface_create( mWlWindow );
490 if( mColorDepth == COLOR_DEPTH_32 )
492 ecore_wl_window_alpha_set( mWlWindow, true );
496 ecore_wl_window_alpha_set( mWlWindow, false );
499 // Get output transform
500 if( !ecore_wl_window_ignore_output_transform_get( mWlWindow ) )
502 Ecore_Wl_Output* output = ecore_wl_window_output_find( mWlWindow );
504 int transform = ecore_wl_output_transform_get( output );
506 mScreenRotationAngle = transform * 90;
507 mScreenRotationFinished = false;
511 void WindowRenderSurfaceEcoreWl::UseExistingRenderable( unsigned int surfaceId )
513 mWlWindow = AnyCast< Ecore_Wl_Window* >( surfaceId );
516 unsigned int WindowRenderSurfaceEcoreWl::GetSurfaceId( Any surface ) const
518 unsigned int surfaceId = 0;
520 if( surface.Empty() == false )
522 // check we have a valid type
523 DALI_ASSERT_ALWAYS( ( (surface.GetType() == typeid (Ecore_Wl_Window *) ) )
524 && "Surface type is invalid" );
526 surfaceId = AnyCast<unsigned int>( surface );
531 void WindowRenderSurfaceEcoreWl::ProcessRotationRequest()
533 mRotationFinished = true;
535 ecore_wl_window_rotation_change_done_send( mWlWindow );
537 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurfaceEcoreWl::ProcessRotationRequest: Rotation Done\n" );
539 if( mThreadSynchronization )
541 mThreadSynchronization->PostRenderComplete();
545 } // namespace Adaptor
547 } // namespace internal