2 * Copyright (c) 2020 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/common/gl-window-impl.h>
23 #include <dali/integration-api/core.h>
24 #include <dali/devel-api/adaptor-framework/orientation.h>
25 #include <dali/devel-api/adaptor-framework/gl-window.h>
26 #include <dali/integration-api/events/touch-integ.h>
27 #include <dali/integration-api/events/key-event-integ.h>
28 #include <dali/devel-api/events/key-event-devel.h>
31 //#include <dali/internal/graphics/gles/egl-graphics.h>
32 #include <dali/internal/window-system/common/event-handler.h>
33 #include <dali/internal/window-system/common/orientation-impl.h>
34 #include <dali/internal/window-system/common/window-factory.h>
35 #include <dali/internal/window-system/common/window-base.h>
36 #include <dali/internal/window-system/common/window-system.h>
37 #include <dali/internal/window-system/common/window-impl.h>
38 #include <dali/internal/window-system/common/window-render-surface.h>
39 #include <dali/internal/window-system/common/window-visibility-observer.h>
40 #include <dali/internal/graphics/gles/egl-graphics-factory.h>
41 #include <dali/internal/window-system/common/display-utils.h>
52 const int MINIMUM_DIMENSION_CHANGE( 1 );
54 #if defined(DEBUG_ENABLED)
55 Debug::Filter* gWindowLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_WINDOW" );
58 } // unnamed namespace
60 GlWindow* GlWindow::New( const PositionSize& positionSize, const std::string& name, const std::string& className, bool isTransparent )
62 GlWindow* window = new GlWindow();
63 window->mIsTransparent = isTransparent;
64 window->Initialize( positionSize, name, className );
71 mDisplayConnection( nullptr ),
72 mEventHandler( nullptr ),
74 mColorDepth( COLOR_DEPTH_24 ),
75 mIsTransparent( false ),
76 mIsFocusAcceptable( false ),
78 mOpaqueState( false ),
79 mResizedEnabled( false ),
82 mIsWindowRotated( false ),
86 mTotalRotationAngle( 0 ),
87 mWindowRotationAngle( 0 ),
88 mScreenRotationAngle( 0 ),
89 mOrientationMode( 0 ),
92 mNativeWindowId( -1 ),
97 mVisibilityChangedSignal(),
99 mGLRenderFrameCallback( 0 ),
100 mGLTerminateCallback( 0 ),
101 mGLRenderCallback( nullptr ),
102 mEGLSurface( nullptr ),
103 mEGLContext( nullptr ),
104 mGLESVersion( Dali::GlWindow::GlesVersion::VERSION_3_0 ),
105 mInitCallback( false ),
108 mIsEGLInitialize( false ),
113 GlWindow::~GlWindow()
117 mEventHandler->RemoveObserver( *this );
120 if( mGLTerminateCallback )
122 mGLTerminateCallback();
125 if( mIsEGLInitialize )
127 GraphicsInterface* graphics = mGraphics.get();
128 EglGraphics *eglGraphics = static_cast<EglGraphics*>( graphics );
129 Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
133 eglImpl.DestroySurface( mEGLSurface );
134 mEGLSurface = nullptr;
139 eglImpl.DestroyContext( mEGLContext );
140 mEGLContext = nullptr;
143 eglImpl.TerminateGles();
145 mGraphics->Destroy();
148 delete mDisplayConnection;
151 void GlWindow::Initialize( const PositionSize& positionSize, const std::string& name, const std::string& className )
153 int screenWidth, screenHeight;
155 mPositionSize = positionSize;
156 WindowSystem::GetScreenSize( screenWidth, screenHeight );
157 if ( (mPositionSize.width == 0) || (mPositionSize.height == 0) )
161 mPositionSize.width = screenWidth;
162 mPositionSize.height = screenHeight;
165 if( screenWidth > screenHeight )
167 mOrientationMode = 1; // Default mode is landscape
171 mOrientationMode = 0; // Default mode is portrate
174 // Create a window base
175 auto windowFactory = Dali::Internal::Adaptor::GetWindowFactory();
177 mWindowBase = windowFactory->CreateWindowBase( mPositionSize, surface, ( mIsTransparent ? true : false ) );
178 mWindowBase->IconifyChangedSignal().Connect( this, &GlWindow::OnIconifyChanged );
179 mWindowBase->FocusChangedSignal().Connect( this, &GlWindow::OnFocusChanged );
183 if( !mPositionSize.IsEmpty() )
185 AddAuxiliaryHint( "wm.policy.win.user.geometry", "1" );
186 mResizedEnabled = true;
193 mColorDepth = COLOR_DEPTH_32;
197 mColorDepth = COLOR_DEPTH_24;
200 SetClass( name, className );
203 mNativeWindowId = mWindowBase->GetNativeWindowId();
206 void GlWindow::SetEventHandler()
208 mEventHandler = EventHandlerPtr( new EventHandler( mWindowBase.get(), *this ) );
209 mEventHandler->AddObserver( *this );
212 void GlWindow::SetClass( const std::string name, const std::string className )
215 mClassName = className;
216 mWindowBase->SetClass( name, className );
219 void GlWindow::SetEglConfig( bool depth, bool stencil, int msaa, Dali::GlWindow::GlesVersion version )
225 mGLESVersion = version;
227 InitializeGraphics();
230 void GlWindow::Raise()
232 mWindowBase->Raise();
233 DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Raise() \n", this, mNativeWindowId );
236 void GlWindow::Lower()
238 mWindowBase->Lower();
239 DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Lower() \n", this, mNativeWindowId );
242 void GlWindow::Activate()
244 mWindowBase->Activate();
245 DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Activate() \n", this, mNativeWindowId );
248 void GlWindow::Show()
256 Dali::GlWindow handle( this );
257 mVisibilityChangedSignal.Emit( handle, true );
262 mEventHandler->Resume();
265 DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Show(): iconified = %d, visible = %d\n", this, mNativeWindowId, mIconified, mVisible );
268 void GlWindow::Hide()
276 Dali::GlWindow handle( this );
277 mVisibilityChangedSignal.Emit( handle, false );
282 mEventHandler->Pause();
285 DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Hide(): iconified = %d, visible = %d\n", this, mNativeWindowId, mIconified, mVisible );
288 unsigned int GlWindow::GetSupportedAuxiliaryHintCount() const
290 return mWindowBase->GetSupportedAuxiliaryHintCount();
293 std::string GlWindow::GetSupportedAuxiliaryHint( unsigned int index ) const
295 return mWindowBase->GetSupportedAuxiliaryHint( index );
298 unsigned int GlWindow::AddAuxiliaryHint( const std::string& hint, const std::string& value )
300 return mWindowBase->AddAuxiliaryHint( hint, value );
303 bool GlWindow::RemoveAuxiliaryHint( unsigned int id )
305 return mWindowBase->RemoveAuxiliaryHint( id );
308 bool GlWindow::SetAuxiliaryHintValue( unsigned int id, const std::string& value )
310 return mWindowBase->SetAuxiliaryHintValue( id, value );
313 std::string GlWindow::GetAuxiliaryHintValue( unsigned int id ) const
315 return mWindowBase->GetAuxiliaryHintValue( id );
318 unsigned int GlWindow::GetAuxiliaryHintId( const std::string& hint ) const
320 return mWindowBase->GetAuxiliaryHintId( hint );
323 void GlWindow::SetInputRegion( const Rect< int >& inputRegion )
325 mWindowBase->SetInputRegion( inputRegion );
327 DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "GlWindow::SetInputRegion: x = %d, y = %d, w = %d, h = %d\n", inputRegion.x, inputRegion.y, inputRegion.width, inputRegion.height );
330 void GlWindow::SetOpaqueState( bool opaque )
332 mOpaqueState = opaque;
334 mWindowBase->SetOpaqueState( opaque );
336 DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "GlWindow::SetOpaqueState: opaque = %d\n", opaque );
339 bool GlWindow::IsOpaqueState() const
344 void GlWindow::SetPositionSize( PositionSize positionSize )
346 if( !mResizedEnabled )
348 AddAuxiliaryHint( "wm.policy.win.user.geometry", "1" );
349 mResizedEnabled = true;
352 bool needToMove = false;
353 bool needToResize = false;
356 if( (fabs(positionSize.x - mPositionSize.x) > MINIMUM_DIMENSION_CHANGE) ||
357 (fabs(positionSize.y - mPositionSize.y) > MINIMUM_DIMENSION_CHANGE) )
363 if( (fabs(positionSize.width - mPositionSize.width) > MINIMUM_DIMENSION_CHANGE) ||
364 (fabs(positionSize.height - mPositionSize.height) > MINIMUM_DIMENSION_CHANGE) )
373 mWindowBase->MoveResize( positionSize );
377 mWindowBase->Resize( positionSize );
379 mPositionSize = positionSize;
385 mWindowBase->Move( positionSize );
386 mPositionSize = positionSize;
390 // If window's size or position is changed, the signal will be emitted to user.
391 if( ( needToMove ) || ( needToResize ) )
393 Uint16Pair newSize( mPositionSize.width, mPositionSize.height );
394 mResizedSignal.Emit( newSize );
398 PositionSize GlWindow::GetPositionSize() const
400 PositionSize positionSize( mPositionSize );
401 if( mTotalRotationAngle == 90 || mTotalRotationAngle == 270 )
403 positionSize.height = mPositionSize.width;
404 positionSize.width = mPositionSize.height;
410 void GlWindow::OnIconifyChanged( bool iconified )
418 Dali::GlWindow handle( this );
419 mVisibilityChangedSignal.Emit( handle, false );
424 mEventHandler->Pause();
427 DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Iconified: visible = %d\n", this, mNativeWindowId, mVisible );
435 Dali::GlWindow handle( this );
436 mVisibilityChangedSignal.Emit( handle, true );
441 mEventHandler->Resume();
444 DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Deiconified: visible = %d\n", this, mNativeWindowId, mVisible );
448 void GlWindow::OnFocusChanged( bool focusIn )
450 Dali::GlWindow handle( this );
451 mFocusChangeSignal.Emit( handle, focusIn );
454 void GlWindow::OnOutputTransformed()
456 int screenRotationAngle = mWindowBase->GetScreenRotationAngle();
457 if( screenRotationAngle != mScreenRotationAngle )
459 mScreenRotationAngle = screenRotationAngle;
460 mTotalRotationAngle = (mWindowRotationAngle + mScreenRotationAngle) % 360;
462 if( mTotalRotationAngle == 90 || mTotalRotationAngle == 270 )
464 mWindowWidth = mPositionSize.height;
465 mWindowHeight = mPositionSize.width;
469 mWindowWidth = mPositionSize.width;
470 mWindowHeight = mPositionSize.height;
473 // Emit Resized signal
474 mResizedSignal.Emit( Dali::Uint16Pair( mWindowWidth, mWindowHeight ) );
478 void GlWindow::OnTouchPoint( Dali::Integration::Point& point, int timeStamp )
480 PointState::Type state = point.GetState();
482 if( state == PointState::DOWN )
487 if( state == PointState::UP )
492 if( !mIsTouched && state == PointState::MOTION )
497 RecalculateTouchPosition( point );
498 Dali::TouchEvent touchEvent = Dali::Integration::NewTouchEvent( timeStamp, point );
499 mTouchSignal.Emit( touchEvent );
502 void GlWindow::OnWheelEvent( Dali::Integration::WheelEvent& wheelEvent )
505 //FeedWheelEvent( wheelEvent );
508 void GlWindow::OnKeyEvent( Dali::Integration::KeyEvent& keyEvent )
510 Dali::KeyEvent event = Dali::DevelKeyEvent::New( keyEvent.keyName, keyEvent.logicalKey, keyEvent.keyString, keyEvent.keyCode,
511 keyEvent.keyModifier, keyEvent.time, static_cast<Dali::KeyEvent::State>(keyEvent.state),
512 keyEvent.compose, keyEvent.deviceName, keyEvent.deviceClass, keyEvent.deviceSubclass );
513 mKeyEventSignal.Emit( event );
516 void GlWindow::OnRotation( const RotationEvent& rotation )
518 mWindowRotationAngle = rotation.angle;
519 mTotalRotationAngle = ( mWindowRotationAngle + mScreenRotationAngle ) % 360;
520 if( mTotalRotationAngle == 90 || mTotalRotationAngle == 270 )
522 mWindowWidth = mPositionSize.height;
523 mWindowHeight = mPositionSize.width;
527 mWindowWidth = mPositionSize.width;
528 mWindowHeight = mPositionSize.height;
532 mIsWindowRotated = true;
533 DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), OnRotation(): resized signal emit [%d x %d]\n", this, mNativeWindowId, mWindowWidth, mWindowHeight );
535 // Emit Resized signal
536 mResizedSignal.Emit( Dali::Uint16Pair( mWindowWidth, mWindowHeight ) );
539 void GlWindow::RecalculateTouchPosition( Integration::Point& point )
541 Vector2 position = point.GetScreenPosition();
542 Vector2 convertedPosition;
544 switch( mTotalRotationAngle )
548 convertedPosition.x = static_cast<float>( mWindowWidth ) - position.y;
549 convertedPosition.y = position.x;
554 convertedPosition.x = static_cast<float>( mWindowWidth ) - position.x;
555 convertedPosition.y = static_cast<float>( mWindowHeight ) - position.y;
560 convertedPosition.x = position.y;
561 convertedPosition.y = static_cast<float>( mWindowHeight ) - position.x;
566 convertedPosition = position;
571 point.SetScreenPosition( convertedPosition );
574 void GlWindow::SetAvailableAnlges( const std::vector< int >& angles )
576 if( angles.size() > 4 )
578 DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::SetAvailableAnlges: Invalid vector size! [%d]\n", angles.size() );
582 mWindowBase->SetAvailableAnlges( angles );
585 bool GlWindow::IsOrientationAvailable( Dali::GlWindow::GlWindowOrientation orientation ) const
587 if( orientation <= Dali::GlWindow::GlWindowOrientation::NO_ORIENTATION_PREFERENCE
588 || orientation > Dali::GlWindow::GlWindowOrientation::LANDSCAPE_INVERSE )
590 DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::IsOrientationAvailable: Invalid input orientation [%d]\n", orientation );
596 int GlWindow::ConvertToAngle( Dali::GlWindow::GlWindowOrientation orientation )
598 int convertAngle = 0;
599 if ( mOrientationMode == 0 )
601 convertAngle = ( static_cast< int >( orientation ) ) * 90;
603 else if( mOrientationMode == 1)
605 switch( orientation )
607 case Dali::GlWindow::GlWindowOrientation::LANDSCAPE:
612 case Dali::GlWindow::GlWindowOrientation::PORTRAIT:
617 case Dali::GlWindow::GlWindowOrientation::LANDSCAPE_INVERSE:
622 case Dali::GlWindow::GlWindowOrientation::PORTRAIT_INVERSE:
627 case Dali::GlWindow::GlWindowOrientation::NO_ORIENTATION_PREFERENCE:
637 Dali::GlWindow::GlWindowOrientation GlWindow::ConvertToOrientation( int angle ) const
639 Dali::GlWindow::GlWindowOrientation orientation = Dali::GlWindow::GlWindowOrientation::NO_ORIENTATION_PREFERENCE;
640 if ( mOrientationMode == 0 ) // Portrate mode
642 orientation = static_cast< Dali::GlWindow::GlWindowOrientation >( angle / 90 );
644 else if( mOrientationMode == 1 ) // Landscape mode
650 orientation = Dali::GlWindow::GlWindowOrientation::LANDSCAPE;
655 orientation = Dali::GlWindow::GlWindowOrientation::PORTRAIT;
660 orientation = Dali::GlWindow::GlWindowOrientation::LANDSCAPE_INVERSE;
665 orientation = Dali::GlWindow::GlWindowOrientation::PORTRAIT_INVERSE;
670 orientation = Dali::GlWindow::GlWindowOrientation::NO_ORIENTATION_PREFERENCE;
678 Dali::GlWindow::GlWindowOrientation GlWindow::GetCurrentOrientation() const
680 DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), GetCurrentOrientation(): %d\n", this, mNativeWindowId, mTotalRotationAngle );
681 return ConvertToOrientation( mTotalRotationAngle );
684 void GlWindow::SetAvailableOrientations( const Dali::Vector< Dali::GlWindow::GlWindowOrientation >& orientations )
686 Dali::Vector<float>::SizeType count = orientations.Count();
687 for( Dali::Vector<float>::SizeType index = 0; index < count; ++index )
689 if( IsOrientationAvailable( orientations[index] ) == false )
691 DALI_LOG_ERROR("Window::SetAvailableRotationAngles, invalid angle: %d\n", orientations[index]);
696 int angle = ConvertToAngle( orientations[index] );
698 for( std::size_t i = 0; i < mAvailableAngles.size(); i++ )
700 if( mAvailableAngles[i] == angle )
709 DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), SetAvailableOrientations: %d\n", this, mNativeWindowId, angle );
710 mAvailableAngles.push_back( angle );
713 SetAvailableAnlges( mAvailableAngles );
716 void GlWindow::SetPreferredOrientation( Dali::GlWindow::GlWindowOrientation orientation )
718 if( IsOrientationAvailable( orientation ) == false )
720 DALI_LOG_ERROR( "Window::SetPreferredOrientation, invalid orientation: %d\n", orientation );
723 mPreferredAngle = ConvertToAngle( orientation );
724 DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), SetPreferredOrientation: %d\n", this, mNativeWindowId, mPreferredAngle );
725 mWindowBase->SetPreferredAngle( mPreferredAngle );
728 void GlWindow::SetChild( Dali::Window& child )
730 if( DALI_UNLIKELY( child ) )
732 mChildWindow = child;
733 Internal::Adaptor::Window& windowImpl = Dali::GetImplementation( mChildWindow );
734 WindowRenderSurface* renderSurface = static_cast<WindowRenderSurface*>( windowImpl.GetSurface() );
735 WindowBase* childWindowBase = renderSurface->GetWindowBase();
736 childWindowBase->SetParent( mWindowBase.get() );
740 void GlWindow::RegisterGlCallback( GlInitialize glInit, GlRenderFrame glRenderFrame, GlTerminate glTerminate )
742 if( mIsEGLInitialize == false )
744 InitializeGraphics();
746 mGLInitCallback = glInit;
747 mGLRenderFrameCallback = glRenderFrame;
748 mGLTerminateCallback = glTerminate;
750 mInitCallback = false;
752 if( !mGLRenderCallback )
754 mGLRenderCallback = MakeCallback( this, &GlWindow::RunCallback );
756 Dali::Adaptor::Get().AddIdle( mGLRenderCallback, true );
760 bool GlWindow::RunCallback()
762 GraphicsInterface* graphics = mGraphics.get();
763 EglGraphics *eglGraphics = static_cast<EglGraphics*>( graphics );
764 Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
766 eglImpl.MakeContextCurrent( mEGLSurface, mEGLContext );
770 mWindowBase->SetEglWindowBufferTransform( mTotalRotationAngle );
771 if( mIsWindowRotated )
773 mWindowBase->SetEglWindowTransform( mWindowRotationAngle );
780 if( mGLInitCallback )
784 mInitCallback = true;
787 if( mGLRenderFrameCallback )
789 mGLRenderFrameCallback();
792 if( mIsWindowRotated )
794 mWindowBase->WindowRotationCompleted( mWindowRotationAngle, mPositionSize.width, mPositionSize.height );
795 mIsWindowRotated = false;
798 eglImpl.SwapBuffers( mEGLSurface );
803 void GlWindow::RenderOnce()
808 int32_t GlWindow::GetNativeId() const
810 return mWindowBase->GetNativeWindowId();
813 void GlWindow::InitializeGraphics()
815 if( !mIsEGLInitialize )
818 std::unique_ptr< GraphicsFactory > graphicsFactoryPtr = Utils::MakeUnique< GraphicsFactory >();
819 auto graphicsFactory = *graphicsFactoryPtr.get();
821 mGraphics = std::unique_ptr< GraphicsInterface >( &graphicsFactory.Create() );
822 GraphicsInterface* graphics = mGraphics.get();
823 EglGraphics *eglGraphics = static_cast<EglGraphics*>( graphics );
824 eglGraphics->Initialize( mDepth, mStencil, mMSAA );
825 eglGraphics->Create();
827 mDisplayConnection = Dali::DisplayConnection::New( *graphics, Dali::RenderSurfaceInterface::Type::WINDOW_RENDER_SURFACE );
828 mDisplayConnection->Initialize();
830 Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
831 if( mGLESVersion == Dali::GlWindow::GlesVersion::VERSION_2_0 )
833 eglImpl.SetGlesVersion( 20 );
835 else if( mGLESVersion == Dali::GlWindow::GlesVersion::VERSION_3_0 )
837 eglImpl.SetGlesVersion( 30 );
840 if( eglImpl.ChooseConfig(true, mColorDepth) == false )
842 if( mGLESVersion == Dali::GlWindow::GlesVersion::VERSION_3_0 )
844 DALI_LOG_RELEASE_INFO( "InitializeGraphics: Fail to choose config with GLES30, retry with GLES20\n" );
845 eglImpl.SetGlesVersion( 20 );
846 mGLESVersion = Dali::GlWindow::GlesVersion::VERSION_2_0;
847 if( eglImpl.ChooseConfig(true, mColorDepth) == false )
849 DALI_LOG_ERROR("InitializeGraphics: Fail to choose config with GLES20");
855 DALI_LOG_ERROR("InitializeGraphics: Fail to choose config with GLES20");
859 eglImpl.CreateWindowContext( mEGLContext );
861 // Create the EGL window
862 EGLNativeWindowType window = mWindowBase->CreateEglWindow( mPositionSize.width, mPositionSize.height );
863 mEGLSurface = eglImpl.CreateSurfaceWindow( window, mColorDepth );
865 mIsEGLInitialize = true;
869 void GlWindow::OnDamaged( const DamageArea& area )