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::SetTransparency( bool transparent )
181 ecore_wl_window_alpha_set( mWlWindow, transparent );
184 void WindowRenderSurface::InitializeEgl( EglInterface& eglIf )
186 DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
188 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
190 eglImpl.ChooseConfig(true, mColorDepth);
193 void WindowRenderSurface::CreateEglSurface( EglInterface& eglIf )
195 DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
197 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
199 // Temporary code for opaque window. We have to modify it after wayland team finish the work.
200 if( mColorDepth == COLOR_DEPTH_32 )
202 ecore_wl_window_alpha_set( mWlWindow, true );
206 ecore_wl_window_alpha_set( mWlWindow, false );
209 // create the EGL window
210 mEglWindow = wl_egl_window_create( mWlSurface, mPosition.width, mPosition.height );
211 EGLNativeWindowType windowType( mEglWindow );
212 eglImpl.CreateSurfaceWindow( windowType, mColorDepth );
217 mLibHandle = dlopen( WAYLAND_EGL_SO, RTLD_LAZY );
219 char* error = dlerror();
220 if( mLibHandle == NULL || error != NULL )
222 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::CreateEglSurface: dlopen error: %s\n", error );
226 mEglWinGetCapabilitiesPtr = reinterpret_cast< EglWinGetCapabilitiesFunction >( dlsym( mLibHandle, "wl_egl_window_get_capabilities" ) );
227 if( !mEglWinGetCapabilitiesPtr )
229 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::CreateEglSurface: Can't load wl_egl_window_get_capabilities\n" );
233 mEglWinSetRotationPtr = reinterpret_cast< EglWinSetRotationFunction >( dlsym( mLibHandle, "wl_egl_window_set_rotation" ) );
234 if( !mEglWinSetRotationPtr )
236 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::CreateEglSurface: Can't load wl_egl_window_set_rotation\n" );
241 if( mEglWinGetCapabilitiesPtr )
243 wl_egl_window_capability capability = static_cast< wl_egl_window_capability >( mEglWinGetCapabilitiesPtr( mEglWindow ) );
244 if( capability == WL_EGL_WINDOW_CAPABILITY_ROTATION_SUPPORTED )
246 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::CreateEglSurface: capability = %d\n", capability );
247 mRotationSupported = true;
252 void WindowRenderSurface::DestroyEglSurface( EglInterface& eglIf )
254 DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
256 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
257 eglImpl.DestroySurface();
259 if( mEglWindow != NULL )
261 wl_egl_window_destroy(mEglWindow);
266 bool WindowRenderSurface::ReplaceEGLSurface( EglInterface& egl )
268 DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
270 if( mEglWindow != NULL )
272 wl_egl_window_destroy(mEglWindow);
276 // Temporary code for opaque window. We have to modify it after wayland team finish the work.
277 if( mColorDepth == COLOR_DEPTH_32 )
279 ecore_wl_window_alpha_set( mWlWindow, true );
283 ecore_wl_window_alpha_set( mWlWindow, false );
286 mEglWindow = wl_egl_window_create( mWlSurface, mPosition.width, mPosition.height );
288 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
289 EGLNativeWindowType windowType( mEglWindow );
290 return eglImpl.ReplaceSurfaceWindow( windowType );
293 void WindowRenderSurface::MoveResize( Dali::PositionSize positionSize )
295 bool needToMove = false;
296 bool needToResize = false;
299 if( (fabs(positionSize.x - mPosition.x) > MINIMUM_DIMENSION_CHANGE) ||
300 (fabs(positionSize.y - mPosition.y) > MINIMUM_DIMENSION_CHANGE) )
306 if( (fabs(positionSize.width - mPosition.width) > MINIMUM_DIMENSION_CHANGE) ||
307 (fabs(positionSize.height - mPosition.height) > MINIMUM_DIMENSION_CHANGE) )
314 ecore_wl_window_position_set( mWlWindow, positionSize.x, positionSize.y );
318 ecore_wl_window_update_size( mWlWindow, positionSize.width, positionSize.height );
321 mPosition = positionSize;
323 wl_egl_window_resize( mEglWindow, mPosition.width, mPosition.height, mPosition.x, mPosition.y );
325 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::MoveResize: %d, %d, %d, %d\n", mPosition.x, mPosition.y, mPosition.width, mPosition.height );
328 void WindowRenderSurface::Map()
330 ecore_wl_window_show(mWlWindow);
333 void WindowRenderSurface::StartRender()
337 bool WindowRenderSurface::PreRender( EglInterface&, Integration::GlAbstraction& )
339 // nothing to do for windows
343 void WindowRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, bool replacingSurface )
347 // Check viewport size
348 Dali::Vector< GLint > viewportSize;
349 viewportSize.Resize( 4 );
351 glAbstraction.GetIntegerv( GL_VIEWPORT, &viewportSize[0] );
353 if( viewportSize[2] == mPosition.width && viewportSize[3] == mPosition.height )
355 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PostRender: Trigger rotation event\n" );
357 mRotationTrigger->Trigger();
359 if( mThreadSynchronization )
361 // Wait until the event-thread complete the rotation event processing
362 mThreadSynchronization->PostRenderWaitForCompletion();
367 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
368 eglImpl.SwapBuffers();
370 if( mRenderNotification )
372 mRenderNotification->Trigger();
376 void WindowRenderSurface::StopRender()
380 void WindowRenderSurface::SetViewMode( ViewMode viewMode )
385 void WindowRenderSurface::CreateWlRenderable()
387 // if width or height are zero, go full screen.
388 if ( (mPosition.width == 0) || (mPosition.height == 0) )
390 // Default window size == screen size
394 ecore_wl_screen_size_get( &mPosition.width, &mPosition.height );
397 mWlWindow = ecore_wl_window_new( 0, mPosition.x, mPosition.y, mPosition.width, mPosition.height, ECORE_WL_WINDOW_BUFFER_TYPE_EGL_WINDOW );
399 if ( mWlWindow == 0 )
401 DALI_ASSERT_ALWAYS(0 && "Failed to create Wayland window");
404 mWlSurface = ecore_wl_window_surface_create( mWlWindow );
407 void WindowRenderSurface::UseExistingRenderable( unsigned int surfaceId )
409 mWlWindow = AnyCast< Ecore_Wl_Window* >( surfaceId );
412 void WindowRenderSurface::SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization )
414 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::SetThreadSynchronization: called\n" );
416 mThreadSynchronization = &threadSynchronization;
419 void WindowRenderSurface::ReleaseLock()
424 void WindowRenderSurface::ProcessRotationRequest()
428 ecore_wl_window_rotation_change_done_send( mWlWindow );
430 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::ProcessRotationRequest: Rotation Done\n" );
432 if( mThreadSynchronization )
434 mThreadSynchronization->PostRenderComplete();