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>
23 #include <dali/integration-api/gl-abstraction.h>
24 #include <dali/integration-api/debug.h>
25 #include <dali/integration-api/gl-defines.h>
29 #include <gl/egl-implementation.h>
30 #include <base/display-connection.h>
31 #include <adaptors/common/adaptor-impl.h>
32 #include <integration-api/trigger-event-factory-interface.h>
37 #if defined(DEBUG_ENABLED)
38 extern Debug::Filter* gRenderSurfaceLogFilter;
47 const int MINIMUM_DIMENSION_CHANGE( 1 ); ///< Minimum change for window to be considered to have moved
48 const char* WAYLAND_EGL_SO( "libwayland-egl.so" );
50 } // unnamed namespace
52 WindowRenderSurface::WindowRenderSurface( Dali::PositionSize positionSize,
54 const std::string& name,
56 : EcoreWlRenderSurface( positionSize, surface, name, isTransparent ),
57 mEglWinGetCapabilitiesPtr( NULL ),
58 mEglWinSetRotationPtr( NULL ),
63 mThreadSynchronization( NULL ),
64 mRotationTrigger( NULL ),
65 mRotationSupported( false ),
68 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "Creating Window\n" );
72 WindowRenderSurface::~WindowRenderSurface()
74 if( mEglWindow != NULL )
76 wl_egl_window_destroy(mEglWindow);
82 ecore_wl_window_free( mWlWindow );
85 if( mRotationTrigger )
87 delete mRotationTrigger;
90 if( mLibHandle != NULL )
92 dlclose( mLibHandle );
96 Ecore_Wl_Window* WindowRenderSurface::GetDrawable()
98 // already an e-core type
102 Any WindowRenderSurface::GetSurface()
104 // already an e-core type
105 return Any( mWlWindow );
108 Ecore_Wl_Window* WindowRenderSurface::GetWlWindow()
113 void WindowRenderSurface::RequestRotation( Dali::Window::WindowOrientation orientation, int width, int height )
115 if( !mRotationSupported )
117 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::Rotate: Rotation is not supported!\n" );
121 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::Rotate: orientation = %d\n", orientation );
123 if( !mRotationTrigger )
125 TriggerEventFactoryInterface& triggerFactory = Internal::Adaptor::Adaptor::GetImplementation( Adaptor::Get() ).GetTriggerEventFactoryInterface();
126 mRotationTrigger = triggerFactory.CreateTriggerEvent( MakeCallback( this, &WindowRenderSurface::ProcessRotationRequest ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER );
129 mPosition.width = width;
130 mPosition.height = height;
135 wl_egl_window_rotation rotation;
137 switch( orientation )
139 case Dali::Window::PORTRAIT:
142 rotation = ROTATION_0;
145 case Dali::Window::LANDSCAPE:
148 rotation = ROTATION_270;
151 case Dali::Window::PORTRAIT_INVERSE:
154 rotation = ROTATION_180;
157 case Dali::Window::LANDSCAPE_INVERSE:
160 rotation = ROTATION_90;
166 rotation = ROTATION_0;
171 ecore_wl_window_rotation_set( mWlWindow, angle );
173 if( mEglWinSetRotationPtr )
175 mEglWinSetRotationPtr( mEglWindow, rotation );
179 void WindowRenderSurface::InitializeEgl( EglInterface& eglIf )
181 DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
183 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
185 eglImpl.ChooseConfig(true, mColorDepth);
188 void WindowRenderSurface::CreateEglSurface( EglInterface& eglIf )
190 DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
192 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
194 // Temporary code for opaque window. We have to modify it after wayland team finish the work.
195 if( mColorDepth == COLOR_DEPTH_32 )
197 ecore_wl_window_alpha_set( mWlWindow, true );
201 ecore_wl_window_alpha_set( mWlWindow, false );
204 // create the EGL window
205 mEglWindow = wl_egl_window_create( mWlSurface, mPosition.width, mPosition.height );
206 EGLNativeWindowType windowType( mEglWindow );
207 eglImpl.CreateSurfaceWindow( windowType, mColorDepth );
212 mLibHandle = dlopen( WAYLAND_EGL_SO, RTLD_LAZY );
214 char* error = dlerror();
215 if( mLibHandle == NULL || error != NULL )
217 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::CreateEglSurface: dlopen error: %s\n", error );
221 mEglWinGetCapabilitiesPtr = reinterpret_cast< EglWinGetCapabilitiesFunction >( dlsym( mLibHandle, "wl_egl_window_get_capabilities" ) );
222 if( !mEglWinGetCapabilitiesPtr )
224 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::CreateEglSurface: Can't load wl_egl_window_get_capabilities\n" );
228 mEglWinSetRotationPtr = reinterpret_cast< EglWinSetRotationFunction >( dlsym( mLibHandle, "wl_egl_window_set_rotation" ) );
229 if( !mEglWinSetRotationPtr )
231 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::CreateEglSurface: Can't load wl_egl_window_set_rotation\n" );
236 if( mEglWinGetCapabilitiesPtr )
238 wl_egl_window_capability capability = static_cast< wl_egl_window_capability >( mEglWinGetCapabilitiesPtr( mEglWindow ) );
239 if( capability == WL_EGL_WINDOW_CAPABILITY_ROTATION_SUPPORTED )
241 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::CreateEglSurface: capability = %d\n", capability );
242 mRotationSupported = true;
247 void WindowRenderSurface::DestroyEglSurface( EglInterface& eglIf )
249 DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
251 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
252 eglImpl.DestroySurface();
254 if( mEglWindow != NULL )
256 wl_egl_window_destroy(mEglWindow);
261 bool WindowRenderSurface::ReplaceEGLSurface( EglInterface& egl )
263 DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
265 if( mEglWindow != NULL )
267 wl_egl_window_destroy(mEglWindow);
271 // Temporary code for opaque window. We have to modify it after wayland team finish the work.
272 if( mColorDepth == COLOR_DEPTH_32 )
274 ecore_wl_window_alpha_set( mWlWindow, true );
278 ecore_wl_window_alpha_set( mWlWindow, false );
281 mEglWindow = wl_egl_window_create( mWlSurface, mPosition.width, mPosition.height );
283 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
284 EGLNativeWindowType windowType( mEglWindow );
285 return eglImpl.ReplaceSurfaceWindow( windowType );
288 void WindowRenderSurface::MoveResize( Dali::PositionSize positionSize )
290 bool needToMove = false;
291 bool needToResize = false;
294 if( (fabs(positionSize.x - mPosition.x) > MINIMUM_DIMENSION_CHANGE) ||
295 (fabs(positionSize.y - mPosition.y) > MINIMUM_DIMENSION_CHANGE) )
301 if( (fabs(positionSize.width - mPosition.width) > MINIMUM_DIMENSION_CHANGE) ||
302 (fabs(positionSize.height - mPosition.height) > MINIMUM_DIMENSION_CHANGE) )
309 ecore_wl_window_position_set( mWlWindow, positionSize.x, positionSize.y );
313 ecore_wl_window_update_size( mWlWindow, positionSize.width, positionSize.height );
316 mPosition = positionSize;
318 wl_egl_window_resize( mEglWindow, mPosition.width, mPosition.height, mPosition.x, mPosition.y );
320 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::MoveResize: %d, %d, %d, %d\n", mPosition.x, mPosition.y, mPosition.width, mPosition.height );
323 void WindowRenderSurface::Map()
325 ecore_wl_window_show(mWlWindow);
328 void WindowRenderSurface::StartRender()
332 bool WindowRenderSurface::PreRender( EglInterface&, Integration::GlAbstraction& )
334 // nothing to do for windows
338 void WindowRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, bool replacingSurface )
342 // Check viewport size
343 Dali::Vector< GLint > viewportSize;
344 viewportSize.Resize( 4 );
346 glAbstraction.GetIntegerv( GL_VIEWPORT, &viewportSize[0] );
348 if( viewportSize[2] == mPosition.width && viewportSize[3] == mPosition.height )
350 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PostRender: Trigger rotation event\n" );
352 mRotationTrigger->Trigger();
354 if( mThreadSynchronization )
356 // Wait until the event-thread complete the rotation event processing
357 mThreadSynchronization->PostRenderWaitForCompletion();
362 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
363 eglImpl.SwapBuffers();
365 if( mRenderNotification )
367 mRenderNotification->Trigger();
371 void WindowRenderSurface::StopRender()
375 void WindowRenderSurface::SetViewMode( ViewMode viewMode )
380 void WindowRenderSurface::CreateWlRenderable()
382 // if width or height are zero, go full screen.
383 if ( (mPosition.width == 0) || (mPosition.height == 0) )
385 // Default window size == screen size
389 ecore_wl_screen_size_get( &mPosition.width, &mPosition.height );
392 mWlWindow = ecore_wl_window_new( 0, mPosition.x, mPosition.y, mPosition.width, mPosition.height, ECORE_WL_WINDOW_BUFFER_TYPE_EGL_WINDOW );
394 if ( mWlWindow == 0 )
396 DALI_ASSERT_ALWAYS(0 && "Failed to create Wayland window");
399 mWlSurface = ecore_wl_window_surface_create( mWlWindow );
402 void WindowRenderSurface::UseExistingRenderable( unsigned int surfaceId )
404 mWlWindow = AnyCast< Ecore_Wl_Window* >( surfaceId );
407 void WindowRenderSurface::SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization )
409 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::SetThreadSynchronization: called\n" );
411 mThreadSynchronization = &threadSynchronization;
414 void WindowRenderSurface::ReleaseLock()
419 void WindowRenderSurface::ProcessRotationRequest()
423 ecore_wl_window_rotation_change_done_send( mWlWindow );
425 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::ProcessRotationRequest: Rotation Done\n" );
427 if( mThreadSynchronization )
429 mThreadSynchronization->PostRenderComplete();