From 22a519fe38414017565958ee4b72e8307213257e Mon Sep 17 00:00:00 2001 From: Daekwang Ryu Date: Tue, 15 Sep 2020 11:49:11 +0900 Subject: [PATCH] [Tizen] Add GlWindow Add GlWindow to support the native GLES Application. Change-Id: I0737eda18fd42caf1cac58e588a05f978479598f --- dali/devel-api/adaptor-framework/gl-window.cpp | 192 +++++ dali/devel-api/adaptor-framework/gl-window.h | 439 +++++++++++ dali/devel-api/file.list | 2 + dali/internal/graphics/gles/egl-graphics.cpp | 12 + dali/internal/graphics/gles/egl-graphics.h | 8 + .../window-system/common/event-handler.cpp | 29 +- dali/internal/window-system/common/event-handler.h | 4 +- .../window-system/common/gl-window-impl.cpp | 878 +++++++++++++++++++++ .../internal/window-system/common/gl-window-impl.h | 418 ++++++++++ dali/internal/window-system/common/window-impl.cpp | 2 +- dali/internal/window-system/file.list | 1 + 11 files changed, 1965 insertions(+), 20 deletions(-) create mode 100644 dali/devel-api/adaptor-framework/gl-window.cpp create mode 100644 dali/devel-api/adaptor-framework/gl-window.h create mode 100644 dali/internal/window-system/common/gl-window-impl.cpp create mode 100644 dali/internal/window-system/common/gl-window-impl.h diff --git a/dali/devel-api/adaptor-framework/gl-window.cpp b/dali/devel-api/adaptor-framework/gl-window.cpp new file mode 100644 index 0000000..b801233 --- /dev/null +++ b/dali/devel-api/adaptor-framework/gl-window.cpp @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include +#include + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ +GlWindow GlWindow::New() +{ + PositionSize positionSize( 0, 0, 0, 0 ); + return Dali::GlWindow::New( positionSize, "", "", false ); +} +GlWindow GlWindow::New(PositionSize positionSize, const std::string& name, const std::string& className, bool isTransparent ) +{ + GlWindow newWindow; + Internal::Adaptor::GlWindow* window = Internal::Adaptor::GlWindow::New( positionSize, name, className, isTransparent ); + if( window == nullptr ) + { + DALI_LOG_ERROR("Fail to create gl-window-impl\n"); + } + else + { + newWindow = GlWindow(window); + } + const bool isAdaptorAvailable = Dali::Adaptor::IsAvailable(); + if( isAdaptorAvailable ) + { + Dali::Adaptor& adaptor = Internal::Adaptor::Adaptor::Get(); + Dali::WindowContainer windows = adaptor.GetWindows(); + if( !windows.empty() ) + { + window->SetChild( windows[0] ); + } + } + return newWindow; +} +GlWindow::GlWindow() +{ +} +GlWindow::~GlWindow() +{ +} +GlWindow::GlWindow(const GlWindow& handle) +: BaseHandle(handle) +{ +} +GlWindow& GlWindow::operator=(const GlWindow& rhs) +{ + BaseHandle::operator=(rhs); + return *this; +} +void GlWindow::SetEglConfig( bool depth, bool stencil, int msaa, GlesVersion version ) +{ + GetImplementation(*this).SetEglConfig( depth, stencil, msaa, version ); +} +void GlWindow::Raise() +{ + GetImplementation(*this).Raise(); +} +void GlWindow::Lower() +{ + GetImplementation(*this).Lower(); +} +void GlWindow::Activate() +{ + GetImplementation(*this).Activate(); +} +void GlWindow::Show() +{ + GetImplementation(*this).Show(); +} +void GlWindow::Hide() +{ + GetImplementation(*this).Hide(); +} +unsigned int GlWindow::GetSupportedAuxiliaryHintCount() const +{ + return GetImplementation(*this).GetSupportedAuxiliaryHintCount(); +} +std::string GlWindow::GetSupportedAuxiliaryHint( unsigned int index ) const +{ + return GetImplementation(*this).GetSupportedAuxiliaryHint( index ); +} +unsigned int GlWindow::AddAuxiliaryHint( const std::string& hint, const std::string& value ) +{ + return GetImplementation(*this).AddAuxiliaryHint( hint, value ); +} +bool GlWindow::RemoveAuxiliaryHint( unsigned int id ) +{ + return GetImplementation(*this).RemoveAuxiliaryHint( id ); +} +bool GlWindow::SetAuxiliaryHintValue( unsigned int id, const std::string& value ) +{ + return GetImplementation(*this).SetAuxiliaryHintValue( id, value ); +} +std::string GlWindow::GetAuxiliaryHintValue( unsigned int id ) const +{ + return GetImplementation(*this).GetAuxiliaryHintValue( id ); +} +unsigned int GlWindow::GetAuxiliaryHintId( const std::string& hint ) const +{ + return GetImplementation(*this).GetAuxiliaryHintId( hint ); +} +void GlWindow::SetInputRegion( const Rect< int >& inputRegion ) +{ + GetImplementation(*this).SetInputRegion( inputRegion ); +} +void GlWindow::SetOpaqueState( bool opaque ) +{ + GetImplementation(*this).SetOpaqueState( opaque ); +} +bool GlWindow::IsOpaqueState() const +{ + return GetImplementation(*this).IsOpaqueState(); +} +void GlWindow::SetPositionSize( PositionSize positionSize ) +{ + GetImplementation(*this).SetPositionSize( positionSize ); +} +PositionSize GlWindow::GetPositionSize() const +{ + return GetImplementation(*this).GetPositionSize(); +} +Dali::GlWindow::GlWindowOrientation GlWindow::GetCurrentOrientation() const +{ + return GetImplementation( *this ).GetCurrentOrientation(); +} +void GlWindow::SetAvailableOrientations( const Dali::Vector< Dali::GlWindow::GlWindowOrientation >& orientations ) +{ + GetImplementation( *this ).SetAvailableOrientations( orientations ); +} +void GlWindow::SetPreferredOrientation( Dali::GlWindow::GlWindowOrientation orientation ) +{ + GetImplementation(*this).SetPreferredOrientation( orientation ); +} +void GlWindow::RegisterGlCallback( GlInitialize glInit, GlRenderFrame glRenderFrame, GlTerminate glTerminate ) +{ + GetImplementation(*this).RegisterGlCallback( glInit, glRenderFrame, glTerminate ); +} +void GlWindow::RenderOnce() +{ + GetImplementation(*this).RenderOnce(); +} +GlWindow::FocusChangeSignalType& GlWindow::FocusChangeSignal() +{ + return GetImplementation(*this).FocusChangeSignal(); +} +GlWindow::ResizedSignalType& GlWindow::ResizedSignal() +{ + return GetImplementation(*this).ResizedSignal(); +} +GlWindow::KeyEventSignalType& GlWindow::KeyEventSignal() +{ + return GetImplementation(*this).KeyEventSignal(); +} +GlWindow::TouchSignalType& GlWindow::TouchSignal() +{ + return GetImplementation(*this).TouchSignal(); +} +GlWindow::VisibilityChangedSignalType& GlWindow::VisibilityChangedSignal() +{ + return GetImplementation(*this).VisibilityChangedSignal(); +} +GlWindow::GlWindow( Internal::Adaptor::GlWindow* window ) +: BaseHandle( window ) +{ +} + +}// Dali diff --git a/dali/devel-api/adaptor-framework/gl-window.h b/dali/devel-api/adaptor-framework/gl-window.h new file mode 100644 index 0000000..e654048 --- /dev/null +++ b/dali/devel-api/adaptor-framework/gl-window.h @@ -0,0 +1,439 @@ +#ifndef DALI_GL_WINDOW_H +#define DALI_GL_WINDOW_H + +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include +#include +#include +#include +#include +#include +#include +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ +/** + * @addtogroup dali_adaptor_framework + * @{ + */ + +typedef Dali::Rect PositionSize; + +namespace Internal DALI_INTERNAL +{ +namespace Adaptor +{ +class GlWindow; +} +} + +namespace +{ +typedef void (*GlInitialize)(); +typedef void (*GlRenderFrame)(); +typedef void (*GlTerminate)(); +} + +class TouchEvent; +struct KeyEvent; + +/** + * @brief The GlWindow class is to draw with native GLES. + * + * This class is the special window. It is for native GLES application. + * So, some special funtions and type are supported. + * In addition, basic window's functions are supported, too. + * + */ +class DALI_ADAPTOR_API GlWindow : public BaseHandle +{ +public: + + using WindowSize = Uint16Pair ; + + typedef Signal< void ( const KeyEvent& ) > KeyEventSignalType; ///< GlWindow Key Event signal type + typedef Signal< void ( const TouchEvent& ) > TouchSignalType; ///< GlWindow Touch Event signal type + typedef Signal< void ( GlWindow, bool ) > FocusChangeSignalType; ///< GlWindow Focus signal type + typedef Signal< void ( WindowSize ) > ResizedSignalType; ///< GlWindow resized signal type + typedef Signal< void ( GlWindow, bool ) > VisibilityChangedSignalType; ///< GlWindow visibility change signal type + +public: + + // Enumerations + + /** + * @brief Enumeration for orientation of the window is the way in which a rectangular page is oriented for normal viewing. + * + * This Enumeration is used the available orientation APIs and the preferred orientation. + * + */ + enum class GlWindowOrientation + { + PORTRAIT = 0, ///< Portrait orientation. The height of the display area is greater than the width. + LANDSCAPE = 1, ///< Landscape orientation. A wide view area is needed. + PORTRAIT_INVERSE = 2, ///< Portrait inverse orientation + LANDSCAPE_INVERSE = 3, ///< Landscape inverse orientation + NO_ORIENTATION_PREFERENCE = -1 ///< Invalid angle value. It is used to initialize or unset the preferred orientation. + }; + + /** + * @brief Enumeration for GLES verion + * + * This Enumeration is used the GLES version for EGL configuration. + * If the device can not support GLES version 3.0 over, the version will be chosen with GLES version 2.0 + * + */ + enum class GlesVersion + { + VERSION_2_0 = 0, ///< GLES version 2.0 + VERSION_3_0, ///< GLES version 3.0 + }; + + /** + * @brief Creates an initialized handle to a new GlWindow. + * + * @return A new GlWindow + * @note This creates an extra GlWindow in addition to the default main GlWindow + */ + static GlWindow New(); + + /** + * @brief Creates an initialized handle to a new GlWindow. + * + * @param[in] positionSize The position and size of the GlWindow + * @param[in] name The GlWindow title + * @param[in] className The GlWindow class name + * @param[in] isTransparent Whether GlWindow is transparent + * @note This creates an extra GlWindow in addition to the default main GlWindow + * @return A new GlWindow + */ + static GlWindow New( PositionSize positionSize, const std::string& name, const std::string& className, bool isTransparent = false ); + + /** + * @brief Creates an uninitialized handle. + * + * This can be initialized using Dali::Application::GetGlWindow() or + * Dali::GlWindow::New(). + * + */ + GlWindow(); + + /** + * @brief Destructor. + * + * This is non-virtual since derived Handle types must not contain data or virtual methods. + * + */ + ~GlWindow(); + + /** + * @brief This copy constructor is required for (smart) pointer semantics. + * + * @param[in] handle A reference to the copied handle + */ + GlWindow(const GlWindow& handle); + + /** + * @brief This assignment operator is required for (smart) pointer semantics. + * + * @param[in] rhs A reference to the copied handle + * @return A reference to this + */ + GlWindow& operator=(const GlWindow& rhs); + + /** + * @brief Sets egl configuration for GlWindow + * + * @param[in] depth the flag of depth buffer. If true is set, 24bit depth buffer is enabled. + * @param[in] stencil the flag of stencil. it true is set, 8bit stencil buffer is enabled. + * @param[in] msaa the bit of msaa. + * @param[in] version the GLES version + * + */ + void SetEglConfig( bool depth, bool stencil, int msaa, GlesVersion version ); + + /** + * @brief Raises GlWindow to the top of GlWindow stack. + * + */ + void Raise(); + + /** + * @brief Lowers GlWindow to the bottom of GlWindow stack. + * + */ + void Lower(); + + /** + * @brief Activates GlWindow to the top of GlWindow stack even it is iconified. + * + */ + void Activate(); + + /** + * @brief Shows the GlWindow if it is hidden. + * + */ + void Show(); + + /** + * @brief Hides the GlWindow if it is showing. + * + */ + void Hide(); + + /** + * @brief Sets a position of the GlWindow. + * + * @param[in] positionSize The new GlWindow position + */ + void SetPositionSize( PositionSize positionSize ); + + /** + * @brief Gets a position of the GlWindow. + * + * @return The position of the GlWindow + */ + PositionSize GetPositionSize() const; + + /** + * @brief Gets the count of supported auxiliary hints of the window. + * + * @return The number of supported auxiliary hints. + * + * @note The window auxiliary hint is the value which is used to decide which actions should be made available to the user by the window manager. + * If you want to set specific hint to your window, then you should check whether it exists in the supported auxiliary hints. + */ + unsigned int GetSupportedAuxiliaryHintCount() const; + + /** + * @brief Gets the supported auxiliary hint string of the window. + * + * @param[in] index The index of the supported auxiliary hint lists + * @return The auxiliary hint string of the index. + * + * @note The window auxiliary hint is the value which is used to decide which actions should be made available to the user by the window manager. + * If you want to set specific hint to your window, then you should check whether it exists in the supported auxiliary hints. + */ + std::string GetSupportedAuxiliaryHint( unsigned int index ) const; + + /** + * @brief Creates an auxiliary hint of the window. + * + * @param[in] hint The auxiliary hint string. + * @param[in] value The value string. + * @return The ID of created auxiliary hint, or @c 0 on failure. + */ + unsigned int AddAuxiliaryHint( const std::string& hint, const std::string& value ); + + /** + * @brief Removes an auxiliary hint of the window. + * + * @param[in] id The ID of the auxiliary hint. + * @return True if no error occurred, false otherwise. + */ + bool RemoveAuxiliaryHint( unsigned int id ); + + /** + * @brief Changes a value of the auxiliary hint. + * + * @param[in] id The auxiliary hint ID. + * @param[in] value The value string to be set. + * @return True if no error occurred, false otherwise. + */ + bool SetAuxiliaryHintValue( unsigned int id, const std::string& value ); + + /** + * @brief Gets a value of the auxiliary hint. + * + * @param[in] id The auxiliary hint ID. + * @return The string value of the auxiliary hint ID, or an empty string if none exists. + */ + std::string GetAuxiliaryHintValue( unsigned int id ) const; + + /** + * @brief Gets a ID of the auxiliary hint string. + * + * @param[in] hint The auxiliary hint string. + * @return The ID of the auxiliary hint string, or @c 0 if none exists. + */ + unsigned int GetAuxiliaryHintId( const std::string& hint ) const; + + /** + * @brief Sets a region to accept input events. + * + * @param[in] inputRegion The region to accept input events. + */ + void SetInputRegion( const Rect< int >& inputRegion ); + + /** + * @brief Sets a transparent window's visual state to opaque. + * @details If a visual state of a transparent window is opaque, + * then the window manager could handle it as an opaque window when calculating visibility. + * + * @param[in] opaque Whether the window's visual state is opaque. + * @remarks This will have no effect on an opaque window. + * It doesn't change transparent window to opaque window but lets the window manager know the visual state of the window. + */ + void SetOpaqueState( bool opaque ); + + /** + * @brief Returns whether a transparent window's visual state is opaque or not. + * + * @return True if the window's visual state is opaque, false otherwise. + * @remarks The return value has no meaning on an opaque window. + */ + bool IsOpaqueState() const; + + /** + * @brief Gets current rotation angle of the window. + * + * @return The current GlWindow rotation angle if previously set, or none + */ + Dali::GlWindow::GlWindowOrientation GetCurrentOrientation() const; + + /** + * @brief Sets available orientations of the window. + * + * This API is for setting several orientations one time. + * + * @param[in] orientations The available orientations list to add + */ + void SetAvailableOrientations( const Dali::Vector& orientations ); + + /** + * @brief Sets a preferred orientation. + * + * @param[in] orientation The preferred orientation + * @pre angle is in the list of available orientation. + * + * @note To unset the preferred orientation, angle should be set NO_ORIENTATION_PREFERENCE. + */ + void SetPreferredOrientation( Dali::GlWindow::GlWindowOrientation orientation ); + + /** + * @brief Registers a GL callback function for application. + * + * @param[in] glInit the callback function for application initialize + * @param[in] glRenderFrame the callback function to render to the frame. + * @param[in] glTerminate the callback function to clean-up application GL resource. + * + */ + void RegisterGlCallback( GlInitialize glInit, GlRenderFrame glRenderFrame, GlTerminate glTerminate ); + + /** + * @brief Renders once more even if GL render functions are not added to idler. + * @note Will not work if the window is hidden or GL render functions are added to idler + * + */ + void RenderOnce(); + +public: // Signals + + /** + * @brief The user should connect to this signal to get a timing when GlWindow gains focus or loses focus. + * + * A callback of the following type may be connected: + * @code + * void YourCallbackName( GlWindow GlWindow, bool focusIn ); + * @endcode + * The parameter is true if GlWindow gains focus, otherwise false. + * and GlWindow means this signal was called from what GlWindow + * + * @return The signal to connect to + */ + FocusChangeSignalType& FocusChangeSignal(); + + /** + * @brief This signal is emitted when the GlWindow is resized. + * + * A callback of the following type may be connected: + * @code + * void YourCallbackName( GlWindow GlWindow, int width, int height ); + * @endcode + * The parameters are the resized width and height. + * and GlWindow means this signal was called from what GlWindow + * + * @return The signal to connect to + */ + ResizedSignalType& ResizedSignal(); + + /** + * @brief This signal is emitted when key event is received. + * + * A callback of the following type may be connected: + * @code + * void YourCallbackName(const KeyEvent& event); + * @endcode + * + * @return The signal to connect to + */ + KeyEventSignalType& KeyEventSignal(); + + /** + * @brief This signal is emitted when the screen is touched and when the touch ends + * (i.e. the down & up touch events only). + * + * If there are multiple touch points, then this will be emitted when the first touch occurs and + * then when the last finger is lifted. + * An interrupted event will also be emitted (if it occurs). + * A callback of the following type may be connected: + * @code + * void YourCallbackName(const TouchEvent& event); + * @endcode + * + * @return The touch signal to connect to + * + * @note Motion events are not emitted. + */ + TouchSignalType& TouchSignal(); + + /** + * @brief This signal is emitted when the window is shown or hidden. + * + * A callback of the following type may be connected: + * @code + * void YourCallbackName( Window window, bool visible ); + * @endcode + * + * @return The signal to connect to + */ + VisibilityChangedSignalType& VisibilityChangedSignal(); + +public: // Not intended for application developers + /// @cond internal + /** + * @brief This constructor is used by Dali::Application::GetGlWindow(). + * @param[in] GlWindow A pointer to the GlWindow + */ + explicit DALI_INTERNAL GlWindow( Internal::Adaptor::GlWindow* GlWindow ); + /// @endcond +}; + +/** + * @} + */ +} // namespace Dali + +#endif // DALI_GL_WINDOW_H diff --git a/dali/devel-api/file.list b/dali/devel-api/file.list index 717cba9..e8cd60b 100755 --- a/dali/devel-api/file.list +++ b/dali/devel-api/file.list @@ -39,6 +39,7 @@ SET( devel_api_src_files ${adaptor_devel_api_dir}/adaptor-framework/window-devel.cpp ${adaptor_devel_api_dir}/adaptor-framework/offscreen-application.cpp ${adaptor_devel_api_dir}/adaptor-framework/offscreen-window.cpp + ${adaptor_devel_api_dir}/adaptor-framework/gl-window.cpp ) @@ -96,6 +97,7 @@ SET( devel_api_adaptor_framework_header_files ${adaptor_devel_api_dir}/adaptor-framework/video-sync-mode.h ${adaptor_devel_api_dir}/adaptor-framework/offscreen-application.h ${adaptor_devel_api_dir}/adaptor-framework/offscreen-window.h + ${adaptor_devel_api_dir}/adaptor-framework/gl-window.h ) diff --git a/dali/internal/graphics/gles/egl-graphics.cpp b/dali/internal/graphics/gles/egl-graphics.cpp index dcbf055..ce3c353 100644 --- a/dali/internal/graphics/gles/egl-graphics.cpp +++ b/dali/internal/graphics/gles/egl-graphics.cpp @@ -71,6 +71,18 @@ void EglGraphics::Initialize( EnvironmentOptions* environmentOptions ) mEglContextHelper = Utils::MakeUnique< EglContextHelperImplementation >(); } +void EglGraphics::Initialize( bool depth, bool stencil, int msaa ) +{ + mDepthBufferRequired = static_cast< Integration::DepthBufferAvailable >( depth ); + mStencilBufferRequired = static_cast< Integration::StencilBufferAvailable >( stencil ); + + mMultiSamplingLevel = msaa; + + mEglSync = Utils::MakeUnique< EglSyncImplementation >(); + + mEglContextHelper = Utils::MakeUnique< EglContextHelperImplementation >(); +} + EglInterface* EglGraphics::Create() { mEglImplementation = Utils::MakeUnique< EglImplementation >( mMultiSamplingLevel, mDepthBufferRequired, mStencilBufferRequired, mPartialUpdateRequired ); diff --git a/dali/internal/graphics/gles/egl-graphics.h b/dali/internal/graphics/gles/egl-graphics.h index 8ee45bc..7476f94 100644 --- a/dali/internal/graphics/gles/egl-graphics.h +++ b/dali/internal/graphics/gles/egl-graphics.h @@ -57,6 +57,14 @@ public: void Initialize( EnvironmentOptions* environmentOptions ) override; /** + * Initialize the graphics interface with specific input parameters + * @param[in] depth The flag to enable depth buffer + * @param[in] stencil The flag to enable stencil buffer + * @param[in] msaa The value of multi sampleing bit + */ + void Initialize( bool depth, bool stencil, int msaa ); + + /** * Creates the graphics interface for EGL * @return The graphics interface for EGL */ diff --git a/dali/internal/window-system/common/event-handler.cpp b/dali/internal/window-system/common/event-handler.cpp index 7a1d02b..25fc86f 100755 --- a/dali/internal/window-system/common/event-handler.cpp +++ b/dali/internal/window-system/common/event-handler.cpp @@ -95,7 +95,7 @@ static uint32_t GetCurrentMilliSeconds(void) } // unnamed namespace #endif -EventHandler::EventHandler( WindowRenderSurface* surface, DamageObserver& damageObserver ) +EventHandler::EventHandler( WindowBase* windowBase, DamageObserver& damageObserver ) : mStyleMonitor( StyleMonitor::Get() ), mDamageObserver( damageObserver ), mAccessibilityAdaptor( AccessibilityAdaptor::Get() ), @@ -103,22 +103,17 @@ EventHandler::EventHandler( WindowRenderSurface* surface, DamageObserver& damage mClipboard( Clipboard::Get() ), mPaused( false ) { - if( surface ) - { - WindowBase* windowBase = surface->GetWindowBase(); - - // Connect signals - windowBase->WindowDamagedSignal().Connect( this, &EventHandler::OnWindowDamaged ); - windowBase->FocusChangedSignal().Connect( this, &EventHandler::OnFocusChanged ); - windowBase->RotationSignal().Connect( this, &EventHandler::OnRotation ); - windowBase->TouchEventSignal().Connect( this, &EventHandler::OnTouchEvent ); - windowBase->WheelEventSignal().Connect( this, &EventHandler::OnWheelEvent ); - windowBase->KeyEventSignal().Connect( this, &EventHandler::OnKeyEvent ); - windowBase->SelectionDataSendSignal().Connect( this, &EventHandler::OnSelectionDataSend ); - windowBase->SelectionDataReceivedSignal().Connect( this, &EventHandler::OnSelectionDataReceived ); - windowBase->StyleChangedSignal().Connect( this, &EventHandler::OnStyleChanged ); - windowBase->AccessibilitySignal().Connect( this, &EventHandler::OnAccessibilityNotification ); - } + // Connect signals + windowBase->WindowDamagedSignal().Connect( this, &EventHandler::OnWindowDamaged ); + windowBase->FocusChangedSignal().Connect( this, &EventHandler::OnFocusChanged ); + windowBase->RotationSignal().Connect( this, &EventHandler::OnRotation ); + windowBase->TouchEventSignal().Connect( this, &EventHandler::OnTouchEvent ); + windowBase->WheelEventSignal().Connect( this, &EventHandler::OnWheelEvent ); + windowBase->KeyEventSignal().Connect( this, &EventHandler::OnKeyEvent ); + windowBase->SelectionDataSendSignal().Connect( this, &EventHandler::OnSelectionDataSend ); + windowBase->SelectionDataReceivedSignal().Connect( this, &EventHandler::OnSelectionDataReceived ); + windowBase->StyleChangedSignal().Connect( this, &EventHandler::OnStyleChanged ); + windowBase->AccessibilitySignal().Connect( this, &EventHandler::OnAccessibilityNotification ); } EventHandler::~EventHandler() diff --git a/dali/internal/window-system/common/event-handler.h b/dali/internal/window-system/common/event-handler.h index 71f4ca5..ba23ce3 100644 --- a/dali/internal/window-system/common/event-handler.h +++ b/dali/internal/window-system/common/event-handler.h @@ -111,10 +111,10 @@ public: /** * Constructor. - * @param[in] surface The render surface of the window. + * @param[in] windowBase The window base to be handled * @param[in] damageObserver The damage observer (to pass damage events to). */ - EventHandler( WindowRenderSurface* surface, DamageObserver& damageObserver ); + EventHandler( WindowBase* windowBase, DamageObserver& damageObserver ); /** * Destructor. diff --git a/dali/internal/window-system/common/gl-window-impl.cpp b/dali/internal/window-system/common/gl-window-impl.cpp new file mode 100644 index 0000000..648feeb --- /dev/null +++ b/dali/internal/window-system/common/gl-window-impl.cpp @@ -0,0 +1,878 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL HEADERS +#include +#include +#include +#include +#include +#include +#include + +// INTERNAL HEADERS +//#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Dali +{ +namespace Internal +{ +namespace Adaptor +{ + +namespace +{ +const int MINIMUM_DIMENSION_CHANGE( 1 ); + +#if defined(DEBUG_ENABLED) +Debug::Filter* gWindowLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_WINDOW" ); +#endif + +} // unnamed namespace + +GlWindow* GlWindow::New( const PositionSize& positionSize, const std::string& name, const std::string& className, bool isTransparent ) +{ + GlWindow* window = new GlWindow(); + window->mIsTransparent = isTransparent; + window->Initialize( positionSize, name, className ); + return window; +} + +GlWindow::GlWindow() +: mWindowBase(), + mGraphics(), + mDisplayConnection( nullptr ), + mEventHandler( nullptr ), + mPositionSize(), + mColorDepth( COLOR_DEPTH_24 ), + mIsTransparent( false ), + mIsFocusAcceptable( false ), + mIconified( false ), + mOpaqueState( false ), + mResizedEnabled( false ), + mVisible( false ), + mIsRotated( false ), + mIsWindowRotated( false ), + mIsTouched( false ), + mAvailableAngles(), + mPreferredAngle( 0 ), + mTotalRotationAngle( 0 ), + mWindowRotationAngle( 0 ), + mScreenRotationAngle( 0 ), + mOrientationMode( 0 ), + mWindowWidth( 0 ), + mWindowHeight( 0 ), + mNativeWindowId( -1 ), + mKeyEventSignal(), + mTouchSignal(), + mFocusChangeSignal(), + mResizedSignal(), + mVisibilityChangedSignal(), + mGLInitCallback( 0 ), + mGLRenderFrameCallback( 0 ), + mGLTerminateCallback( 0 ), + mGLRenderCallback( nullptr ), + mEGLSurface( nullptr ), + mEGLContext( nullptr ), + mGLESVersion( Dali::GlWindow::GlesVersion::VERSION_3_0 ), + mInitCallback( false ), + mDepth( false ), + mStencil( false ), + mIsEGLInitialize( false ), + mMSAA( 0 ) +{ +} + +GlWindow::~GlWindow() +{ + if ( mEventHandler ) + { + mEventHandler->RemoveObserver( *this ); + } + + if( mGLTerminateCallback ) + { + mGLTerminateCallback(); + } + + if( mIsEGLInitialize ) + { + GraphicsInterface* graphics = mGraphics.get(); + EglGraphics *eglGraphics = static_cast( graphics ); + Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation(); + + if( mEGLSurface ) + { + eglImpl.DestroySurface( mEGLSurface ); + mEGLSurface = nullptr; + } + + if( mEGLContext ) + { + eglImpl.DestroyContext( mEGLContext ); + mEGLContext = nullptr; + } + + eglImpl.TerminateGles(); + + mGraphics->Destroy(); + } + + delete mDisplayConnection; +} + +void GlWindow::Initialize( const PositionSize& positionSize, const std::string& name, const std::string& className ) +{ + int screenWidth, screenHeight; + + mPositionSize = positionSize; + WindowSystem::GetScreenSize( screenWidth, screenHeight ); + if ( (mPositionSize.width == 0) || (mPositionSize.height == 0) ) + { + mPositionSize.x = 0; + mPositionSize.y = 0; + mPositionSize.width = screenWidth; + mPositionSize.height = screenHeight; + } + + if( screenWidth > screenHeight ) + { + mOrientationMode = 1; // Default mode is landscape + } + else + { + mOrientationMode = 0; // Default mode is portrate + } + + // Create a window base + auto windowFactory = Dali::Internal::Adaptor::GetWindowFactory(); + Any surface; + mWindowBase = windowFactory->CreateWindowBase( mPositionSize, surface, ( mIsTransparent ? true : false ) ); + mWindowBase->IconifyChangedSignal().Connect( this, &GlWindow::OnIconifyChanged ); + mWindowBase->FocusChangedSignal().Connect( this, &GlWindow::OnFocusChanged ); + + SetEventHandler(); + + if( !mPositionSize.IsEmpty() ) + { + AddAuxiliaryHint( "wm.policy.win.user.geometry", "1" ); + mResizedEnabled = true; + } + + mWindowBase->Show(); + + if( mIsTransparent ) + { + mColorDepth = COLOR_DEPTH_32; + } + else + { + mColorDepth = COLOR_DEPTH_24; + } + + SetClass( name, className ); + + // For Debugging + mNativeWindowId = mWindowBase->GetNativeWindowId(); +} + +void GlWindow::SetEventHandler() +{ + mEventHandler = EventHandlerPtr( new EventHandler( mWindowBase.get(), *this ) ); + mEventHandler->AddObserver( *this ); +} + +void GlWindow::SetClass( const std::string name, const std::string className ) +{ + mName = name; + mClassName = className; + mWindowBase->SetClass( name, className ); +} + +void GlWindow::SetEglConfig( bool depth, bool stencil, int msaa, Dali::GlWindow::GlesVersion version ) +{ + // Init Graphics + mDepth = depth; + mStencil = stencil; + mMSAA = msaa; + mGLESVersion = version; + + InitializeGraphics(); +} + +void GlWindow::Raise() +{ + mWindowBase->Raise(); + DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Raise() \n", this, mNativeWindowId ); +} + +void GlWindow::Lower() +{ + mWindowBase->Lower(); + DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Lower() \n", this, mNativeWindowId ); +} + +void GlWindow::Activate() +{ + mWindowBase->Activate(); + DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Activate() \n", this, mNativeWindowId ); +} + +void GlWindow::Show() +{ + mVisible = true; + + mWindowBase->Show(); + + if( !mIconified ) + { + Dali::GlWindow handle( this ); + mVisibilityChangedSignal.Emit( handle, true ); + } + + if( mEventHandler ) + { + mEventHandler->Resume(); + } + + DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Show(): iconified = %d, visible = %d\n", this, mNativeWindowId, mIconified, mVisible ); +} + +void GlWindow::Hide() +{ + mVisible = false; + + mWindowBase->Hide(); + + if( !mIconified ) + { + Dali::GlWindow handle( this ); + mVisibilityChangedSignal.Emit( handle, false ); + } + + if( mEventHandler ) + { + mEventHandler->Pause(); + } + + DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Hide(): iconified = %d, visible = %d\n", this, mNativeWindowId, mIconified, mVisible ); +} + +unsigned int GlWindow::GetSupportedAuxiliaryHintCount() const +{ + return mWindowBase->GetSupportedAuxiliaryHintCount(); +} + +std::string GlWindow::GetSupportedAuxiliaryHint( unsigned int index ) const +{ + return mWindowBase->GetSupportedAuxiliaryHint( index ); +} + +unsigned int GlWindow::AddAuxiliaryHint( const std::string& hint, const std::string& value ) +{ + return mWindowBase->AddAuxiliaryHint( hint, value ); +} + +bool GlWindow::RemoveAuxiliaryHint( unsigned int id ) +{ + return mWindowBase->RemoveAuxiliaryHint( id ); +} + +bool GlWindow::SetAuxiliaryHintValue( unsigned int id, const std::string& value ) +{ + return mWindowBase->SetAuxiliaryHintValue( id, value ); +} + +std::string GlWindow::GetAuxiliaryHintValue( unsigned int id ) const +{ + return mWindowBase->GetAuxiliaryHintValue( id ); +} + +unsigned int GlWindow::GetAuxiliaryHintId( const std::string& hint ) const +{ + return mWindowBase->GetAuxiliaryHintId( hint ); +} + +void GlWindow::SetInputRegion( const Rect< int >& inputRegion ) +{ + mWindowBase->SetInputRegion( inputRegion ); + + 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 ); +} + +void GlWindow::SetOpaqueState( bool opaque ) +{ + mOpaqueState = opaque; + + mWindowBase->SetOpaqueState( opaque ); + + DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "GlWindow::SetOpaqueState: opaque = %d\n", opaque ); +} + +bool GlWindow::IsOpaqueState() const +{ + return mOpaqueState; +} + +void GlWindow::SetPositionSize( PositionSize positionSize ) +{ + if( !mResizedEnabled ) + { + AddAuxiliaryHint( "wm.policy.win.user.geometry", "1" ); + mResizedEnabled = true; + } + + bool needToMove = false; + bool needToResize = false; + + // Check moving + if( (fabs(positionSize.x - mPositionSize.x) > MINIMUM_DIMENSION_CHANGE) || + (fabs(positionSize.y - mPositionSize.y) > MINIMUM_DIMENSION_CHANGE) ) + { + needToMove = true; + } + + // Check resizing + if( (fabs(positionSize.width - mPositionSize.width) > MINIMUM_DIMENSION_CHANGE) || + (fabs(positionSize.height - mPositionSize.height) > MINIMUM_DIMENSION_CHANGE) ) + { + needToResize = true; + } + + if( needToResize ) + { + if( needToMove ) + { + mWindowBase->MoveResize( positionSize ); + } + else + { + mWindowBase->Resize( positionSize ); + } + mPositionSize = positionSize; + } + else + { + if( needToMove ) + { + mWindowBase->Move( positionSize ); + mPositionSize = positionSize; + } + } + + // If window's size or position is changed, the signal will be emitted to user. + if( ( needToMove ) || ( needToResize ) ) + { + Uint16Pair newSize( mPositionSize.width, mPositionSize.height ); + mResizedSignal.Emit( newSize ); + } +} + +PositionSize GlWindow::GetPositionSize() const +{ + PositionSize positionSize( mPositionSize ); + if( mTotalRotationAngle == 90 || mTotalRotationAngle == 270 ) + { + positionSize.height = mPositionSize.width; + positionSize.width = mPositionSize.height; + } + + return positionSize; +} + +void GlWindow::OnIconifyChanged( bool iconified ) +{ + if( iconified ) + { + mIconified = true; + + if( mVisible ) + { + Dali::GlWindow handle( this ); + mVisibilityChangedSignal.Emit( handle, false ); + } + + if( mEventHandler ) + { + mEventHandler->Pause(); + } + + DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Iconified: visible = %d\n", this, mNativeWindowId, mVisible ); + } + else + { + mIconified = false; + + if( mVisible ) + { + Dali::GlWindow handle( this ); + mVisibilityChangedSignal.Emit( handle, true ); + } + + if( mEventHandler ) + { + mEventHandler->Resume(); + } + + DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Deiconified: visible = %d\n", this, mNativeWindowId, mVisible ); + } +} + +void GlWindow::OnFocusChanged( bool focusIn ) +{ + Dali::GlWindow handle( this ); + mFocusChangeSignal.Emit( handle, focusIn ); +} + +void GlWindow::OnOutputTransformed() +{ + int screenRotationAngle = mWindowBase->GetScreenRotationAngle(); + if( screenRotationAngle != mScreenRotationAngle ) + { + mScreenRotationAngle = screenRotationAngle; + mTotalRotationAngle = (mWindowRotationAngle + mScreenRotationAngle) % 360; + + if( mTotalRotationAngle == 90 || mTotalRotationAngle == 270 ) + { + mWindowWidth = mPositionSize.height; + mWindowHeight = mPositionSize.width; + } + else + { + mWindowWidth = mPositionSize.width; + mWindowHeight = mPositionSize.height; + } + + // Emit Resized signal + mResizedSignal.Emit( Dali::Uint16Pair( mWindowWidth, mWindowHeight ) ); + } +} + +void GlWindow::OnTouchPoint( Dali::Integration::Point& point, int timeStamp ) +{ + PointState::Type state = point.GetState(); + + if( state == PointState::DOWN ) + { + mIsTouched = true; + } + + if( state == PointState::UP ) + { + mIsTouched = false; + } + + if( !mIsTouched && state == PointState::MOTION ) + { + return; + } + + RecalculateTouchPosition( point ); + Dali::TouchEvent touchEvent = Dali::Integration::NewTouchEvent( timeStamp, point ); + mTouchSignal.Emit( touchEvent ); +} + +void GlWindow::OnWheelEvent( Dali::Integration::WheelEvent& wheelEvent ) +{ + // TODO: + //FeedWheelEvent( wheelEvent ); +} + +void GlWindow::OnKeyEvent( Dali::Integration::KeyEvent& keyEvent ) +{ + Dali::KeyEvent event = Dali::DevelKeyEvent::New( keyEvent.keyName, keyEvent.logicalKey, keyEvent.keyString, keyEvent.keyCode, + keyEvent.keyModifier, keyEvent.time, static_cast(keyEvent.state), + keyEvent.compose, keyEvent.deviceName, keyEvent.deviceClass, keyEvent.deviceSubclass ); + mKeyEventSignal.Emit( event ); +} + +void GlWindow::OnRotation( const RotationEvent& rotation ) +{ + mWindowRotationAngle = rotation.angle; + mTotalRotationAngle = ( mWindowRotationAngle + mScreenRotationAngle ) % 360; + if( mTotalRotationAngle == 90 || mTotalRotationAngle == 270 ) + { + mWindowWidth = mPositionSize.height; + mWindowHeight = mPositionSize.width; + } + else + { + mWindowWidth = mPositionSize.width; + mWindowHeight = mPositionSize.height; + } + + mIsRotated = true; + mIsWindowRotated = true; + DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), OnRotation(): resized signal emit [%d x %d]\n", this, mNativeWindowId, mWindowWidth, mWindowHeight ); + + // Emit Resized signal + mResizedSignal.Emit( Dali::Uint16Pair( mWindowWidth, mWindowHeight ) ); +} + +void GlWindow::RecalculateTouchPosition( Integration::Point& point ) +{ + Vector2 position = point.GetScreenPosition(); + Vector2 convertedPosition; + + switch( mTotalRotationAngle ) + { + case 90: + { + convertedPosition.x = static_cast( mWindowWidth ) - position.y; + convertedPosition.y = position.x; + break; + } + case 180: + { + convertedPosition.x = static_cast( mWindowWidth ) - position.x; + convertedPosition.y = static_cast( mWindowHeight ) - position.y; + break; + } + case 270: + { + convertedPosition.x = position.y; + convertedPosition.y = static_cast( mWindowHeight ) - position.x; + break; + } + default: + { + convertedPosition = position; + break; + } + } + + point.SetScreenPosition( convertedPosition ); +} + +void GlWindow::SetAvailableAnlges( const std::vector< int >& angles ) +{ + if( angles.size() > 4 ) + { + DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::SetAvailableAnlges: Invalid vector size! [%d]\n", angles.size() ); + return; + } + + mWindowBase->SetAvailableAnlges( angles ); +} + +bool GlWindow::IsOrientationAvailable( Dali::GlWindow::GlWindowOrientation orientation ) const +{ + if( orientation <= Dali::GlWindow::GlWindowOrientation::NO_ORIENTATION_PREFERENCE + || orientation > Dali::GlWindow::GlWindowOrientation::LANDSCAPE_INVERSE ) + { + DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::IsOrientationAvailable: Invalid input orientation [%d]\n", orientation ); + return false; + } + return true; +} + +int GlWindow::ConvertToAngle( Dali::GlWindow::GlWindowOrientation orientation ) +{ + int convertAngle = 0; + if ( mOrientationMode == 0 ) + { + convertAngle = ( static_cast< int >( orientation ) ) * 90; + } + else if( mOrientationMode == 1) + { + switch( orientation ) + { + case Dali::GlWindow::GlWindowOrientation::LANDSCAPE: + { + convertAngle = 0; + break; + } + case Dali::GlWindow::GlWindowOrientation::PORTRAIT: + { + convertAngle = 90; + break; + } + case Dali::GlWindow::GlWindowOrientation::LANDSCAPE_INVERSE: + { + convertAngle = 180; + break; + } + case Dali::GlWindow::GlWindowOrientation::PORTRAIT_INVERSE: + { + convertAngle = 270; + break; + } + case Dali::GlWindow::GlWindowOrientation::NO_ORIENTATION_PREFERENCE: + { + convertAngle = -1; + break; + } + } + } + return convertAngle; +} + +Dali::GlWindow::GlWindowOrientation GlWindow::ConvertToOrientation( int angle ) const +{ + Dali::GlWindow::GlWindowOrientation orientation = Dali::GlWindow::GlWindowOrientation::NO_ORIENTATION_PREFERENCE; + if ( mOrientationMode == 0 ) // Portrate mode + { + orientation = static_cast< Dali::GlWindow::GlWindowOrientation >( angle / 90 ); + } + else if( mOrientationMode == 1 ) // Landscape mode + { + switch( angle ) + { + case 0: + { + orientation = Dali::GlWindow::GlWindowOrientation::LANDSCAPE; + break; + } + case 90: + { + orientation = Dali::GlWindow::GlWindowOrientation::PORTRAIT; + break; + } + case 180: + { + orientation = Dali::GlWindow::GlWindowOrientation::LANDSCAPE_INVERSE; + break; + } + case 270: + { + orientation = Dali::GlWindow::GlWindowOrientation::PORTRAIT_INVERSE; + break; + } + case -1: + { + orientation = Dali::GlWindow::GlWindowOrientation::NO_ORIENTATION_PREFERENCE; + break; + } + } + } + return orientation; +} + +Dali::GlWindow::GlWindowOrientation GlWindow::GetCurrentOrientation() const +{ + DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), GetCurrentOrientation(): %d\n", this, mNativeWindowId, mTotalRotationAngle ); + return ConvertToOrientation( mTotalRotationAngle ); +} + +void GlWindow::SetAvailableOrientations( const Dali::Vector< Dali::GlWindow::GlWindowOrientation >& orientations ) +{ + Dali::Vector::SizeType count = orientations.Count(); + for( Dali::Vector::SizeType index = 0; index < count; ++index ) + { + if( IsOrientationAvailable( orientations[index] ) == false ) + { + DALI_LOG_ERROR("Window::SetAvailableRotationAngles, invalid angle: %d\n", orientations[index]); + continue; + } + + bool found = false; + int angle = ConvertToAngle( orientations[index] ); + + for( std::size_t i = 0; i < mAvailableAngles.size(); i++ ) + { + if( mAvailableAngles[i] == angle ) + { + found = true; + break; + } + } + + if( !found ) + { + DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), SetAvailableOrientations: %d\n", this, mNativeWindowId, angle ); + mAvailableAngles.push_back( angle ); + } + } + SetAvailableAnlges( mAvailableAngles ); +} + +void GlWindow::SetPreferredOrientation( Dali::GlWindow::GlWindowOrientation orientation ) +{ + if( IsOrientationAvailable( orientation ) == false ) + { + DALI_LOG_ERROR( "Window::SetPreferredOrientation, invalid orientation: %d\n", orientation ); + return; + } + mPreferredAngle = ConvertToAngle( orientation ); + DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), SetPreferredOrientation: %d\n", this, mNativeWindowId, mPreferredAngle ); + mWindowBase->SetPreferredAngle( mPreferredAngle ); +} + +void GlWindow::SetChild( Dali::Window& child ) +{ + if( DALI_UNLIKELY( child ) ) + { + mChildWindow = child; + Internal::Adaptor::Window& windowImpl = Dali::GetImplementation( mChildWindow ); + WindowRenderSurface* renderSurface = static_cast( windowImpl.GetSurface() ); + WindowBase* childWindowBase = renderSurface->GetWindowBase(); + childWindowBase->SetParent( mWindowBase.get() ); + } +} + +void GlWindow::RegisterGlCallback( GlInitialize glInit, GlRenderFrame glRenderFrame, GlTerminate glTerminate ) +{ + if( mIsEGLInitialize == false ) + { + InitializeGraphics(); + } + mGLInitCallback = glInit; + mGLRenderFrameCallback = glRenderFrame; + mGLTerminateCallback = glTerminate; + + mInitCallback = false; + + if( !mGLRenderCallback ) + { + mGLRenderCallback = MakeCallback( this, &GlWindow::RunCallback ); + + Dali::Adaptor::Get().AddIdle( mGLRenderCallback, true ); + } +} + +bool GlWindow::RunCallback() +{ + GraphicsInterface* graphics = mGraphics.get(); + EglGraphics *eglGraphics = static_cast( graphics ); + Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation(); + + eglImpl.MakeContextCurrent( mEGLSurface, mEGLContext ); + + if( mIsRotated ) + { + mWindowBase->SetEglWindowBufferTransform( mTotalRotationAngle ); + if( mIsWindowRotated ) + { + mWindowBase->SetEglWindowTransform( mWindowRotationAngle ); + } + mIsRotated = false; + } + + if( !mInitCallback ) + { + if( mGLInitCallback ) + { + mGLInitCallback(); + } + mInitCallback = true; + } + + if( mGLRenderFrameCallback ) + { + mGLRenderFrameCallback(); + } + + if( mIsWindowRotated ) + { + mWindowBase->WindowRotationCompleted( mWindowRotationAngle, mPositionSize.width, mPositionSize.height ); + mIsWindowRotated = false; + } + + eglImpl.SwapBuffers( mEGLSurface ); + + return true; +} + +void GlWindow::RenderOnce() +{ + RunCallback(); +} + +int32_t GlWindow::GetNativeId() const +{ + return mWindowBase->GetNativeWindowId(); +} + +void GlWindow::InitializeGraphics() +{ + if( !mIsEGLInitialize ) + { + // Init Graphics + std::unique_ptr< GraphicsFactory > graphicsFactoryPtr = Utils::MakeUnique< GraphicsFactory >(); + auto graphicsFactory = *graphicsFactoryPtr.get(); + + mGraphics = std::unique_ptr< GraphicsInterface >( &graphicsFactory.Create() ); + GraphicsInterface* graphics = mGraphics.get(); + EglGraphics *eglGraphics = static_cast( graphics ); + eglGraphics->Initialize( mDepth, mStencil, mMSAA ); + eglGraphics->Create(); + + mDisplayConnection = Dali::DisplayConnection::New( *graphics, Dali::RenderSurfaceInterface::Type::WINDOW_RENDER_SURFACE ); + mDisplayConnection->Initialize(); + + Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation(); + if( mGLESVersion == Dali::GlWindow::GlesVersion::VERSION_2_0 ) + { + eglImpl.SetGlesVersion( 20 ); + } + else if( mGLESVersion == Dali::GlWindow::GlesVersion::VERSION_3_0 ) + { + eglImpl.SetGlesVersion( 30 ); + } + + if( eglImpl.ChooseConfig(true, mColorDepth) == false ) + { + if( mGLESVersion == Dali::GlWindow::GlesVersion::VERSION_3_0 ) + { + DALI_LOG_RELEASE_INFO( "InitializeGraphics: Fail to choose config with GLES30, retry with GLES20\n" ); + eglImpl.SetGlesVersion( 20 ); + mGLESVersion = Dali::GlWindow::GlesVersion::VERSION_2_0; + if( eglImpl.ChooseConfig(true, mColorDepth) == false ) + { + DALI_LOG_ERROR("InitializeGraphics: Fail to choose config with GLES20"); + return; + } + } + else + { + DALI_LOG_ERROR("InitializeGraphics: Fail to choose config with GLES20"); + return; + } + } + eglImpl.CreateWindowContext( mEGLContext ); + + // Create the EGL window + EGLNativeWindowType window = mWindowBase->CreateEglWindow( mPositionSize.width, mPositionSize.height ); + mEGLSurface = eglImpl.CreateSurfaceWindow( window, mColorDepth ); + + mIsEGLInitialize = true; + } +} + +void GlWindow::OnDamaged( const DamageArea& area ) +{ + +} + +} // Adaptor + +} // Internal + +} // Dali diff --git a/dali/internal/window-system/common/gl-window-impl.h b/dali/internal/window-system/common/gl-window-impl.h new file mode 100644 index 0000000..4dbe7f8 --- /dev/null +++ b/dali/internal/window-system/common/gl-window-impl.h @@ -0,0 +1,418 @@ +#ifndef DALI_INTERNAL_WINDOWSYSTEM_COMMON_GL_WINDOW_IMPL_H +#define DALI_INTERNAL_WINDOWSYSTEM_COMMON_GL_WINDOW_IMPL_H + +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include +#include +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include + +namespace Dali +{ +class Adaptor; + +namespace Internal +{ +namespace Adaptor +{ +class WindowBase; + +class GlWindow; +using GlWindowPtr = IntrusivePtr< GlWindow >; +using EventHandlerPtr = IntrusivePtr< EventHandler >; + +/** + * Window provides a surface to render onto with orientation. + */ +class GlWindow : public BaseObject, public EventHandler::Observer, public DamageObserver, public ConnectionTracker +{ +public: + + using KeyEventSignalType = Dali::GlWindow::KeyEventSignalType; + using TouchSignalType = Dali::GlWindow::TouchSignalType; + using FocusChangeSignalType = Dali::GlWindow::FocusChangeSignalType; + using ResizedSignalType = Dali::GlWindow::ResizedSignalType; + using VisibilityChangedSignalType = Dali::GlWindow::VisibilityChangedSignalType; + using SignalType = Signal< void () >; + + /** + * @brief Create a new GlWindow. This should only be called once by the Application class + * @param[in] surface The surface used to render on. + * @param[in] positionSize The position and size of the window + * @param[in] name The window title + * @param[in] className The window class name + * @param[in] isTransparent Whether window is transparent + * @return A newly allocated Window + */ + static GlWindow* New( const PositionSize& positionSize, const std::string& name, const std::string& className, bool isTransparent = false ); + + /** + * @copydoc Dali::GlWindow::SetEglConfig() + */ + void SetEglConfig( bool depth, bool stencil, int msaa, Dali::GlWindow::GlesVersion version ); + + /** + * @copydoc Dali::GlWindow::Raise() + */ + void Raise(); + + /** + * @copydoc Dali::GlWindow::Lower() + */ + void Lower(); + + /** + * @copydoc Dali::GlWindow::Activate() + */ + void Activate(); + + /** + * @copydoc Dali::GlWindow::Show() + */ + void Show(); + + /** + * @copydoc Dali::GlWindow::Hide() + */ + void Hide(); + + /** + * @copydoc Dali::GlWindow::GetSupportedAuxiliaryHintCount() + */ + unsigned int GetSupportedAuxiliaryHintCount() const; + + /** + * @copydoc Dali::GlWindow::GetSupportedAuxiliaryHint() + */ + std::string GetSupportedAuxiliaryHint( unsigned int index ) const; + + /** + * @copydoc Dali::GlWindow::AddAuxiliaryHint() + */ + unsigned int AddAuxiliaryHint( const std::string& hint, const std::string& value ); + + /** + * @copydoc Dali::GlWindow::RemoveAuxiliaryHint() + */ + bool RemoveAuxiliaryHint( unsigned int id ); + + /** + * @copydoc Dali::GlWindow::SetAuxiliaryHintValue() + */ + bool SetAuxiliaryHintValue( unsigned int id, const std::string& value ); + + /** + * @copydoc Dali::GlWindow::GetAuxiliaryHintValue() + */ + std::string GetAuxiliaryHintValue( unsigned int id ) const; + + /** + * @copydoc Dali::GlWindow::GetAuxiliaryHintId() + */ + unsigned int GetAuxiliaryHintId( const std::string& hint ) const; + + /** + * @copydoc Dali::GlWindow::SetInputRegion() + */ + void SetInputRegion( const Rect< int >& inputRegion ); + + /** + * @copydoc Dali::GlWindow::SetOpaqueState() + */ + void SetOpaqueState( bool opaque ); + + /** + * @copydoc Dali::GlWindow::IsOpaqueState() + */ + bool IsOpaqueState() const; + + /** + * @copydoc Dali::GlWindow::SetPositionSize() + */ + void SetPositionSize( PositionSize positionSize ); + + /** + * @copydoc Dali::GlWindow::GetPositionSize() + */ + PositionSize GetPositionSize() const; + + /** + * @copydoc Dali::GlWindow::GetCurrentOrientation() const + */ + Dali::GlWindow::GlWindowOrientation GetCurrentOrientation() const; + + /** + * @copydoc Dali::GlWindow::SetAvailableOrientations() + */ + void SetAvailableOrientations( const Dali::Vector< Dali::GlWindow::GlWindowOrientation >& orientations ); + + /** + * @copydoc Dali::GlWindow::SetPreferredOrientation() + */ + void SetPreferredOrientation( Dali::GlWindow::GlWindowOrientation orientation ); + + /** + * @copydoc Dali::GlWindow::RegisterGlCallback() + */ + void RegisterGlCallback( GlInitialize glInit, GlRenderFrame glRenderFrame, GlTerminate glTerminate ); + + /** + * @copydoc Dali::GlWindow::RenderOnce() + */ + void RenderOnce(); + +public: // For implementation + /** + * @brief Sets child window with Dali::Window + * + * Currently the child window is default window. + */ + void SetChild( Dali::Window& child ); + +private: + + /** + * Private constructor. + * @sa Window::New() + */ + GlWindow(); + + /** + * Destructor + */ + virtual ~GlWindow(); + + /** + * Second stage initialization + */ + void Initialize( const PositionSize& positionSize, const std::string& name, const std::string& className ); + + /** + * Called when the window becomes iconified or deiconified. + */ + void OnIconifyChanged( bool iconified ); + + /** + * Called when the window focus is changed. + */ + void OnFocusChanged( bool focusIn ); + + /** + * Called when the output is transformed. + */ + void OnOutputTransformed(); + + /** + * Called when the window receives a delete request. + */ + void OnDeleteRequest(); + + /** + * @brief Set available rotation angle to window base. + */ + void SetAvailableAnlges( const std::vector< int >& angles ); + + /** + * @brief Check available window rotation angle for Available angle. + */ + bool IsOrientationAvailable( Dali::GlWindow::GlWindowOrientation orientation ) const; + + /** + * @brief Convert from window orientation to angle using orientation mode value. + */ + int ConvertToAngle( Dali::GlWindow::GlWindowOrientation orientation ); + + /** + * @brief Convert from angle to window orientation using orientation mode value. + */ + Dali::GlWindow::GlWindowOrientation ConvertToOrientation( int angle ) const; + + /** + * @brief Run Ui GL callback function. + */ + bool RunCallback(); + + /** + * @brief Initialize and create EGL resource + */ + void InitializeGraphics(); + + /** + * @brief Sets event handler for window's events. + */ + void SetEventHandler() ; + + /** + * @brief Gets the native window handle + */ + Dali::Any GetNativeHandle() const; + + /** + * @brief Gets the native window handle ID + */ + int32_t GetNativeId() const; + + /** + * @brief calculate touch position for rotation. + */ + void RecalculateTouchPosition( Integration::Point& point ) ; + + /** + * @brief Sets window and class name. + */ + void SetClass( const std::string name, const std::string className ); + +private: + + /** + * @copydoc Dali::Internal::Adaptor::EventHandler::Observer::OnTouchPoint + */ + void OnTouchPoint( Dali::Integration::Point& point, int timeStamp ) override; + + /** + * @copydoc Dali::Internal::Adaptor::EventHandler::Observer::OnWheelEvent + */ + void OnWheelEvent( Dali::Integration::WheelEvent& wheelEvent ) override; + + /** + * @copydoc Dali::Internal::Adaptor::EventHandler::Observer::OnKeyEvent + */ + void OnKeyEvent( Dali::Integration::KeyEvent& keyEvent ) override; + + /** + * @copydoc Dali::Internal::Adaptor::EventHandler::Observer::OnRotation + */ + void OnRotation( const RotationEvent& rotation ) override; + +private: // From Dali::Internal::Adaptor::DamageObserver + + /** + * @copydoc Dali::Internal::Adaptor::DamageObserver::OnDamaged() + */ + void OnDamaged( const DamageArea& area ); + +public: // Signals + + /** + * @copydoc Dali::GlWindow::FocusChangeSignal() + */ + FocusChangeSignalType& FocusChangeSignal() { return mFocusChangeSignal; } + + /** + * @copydoc Dali::GlWindow::ResizedSignal() + */ + ResizedSignalType& ResizedSignal() { return mResizedSignal; } + + /** + * @copydoc Dali::GlWindow::KeyEventSignal() + */ + KeyEventSignalType& KeyEventSignal() { return mKeyEventSignal; } + + /** + * @copydoc Dali::GlWindow::TouchSignal() + */ + TouchSignalType& TouchSignal() { return mTouchSignal; } + + /** + * @copydoc Dali::GlWindow::VisibilityChangedSignal() + */ + VisibilityChangedSignalType& VisibilityChangedSignal() { return mVisibilityChangedSignal; } + +private: + + std::unique_ptr< WindowBase > mWindowBase; + std::unique_ptr< GraphicsInterface > mGraphics; ///< Graphics interface + Dali::DisplayConnection* mDisplayConnection; + std::string mName; + std::string mClassName; + EventHandlerPtr mEventHandler; ///< The window events handler + PositionSize mPositionSize; + ColorDepth mColorDepth; + Dali::Window mChildWindow; + bool mIsTransparent:1; + bool mIsFocusAcceptable:1; + bool mIconified:1; + bool mOpaqueState:1; + bool mResizedEnabled:1; + bool mVisible:1; + bool mIsRotated:1; + bool mIsWindowRotated:1; + bool mIsTouched:1; + + std::vector< int > mAvailableAngles; + int mPreferredAngle; + int mTotalRotationAngle; ///< The angle of window + screen rotation angle % 360 + int mWindowRotationAngle; ///< The angle of window rotation angle + int mScreenRotationAngle; ///< The angle of screen rotation angle + int mOrientationMode; ///< 0: Default portrati, 1:Default landscape + int mWindowWidth; ///< The width of the window + int mWindowHeight; ///< The height of the window + int mNativeWindowId; ///< The Native Window Id + + // Signals + KeyEventSignalType mKeyEventSignal; + TouchSignalType mTouchSignal; + FocusChangeSignalType mFocusChangeSignal; + ResizedSignalType mResizedSignal; + VisibilityChangedSignalType mVisibilityChangedSignal; + + // EGL, GL Resource + GlInitialize mGLInitCallback; + GlRenderFrame mGLRenderFrameCallback; + GlTerminate mGLTerminateCallback; + CallbackBase* mGLRenderCallback; + EGLSurface mEGLSurface; + EGLContext mEGLContext; + Dali::GlWindow::GlesVersion mGLESVersion; + bool mInitCallback:1; + bool mDepth:1; + bool mStencil:1; + bool mIsEGLInitialize:1; + int mMSAA; +}; + +} // namespace Adaptor +} // namepsace Internal + +// Helpers for public-api forwarding methods + +inline Internal::Adaptor::GlWindow& GetImplementation(Dali::GlWindow& window) +{ + DALI_ASSERT_ALWAYS( window && "Window handle is empty" ); + BaseObject& object = window.GetBaseObject(); + return static_cast(object); +} + +inline const Internal::Adaptor::GlWindow& GetImplementation(const Dali::GlWindow& window) +{ + DALI_ASSERT_ALWAYS( window && "Window handle is empty" ); + const BaseObject& object = window.GetBaseObject(); + return static_cast(object); +} + +} // namespace Dali + +#endif // DALI_INTERNAL_WINDOWSYSTEM_COMMON_GL_WINDOW_IMPL_H diff --git a/dali/internal/window-system/common/window-impl.cpp b/dali/internal/window-system/common/window-impl.cpp index a214144..1031461 100755 --- a/dali/internal/window-system/common/window-impl.cpp +++ b/dali/internal/window-system/common/window-impl.cpp @@ -154,7 +154,7 @@ void Window::Initialize(Any surface, const PositionSize& positionSize, const std void Window::OnAdaptorSet(Dali::Adaptor& adaptor) { - mEventHandler = EventHandlerPtr(new EventHandler( mWindowSurface, *mAdaptor ) ); + mEventHandler = EventHandlerPtr(new EventHandler( mWindowSurface->GetWindowBase(), *mAdaptor ) ); mEventHandler->AddObserver( *this ); } diff --git a/dali/internal/window-system/file.list b/dali/internal/window-system/file.list index 7dffb60..a04299b 100644 --- a/dali/internal/window-system/file.list +++ b/dali/internal/window-system/file.list @@ -8,6 +8,7 @@ SET( adaptor_window_system_common_src_files ${adaptor_window_system_dir}/common/window-base.cpp ${adaptor_window_system_dir}/common/window-impl.cpp ${adaptor_window_system_dir}/common/window-render-surface.cpp + ${adaptor_window_system_dir}/common/gl-window-impl.cpp ) # module: window-system, backend: tizen-wayland -- 2.7.4