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/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/integration-api/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>
34 #if defined(DEBUG_ENABLED)
35 extern Debug::Filter* gRenderSurfaceLogFilter;
44 const int MINIMUM_DIMENSION_CHANGE( 1 ); ///< Minimum change for window to be considered to have moved
46 } // unnamed namespace
48 WindowRenderSurface::WindowRenderSurface( Dali::PositionSize positionSize,
50 const std::string& name,
52 : EcoreWlRenderSurface( positionSize, surface, name, isTransparent ),
54 mEcore_Wl2_display( NULL ),
57 mThreadSynchronization( NULL ),
58 mRotationTrigger( NULL ),
60 mScreenRotationAngle( 0 ),
61 mRotationSupported( false ),
62 mRotationFinished( true ),
63 mScreenRotationFinished( true ),
64 mResizeFinished( true )
66 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "Creating Window\n" );
70 WindowRenderSurface::~WindowRenderSurface()
72 if( mEglWindow != NULL )
74 DALI_LOG_RELEASE_INFO("Egl window is destroyed by wl2 WindowRenderSurface Destructor\n");
75 wl_egl_window_destroy(mEglWindow);
81 ecore_wl2_window_free( mWlWindow );
84 if( mRotationTrigger )
86 delete mRotationTrigger;
91 Ecore_Wl2_Window* WindowRenderSurface::GetDrawable()
93 // already an e-core type
97 Any WindowRenderSurface::GetSurface()
99 // already an e-core type
100 return Any( mWlWindow );
103 Ecore_Wl2_Window* WindowRenderSurface::GetWlWindow()
108 void WindowRenderSurface::RequestRotation( int angle, int width, int height )
110 if( !mRotationSupported )
112 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::Rotate: Rotation is not supported!\n" );
116 if( !mRotationTrigger )
118 TriggerEventFactoryInterface& triggerFactory = Internal::Adaptor::Adaptor::GetImplementation( Adaptor::Get() ).GetTriggerEventFactoryInterface();
119 mRotationTrigger = triggerFactory.CreateTriggerEvent( MakeCallback( this, &WindowRenderSurface::ProcessRotationRequest ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER );
122 mPositionSize.width = width;
123 mPositionSize.height = height;
125 mRotationAngle = angle;
126 mRotationFinished = false;
128 ecore_wl2_window_rotation_set( mWlWindow, mRotationAngle );
130 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::Rotate: angle = %d screen rotation = %d\n", mRotationAngle, mScreenRotationAngle );
133 void WindowRenderSurface::OutputTransformed()
137 if( ecore_wl2_window_ignore_output_transform_get( mWlWindow ) )
143 transform = ecore_wl2_output_transform_get( ecore_wl2_window_output_find( mWlWindow ) );
146 mScreenRotationAngle = transform * 90;
147 mScreenRotationFinished = false;
149 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::OutputTransformed: angle = %d screen rotation = %d\n", mRotationAngle, mScreenRotationAngle );
152 void WindowRenderSurface::SetTransparency( bool transparent )
154 ecore_wl2_window_alpha_set( mWlWindow, transparent );
157 void WindowRenderSurface::InitializeEgl( EglInterface& eglIf )
159 DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
161 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
163 eglImpl.ChooseConfig(true, mColorDepth);
166 void WindowRenderSurface::CreateEglSurface( EglInterface& eglIf )
168 DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
170 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
172 // create the EGL window
173 if( mScreenRotationAngle == 0 || mScreenRotationAngle == 180 )
175 mEglWindow = wl_egl_window_create( mWlSurface, mPositionSize.width, mPositionSize.height );
179 mEglWindow = wl_egl_window_create( mWlSurface, mPositionSize.height, mPositionSize.width );
182 EGLNativeWindowType windowType( mEglWindow );
183 eglImpl.CreateSurfaceWindow( windowType, mColorDepth );
186 wl_egl_window_capability capability = static_cast< wl_egl_window_capability >( wl_egl_window_get_capabilities( mEglWindow ) );
187 if( capability == WL_EGL_WINDOW_CAPABILITY_ROTATION_SUPPORTED )
189 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::CreateEglSurface: capability = %d\n", capability );
190 mRotationSupported = true;
193 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::CreateEglSurface: w = %d h = %d angle = %d screen rotation = %d\n", mPositionSize.width, mPositionSize.height, mRotationAngle, mScreenRotationAngle );
196 void WindowRenderSurface::DestroyEglSurface( EglInterface& eglIf )
198 DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
200 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
201 eglImpl.DestroySurface();
203 if( mEglWindow != NULL )
205 DALI_LOG_RELEASE_INFO("Egl window is destroyed by wl2 WindowRenderSurface::DestroyEglSurface()\n");
206 wl_egl_window_destroy(mEglWindow);
211 bool WindowRenderSurface::ReplaceEGLSurface( EglInterface& egl )
213 DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
215 if( mEglWindow != NULL )
217 DALI_LOG_RELEASE_INFO("Egl window is destroyed by wl2 WindowRenderSurface::ReplaceEGLSurface()\n");
218 wl_egl_window_destroy(mEglWindow);
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 // Set screen rotation
232 mScreenRotationFinished = false;
234 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
235 EGLNativeWindowType windowType( mEglWindow );
236 return eglImpl.ReplaceSurfaceWindow( windowType );
239 void WindowRenderSurface::MoveResize( Dali::PositionSize positionSize )
241 bool needToMove = false;
242 bool needToResize = false;
245 if( (fabs(positionSize.x - mPositionSize.x) > MINIMUM_DIMENSION_CHANGE) ||
246 (fabs(positionSize.y - mPositionSize.y) > MINIMUM_DIMENSION_CHANGE) )
252 if( (fabs(positionSize.width - mPositionSize.width) > MINIMUM_DIMENSION_CHANGE) ||
253 (fabs(positionSize.height - mPositionSize.height) > MINIMUM_DIMENSION_CHANGE) )
258 if( needToMove || needToResize )
260 ecore_wl2_window_geometry_set( mWlWindow, positionSize.x, positionSize.y, positionSize.width, positionSize.height );
263 mResizeFinished = false;
267 mPositionSize = positionSize;
269 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::MoveResize: %d, %d, %d, %d\n", mPositionSize.x, mPositionSize.y, mPositionSize.width, mPositionSize.height );
272 void WindowRenderSurface::Map()
274 ecore_wl2_window_show(mWlWindow);
277 void WindowRenderSurface::StartRender()
281 bool WindowRenderSurface::PreRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, bool resizingSurface )
283 if( resizingSurface )
285 #ifdef OVER_TIZEN_VERSION_4
286 // Window rotate or screen rotate
287 if( !mRotationFinished || !mScreenRotationFinished )
289 wl_egl_window_rotation rotation;
290 wl_output_transform bufferTransform;
291 int totalAngle = (mRotationAngle + mScreenRotationAngle) % 360;
297 rotation = ROTATION_0;
298 bufferTransform = WL_OUTPUT_TRANSFORM_NORMAL;
303 rotation = ROTATION_270;
304 bufferTransform = WL_OUTPUT_TRANSFORM_90;
309 rotation = ROTATION_180;
310 bufferTransform = WL_OUTPUT_TRANSFORM_180;
315 rotation = ROTATION_90;
316 bufferTransform = WL_OUTPUT_TRANSFORM_270;
321 rotation = ROTATION_0;
322 bufferTransform = WL_OUTPUT_TRANSFORM_NORMAL;
327 wl_egl_window_set_rotation( mEglWindow, rotation );
329 wl_egl_window_set_buffer_transform( mEglWindow, bufferTransform );
331 // Reset only screen rotation flag
332 mScreenRotationFinished = true;
334 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PreRender: Set rotation [%d] [%d]\n", mRotationAngle, mScreenRotationAngle );
337 // Only window rotate
338 if( !mRotationFinished )
340 wl_output_transform windowTransform;
342 switch( mRotationAngle )
346 windowTransform = WL_OUTPUT_TRANSFORM_NORMAL;
351 windowTransform = WL_OUTPUT_TRANSFORM_90;
356 windowTransform = WL_OUTPUT_TRANSFORM_180;
361 windowTransform = WL_OUTPUT_TRANSFORM_270;
366 windowTransform = WL_OUTPUT_TRANSFORM_NORMAL;
371 wl_egl_window_set_window_transform( mEglWindow, windowTransform );
376 if( !mResizeFinished )
378 wl_egl_window_resize( mEglWindow, mPositionSize.width, mPositionSize.height, mPositionSize.x, mPositionSize.y );
379 mResizeFinished = true;
381 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PreRender: Set resize\n" );
388 void WindowRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, bool replacingSurface, bool resizingSurface )
390 if( resizingSurface )
392 if( !mRotationFinished )
394 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PostRender: Trigger rotation event\n" );
396 mRotationTrigger->Trigger();
398 if( mThreadSynchronization )
400 // Wait until the event-thread complete the rotation event processing
401 mThreadSynchronization->PostRenderWaitForCompletion();
406 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
407 eglImpl.SwapBuffers();
409 if( mRenderNotification )
411 mRenderNotification->Trigger();
415 void WindowRenderSurface::StopRender()
419 void WindowRenderSurface::SetViewMode( ViewMode viewMode )
424 void WindowRenderSurface::CreateWlRenderable()
427 // use default display name as getenv("WAYLAND_DISPLAY")
428 // If specific name is needed,
429 // the name will be changed and should change the code of using ecore_wl2_connected_display_get()
430 // Because default name is used in ecore_wl2_connected_display_get()'s use case.
431 if ( mEcore_Wl2_display == NULL )
433 mEcore_Wl2_display = ecore_wl2_display_connect(NULL);
435 if ( mEcore_Wl2_display == NULL )
437 DALI_LOG_ERROR("Fail to connect ecore_wl2_display");
441 // if width or height are zero, go full screen.
442 if ( (mPositionSize.width == 0) || (mPositionSize.height == 0) )
444 // Default window size == screen size
448 ecore_wl2_display_screen_size_get( mEcore_Wl2_display, &mPositionSize.width, &mPositionSize.height );
451 mWlWindow = ecore_wl2_window_new( mEcore_Wl2_display, NULL, mPositionSize.x, mPositionSize.y, mPositionSize.width, mPositionSize.height );
452 if ( mWlWindow == 0 )
454 DALI_ASSERT_ALWAYS(0 && "Failed to create Wayland window");
457 mWlSurface = ecore_wl2_window_surface_get( mWlWindow );
459 if( mColorDepth == COLOR_DEPTH_32 )
461 ecore_wl2_window_alpha_set( mWlWindow, true );
465 ecore_wl2_window_alpha_set( mWlWindow, false );
468 ecore_wl2_window_type_set( mWlWindow, ECORE_WL2_WINDOW_TYPE_TOPLEVEL);
470 // Get output transform
471 if( !ecore_wl2_window_ignore_output_transform_get( mWlWindow ) )
473 Ecore_Wl2_Output* output = ecore_wl2_window_output_find( mWlWindow );
475 int transform = ecore_wl2_output_transform_get( output );
477 mScreenRotationAngle = transform * 90;
478 mScreenRotationFinished = false;
482 void WindowRenderSurface::UseExistingRenderable( unsigned int surfaceId )
484 mWlWindow = AnyCast< Ecore_Wl2_Window* >( surfaceId );
487 void WindowRenderSurface::SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization )
489 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::SetThreadSynchronization: called\n" );
491 mThreadSynchronization = &threadSynchronization;
494 void WindowRenderSurface::ReleaseLock()
499 void WindowRenderSurface::ProcessRotationRequest()
501 mRotationFinished = true;
503 ecore_wl2_window_rotation_change_done_send( mWlWindow, mRotationAngle, mPositionSize.width, mPositionSize.height );
505 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::ProcessRotationRequest: Rotation Done\n" );
507 if( mThreadSynchronization )
509 mThreadSynchronization->PostRenderComplete();