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>
30 //#include <dali/internal/graphics/gles/egl-graphics.h>
31 #include <dali/internal/window-system/common/event-handler.h>
32 #include <dali/internal/window-system/common/orientation-impl.h>
33 #include <dali/internal/window-system/common/window-factory.h>
34 #include <dali/internal/window-system/common/window-base.h>
35 #include <dali/internal/window-system/common/window-system.h>
36 #include <dali/internal/window-system/common/window-impl.h>
37 #include <dali/internal/window-system/common/window-render-surface.h>
38 #include <dali/internal/window-system/common/window-visibility-observer.h>
39 #include <dali/internal/graphics/gles/egl-graphics-factory.h>
40 #include <dali/internal/window-system/common/display-utils.h>
51 const int MINIMUM_DIMENSION_CHANGE( 1 );
53 #if defined(DEBUG_ENABLED)
54 Debug::Filter* gWindowLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_WINDOW" );
57 } // unnamed namespace
59 GlWindow* GlWindow::New( const PositionSize& positionSize, const std::string& name, const std::string& className, bool isTransparent )
61 GlWindow* window = new GlWindow();
62 window->mIsTransparent = isTransparent;
63 window->Initialize( positionSize, name, className );
70 mDisplayConnection( nullptr ),
71 mEventHandler( nullptr ),
73 mColorDepth( COLOR_DEPTH_24 ),
74 mIsTransparent( false ),
75 mIsFocusAcceptable( false ),
77 mOpaqueState( false ),
78 mResizedEnabled( false ),
81 mIsWindowRotated( false ),
85 mTotalRotationAngle( 0 ),
86 mWindowRotationAngle( 0 ),
87 mScreenRotationAngle( 0 ),
88 mOrientationMode( 0 ),
91 mNativeWindowId( -1 ),
96 mVisibilityChangedSignal(),
97 mGLRenderCallback( nullptr ),
98 mEGLSurface( nullptr ),
99 mEGLContext( nullptr ),
100 mGLESVersion( Dali::GlWindow::GlesVersion::VERSION_3_0 ),
101 mInitCallback( false ),
104 mIsEGLInitialize( false ),
109 GlWindow::~GlWindow()
113 mEventHandler->RemoveObserver( *this );
116 mGLTerminateCallback();
118 if( mIsEGLInitialize )
120 GraphicsInterface* graphics = mGraphics.get();
121 EglGraphics *eglGraphics = static_cast<EglGraphics*>( graphics );
122 Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
126 eglImpl.DestroySurface( mEGLSurface );
127 mEGLSurface = nullptr;
132 eglImpl.DestroyContext( mEGLContext );
133 mEGLContext = nullptr;
136 eglImpl.TerminateGles();
138 mGraphics->Destroy();
141 delete mDisplayConnection;
144 void GlWindow::Initialize( const PositionSize& positionSize, const std::string& name, const std::string& className )
146 int screenWidth, screenHeight;
148 mPositionSize = positionSize;
149 WindowSystem::GetScreenSize( screenWidth, screenHeight );
150 if ( (mPositionSize.width == 0) || (mPositionSize.height == 0) )
154 mPositionSize.width = screenWidth;
155 mPositionSize.height = screenHeight;
158 if( screenWidth > screenHeight )
160 mOrientationMode = 1; // Default mode is landscape
164 mOrientationMode = 0; // Default mode is portrate
167 // Create a window base
168 auto windowFactory = Dali::Internal::Adaptor::GetWindowFactory();
170 mWindowBase = windowFactory->CreateWindowBase( mPositionSize, surface, ( mIsTransparent ? true : false ) );
171 mWindowBase->IconifyChangedSignal().Connect( this, &GlWindow::OnIconifyChanged );
172 mWindowBase->FocusChangedSignal().Connect( this, &GlWindow::OnFocusChanged );
176 if( !mPositionSize.IsEmpty() )
178 AddAuxiliaryHint( "wm.policy.win.user.geometry", "1" );
179 mResizedEnabled = true;
186 mColorDepth = COLOR_DEPTH_32;
190 mColorDepth = COLOR_DEPTH_24;
193 SetClass( name, className );
196 mNativeWindowId = mWindowBase->GetNativeWindowId();
199 void GlWindow::SetEventHandler()
201 mEventHandler = EventHandlerPtr( new EventHandler( mWindowBase.get(), *this ) );
202 mEventHandler->AddObserver( *this );
205 void GlWindow::SetClass( const std::string name, const std::string className )
208 mClassName = className;
209 mWindowBase->SetClass( name, className );
212 void GlWindow::SetEglConfig( bool depth, bool stencil, int msaa, Dali::GlWindow::GlesVersion version )
218 mGLESVersion = version;
220 InitializeGraphics();
223 void GlWindow::Raise()
225 mWindowBase->Raise();
226 DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Raise() \n", this, mNativeWindowId );
229 void GlWindow::Lower()
231 mWindowBase->Lower();
232 DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Lower() \n", this, mNativeWindowId );
235 void GlWindow::Activate()
237 mWindowBase->Activate();
238 DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Activate() \n", this, mNativeWindowId );
241 void GlWindow::Show()
249 Dali::GlWindow handle( this );
250 mVisibilityChangedSignal.Emit( handle, true );
255 mEventHandler->Resume();
258 DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Show(): iconified = %d, visible = %d\n", this, mNativeWindowId, mIconified, mVisible );
261 void GlWindow::Hide()
269 Dali::GlWindow handle( this );
270 mVisibilityChangedSignal.Emit( handle, false );
275 mEventHandler->Pause();
278 DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Hide(): iconified = %d, visible = %d\n", this, mNativeWindowId, mIconified, mVisible );
281 unsigned int GlWindow::GetSupportedAuxiliaryHintCount() const
283 return mWindowBase->GetSupportedAuxiliaryHintCount();
286 std::string GlWindow::GetSupportedAuxiliaryHint( unsigned int index ) const
288 return mWindowBase->GetSupportedAuxiliaryHint( index );
291 unsigned int GlWindow::AddAuxiliaryHint( const std::string& hint, const std::string& value )
293 return mWindowBase->AddAuxiliaryHint( hint, value );
296 bool GlWindow::RemoveAuxiliaryHint( unsigned int id )
298 return mWindowBase->RemoveAuxiliaryHint( id );
301 bool GlWindow::SetAuxiliaryHintValue( unsigned int id, const std::string& value )
303 return mWindowBase->SetAuxiliaryHintValue( id, value );
306 std::string GlWindow::GetAuxiliaryHintValue( unsigned int id ) const
308 return mWindowBase->GetAuxiliaryHintValue( id );
311 unsigned int GlWindow::GetAuxiliaryHintId( const std::string& hint ) const
313 return mWindowBase->GetAuxiliaryHintId( hint );
316 void GlWindow::SetInputRegion( const Rect< int >& inputRegion )
318 mWindowBase->SetInputRegion( inputRegion );
320 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 );
323 void GlWindow::SetOpaqueState( bool opaque )
325 mOpaqueState = opaque;
327 mWindowBase->SetOpaqueState( opaque );
329 DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "GlWindow::SetOpaqueState: opaque = %d\n", opaque );
332 bool GlWindow::IsOpaqueState() const
337 void GlWindow::SetPositionSize( PositionSize positionSize )
339 if( !mResizedEnabled )
341 AddAuxiliaryHint( "wm.policy.win.user.geometry", "1" );
342 mResizedEnabled = true;
345 bool needToMove = false;
346 bool needToResize = false;
349 if( (fabs(positionSize.x - mPositionSize.x) > MINIMUM_DIMENSION_CHANGE) ||
350 (fabs(positionSize.y - mPositionSize.y) > MINIMUM_DIMENSION_CHANGE) )
356 if( (fabs(positionSize.width - mPositionSize.width) > MINIMUM_DIMENSION_CHANGE) ||
357 (fabs(positionSize.height - mPositionSize.height) > MINIMUM_DIMENSION_CHANGE) )
366 mWindowBase->MoveResize( positionSize );
370 mWindowBase->Resize( positionSize );
372 mPositionSize = positionSize;
378 mWindowBase->Move( positionSize );
379 mPositionSize = positionSize;
383 // If window's size or position is changed, the signal will be emitted to user.
384 if( ( needToMove ) || ( needToResize ) )
386 Uint16Pair newSize( mPositionSize.width, mPositionSize.height );
387 mResizedSignal.Emit( newSize );
391 PositionSize GlWindow::GetPositionSize() const
393 PositionSize positionSize( mPositionSize );
394 if( mTotalRotationAngle == 90 || mTotalRotationAngle == 270 )
396 positionSize.height = mPositionSize.width;
397 positionSize.width = mPositionSize.height;
403 void GlWindow::OnIconifyChanged( bool iconified )
411 Dali::GlWindow handle( this );
412 mVisibilityChangedSignal.Emit( handle, false );
417 mEventHandler->Pause();
420 DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Iconified: visible = %d\n", this, mNativeWindowId, mVisible );
428 Dali::GlWindow handle( this );
429 mVisibilityChangedSignal.Emit( handle, true );
434 mEventHandler->Resume();
437 DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Deiconified: visible = %d\n", this, mNativeWindowId, mVisible );
441 void GlWindow::OnFocusChanged( bool focusIn )
443 Dali::GlWindow handle( this );
444 mFocusChangeSignal.Emit( handle, focusIn );
447 void GlWindow::OnOutputTransformed()
449 int screenRotationAngle = mWindowBase->GetScreenRotationAngle();
450 if( screenRotationAngle != mScreenRotationAngle )
452 mScreenRotationAngle = screenRotationAngle;
453 mTotalRotationAngle = (mWindowRotationAngle + mScreenRotationAngle) % 360;
455 if( mTotalRotationAngle == 90 || mTotalRotationAngle == 270 )
457 mWindowWidth = mPositionSize.height;
458 mWindowHeight = mPositionSize.width;
462 mWindowWidth = mPositionSize.width;
463 mWindowHeight = mPositionSize.height;
466 // Emit Resized signal
467 mResizedSignal.Emit( Dali::Uint16Pair( mWindowWidth, mWindowHeight ) );
471 void GlWindow::OnTouchPoint( Dali::Integration::Point& point, int timeStamp )
473 PointState::Type state = point.GetState();
475 if( state == PointState::DOWN )
480 if( state == PointState::UP )
485 if( !mIsTouched && state == PointState::MOTION )
490 Dali::TouchEvent touchEvent = Dali::Integration::NewTouchEvent( timeStamp, point );
491 mTouchSignal.Emit( touchEvent );
494 void GlWindow::OnWheelEvent( Dali::Integration::WheelEvent& wheelEvent )
497 //FeedWheelEvent( wheelEvent );
500 void GlWindow::OnKeyEvent( Dali::Integration::KeyEvent& keyEvent )
502 Dali::KeyEvent event = Dali::Integration::KeyEvent::Convert( keyEvent );
503 mKeyEventSignal.Emit( event );
506 void GlWindow::OnRotation( const RotationEvent& rotation )
508 mWindowRotationAngle = rotation.angle;
509 mTotalRotationAngle = ( mWindowRotationAngle + mScreenRotationAngle ) % 360;
510 if( mTotalRotationAngle == 90 || mTotalRotationAngle == 270 )
512 mWindowWidth = mPositionSize.height;
513 mWindowHeight = mPositionSize.width;
517 mWindowWidth = mPositionSize.width;
518 mWindowHeight = mPositionSize.height;
522 mIsWindowRotated = true;
523 DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), OnRotation(): resized signal emit [%d x %d]\n", this, mNativeWindowId, mWindowWidth, mWindowHeight );
525 // Emit Resized signal
526 mResizedSignal.Emit( Dali::Uint16Pair( mWindowWidth, mWindowHeight ) );
529 void GlWindow::RecalculateTouchPosition( Integration::Point& point )
531 Vector2 position = point.GetScreenPosition();
532 Vector2 convertedPosition;
534 switch( mTotalRotationAngle )
538 convertedPosition.x = static_cast<float>( mWindowWidth ) - position.y;
539 convertedPosition.y = position.x;
544 convertedPosition.x = static_cast<float>( mWindowWidth ) - position.x;
545 convertedPosition.y = static_cast<float>( mWindowHeight ) - position.y;
550 convertedPosition.x = position.y;
551 convertedPosition.y = static_cast<float>( mWindowHeight ) - position.x;
556 convertedPosition = position;
561 point.SetScreenPosition( convertedPosition );
564 void GlWindow::SetAvailableAnlges( const std::vector< int >& angles )
566 if( angles.size() > 4 )
568 DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::SetAvailableAnlges: Invalid vector size! [%d]\n", angles.size() );
572 mWindowBase->SetAvailableAnlges( angles );
575 bool GlWindow::IsOrientationAvailable( Dali::GlWindow::GlWindowOrientation orientation ) const
577 if( orientation <= Dali::GlWindow::GlWindowOrientation::NO_ORIENTATION_PREFERENCE
578 || orientation > Dali::GlWindow::GlWindowOrientation::LANDSCAPE_INVERSE )
580 DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::IsOrientationAvailable: Invalid input orientation [%d]\n", orientation );
586 int GlWindow::ConvertToAngle( Dali::GlWindow::GlWindowOrientation orientation )
588 int convertAngle = 0;
589 if ( mOrientationMode == 0 )
591 convertAngle = ( static_cast< int >( orientation ) ) * 90;
593 else if( mOrientationMode == 1)
595 switch( orientation )
597 case Dali::GlWindow::GlWindowOrientation::LANDSCAPE:
602 case Dali::GlWindow::GlWindowOrientation::PORTRAIT:
607 case Dali::GlWindow::GlWindowOrientation::LANDSCAPE_INVERSE:
612 case Dali::GlWindow::GlWindowOrientation::PORTRAIT_INVERSE:
617 case Dali::GlWindow::GlWindowOrientation::NO_ORIENTATION_PREFERENCE:
627 Dali::GlWindow::GlWindowOrientation GlWindow::ConvertToOrientation( int angle ) const
629 Dali::GlWindow::GlWindowOrientation orientation = Dali::GlWindow::GlWindowOrientation::NO_ORIENTATION_PREFERENCE;
630 if ( mOrientationMode == 0 ) // Portrate mode
632 orientation = static_cast< Dali::GlWindow::GlWindowOrientation >( angle / 90 );
634 else if( mOrientationMode == 1 ) // Landscape mode
640 orientation = Dali::GlWindow::GlWindowOrientation::LANDSCAPE;
645 orientation = Dali::GlWindow::GlWindowOrientation::PORTRAIT;
650 orientation = Dali::GlWindow::GlWindowOrientation::LANDSCAPE_INVERSE;
655 orientation = Dali::GlWindow::GlWindowOrientation::PORTRAIT_INVERSE;
660 orientation = Dali::GlWindow::GlWindowOrientation::NO_ORIENTATION_PREFERENCE;
668 Dali::GlWindow::GlWindowOrientation GlWindow::GetCurrentOrientation() const
670 DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), GetCurrentOrientation(): %d\n", this, mNativeWindowId, mTotalRotationAngle );
671 return ConvertToOrientation( mTotalRotationAngle );
674 void GlWindow::SetAvailableOrientations( const Dali::Vector< Dali::GlWindow::GlWindowOrientation >& orientations )
676 Dali::Vector<float>::SizeType count = orientations.Count();
677 for( Dali::Vector<float>::SizeType index = 0; index < count; ++index )
679 if( IsOrientationAvailable( orientations[index] ) == false )
681 DALI_LOG_ERROR("Window::SetAvailableRotationAngles, invalid angle: %d\n", orientations[index]);
686 int angle = ConvertToAngle( orientations[index] );
688 for( std::size_t i = 0; i < mAvailableAngles.size(); i++ )
690 if( mAvailableAngles[i] == angle )
699 DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), SetAvailableOrientations: %d\n", this, mNativeWindowId, angle );
700 mAvailableAngles.push_back( angle );
703 SetAvailableAnlges( mAvailableAngles );
706 void GlWindow::SetPreferredOrientation( Dali::GlWindow::GlWindowOrientation orientation )
708 if( IsOrientationAvailable( orientation ) == false )
710 DALI_LOG_ERROR( "Window::SetPreferredOrientation, invalid orientation: %d\n", orientation );
713 mPreferredAngle = ConvertToAngle( orientation );
714 DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), SetPreferredOrientation: %d\n", this, mNativeWindowId, mPreferredAngle );
715 mWindowBase->SetPreferredAngle( mPreferredAngle );
718 void GlWindow::SetChild( Dali::Window& child )
720 if( DALI_UNLIKELY( child ) )
722 mChildWindow = child;
723 Internal::Adaptor::Window& windowImpl = Dali::GetImplementation( mChildWindow );
724 WindowRenderSurface* renderSurface = static_cast<WindowRenderSurface*>( windowImpl.GetSurface() );
725 WindowBase* childWindowBase = renderSurface->GetWindowBase();
726 childWindowBase->SetParent( mWindowBase.get() );
730 void GlWindow::RegisterGlCallback( GlInitialize glInit, GlRenderFrame glRenderFrame, GlTerminate glTerminate )
732 if( mIsEGLInitialize == false )
734 InitializeGraphics();
736 mGLInitCallback = glInit;
737 mGLRenderFrameCallback = glRenderFrame;
738 mGLTerminateCallback = glTerminate;
740 mInitCallback = false;
742 if( !mGLRenderCallback )
744 mGLRenderCallback = MakeCallback( this, &GlWindow::RunCallback );
746 Dali::Adaptor::Get().AddIdle( mGLRenderCallback, true );
750 bool GlWindow::RunCallback()
752 GraphicsInterface* graphics = mGraphics.get();
753 EglGraphics *eglGraphics = static_cast<EglGraphics*>( graphics );
754 Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
756 eglImpl.MakeContextCurrent( mEGLSurface, mEGLContext );
760 mWindowBase->SetEglWindowBufferTransform( mTotalRotationAngle );
761 if( mIsWindowRotated )
763 mWindowBase->SetEglWindowTransform( mWindowRotationAngle );
771 mInitCallback = true;
774 mGLRenderFrameCallback();
776 if( mIsWindowRotated )
778 mWindowBase->WindowRotationCompleted( mWindowRotationAngle, mPositionSize.width, mPositionSize.height );
779 mIsWindowRotated = false;
782 eglImpl.SwapBuffers( mEGLSurface );
787 void GlWindow::RenderOnce()
792 int32_t GlWindow::GetNativeId() const
794 return mWindowBase->GetNativeWindowId();
797 void GlWindow::InitializeGraphics()
799 if( !mIsEGLInitialize )
802 std::unique_ptr< GraphicsFactory > graphicsFactoryPtr = Utils::MakeUnique< GraphicsFactory >();
803 auto graphicsFactory = *graphicsFactoryPtr.get();
805 mGraphics = std::unique_ptr< GraphicsInterface >( &graphicsFactory.Create() );
806 GraphicsInterface* graphics = mGraphics.get();
807 EglGraphics *eglGraphics = static_cast<EglGraphics*>( graphics );
808 eglGraphics->Initialize( mDepth, mStencil, mMSAA );
809 eglGraphics->Create();
811 mDisplayConnection = Dali::DisplayConnection::New( *graphics, Dali::RenderSurfaceInterface::Type::WINDOW_RENDER_SURFACE );
812 mDisplayConnection->Initialize();
814 Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
815 if( mGLESVersion == Dali::GlWindow::GlesVersion::VERSION_2_0 )
817 eglImpl.SetGlesVersion( 20 );
819 else if( mGLESVersion == Dali::GlWindow::GlesVersion::VERSION_3_0 )
821 eglImpl.SetGlesVersion( 30 );
824 if( eglImpl.ChooseConfig(true, mColorDepth) == false )
826 if( mGLESVersion == Dali::GlWindow::GlesVersion::VERSION_3_0 )
828 DALI_LOG_RELEASE_INFO( "InitializeGraphics: Fail to choose config with GLES30, retry with GLES20\n" );
829 eglImpl.SetGlesVersion( 20 );
830 mGLESVersion = Dali::GlWindow::GlesVersion::VERSION_2_0;
831 if( eglImpl.ChooseConfig(true, mColorDepth) == false )
833 DALI_LOG_ERROR("InitializeGraphics: Fail to choose config with GLES20");
839 DALI_LOG_ERROR("InitializeGraphics: Fail to choose config with GLES20");
843 eglImpl.CreateWindowContext( mEGLContext );
845 // Create the EGL window
846 EGLNativeWindowType window = mWindowBase->CreateEglWindow( mPositionSize.width, mPositionSize.height );
847 mEGLSurface = eglImpl.CreateSurfaceWindow( window, mColorDepth );
849 mIsEGLInitialize = true;
853 void GlWindow::OnDamaged( const DamageArea& area )