From: Wonsik Jung Date: Fri, 13 Nov 2020 09:48:27 +0000 (+0900) Subject: Add render threading for GlWindow X-Git-Tag: dali_2.0.11~6^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=08e77ea295c254e05a9503875261cb4722898a64;p=platform%2Fcore%2Fuifw%2Fdali-adaptor.git Add render threading for GlWindow Add the render threading for GlWindow. The user callback works on the separated render thread. Change-Id: Ic2470a1fc70f02fa0d1819e8bb36c6e62325022c --- diff --git a/dali/devel-api/adaptor-framework/gl-window.cpp b/dali/devel-api/adaptor-framework/gl-window.cpp index 7eccfec..bd85059 100644 --- a/dali/devel-api/adaptor-framework/gl-window.cpp +++ b/dali/devel-api/adaptor-framework/gl-window.cpp @@ -185,6 +185,16 @@ void GlWindow::RenderOnce() GetImplementation(*this).RenderOnce(); } +void GlWindow::SetRenderingMode( RenderingMode mode ) +{ + GetImplementation(*this).SetRenderingMode( mode ); +} + +GlWindow::RenderingMode GlWindow::GetRenderingMode() const +{ + return GetImplementation(*this).GetRenderingMode(); +} + GlWindow::FocusChangeSignalType& GlWindow::FocusChangeSignal() { return GetImplementation(*this).FocusChangeSignal(); diff --git a/dali/devel-api/adaptor-framework/gl-window.h b/dali/devel-api/adaptor-framework/gl-window.h index 986c3ff..ccd51fa 100644 --- a/dali/devel-api/adaptor-framework/gl-window.h +++ b/dali/devel-api/adaptor-framework/gl-window.h @@ -90,6 +90,20 @@ public: }; /** + * @brief Enumeration for rendering mode + * + * This Enumeration is used to choose the rendering mode. + * It has two options. + * One of them is continuous mode. It is rendered continuously. + * The other is on demand mode. It is rendered by application. + */ + enum class RenderingMode + { + CONTINUOUS, ///< continuous mode + ON_DEMAND ///< on demand by application + }; + + /** * @brief Creates an initialized handle to a new GlWindow. * * @return A new GlWindow @@ -362,6 +376,26 @@ public: */ void RenderOnce(); + /** + * @brief Sets rendering mode. + * + * @param[in] mode the rendering mode for GlWindow + * + * @note The default Rendering mode is continuous. + * If OnDemand mode is set, it is rendered by RenderOnce() + */ + void SetRenderingMode( RenderingMode mode ); + + /** + * @brief Gets rendering mode. + * + * @return current rendering mode in this GlWindow + * + * @note The default Rendering mode is continuous. + * If OnDemand mode is set, it is rendered by RenderOnce() + */ + RenderingMode GetRenderingMode() const; + public: // Signals /** diff --git a/dali/internal/window-system/common/gl-window-impl.cpp b/dali/internal/window-system/common/gl-window-impl.cpp index 520082b..89d4398 100644 --- a/dali/internal/window-system/common/gl-window-impl.cpp +++ b/dali/internal/window-system/common/gl-window-impl.cpp @@ -66,9 +66,8 @@ GlWindow::GlWindow() : mWindowBase(), mGraphics(), mDisplayConnection(nullptr), + mGlWindowRenderThread(nullptr), mEventHandler(nullptr), - mPositionSize(), - mColorDepth(COLOR_DEPTH_24), mIsTransparent(false), mIsFocusAcceptable(false), mIconified(false), @@ -78,7 +77,13 @@ GlWindow::GlWindow() mIsRotated(false), mIsWindowRotated(false), mIsTouched(false), + mIsEGLInitialized(false), + mDepth(false), + mStencil(false), + mPositionSize(), mAvailableAngles(), + mColorDepth(COLOR_DEPTH_24), + mRenderingMode(Dali::GlWindow::RenderingMode::CONTINUOUS), mPreferredAngle(0), mTotalRotationAngle(0), mWindowRotationAngle(0), @@ -87,23 +92,12 @@ GlWindow::GlWindow() mWindowWidth(0), mWindowHeight(0), mNativeWindowId(-1), + mMSAA(0), mKeyEventSignal(), mTouchedSignal(), mFocusChangeSignal(), mResizeSignal(), - mVisibilityChangedSignal(), - mGLInitCallback(), - mGLRenderFrameCallback(), - mGLTerminateCallback(), - mGLRenderCallback(nullptr), - mEGLSurface(nullptr), - mEGLContext(nullptr), - mGLESVersion(Dali::GlWindow::GlesVersion::VERSION_3_0), - mInitCallback(false), - mDepth(false), - mStencil(false), - mIsEGLInitialize(false), - mMSAA(0) + mVisibilityChangedSignal() { } @@ -114,31 +108,14 @@ GlWindow::~GlWindow() mEventHandler->RemoveObserver(*this); } - if(mGLTerminateCallback) + if(mGlWindowRenderThread) { - CallbackBase::Execute(*mGLTerminateCallback); + mGlWindowRenderThread->Stop(); + mGlWindowRenderThread->Join(); } - if(mIsEGLInitialize) + if(mIsEGLInitialized) { - 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(); } } @@ -217,12 +194,24 @@ void GlWindow::SetClass(const std::string& name, const std::string className) void GlWindow::SetEglConfig(bool depth, bool stencil, int msaa, Dali::GlWindow::GlesVersion version) { // Init Graphics - mDepth = depth; - mStencil = stencil; - mMSAA = msaa; - mGLESVersion = version; + mDepth = depth; + mStencil = stencil; + mMSAA = msaa; InitializeGraphics(); + + int rVersion = 30; + + if(version == Dali::GlWindow::GlesVersion::VERSION_2_0) + { + rVersion = 20; + } + else if(version == Dali::GlWindow::GlesVersion::VERSION_3_0) + { + rVersion = 30; + } + + mGlWindowRenderThread->SetEglConfig(depth, stencil, msaa, rVersion); } void GlWindow::Raise() @@ -260,6 +249,11 @@ void GlWindow::Show() mEventHandler->Resume(); } + if(mGlWindowRenderThread) + { + mGlWindowRenderThread->Resume(); + } + DALI_LOG_RELEASE_INFO("Window (%p), WinId (%d), Show(): iconified = %d, visible = %d\n", this, mNativeWindowId, mIconified, mVisible); } @@ -280,6 +274,11 @@ void GlWindow::Hide() mEventHandler->Pause(); } + if(mGlWindowRenderThread) + { + mGlWindowRenderThread->Pause(); + } + DALI_LOG_RELEASE_INFO("Window (%p), WinId (%d), Hide(): iconified = %d, visible = %d\n", this, mNativeWindowId, mIconified, mVisible); } @@ -423,6 +422,11 @@ void GlWindow::OnIconifyChanged(bool iconified) mEventHandler->Pause(); } + if(mGlWindowRenderThread) + { + mGlWindowRenderThread->Pause(); + } + DALI_LOG_RELEASE_INFO("Window (%p), WinId (%d), Iconified: visible = %d\n", this, mNativeWindowId, mVisible); } else @@ -440,6 +444,11 @@ void GlWindow::OnIconifyChanged(bool iconified) mEventHandler->Resume(); } + if(mGlWindowRenderThread) + { + mGlWindowRenderThread->Resume(); + } + DALI_LOG_RELEASE_INFO("Window (%p), WinId (%d), Deiconified: visible = %d\n", this, mNativeWindowId, mVisible); } } @@ -745,87 +754,44 @@ void GlWindow::SetChild(Dali::Window& child) void GlWindow::RegisterGlCallback(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback) { - if(mIsEGLInitialize == false) + if(mIsEGLInitialized == false) { InitializeGraphics(); } - mGLInitCallback = std::unique_ptr(initCallback); - mGLRenderFrameCallback = std::unique_ptr(renderFrameCallback); - mGLTerminateCallback = std::unique_ptr(terminateCallback); - - mInitCallback = false; - - if(!mGLRenderCallback) - { - mGLRenderCallback = MakeCallback(this, &GlWindow::RunCallback); - - if(Dali::Adaptor::IsAvailable()) - { - Dali::Adaptor::Get().AddIdle(mGLRenderCallback, true); - } - else - { - DALI_LOG_RELEASE_INFO("RegisterGlCallback: Adaptor is not avaiable\n"); - } - } + mGlWindowRenderThread->RegisterGlCallback(initCallback, renderFrameCallback, terminateCallback); + mGlWindowRenderThread->Start(); } -bool GlWindow::RunCallback() +void GlWindow::RenderOnce() { - GraphicsInterface* graphics = mGraphics.get(); - EglGraphics* eglGraphics = static_cast(graphics); - Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation(); - - eglImpl.MakeContextCurrent(mEGLSurface, mEGLContext); - - int renderFrameResult = 0; - - if(mIsRotated) + if(mGlWindowRenderThread) { - mWindowBase->SetEglWindowBufferTransform(mTotalRotationAngle); - if(mIsWindowRotated) - { - mWindowBase->SetEglWindowTransform(mWindowRotationAngle); - } - mIsRotated = false; + mGlWindowRenderThread->RenderOnce(); } +} - if(!mInitCallback) +void GlWindow::SetRenderingMode(Dali::GlWindow::RenderingMode mode) +{ + mRenderingMode = mode; + if(mGlWindowRenderThread) { - if(mGLInitCallback) + bool onDemand = false; + if(mRenderingMode == Dali::GlWindow::RenderingMode::ON_DEMAND) { - CallbackBase::Execute(*mGLInitCallback); + onDemand = true; } - mInitCallback = true; - } - - if(mGLRenderFrameCallback) - { - renderFrameResult = CallbackBase::ExecuteReturn(*mGLRenderFrameCallback); - } - - if(mIsWindowRotated) - { - mWindowBase->WindowRotationCompleted(mWindowRotationAngle, mPositionSize.width, mPositionSize.height); - mIsWindowRotated = false; + mGlWindowRenderThread->SetOnDemandRenderMode(onDemand); } - - if(renderFrameResult) - { - eglImpl.SwapBuffers(mEGLSurface); - } - - return true; } -void GlWindow::RenderOnce() +Dali::GlWindow::RenderingMode GlWindow::GetRenderingMode() const { - RunCallback(); + return mRenderingMode; } void GlWindow::InitializeGraphics() { - if(!mIsEGLInitialize) + if(!mIsEGLInitialized) { // Init Graphics std::unique_ptr graphicsFactoryPtr = Utils::MakeUnique(mEnvironmentOptions); @@ -839,42 +805,24 @@ void GlWindow::InitializeGraphics() mDisplayConnection = std::unique_ptr(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) + // Create Render Thread + mGlWindowRenderThread = std::unique_ptr(new GlWindowRenderThread(mPositionSize, mColorDepth)); + if(!mGlWindowRenderThread) { - eglImpl.SetGlesVersion(20); - } - else if(mGLESVersion == Dali::GlWindow::GlesVersion::VERSION_3_0) - { - eglImpl.SetGlesVersion(30); + DALI_LOG_ERROR("Fail to create GlWindow Render Thread!!!!\n"); + return; } - if(eglImpl.ChooseConfig(true, mColorDepth) == false) + mGlWindowRenderThread->SetGraphicsInterface(graphics); + mGlWindowRenderThread->SetWindowBase(mWindowBase.get()); + bool onDemand = false; + if(mRenderingMode == Dali::GlWindow::RenderingMode::ON_DEMAND) { - 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; - } + onDemand = true; } - eglImpl.CreateWindowContext(mEGLContext); - - // Create the EGL window - EGLNativeWindowType window = mWindowBase->CreateEglWindow(mPositionSize.width, mPositionSize.height); - mEGLSurface = eglImpl.CreateSurfaceWindow(window, mColorDepth); + mGlWindowRenderThread->SetOnDemandRenderMode(onDemand); - mIsEGLInitialize = true; + mIsEGLInitialized = true; } } diff --git a/dali/internal/window-system/common/gl-window-impl.h b/dali/internal/window-system/common/gl-window-impl.h index a5f5fb0..4102736 100644 --- a/dali/internal/window-system/common/gl-window-impl.h +++ b/dali/internal/window-system/common/gl-window-impl.h @@ -28,7 +28,7 @@ #include #include #include -#include +#include namespace Dali { @@ -182,6 +182,16 @@ public: */ void RenderOnce(); + /** + * @copydoc Dali::GlWindow::SetRenderingMode() + */ + void SetRenderingMode(Dali::GlWindow::RenderingMode mode); + + /** + * @copydoc Dali::GlWindow::GetRenderingMode() + */ + Dali::GlWindow::RenderingMode GetRenderingMode() const; + public: // For implementation /** * @brief Sets child window with Dali::Window @@ -273,13 +283,6 @@ private: WindowOrientation ConvertToOrientation(int angle) const; /** - * @brief Run Ui GL callback function. - * - * @return true is the callback function works continuos. - */ - bool RunCallback(); - - /** * @brief Initialize and create EGL resource */ void InitializeGraphics(); @@ -372,14 +375,13 @@ public: // Signals private: std::unique_ptr mWindowBase; - std::unique_ptr mGraphics; ///< Graphics interface - std::unique_ptr mDisplayConnection; + std::unique_ptr mGraphics; ///< Graphics interface + std::unique_ptr mDisplayConnection; ///< The native display connection + std::unique_ptr mGlWindowRenderThread; ///< The render thread + EventHandlerPtr mEventHandler; ///< The window events handler + Dali::Window mChildWindow; ///< The default child UI Window 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; @@ -389,16 +391,25 @@ private: bool mIsRotated : 1; bool mIsWindowRotated : 1; bool mIsTouched : 1; + bool mIsEGLInitialized : 1; + bool mDepth : 1; + bool mStencil : 1; - std::vector 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 + PositionSize mPositionSize; ///< The window position and size + EnvironmentOptions mEnvironmentOptions; + std::vector mAvailableAngles; ///< The list of available angle + ColorDepth mColorDepth; ///< The color depth of window + Dali::GlWindow::RenderingMode mRenderingMode; ///< The rendering mode + + int mPreferredAngle; ///< The angle of preferred angle + 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 + int mMSAA; ///< The multisample anti-aliasing for EGL Configuration // Signals KeyEventSignalType mKeyEventSignal; @@ -406,21 +417,6 @@ private: FocusChangeSignalType mFocusChangeSignal; ResizeSignalType mResizeSignal; VisibilityChangedSignalType mVisibilityChangedSignal; - - // EGL, GL Resource - EnvironmentOptions mEnvironmentOptions; - std::unique_ptr mGLInitCallback; - std::unique_ptr mGLRenderFrameCallback; - std::unique_ptr 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 diff --git a/dali/internal/window-system/common/gl-window-render-thread.cpp b/dali/internal/window-system/common/gl-window-render-thread.cpp new file mode 100644 index 0000000..783ff36 --- /dev/null +++ b/dali/internal/window-system/common/gl-window-render-thread.cpp @@ -0,0 +1,274 @@ +/* + * 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. + * + */ + +#include + +#include +#include +#include + +namespace Dali +{ +namespace Internal +{ +namespace Adaptor +{ +namespace +{ +const unsigned int NANOSECONDS_PER_SECOND(1e+9); + +// The following values will get calculated at compile time +const float DEFAULT_FRAME_DURATION_IN_SECONDS(1.0f / 60.0f); +const uint64_t DEFAULT_FRAME_DURATION_IN_NANOSECONDS(DEFAULT_FRAME_DURATION_IN_SECONDS* NANOSECONDS_PER_SECOND); + +} // namespace + +GlWindowRenderThread::GlWindowRenderThread(PositionSize positionSize, ColorDepth colorDepth) +: mGraphics(nullptr), + mWindowBase(nullptr), + mLogFactory(Dali::Adaptor::Get().GetLogFactory()), + mPositionSize(positionSize), + mColorDepth(colorDepth), + mGLInitCallback(), + mGLRenderFrameCallback(), + mGLTerminateCallback(), + mEGLSurface(nullptr), + mEGLContext(nullptr), + mDepth(false), + mStencil(false), + mIsEGLInitialize(false), + mGLESVersion(30), //Default GLES version 30 + mMSAA(0), + mRenderThreadWaitCondition(), + mDestroyRenderThread(0), + mPauseRenderThread(0), + mRenderingMode(0), + mRequestRenderOnce(0) +{ + unsigned int refrashRate = 1u; + mDefaultFrameDurationNanoseconds = uint64_t(refrashRate) * DEFAULT_FRAME_DURATION_IN_NANOSECONDS; +} + +GlWindowRenderThread::~GlWindowRenderThread() +{ +} + +void GlWindowRenderThread::SetGraphicsInterface(GraphicsInterface* graphics) +{ + mGraphics = graphics; +} + +void GlWindowRenderThread::SetWindowBase(WindowBase* windowBase) +{ + mWindowBase = windowBase; +} + +void GlWindowRenderThread::SetEglConfig(bool depth, bool stencil, int msaa, int version) +{ + mDepth = depth; + mStencil = stencil; + mMSAA = msaa; + mGLESVersion = version; +} + +void GlWindowRenderThread::Pause() +{ + ConditionalWait::ScopedLock lock(mRenderThreadWaitCondition); + mPauseRenderThread = 1; + DALI_LOG_RELEASE_INFO("GlWindowRenderThread::Pause()\n"); +} + +void GlWindowRenderThread::Resume() +{ + ConditionalWait::ScopedLock lock(mRenderThreadWaitCondition); + mPauseRenderThread = 0; + DALI_LOG_RELEASE_INFO("GlWindowRenderThread::Resume()\n"); + mRenderThreadWaitCondition.Notify(lock); +} + +void GlWindowRenderThread::Stop() +{ + ConditionalWait::ScopedLock lock(mRenderThreadWaitCondition); + mDestroyRenderThread = 1; + DALI_LOG_RELEASE_INFO("GlWindowRenderThread::Stop()\n"); + mRenderThreadWaitCondition.Notify(lock); +} + +void GlWindowRenderThread::RegisterGlCallback(CallbackBase* initCallback, + CallbackBase* renderFrameCallback, + CallbackBase* terminateCallback) +{ + mGLInitCallback = std::unique_ptr(initCallback); + mGLRenderFrameCallback = std::unique_ptr(renderFrameCallback); + mGLTerminateCallback = std::unique_ptr(terminateCallback); +} + +void GlWindowRenderThread::SetOnDemandRenderMode(bool onDemand) +{ + ConditionalWait::ScopedLock lock(mRenderThreadWaitCondition); + mRenderingMode = static_cast(onDemand); + DALI_LOG_RELEASE_INFO("GlWindowRenderThread::SetOnDemandRenderMode(): mRenderingMode: %d\n", mRenderingMode); + if(!onDemand) + { + mRenderThreadWaitCondition.Notify(lock); + } +} + +void GlWindowRenderThread::RenderOnce() +{ + ConditionalWait::ScopedLock lock(mRenderThreadWaitCondition); + mRequestRenderOnce = 1; + mRenderThreadWaitCondition.Notify(lock); +} + +void GlWindowRenderThread::Run() +{ + Dali::SetThreadName("GlWindowRenderThread"); + mLogFactory.InstallLogFunction(); + + int renderFrameResult = 0; + EglGraphics* eglGraphics = static_cast(mGraphics); + + Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation(); + + InitializeGraphics(eglGraphics); + + eglImpl.MakeContextCurrent(mEGLSurface, mEGLContext); + + if(mGLInitCallback) + { + CallbackBase::Execute(*mGLInitCallback); + } + + uint64_t timeToSleepUntil = 0; + + while(RenderReady(timeToSleepUntil)) + { + uint64_t currentFrameStartTime = 0; + TimeService::GetNanoseconds(currentFrameStartTime); + + if(mGLRenderFrameCallback) + { + renderFrameResult = CallbackBase::ExecuteReturn(*mGLRenderFrameCallback); + + if(renderFrameResult) + { + eglImpl.SwapBuffers(mEGLSurface); + } + } + renderFrameResult = 0; + + if(timeToSleepUntil == 0) + { + timeToSleepUntil = currentFrameStartTime + mDefaultFrameDurationNanoseconds; + } + else + { + timeToSleepUntil += mDefaultFrameDurationNanoseconds; + uint64_t currentFrameEndTime = 0; + TimeService::GetNanoseconds(currentFrameEndTime); + while(currentFrameEndTime > timeToSleepUntil + mDefaultFrameDurationNanoseconds) + { + timeToSleepUntil += mDefaultFrameDurationNanoseconds; + } + } + + TimeService::SleepUntil(timeToSleepUntil); + + if(mRequestRenderOnce) + { + mRequestRenderOnce = 0; + } + } + + if(mGLTerminateCallback) + { + CallbackBase::Execute(*mGLTerminateCallback); + } + + if(mIsEGLInitialize) + { + EglGraphics* eglGraphics = static_cast(mGraphics); + Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation(); + + if(mEGLSurface) + { + eglImpl.DestroySurface(mEGLSurface); + mEGLSurface = nullptr; + } + + if(mEGLContext) + { + eglImpl.DestroyContext(mEGLContext); + mEGLContext = nullptr; + } + + eglImpl.TerminateGles(); + } +} + +void GlWindowRenderThread::InitializeGraphics(EglGraphics* eglGraphics) +{ + mIsEGLInitialize = true; + + Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation(); + eglImpl.SetGlesVersion(mGLESVersion); + + if(eglImpl.ChooseConfig(true, mColorDepth) == false) + { + if(mGLESVersion == 30) + { + DALI_LOG_RELEASE_INFO("InitializeGraphics: Fail to choose config with GLES30, retry with GLES20\n"); + eglImpl.SetGlesVersion(20); + mGLESVersion = 20; + 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); +} + +bool GlWindowRenderThread::RenderReady(uint64_t& timeToSleepUntil) +{ + ConditionalWait::ScopedLock updateLock(mRenderThreadWaitCondition); + while((!mDestroyRenderThread && mRenderingMode && !mRequestRenderOnce) || mPauseRenderThread) + { + timeToSleepUntil = 0; + mRenderThreadWaitCondition.Wait(updateLock); + } + + // Keep the update-render thread alive if this thread is NOT to be destroyed + return !mDestroyRenderThread; +} + +} // namespace Adaptor + +} // namespace Internal + +} // namespace Dali diff --git a/dali/internal/window-system/common/gl-window-render-thread.h b/dali/internal/window-system/common/gl-window-render-thread.h new file mode 100644 index 0000000..8111d69 --- /dev/null +++ b/dali/internal/window-system/common/gl-window-render-thread.h @@ -0,0 +1,200 @@ +#ifndef DALI_INTERNAL_WINDOWSYSTEM_COMMON_GL_WINDOW_RENDER_THREAD_H +#define DALI_INTERNAL_WINDOWSYSTEM_COMMON_GL_WINDOW_RENDER_THREAD_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 + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ +class Adaptor; + +namespace Internal +{ +namespace Adaptor +{ +class WindowBase; +class GlWindow; + +/** + * @brief It is for render thread for GlWindow. + * User callbacks works in the thread. + * + * Key Points: + * 1. Two Threads: + * a. Main/Event Thread. + * b. Render Thread. + * 2. There is NO VSync thread: + * a. We calculate the difference between these two times and if: + * i. The difference is less than the default frame time, we sleep. + * ii. If it’s more or the same, we continue. + * 3. Support Rendering mode + * a. CONTINUOUS mode + * i. The rendering loop works continuously. + * b. ON_DEMAND mode + * i. The rendering works by user's request. + * ii. User's request is the renderOnce()'s function calling. + */ + +class GlWindowRenderThread : public Dali::Thread +{ +public: + /** + * Constructor + * + * @param[in] positionSize The position and size of the physical window + * @param[in] depth color depth of the physical window + */ + GlWindowRenderThread(PositionSize positionSize, ColorDepth colorDepth); + + /** + * destructor. + */ + virtual ~GlWindowRenderThread(); + + /** + * Sets the GraphicsInterface instance. + * This graphics instance is used to create and initialize graphics resource + * + * @param[in] graphics The graphice instance + */ + void SetGraphicsInterface(GraphicsInterface* graphics); + + /** + * Sets the WindowBase instance + * This WindowBase instance is used to call wl egl window APIs. + * + * @param[in] windowBase The WindowBase instance + */ + void SetWindowBase(WindowBase* windowBase); + + /** + * @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, int version); + + /** + * Pauses the Render Thread. + * It is called when GlWindow is iconified or hidden. + * + * This will lock the mutex in mRenderThreadWaitCondition. + */ + void Pause(); + + /** + * Resumes the Render Thread. + * It is called when GlWindow is de-iconified or shown. + * + * This will lock the mutex in mRenderThreadWaitCondition. + */ + void Resume(); + + /** + * Stops the Render Thread. + * This will lock the mutex in mRenderThreadWaitCondition. + * + * @note Should only be called in Stop as calling this will kill the render thread. + */ + void Stop(); + + /** + * @copydoc Dali::GlWindow::RegisterGlCallback() + */ + void RegisterGlCallback(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback); + + /** + * Enable OnDemand Rendering Mode + * + * @param[in] onDemand the flag of OnDemand Rendering Mode. If the flag is true, rendering mode is OnDemand, otherwise the flag is false, rendering mode is continuous mode. + */ + void SetOnDemandRenderMode(bool onDemand); + + /** + * @copydoc Dali::GlWindow::RenderOnce() + */ + void RenderOnce(); + +protected: + /** + * The Render thread loop. This thread will be destroyed on exit from this function. + */ + virtual void Run(); + +private: + /** + * @brief Initialize and create EGL resource + */ + void InitializeGraphics(EglGraphics* eglGraphics); + + /** + * Called by the Render Thread which ensures a wait if required. + * + * @param[out] timeToSleepUntil The time remaining in nanoseconds to keep the thread sleeping before resuming. + * @return false, if the thread should stop. + */ + bool RenderReady(uint64_t& timeToSleepUntil); + +private: + GraphicsInterface* mGraphics; ///< Graphics interface + WindowBase* mWindowBase; + + const Dali::LogFactoryInterface& mLogFactory; + + PositionSize mPositionSize; ///< Position + ColorDepth mColorDepth; + + // EGL, GL Resource + std::unique_ptr mGLInitCallback; + std::unique_ptr mGLRenderFrameCallback; + std::unique_ptr mGLTerminateCallback; + EGLSurface mEGLSurface; + EGLContext mEGLContext; + bool mDepth : 1; + bool mStencil : 1; + bool mIsEGLInitialize : 1; + int mGLESVersion; + int mMSAA; + + // To manage the render/main thread + ConditionalWait mRenderThreadWaitCondition; ///< The wait condition for the update-render-thread. + volatile unsigned int mDestroyRenderThread; ///< Stop render thread. It means this rendter thread will be destoried. + volatile unsigned int mPauseRenderThread; ///< Sleep render thread by pause. + volatile unsigned int mRenderingMode; ///< Rendering Mode, 0: continuous, 1:OnDemad + volatile unsigned int mRequestRenderOnce; ///< Request rendering once + + uint64_t mDefaultFrameDurationNanoseconds; ///< Default duration of a frame (used for sleeping if not enough time elapsed). Not protected by lock, but written to rarely so not worth adding a lock when reading. + +}; // GlWindowRenderThread + +} // namespace Adaptor +} // namespace Internal +} // namespace Dali + +#endif diff --git a/dali/internal/window-system/file.list b/dali/internal/window-system/file.list index 4f7b234..101958f 100644 --- a/dali/internal/window-system/file.list +++ b/dali/internal/window-system/file.list @@ -9,6 +9,7 @@ SET( adaptor_window_system_common_src_files ${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 + ${adaptor_window_system_dir}/common/gl-window-render-thread.cpp ) # module: window-system, backend: tizen-wayland