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 <window-render-surface.h>
22 #include <dali/integration-api/gl-abstraction.h>
23 #include <dali/integration-api/debug.h>
27 #include <gl/egl-implementation.h>
28 #include <adaptors/common/adaptor-impl.h>
29 #include <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 ),
56 mThreadSynchronization( NULL ),
57 mRotationTrigger( NULL ),
59 mScreenRotationAngle( 0 ),
60 mRotationSupported( false ),
61 mRotationFinished( true ),
62 mScreenRotationFinished( true )
64 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "Creating Window\n" );
68 WindowRenderSurface::~WindowRenderSurface()
70 if( mEglWindow != NULL )
72 wl_egl_window_destroy(mEglWindow);
78 ecore_wl_window_free( mWlWindow );
81 if( mRotationTrigger )
83 delete mRotationTrigger;
88 Ecore_Wl_Window* WindowRenderSurface::GetDrawable()
90 // already an e-core type
94 Any WindowRenderSurface::GetSurface()
96 // already an e-core type
97 return Any( mWlWindow );
100 Ecore_Wl_Window* WindowRenderSurface::GetWlWindow()
105 void WindowRenderSurface::RequestRotation( int angle, int width, int height )
107 if( !mRotationSupported )
109 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::Rotate: Rotation is not supported!\n" );
113 if( !mRotationTrigger )
115 TriggerEventFactoryInterface& triggerFactory = Internal::Adaptor::Adaptor::GetImplementation( Adaptor::Get() ).GetTriggerEventFactoryInterface();
116 mRotationTrigger = triggerFactory.CreateTriggerEvent( MakeCallback( this, &WindowRenderSurface::ProcessRotationRequest ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER );
119 mPositionSize.width = width;
120 mPositionSize.height = height;
122 mRotationAngle = angle;
123 mRotationFinished = false;
125 ecore_wl_window_rotation_set( mWlWindow, mRotationAngle );
127 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::Rotate: angle = %d screen rotation = %d\n", mRotationAngle, mScreenRotationAngle );
130 void WindowRenderSurface::OutputTransformed()
134 if( ecore_wl_window_ignore_output_transform_get( mWlWindow ) )
140 transform = ecore_wl_output_transform_get( ecore_wl_window_output_find( mWlWindow ) );
143 mScreenRotationAngle = transform * 90;
144 mScreenRotationFinished = false;
146 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::OutputTransformed: angle = %d screen rotation = %d\n", mRotationAngle, mScreenRotationAngle );
149 void WindowRenderSurface::InitializeEgl( EglInterface& eglIf )
151 DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
153 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
155 eglImpl.ChooseConfig(true, mColorDepth);
158 void WindowRenderSurface::CreateEglSurface( EglInterface& eglIf )
160 DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
162 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
164 // create the EGL window
165 if( mScreenRotationAngle == 0 || mScreenRotationAngle == 180 )
167 mEglWindow = wl_egl_window_create( mWlSurface, mPositionSize.width, mPositionSize.height );
171 mEglWindow = wl_egl_window_create( mWlSurface, mPositionSize.height, mPositionSize.width );
174 EGLNativeWindowType windowType( mEglWindow );
175 eglImpl.CreateSurfaceWindow( windowType, mColorDepth );
177 #ifdef SCREEN_ROTATION_ENABLED
179 wl_egl_window_capability capability = static_cast< wl_egl_window_capability >( wl_egl_window_get_capabilities( mEglWindow ) );
180 if( capability == WL_EGL_WINDOW_CAPABILITY_ROTATION_SUPPORTED )
182 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::CreateEglSurface: capability = %d\n", capability );
183 mRotationSupported = true;
186 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::CreateEglSurface: w = %d h = %d angle = %d screen rotation = %d\n", mPositionSize.width, mPositionSize.height, mRotationAngle, mScreenRotationAngle );
190 void WindowRenderSurface::DestroyEglSurface( EglInterface& eglIf )
192 DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
194 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
195 eglImpl.DestroySurface();
197 if( mEglWindow != NULL )
199 wl_egl_window_destroy(mEglWindow);
204 bool WindowRenderSurface::ReplaceEGLSurface( EglInterface& egl )
206 DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
208 if( mEglWindow != NULL )
210 wl_egl_window_destroy(mEglWindow);
214 if( mScreenRotationAngle == 0 || mScreenRotationAngle == 180 )
216 mEglWindow = wl_egl_window_create( mWlSurface, mPositionSize.width, mPositionSize.height );
220 mEglWindow = wl_egl_window_create( mWlSurface, mPositionSize.height, mPositionSize.width );
223 // Set screen rotation
224 mScreenRotationFinished = false;
226 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
227 EGLNativeWindowType windowType( mEglWindow );
228 return eglImpl.ReplaceSurfaceWindow( windowType );
231 void WindowRenderSurface::MoveResize( Dali::PositionSize positionSize )
233 bool needToMove = false;
234 bool needToResize = false;
237 if( (fabs(positionSize.x - mPositionSize.x) > MINIMUM_DIMENSION_CHANGE) ||
238 (fabs(positionSize.y - mPositionSize.y) > MINIMUM_DIMENSION_CHANGE) )
244 if( (fabs(positionSize.width - mPositionSize.width) > MINIMUM_DIMENSION_CHANGE) ||
245 (fabs(positionSize.height - mPositionSize.height) > MINIMUM_DIMENSION_CHANGE) )
252 ecore_wl_window_move(mWlWindow, positionSize.x, positionSize.y);
253 mPositionSize = positionSize;
257 ecore_wl_window_resize(mWlWindow, positionSize.width, positionSize.height, 0);
258 mPositionSize = positionSize;
263 void WindowRenderSurface::Map()
265 ecore_wl_window_show(mWlWindow);
268 void WindowRenderSurface::StartRender()
272 bool WindowRenderSurface::PreRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, bool resizingSurface )
274 #ifdef SCREEN_ROTATION_ENABLED
275 if( resizingSurface )
277 // Window rotate or screen rotate
278 if( !mRotationFinished || !mScreenRotationFinished )
280 wl_egl_window_rotation rotation;
281 wl_output_transform bufferTransform;
282 int totalAngle = (mRotationAngle + mScreenRotationAngle) % 360;
288 rotation = ROTATION_0;
289 bufferTransform = WL_OUTPUT_TRANSFORM_NORMAL;
294 rotation = ROTATION_270;
295 bufferTransform = WL_OUTPUT_TRANSFORM_90;
300 rotation = ROTATION_180;
301 bufferTransform = WL_OUTPUT_TRANSFORM_180;
306 rotation = ROTATION_90;
307 bufferTransform = WL_OUTPUT_TRANSFORM_270;
312 rotation = ROTATION_0;
313 bufferTransform = WL_OUTPUT_TRANSFORM_NORMAL;
318 wl_egl_window_set_rotation( mEglWindow, rotation );
320 wl_egl_window_set_buffer_transform( mEglWindow, bufferTransform );
322 // Reset only screen rotation flag
323 mScreenRotationFinished = true;
325 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PreRender: Set rotation [%d] [%d]\n", mRotationAngle, mScreenRotationAngle );
328 // Only window rotate
329 if( !mRotationFinished )
331 wl_output_transform windowTransform;
333 switch( mRotationAngle )
337 windowTransform = WL_OUTPUT_TRANSFORM_NORMAL;
342 windowTransform = WL_OUTPUT_TRANSFORM_90;
347 windowTransform = WL_OUTPUT_TRANSFORM_180;
352 windowTransform = WL_OUTPUT_TRANSFORM_270;
357 windowTransform = WL_OUTPUT_TRANSFORM_NORMAL;
362 wl_egl_window_set_window_transform( mEglWindow, windowTransform );
370 void WindowRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, bool replacingSurface, bool resizingSurface )
372 #ifdef SCREEN_ROTATION_ENABLED
373 if( resizingSurface )
375 if( !mRotationFinished )
377 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PostRender: Trigger rotation event\n" );
379 mRotationTrigger->Trigger();
381 if( mThreadSynchronization )
383 // Wait until the event-thread complete the rotation event processing
384 mThreadSynchronization->PostRenderWaitForCompletion();
390 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
391 eglImpl.SwapBuffers();
393 if( mRenderNotification )
395 mRenderNotification->Trigger();
399 void WindowRenderSurface::StopRender()
403 void WindowRenderSurface::SetViewMode( ViewMode viewMode )
408 void WindowRenderSurface::CreateWlRenderable()
410 // if width or height are zero, go full screen.
411 if ( (mPositionSize.width == 0) || (mPositionSize.height == 0) )
413 // Default window size == screen size
417 ecore_wl_screen_size_get( &mPositionSize.width, &mPositionSize.height );
420 mWlWindow = ecore_wl_window_new( 0, mPositionSize.x, mPositionSize.y, mPositionSize.width, mPositionSize.height, ECORE_WL_WINDOW_BUFFER_TYPE_EGL_WINDOW );
422 if ( mWlWindow == 0 )
424 DALI_ASSERT_ALWAYS(0 && "Failed to create Wayland window");
427 mWlSurface = ecore_wl_window_surface_create( mWlWindow );
429 if( mColorDepth == COLOR_DEPTH_32 )
431 ecore_wl_window_alpha_set( mWlWindow, true );
435 ecore_wl_window_alpha_set( mWlWindow, false );
438 // Get output transform
439 if( !ecore_wl_window_ignore_output_transform_get( mWlWindow ) )
441 Ecore_Wl_Output* output = ecore_wl_window_output_find( mWlWindow );
443 int transform = ecore_wl_output_transform_get( output );
445 mScreenRotationAngle = transform * 90;
446 mScreenRotationFinished = false;
450 void WindowRenderSurface::UseExistingRenderable( unsigned int surfaceId )
452 mWlWindow = AnyCast< Ecore_Wl_Window* >( surfaceId );
455 void WindowRenderSurface::SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization )
457 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::SetThreadSynchronization: called\n" );
459 mThreadSynchronization = &threadSynchronization;
462 void WindowRenderSurface::ReleaseLock()
467 void WindowRenderSurface::ProcessRotationRequest()
469 #ifdef SCREEN_ROTATION_ENABLED
470 mRotationFinished = true;
472 ecore_wl_window_rotation_change_done_send( mWlWindow );
474 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::ProcessRotationRequest: Rotation Done\n" );
476 if( mThreadSynchronization )
478 mThreadSynchronization->PostRenderComplete();