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/ecore-wl2/window-render-surface-ecore-wl2.h>
22 #include <dali/integration-api/gl-abstraction.h>
23 #include <dali/integration-api/debug.h>
26 #include <dali/internal/graphics/gles20/egl-implementation.h>
27 #include <dali/internal/adaptor/common/adaptor-impl.h>
28 #include <dali/integration-api/trigger-event-factory-interface.h>
40 const int MINIMUM_DIMENSION_CHANGE( 1 ); ///< Minimum change for window to be considered to have moved
42 #if defined(DEBUG_ENABLED)
43 Debug::Filter* gWindowRenderSurfaceLogFilter = Debug::Filter::New(Debug::Verbose, false, "LOG_WINDOW_RENDER_SURFACE_ECORE_WL2");
46 } // unnamed namespace
48 WindowRenderSurfaceEcoreWl2::WindowRenderSurfaceEcoreWl2( Dali::PositionSize positionSize,
50 const std::string& name,
53 mPositionSize( positionSize ),
57 mThreadSynchronization( NULL ),
58 mRenderNotification( NULL ),
59 mRotationTrigger( NULL ),
60 mColorDepth( isTransparent ? COLOR_DEPTH_32 : COLOR_DEPTH_24 ),
62 mScreenRotationAngle( 0 ),
64 mRotationSupported( false ),
65 mRotationFinished( true ),
66 mScreenRotationFinished( true ),
67 mResizeFinished( true )
69 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "Creating Window\n" );
70 Initialize( surface );
73 WindowRenderSurfaceEcoreWl2::~WindowRenderSurfaceEcoreWl2()
75 if( mEglWindow != NULL )
77 wl_egl_window_destroy(mEglWindow);
83 ecore_wl2_window_free( mWlWindow );
86 if( mRotationTrigger )
88 delete mRotationTrigger;
97 void WindowRenderSurfaceEcoreWl2::Initialize( Any surface )
99 // see if there is a surface in Any surface
100 unsigned int surfaceId = GetSurfaceId( surface );
102 // if the surface is empty, create a new one.
105 // we own the surface about to created
112 // XLib should already be initialized so no point in calling XInitThreads
113 UseExistingRenderable( surfaceId );
117 Ecore_Wl2_Window* WindowRenderSurfaceEcoreWl2::GetWlWindow()
122 void WindowRenderSurfaceEcoreWl2::OutputTransformed()
126 if( ecore_wl2_window_ignore_output_transform_get( mWlWindow ) )
132 transform = ecore_wl2_output_transform_get( ecore_wl2_window_output_find( mWlWindow ) );
135 mScreenRotationAngle = transform * 90;
136 mScreenRotationFinished = false;
138 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurfaceEcoreWl2::OutputTransformed: angle = %d screen rotation = %d\n", mRotationAngle, mScreenRotationAngle );
141 Any WindowRenderSurfaceEcoreWl2::GetWindow()
146 void WindowRenderSurfaceEcoreWl2::Map()
148 ecore_wl2_window_show( mWlWindow );
151 void WindowRenderSurfaceEcoreWl2::SetRenderNotification( TriggerEventInterface* renderNotification )
153 mRenderNotification = renderNotification;
156 void WindowRenderSurfaceEcoreWl2::SetTransparency( bool transparent )
158 ecore_wl2_window_alpha_set( mWlWindow, transparent );
161 void WindowRenderSurfaceEcoreWl2::RequestRotation( int angle, int width, int height )
163 if( !mRotationSupported )
165 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurfaceEcoreWl2::Rotate: Rotation is not supported!\n" );
169 if( !mRotationTrigger )
171 TriggerEventFactoryInterface& triggerFactory = Internal::Adaptor::Adaptor::GetImplementation( Adaptor::Get() ).GetTriggerEventFactoryInterface();
172 mRotationTrigger = triggerFactory.CreateTriggerEvent( MakeCallback( this, &WindowRenderSurfaceEcoreWl2::ProcessRotationRequest ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER );
175 mPositionSize.width = width;
176 mPositionSize.height = height;
178 mRotationAngle = angle;
179 mRotationFinished = false;
181 ecore_wl2_window_rotation_set( mWlWindow, mRotationAngle );
183 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurfaceEcoreWl2::Rotate: angle = %d screen rotation = %d\n", mRotationAngle, mScreenRotationAngle );
186 PositionSize WindowRenderSurfaceEcoreWl2::GetPositionSize() const
188 return mPositionSize;
191 void WindowRenderSurfaceEcoreWl2::GetDpi( unsigned int& dpiHorizontal, unsigned int& dpiVertical )
196 Ecore_Wl2_Output* output = ecore_wl2_window_output_find( mWlWindow );
198 // 1 inch = 25.4 millimeters
199 xres = ecore_wl2_output_dpi_get( output );
200 yres = ecore_wl2_output_dpi_get( output );
202 dpiHorizontal = int( xres + 0.5f ); // rounding
203 dpiVertical = int( yres + 0.5f );
206 void WindowRenderSurfaceEcoreWl2::InitializeEgl( EglInterface& eglIf )
208 DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
210 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
212 eglImpl.ChooseConfig(true, mColorDepth);
215 void WindowRenderSurfaceEcoreWl2::CreateEglSurface( EglInterface& eglIf )
217 DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
219 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
221 // create the EGL window
222 if( mScreenRotationAngle == 0 || mScreenRotationAngle == 180 )
224 mEglWindow = wl_egl_window_create( mWlSurface, mPositionSize.width, mPositionSize.height );
228 mEglWindow = wl_egl_window_create( mWlSurface, mPositionSize.height, mPositionSize.width );
231 EGLNativeWindowType windowType( mEglWindow );
232 eglImpl.CreateSurfaceWindow( windowType, mColorDepth );
235 wl_egl_window_capability capability = static_cast< wl_egl_window_capability >( wl_egl_window_get_capabilities( mEglWindow ) );
236 if( capability == WL_EGL_WINDOW_CAPABILITY_ROTATION_SUPPORTED )
238 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurfaceEcoreWl2::CreateEglSurface: capability = %d\n", capability );
239 mRotationSupported = true;
242 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurfaceEcoreWl2::CreateEglSurface: w = %d h = %d angle = %d screen rotation = %d\n", mPositionSize.width, mPositionSize.height, mRotationAngle, mScreenRotationAngle );
245 void WindowRenderSurfaceEcoreWl2::DestroyEglSurface( EglInterface& eglIf )
247 DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
249 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
250 eglImpl.DestroySurface();
252 if( mEglWindow != NULL )
254 wl_egl_window_destroy(mEglWindow);
259 bool WindowRenderSurfaceEcoreWl2::ReplaceEGLSurface( EglInterface& egl )
261 DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
263 if( mEglWindow != NULL )
265 wl_egl_window_destroy(mEglWindow);
269 if( mScreenRotationAngle == 0 || mScreenRotationAngle == 180 )
271 mEglWindow = wl_egl_window_create( mWlSurface, mPositionSize.width, mPositionSize.height );
275 mEglWindow = wl_egl_window_create( mWlSurface, mPositionSize.height, mPositionSize.width );
278 // Set screen rotation
279 mScreenRotationFinished = false;
281 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
282 EGLNativeWindowType windowType( mEglWindow );
283 return eglImpl.ReplaceSurfaceWindow( windowType );
286 void WindowRenderSurfaceEcoreWl2::MoveResize( Dali::PositionSize positionSize )
288 bool needToMove = false;
289 bool needToResize = false;
292 if( (fabs(positionSize.x - mPositionSize.x) > MINIMUM_DIMENSION_CHANGE) ||
293 (fabs(positionSize.y - mPositionSize.y) > MINIMUM_DIMENSION_CHANGE) )
299 if( (fabs(positionSize.width - mPositionSize.width) > MINIMUM_DIMENSION_CHANGE) ||
300 (fabs(positionSize.height - mPositionSize.height) > MINIMUM_DIMENSION_CHANGE) )
305 if( needToMove || needToResize )
307 ecore_wl2_window_geometry_set( mWlWindow, positionSize.x, positionSize.y, positionSize.width, positionSize.height );
311 mResizeFinished = false;
315 mPositionSize = positionSize;
317 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurfaceEcoreWl2::MoveResize: %d, %d, %d, %d\n", mPositionSize.x, mPositionSize.y, mPositionSize.width, mPositionSize.height );
320 void WindowRenderSurfaceEcoreWl2::SetViewMode( ViewMode viewMode )
324 void WindowRenderSurfaceEcoreWl2::StartRender()
328 bool WindowRenderSurfaceEcoreWl2::PreRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, bool resizingSurface )
330 if( resizingSurface )
332 #ifdef OVER_TIZEN_VERSION_4
333 // Window rotate or screen rotate
334 if( !mRotationFinished || !mScreenRotationFinished )
336 wl_egl_window_rotation rotation;
337 wl_output_transform bufferTransform;
338 int totalAngle = (mRotationAngle + mScreenRotationAngle) % 360;
344 rotation = ROTATION_0;
345 bufferTransform = WL_OUTPUT_TRANSFORM_NORMAL;
350 rotation = ROTATION_270;
351 bufferTransform = WL_OUTPUT_TRANSFORM_90;
356 rotation = ROTATION_180;
357 bufferTransform = WL_OUTPUT_TRANSFORM_180;
362 rotation = ROTATION_90;
363 bufferTransform = WL_OUTPUT_TRANSFORM_270;
368 rotation = ROTATION_0;
369 bufferTransform = WL_OUTPUT_TRANSFORM_NORMAL;
374 wl_egl_window_set_rotation( mEglWindow, rotation );
376 wl_egl_window_set_buffer_transform( mEglWindow, bufferTransform );
378 // Reset only screen rotation flag
379 mScreenRotationFinished = true;
381 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurfaceEcoreWl2::PreRender: Set rotation [%d] [%d]\n", mRotationAngle, mScreenRotationAngle );
384 // Only window rotate
385 if( !mRotationFinished )
387 wl_output_transform windowTransform;
389 switch( mRotationAngle )
393 windowTransform = WL_OUTPUT_TRANSFORM_NORMAL;
398 windowTransform = WL_OUTPUT_TRANSFORM_90;
403 windowTransform = WL_OUTPUT_TRANSFORM_180;
408 windowTransform = WL_OUTPUT_TRANSFORM_270;
413 windowTransform = WL_OUTPUT_TRANSFORM_NORMAL;
418 wl_egl_window_set_window_transform( mEglWindow, windowTransform );
423 if( !mResizeFinished )
425 wl_egl_window_resize( mEglWindow, mPositionSize.width, mPositionSize.height, mPositionSize.x, mPositionSize.y );
426 mResizeFinished = true;
428 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurfaceEcoreWl2::PreRender: Set resize\n" );
435 void WindowRenderSurfaceEcoreWl2::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, bool replacingSurface, bool resizingSurface )
437 if( resizingSurface )
439 if( !mRotationFinished )
441 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurfaceEcoreWl2::PostRender: Trigger rotation event\n" );
443 mRotationTrigger->Trigger();
445 if( mThreadSynchronization )
447 // Wait until the event-thread complete the rotation event processing
448 mThreadSynchronization->PostRenderWaitForCompletion();
453 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
454 eglImpl.SwapBuffers();
456 if( mRenderNotification )
458 mRenderNotification->Trigger();
462 void WindowRenderSurfaceEcoreWl2::StopRender()
466 void WindowRenderSurfaceEcoreWl2::SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization )
468 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurfaceEcoreWl2::SetThreadSynchronization: called\n" );
470 mThreadSynchronization = &threadSynchronization;
473 void WindowRenderSurfaceEcoreWl2::ReleaseLock()
478 RenderSurface::Type WindowRenderSurfaceEcoreWl2::GetSurfaceType()
480 return RenderSurface::WINDOW_RENDER_SURFACE;
483 void WindowRenderSurfaceEcoreWl2::CreateRenderable()
485 Ecore_Wl2_Display* display = ecore_wl2_display_connect( NULL );
488 DALI_ASSERT_ALWAYS(0 && "Failed to get display");
491 // if width or height are zero, go full screen.
492 if ( (mPositionSize.width == 0) || (mPositionSize.height == 0) )
494 // Default window size == screen size
498 ecore_wl2_display_screen_size_get( display, &mPositionSize.width, &mPositionSize.height );
501 mWlWindow = ecore_wl2_window_new( display, NULL, mPositionSize.x, mPositionSize.y, mPositionSize.width, mPositionSize.height );
503 if ( mWlWindow == 0 )
505 DALI_ASSERT_ALWAYS(0 && "Failed to create Wayland window");
508 mWlSurface = ecore_wl2_window_surface_get( mWlWindow );
510 if( mColorDepth == COLOR_DEPTH_32 )
512 ecore_wl2_window_alpha_set( mWlWindow, true );
516 ecore_wl2_window_alpha_set( mWlWindow, false );
519 ecore_wl2_window_type_set( mWlWindow, ECORE_WL2_WINDOW_TYPE_TOPLEVEL );
521 // Get output transform
522 if( !ecore_wl2_window_ignore_output_transform_get( mWlWindow ) )
524 Ecore_Wl2_Output* output = ecore_wl2_window_output_find( mWlWindow );
526 int transform = ecore_wl2_output_transform_get( output );
528 mScreenRotationAngle = transform * 90;
529 mScreenRotationFinished = false;
533 void WindowRenderSurfaceEcoreWl2::UseExistingRenderable( unsigned int surfaceId )
535 mWlWindow = AnyCast< Ecore_Wl2_Window* >( surfaceId );
538 unsigned int WindowRenderSurfaceEcoreWl2::GetSurfaceId( Any surface ) const
540 unsigned int surfaceId = 0;
542 if( surface.Empty() == false )
544 // check we have a valid type
545 DALI_ASSERT_ALWAYS( ( (surface.GetType() == typeid (Ecore_Wl2_Window *) ) )
546 && "Surface type is invalid" );
548 surfaceId = AnyCast<unsigned int>( surface );
553 void WindowRenderSurfaceEcoreWl2::ProcessRotationRequest()
555 mRotationFinished = true;
557 ecore_wl2_window_rotation_change_done_send( mWlWindow, mRotationAngle, mPositionSize.width, mPositionSize.height );
559 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurfaceEcoreWl2::ProcessRotationRequest: Rotation Done\n" );
561 if( mThreadSynchronization )
563 mThreadSynchronization->PostRenderComplete();
567 } // namespace Adaptor
569 } // namespace internal