2 * Copyright (c) 2021 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>
22 #include <dali/devel-api/adaptor-framework/gl-window.h>
23 #include <dali/devel-api/adaptor-framework/orientation.h>
24 #include <dali/devel-api/events/key-event-devel.h>
25 #include <dali/integration-api/core.h>
26 #include <dali/integration-api/events/key-event-integ.h>
27 #include <dali/integration-api/events/touch-integ.h>
30 #include <dali/internal/graphics/gles/egl-graphics-factory.h>
31 #include <dali/internal/window-system/common/display-utils.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-base.h>
35 #include <dali/internal/window-system/common/window-factory.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-system.h>
39 #include <dali/internal/window-system/common/window-visibility-observer.h>
49 const int MINIMUM_DIMENSION_CHANGE(1);
51 #if defined(DEBUG_ENABLED)
52 Debug::Filter* gWindowLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_WINDOW");
55 } // unnamed namespace
57 GlWindow* GlWindow::New(const PositionSize& positionSize, const std::string& name, const std::string& className, bool isTransparent)
59 GlWindow* window = new GlWindow();
60 window->mIsTransparent = isTransparent;
61 window->Initialize(positionSize, name, className);
68 mDisplayConnection(nullptr),
69 mGlWindowRenderThread(nullptr),
70 mEventHandler(nullptr),
71 mIsTransparent(false),
72 mIsFocusAcceptable(false),
75 mResizeEnabled(false),
77 mIsWindowRotated(false),
79 mIsEGLInitialized(false),
84 mColorDepth(COLOR_DEPTH_24),
85 mRenderingMode(Dali::GlWindow::RenderingMode::CONTINUOUS),
87 mTotalRotationAngle(0),
88 mWindowRotationAngle(0),
89 mScreenRotationAngle(0),
99 mVisibilityChangedSignal()
103 GlWindow::~GlWindow()
107 mEventHandler->RemoveObserver(*this);
110 if(mGlWindowRenderThread)
112 mGlWindowRenderThread->Stop();
113 mGlWindowRenderThread->Join();
116 if(mIsEGLInitialized)
118 mGraphics->Destroy();
122 void GlWindow::Initialize(const PositionSize& positionSize, const std::string& name, const std::string& className)
124 int screenWidth, screenHeight;
126 mPositionSize = positionSize;
127 WindowSystem::GetScreenSize(screenWidth, screenHeight);
128 if((mPositionSize.width == 0) || (mPositionSize.height == 0))
132 mPositionSize.width = screenWidth;
133 mPositionSize.height = screenHeight;
136 if(screenWidth > screenHeight)
138 mOrientationMode = 1; // Default mode is landscape
142 mOrientationMode = 0; // Default mode is portrate
145 // Create a window base
146 auto windowFactory = Dali::Internal::Adaptor::GetWindowFactory();
148 mWindowBase = windowFactory->CreateWindowBase(mPositionSize, surface, (mIsTransparent ? true : false));
149 mWindowBase->IconifyChangedSignal().Connect(this, &GlWindow::OnIconifyChanged);
150 mWindowBase->FocusChangedSignal().Connect(this, &GlWindow::OnFocusChanged);
151 mWindowBase->OutputTransformedSignal().Connect(this, &GlWindow::OnOutputTransformed);
153 if(Dali::Adaptor::IsAvailable())
158 if(!mPositionSize.IsEmpty())
160 AddAuxiliaryHint("wm.policy.win.user.geometry", "1");
161 mResizeEnabled = true;
168 mColorDepth = COLOR_DEPTH_32;
172 mColorDepth = COLOR_DEPTH_24;
175 SetClass(name, className);
178 mNativeWindowId = mWindowBase->GetNativeWindowId();
181 void GlWindow::SetEventHandler()
183 mEventHandler = EventHandlerPtr(new EventHandler(mWindowBase.get(), *this));
184 mEventHandler->AddObserver(*this);
187 void GlWindow::SetClass(const std::string& name, const std::string className)
190 mClassName = className;
191 mWindowBase->SetClass(name, className);
194 void GlWindow::SetEglConfig(bool depth, bool stencil, int msaa, Dali::GlWindow::GlesVersion version)
201 InitializeGraphics();
205 if(version == Dali::GlWindow::GlesVersion::VERSION_2_0)
209 else if(version == Dali::GlWindow::GlesVersion::VERSION_3_0)
214 mGlWindowRenderThread->SetEglConfig(depth, stencil, msaa, rVersion);
217 void GlWindow::Raise()
219 mWindowBase->Raise();
220 DALI_LOG_RELEASE_INFO("Window (%p), WinId (%d), Raise() \n", this, mNativeWindowId);
223 void GlWindow::Lower()
225 mWindowBase->Lower();
226 DALI_LOG_RELEASE_INFO("Window (%p), WinId (%d), Lower() \n", this, mNativeWindowId);
229 void GlWindow::Activate()
231 mWindowBase->Activate();
232 DALI_LOG_RELEASE_INFO("Window (%p), WinId (%d), Activate() \n", this, mNativeWindowId);
235 void GlWindow::Show()
243 Dali::GlWindow handle(this);
244 mVisibilityChangedSignal.Emit(handle, true);
249 mEventHandler->Resume();
252 if(mGlWindowRenderThread)
254 mGlWindowRenderThread->Resume();
257 DALI_LOG_RELEASE_INFO("Window (%p), WinId (%d), Show(): iconified = %d, visible = %d\n", this, mNativeWindowId, mIconified, mVisible);
260 void GlWindow::Hide()
268 Dali::GlWindow handle(this);
269 mVisibilityChangedSignal.Emit(handle, false);
274 mEventHandler->Pause();
277 if(mGlWindowRenderThread)
279 mGlWindowRenderThread->Pause();
282 DALI_LOG_RELEASE_INFO("Window (%p), WinId (%d), Hide(): iconified = %d, visible = %d\n", this, mNativeWindowId, mIconified, mVisible);
285 unsigned int GlWindow::GetSupportedAuxiliaryHintCount() const
287 return mWindowBase->GetSupportedAuxiliaryHintCount();
290 std::string GlWindow::GetSupportedAuxiliaryHint(unsigned int index) const
292 return mWindowBase->GetSupportedAuxiliaryHint(index);
295 unsigned int GlWindow::AddAuxiliaryHint(const std::string& hint, const std::string& value)
297 return mWindowBase->AddAuxiliaryHint(hint, value);
300 bool GlWindow::RemoveAuxiliaryHint(unsigned int id)
302 return mWindowBase->RemoveAuxiliaryHint(id);
305 bool GlWindow::SetAuxiliaryHintValue(unsigned int id, const std::string& value)
307 return mWindowBase->SetAuxiliaryHintValue(id, value);
310 std::string GlWindow::GetAuxiliaryHintValue(unsigned int id) const
312 return mWindowBase->GetAuxiliaryHintValue(id);
315 unsigned int GlWindow::GetAuxiliaryHintId(const std::string& hint) const
317 return mWindowBase->GetAuxiliaryHintId(hint);
320 void GlWindow::SetInputRegion(const Rect<int>& inputRegion)
322 mWindowBase->SetInputRegion(inputRegion);
324 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);
327 void GlWindow::SetOpaqueState(bool opaque)
329 mOpaqueState = opaque;
331 mWindowBase->SetOpaqueState(opaque);
333 DALI_LOG_INFO(gWindowLogFilter, Debug::Verbose, "GlWindow::SetOpaqueState: opaque = %d\n", opaque);
336 bool GlWindow::IsOpaqueState() const
341 void GlWindow::SetPositionSize(PositionSize positionSize)
345 AddAuxiliaryHint("wm.policy.win.user.geometry", "1");
346 mResizeEnabled = true;
349 bool needToMove = false;
350 bool needToResize = false;
353 if((fabs(positionSize.x - mPositionSize.x) > MINIMUM_DIMENSION_CHANGE) ||
354 (fabs(positionSize.y - mPositionSize.y) > MINIMUM_DIMENSION_CHANGE))
360 if((fabs(positionSize.width - mPositionSize.width) > MINIMUM_DIMENSION_CHANGE) ||
361 (fabs(positionSize.height - mPositionSize.height) > MINIMUM_DIMENSION_CHANGE))
370 mWindowBase->MoveResize(positionSize);
374 mWindowBase->Resize(positionSize);
376 mPositionSize = positionSize;
382 mWindowBase->Move(positionSize);
383 mPositionSize = positionSize;
387 // If window's size or position is changed, the signal will be emitted to user.
388 if(needToMove || needToResize)
390 Uint16Pair newSize(mPositionSize.width, mPositionSize.height);
391 Dali::GlWindow handle(this);
392 mResizeSignal.Emit(newSize);
394 if(mGlWindowRenderThread)
396 mGlWindowRenderThread->RequestWindowResize(mPositionSize.width, mPositionSize.height);
401 PositionSize GlWindow::GetPositionSize() const
403 PositionSize positionSize(mPositionSize);
404 if(mTotalRotationAngle == 90 || mTotalRotationAngle == 270)
406 positionSize.height = mPositionSize.width;
407 positionSize.width = mPositionSize.height;
413 void GlWindow::OnIconifyChanged(bool iconified)
421 Dali::GlWindow handle(this);
422 mVisibilityChangedSignal.Emit(handle, false);
427 mEventHandler->Pause();
430 if(mGlWindowRenderThread)
432 mGlWindowRenderThread->Pause();
435 DALI_LOG_RELEASE_INFO("Window (%p), WinId (%d), Iconified: visible = %d\n", this, mNativeWindowId, mVisible);
443 Dali::GlWindow handle(this);
444 mVisibilityChangedSignal.Emit(handle, true);
449 mEventHandler->Resume();
452 if(mGlWindowRenderThread)
454 mGlWindowRenderThread->Resume();
457 DALI_LOG_RELEASE_INFO("Window (%p), WinId (%d), Deiconified: visible = %d\n", this, mNativeWindowId, mVisible);
461 void GlWindow::OnFocusChanged(bool focusIn)
463 Dali::GlWindow handle(this);
464 mFocusChangeSignal.Emit(handle, focusIn);
467 void GlWindow::OnOutputTransformed()
469 int newScreenRotationAngle = mWindowBase->GetScreenRotationAngle();
470 DALI_LOG_RELEASE_INFO("GlWindow::OnOutputTransformed(), screen rotation occurs, old[%d], new[%d\n", mScreenRotationAngle, newScreenRotationAngle);
472 if(newScreenRotationAngle != mScreenRotationAngle)
474 UpdateScreenRotation(newScreenRotationAngle);
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 Dali::GlWindow handle(this);
500 mTouchedSignal.Emit(touchEvent);
503 void GlWindow::OnWheelEvent(Dali::Integration::WheelEvent& wheelEvent)
506 //FeedWheelEvent( wheelEvent );
509 void GlWindow::OnKeyEvent(Dali::Integration::KeyEvent& keyEvent)
511 Dali::KeyEvent event = Dali::DevelKeyEvent::New(keyEvent.keyName, keyEvent.logicalKey, keyEvent.keyString, keyEvent.keyCode, keyEvent.keyModifier, keyEvent.time, static_cast<Dali::KeyEvent::State>(keyEvent.state), keyEvent.compose, keyEvent.deviceName, keyEvent.deviceClass, keyEvent.deviceSubclass);
512 Dali::GlWindow handle(this);
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;
531 DALI_LOG_RELEASE_INFO("Window (%p), WinId (%d), OnRotation(): resize signal emit [%d x %d]\n", this, mNativeWindowId, mWindowWidth, mWindowHeight);
533 // Emit Resize signal
534 Dali::GlWindow handle(this);
535 mResizeSignal.Emit(Dali::Uint16Pair(mWindowWidth, mWindowHeight));
537 if(mGlWindowRenderThread)
539 mGlWindowRenderThread->RequestWindowRotate(mWindowRotationAngle);
543 void GlWindow::RecalculateTouchPosition(Integration::Point& point)
545 Vector2 position = point.GetScreenPosition();
546 Vector2 convertedPosition;
548 switch(mTotalRotationAngle)
552 convertedPosition.x = static_cast<float>(mWindowWidth) - position.y;
553 convertedPosition.y = position.x;
558 convertedPosition.x = static_cast<float>(mWindowWidth) - position.x;
559 convertedPosition.y = static_cast<float>(mWindowHeight) - position.y;
564 convertedPosition.x = position.y;
565 convertedPosition.y = static_cast<float>(mWindowHeight) - position.x;
570 convertedPosition = position;
575 point.SetScreenPosition(convertedPosition);
578 void GlWindow::SetAvailableAnlges(const std::vector<int>& angles)
580 if(angles.size() > 4)
582 DALI_LOG_INFO(gWindowLogFilter, Debug::Verbose, "Window::SetAvailableAnlges: Invalid vector size! [%d]\n", angles.size());
586 mWindowBase->SetAvailableAnlges(angles);
589 bool GlWindow::IsOrientationAvailable(WindowOrientation orientation) const
591 if(orientation <= WindowOrientation::NO_ORIENTATION_PREFERENCE || orientation > WindowOrientation::LANDSCAPE_INVERSE)
593 DALI_LOG_INFO(gWindowLogFilter, Debug::Verbose, "Window::IsOrientationAvailable: Invalid input orientation [%d]\n", orientation);
599 int GlWindow::ConvertToAngle(WindowOrientation orientation)
601 int convertAngle = 0;
602 if(mOrientationMode == 0)
604 convertAngle = static_cast<int>(orientation);
606 else if(mOrientationMode == 1)
610 case WindowOrientation::LANDSCAPE:
615 case WindowOrientation::PORTRAIT:
620 case WindowOrientation::LANDSCAPE_INVERSE:
625 case WindowOrientation::PORTRAIT_INVERSE:
630 case WindowOrientation::NO_ORIENTATION_PREFERENCE:
640 WindowOrientation GlWindow::ConvertToOrientation(int angle) const
642 WindowOrientation orientation = WindowOrientation::NO_ORIENTATION_PREFERENCE;
643 if(mOrientationMode == 0) // Portrate mode
645 orientation = static_cast<WindowOrientation>(angle);
647 else if(mOrientationMode == 1) // Landscape mode
653 orientation = WindowOrientation::LANDSCAPE;
658 orientation = WindowOrientation::PORTRAIT;
663 orientation = WindowOrientation::LANDSCAPE_INVERSE;
668 orientation = WindowOrientation::PORTRAIT_INVERSE;
673 orientation = WindowOrientation::NO_ORIENTATION_PREFERENCE;
681 WindowOrientation GlWindow::GetCurrentOrientation() const
683 DALI_LOG_RELEASE_INFO("Window (%p), WinId (%d), GetCurrentOrientation(): %d\n", this, mNativeWindowId, mTotalRotationAngle);
684 return ConvertToOrientation(mTotalRotationAngle);
687 void GlWindow::SetAvailableOrientations(const Dali::Vector<WindowOrientation>& orientations)
689 Dali::Vector<float>::SizeType count = orientations.Count();
690 for(Dali::Vector<float>::SizeType index = 0; index < count; ++index)
692 if(IsOrientationAvailable(orientations[index]) == false)
694 DALI_LOG_ERROR("Window::SetAvailableRotationAngles, invalid angle: %d\n", orientations[index]);
699 int angle = ConvertToAngle(orientations[index]);
701 for(std::size_t i = 0; i < mAvailableAngles.size(); i++)
703 if(mAvailableAngles[i] == angle)
712 DALI_LOG_RELEASE_INFO("Window (%p), WinId (%d), SetAvailableOrientations: %d\n", this, mNativeWindowId, angle);
713 mAvailableAngles.push_back(angle);
716 SetAvailableAnlges(mAvailableAngles);
719 void GlWindow::SetPreferredOrientation(WindowOrientation orientation)
721 if(IsOrientationAvailable(orientation) == false)
723 DALI_LOG_ERROR("Window::SetPreferredOrientation, invalid orientation: %d\n", orientation);
726 mPreferredAngle = ConvertToAngle(orientation);
727 DALI_LOG_RELEASE_INFO("Window (%p), WinId (%d), SetPreferredOrientation: %d\n", this, mNativeWindowId, mPreferredAngle);
728 mWindowBase->SetPreferredAngle(mPreferredAngle);
731 void GlWindow::SetChild(Dali::Window& child)
733 if(DALI_UNLIKELY(child))
735 mChildWindow = child;
736 Internal::Adaptor::Window& windowImpl = Dali::GetImplementation(mChildWindow);
737 WindowRenderSurface* renderSurface = static_cast<WindowRenderSurface*>(windowImpl.GetSurface());
740 WindowBase* childWindowBase = renderSurface->GetWindowBase();
743 childWindowBase->SetParent(mWindowBase.get(), false);
749 void GlWindow::RegisterGlCallback(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback)
751 if(mIsEGLInitialized == false)
753 InitializeGraphics();
755 mGlWindowRenderThread->RegisterGlCallback(initCallback, renderFrameCallback, terminateCallback);
756 mGlWindowRenderThread->Start();
759 void GlWindow::RenderOnce()
761 if(mGlWindowRenderThread)
763 mGlWindowRenderThread->RenderOnce();
767 void GlWindow::SetRenderingMode(Dali::GlWindow::RenderingMode mode)
769 mRenderingMode = mode;
770 if(mGlWindowRenderThread)
772 bool onDemand = false;
773 if(mRenderingMode == Dali::GlWindow::RenderingMode::ON_DEMAND)
777 mGlWindowRenderThread->SetOnDemandRenderMode(onDemand);
781 Dali::GlWindow::RenderingMode GlWindow::GetRenderingMode() const
783 return mRenderingMode;
786 void GlWindow::InitializeGraphics()
788 if(!mIsEGLInitialized)
791 std::unique_ptr<GraphicsFactory> graphicsFactoryPtr = Utils::MakeUnique<GraphicsFactory>(mEnvironmentOptions);
792 auto graphicsFactory = *graphicsFactoryPtr.get();
794 mGraphics = std::unique_ptr<GraphicsInterface>(&graphicsFactory.Create());
795 GraphicsInterface* graphics = mGraphics.get();
796 EglGraphics* eglGraphics = static_cast<EglGraphics*>(graphics);
797 eglGraphics->Initialize(mDepth, mStencil, false, mMSAA);
799 mDisplayConnection = std::unique_ptr<Dali::DisplayConnection>(Dali::DisplayConnection::New(*graphics, Dali::RenderSurfaceInterface::Type::WINDOW_RENDER_SURFACE));
800 mDisplayConnection->Initialize();
802 // Create Render Thread
803 mGlWindowRenderThread = std::unique_ptr<Dali::Internal::Adaptor::GlWindowRenderThread>(new GlWindowRenderThread(mPositionSize, mColorDepth));
804 if(!mGlWindowRenderThread)
806 DALI_LOG_ERROR("Fail to create GlWindow Render Thread!!!!\n");
810 mGlWindowRenderThread->SetGraphicsInterface(graphics);
811 mGlWindowRenderThread->SetWindowBase(mWindowBase.get());
812 bool onDemand = false;
813 if(mRenderingMode == Dali::GlWindow::RenderingMode::ON_DEMAND)
817 mGlWindowRenderThread->SetOnDemandRenderMode(onDemand);
819 mIsEGLInitialized = true;
821 // Check screen rotation
822 int newScreenRotationAngle = mWindowBase->GetScreenRotationAngle();
823 DALI_LOG_RELEASE_INFO("GlWindow::InitializeGraphics(), GetScreenRotationAngle(): %d\n", mScreenRotationAngle);
824 if(newScreenRotationAngle != 0)
826 UpdateScreenRotation(newScreenRotationAngle);
831 void GlWindow::OnDamaged(const DamageArea& area)
835 void GlWindow::UpdateScreenRotation(int newAngle)
837 mScreenRotationAngle = newAngle;
838 mTotalRotationAngle = (mWindowRotationAngle + mScreenRotationAngle) % 360;
840 if(mTotalRotationAngle == 90 || mTotalRotationAngle == 270)
842 mWindowWidth = mPositionSize.height;
843 mWindowHeight = mPositionSize.width;
847 mWindowWidth = mPositionSize.width;
848 mWindowHeight = mPositionSize.height;
851 // Emit Resize signal
852 Dali::GlWindow handle(this);
853 mResizeSignal.Emit(Dali::Uint16Pair(mWindowWidth, mWindowHeight));
855 if(mGlWindowRenderThread)
857 DALI_LOG_RELEASE_INFO("GlWindow::UpdateScreenRotation(), RequestScreenRotatem(), mScreenRotationAngle: %d\n", mScreenRotationAngle);
858 mGlWindowRenderThread->RequestScreenRotate(mScreenRotationAngle);
862 } // namespace Adaptor
864 } // namespace Internal