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 ),
62 mThreadSynchronization( NULL ),
63 mRotationTrigger( NULL ),
64 mRotationSupported( false ),
67 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "Creating Window\n" );
71 WindowRenderSurface::~WindowRenderSurface()
73 if( mEglWindow != NULL )
75 wl_egl_window_destroy(mEglWindow);
81 ecore_wl_window_free( mWlWindow );
84 if( mRotationTrigger )
86 delete mRotationTrigger;
89 if( mLibHandle != NULL )
91 dlclose( mLibHandle );
95 Ecore_Wl_Window* WindowRenderSurface::GetDrawable()
97 // already an e-core type
101 Any WindowRenderSurface::GetSurface()
103 // already an e-core type
104 return Any( mWlWindow );
107 Ecore_Wl_Window* WindowRenderSurface::GetWlWindow()
112 void WindowRenderSurface::RequestRotation( Dali::Window::WindowOrientation orientation, int width, int height )
114 if( !mRotationSupported )
116 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::Rotate: Rotation is not supported!\n" );
120 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::Rotate: orientation = %d\n", orientation );
122 if( !mRotationTrigger )
124 TriggerEventFactoryInterface& triggerFactory = Internal::Adaptor::Adaptor::GetImplementation( Adaptor::Get() ).GetTriggerEventFactoryInterface();
125 mRotationTrigger = triggerFactory.CreateTriggerEvent( MakeCallback( this, &WindowRenderSurface::ProcessRotationRequest ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER );
128 mPosition.width = width;
129 mPosition.height = height;
134 wl_egl_window_rotation rotation;
136 switch( orientation )
138 case Dali::Window::PORTRAIT:
141 rotation = ROTATION_0;
144 case Dali::Window::LANDSCAPE:
147 rotation = ROTATION_270;
150 case Dali::Window::PORTRAIT_INVERSE:
153 rotation = ROTATION_180;
156 case Dali::Window::LANDSCAPE_INVERSE:
159 rotation = ROTATION_90;
165 rotation = ROTATION_0;
170 ecore_wl_window_rotation_set( mWlWindow, angle );
172 if( mEglWinSetRotationPtr )
174 mEglWinSetRotationPtr( mEglWindow, rotation );
178 void WindowRenderSurface::InitializeEgl( EglInterface& eglIf )
180 DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
182 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
184 eglImpl.ChooseConfig(true, mColorDepth);
187 void WindowRenderSurface::CreateEglSurface( EglInterface& eglIf )
189 DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
191 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
193 // Temporary code for opaque window. We have to modify it after wayland team finish the work.
194 if( mColorDepth == COLOR_DEPTH_32 )
196 ecore_wl_window_alpha_set( mWlWindow, true );
200 ecore_wl_window_alpha_set( mWlWindow, false );
203 // create the EGL surface
204 ecore_wl_window_surface_create(mWlWindow);
205 mEglWindow = wl_egl_window_create(ecore_wl_window_surface_get(mWlWindow), 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(ecore_wl_window_surface_get(mWlWindow), 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_move(mWlWindow, positionSize.x, positionSize.y);
310 mPosition = positionSize;
314 ecore_wl_window_resize(mWlWindow, positionSize.width, positionSize.height, 0);
315 mPosition = positionSize;
320 void WindowRenderSurface::Map()
322 ecore_wl_window_show(mWlWindow);
325 void WindowRenderSurface::StartRender()
329 bool WindowRenderSurface::PreRender( EglInterface&, Integration::GlAbstraction& )
331 // nothing to do for windows
335 void WindowRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, bool replacingSurface )
339 // Check viewport size
340 Dali::Vector< GLint > viewportSize;
341 viewportSize.Resize( 4 );
343 glAbstraction.GetIntegerv( GL_VIEWPORT, &viewportSize[0] );
345 if( viewportSize[2] == mPosition.width && viewportSize[3] == mPosition.height )
347 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PostRender: Trigger rotation event\n" );
349 mRotationTrigger->Trigger();
351 if( mThreadSynchronization )
353 // Wait until the event-thread complete the rotation event processing
354 mThreadSynchronization->PostRenderWaitForCompletion();
359 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
360 eglImpl.SwapBuffers();
362 if( mRenderNotification )
364 mRenderNotification->Trigger();
368 void WindowRenderSurface::StopRender()
372 void WindowRenderSurface::SetViewMode( ViewMode viewMode )
377 void WindowRenderSurface::CreateWlRenderable()
379 // if width or height are zero, go full screen.
380 if ( (mPosition.width == 0) || (mPosition.height == 0) )
382 // Default window size == screen size
386 ecore_wl_screen_size_get( &mPosition.width, &mPosition.height );
389 mWlWindow = ecore_wl_window_new( 0, mPosition.x, mPosition.y, mPosition.width, mPosition.height, ECORE_WL_WINDOW_BUFFER_TYPE_EGL_WINDOW );
391 if ( mWlWindow == 0 )
393 DALI_ASSERT_ALWAYS(0 && "Failed to create Wayland window");
397 void WindowRenderSurface::UseExistingRenderable( unsigned int surfaceId )
399 mWlWindow = AnyCast< Ecore_Wl_Window* >( surfaceId );
402 void WindowRenderSurface::SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization )
404 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::SetThreadSynchronization: called\n" );
406 mThreadSynchronization = &threadSynchronization;
409 void WindowRenderSurface::ReleaseLock()
414 void WindowRenderSurface::ProcessRotationRequest()
418 ecore_wl_window_rotation_change_done_send( mWlWindow );
420 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::ProcessRotationRequest: Rotation Done\n" );
422 if( mThreadSynchronization )
424 mThreadSynchronization->PostRenderComplete();