From: Daekwang Ryu Date: Wed, 20 Jan 2021 10:18:48 +0000 (+0900) Subject: init glview X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=871641eaa98a75c003a4d6e22bd280eaa83c582d;p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git init glview Change-Id: I59934b5ec888b9c5085a08a7bdc79dae812c9fee glview Change-Id: I740061ae91b91d97c3cbc46842bdb216c0a20c74 Build OK Change-Id: I5e437b9abede0cff92b5467a942e6d068d338391 Fix Any Change-Id: I6c53e1afe61554afb59101142c71454975c2a70b Clear Sample OK Change-Id: I8a61364de45275a6c7431843697b16273e7fa2c8 Triangle sample OK Change-Id: I6a3ca525cfbb2cb0d6e7b5967d76d02d35af92c0 --- diff --git a/dali-toolkit/dali-toolkit.h b/dali-toolkit/dali-toolkit.h index 26f96a69f3..75d572552b 100644 --- a/dali-toolkit/dali-toolkit.h +++ b/dali-toolkit/dali-toolkit.h @@ -2,7 +2,7 @@ #define DALI_TOOLKIT_H /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * Copyright (c) 2021 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. @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include diff --git a/dali-toolkit/internal/controls/gl-view/gl-renderer.cpp b/dali-toolkit/internal/controls/gl-view/gl-renderer.cpp new file mode 100644 index 0000000000..5a789b5ca8 --- /dev/null +++ b/dali-toolkit/internal/controls/gl-view/gl-renderer.cpp @@ -0,0 +1,324 @@ +/* + * Copyright 2019 by Samsung Electronics, Inc., + * + * This software is the confidential and proprietary information + * of Samsung Electronics, Inc. ("Confidential Information"). You + * shall not disclose such Confidential Information and shall use + * it only in accordance with the terms of the license agreement + * you entered into with Samsung. + * + */ + +// CLASS HEADER +#include "gl-renderer.h" + +//INTERNAL INCLUDES +// #include "dali-ext-dlog.h" +// #include "rendering-behavior-manager.h" + +//EXTERNAL INCLUDES +// #include +// #include +// #include +#include +#include +// #include +// #include +// #include +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Internal +{ +namespace +{ +const unsigned int DEFAULT_SLEEP_TIME = 16u; +} + +// struct EglData +// { +// public: +// EGLNativeDisplayType mNativeDisplay; +// tbm_surface_queue_h mNativeWindow; +// EGLDisplay mEglDisplay; +// EGLConfig mEglConfig; +// EGLSurface mEglSurface; +// EGLContext mEglContext; + +// EglData() +// : mNativeDisplay(NULL), +// mNativeWindow(NULL), +// mEglDisplay(EGL_NO_DISPLAY), +// mEglConfig(NULL), +// mEglSurface(EGL_NO_SURFACE), +// mEglContext(EGL_NO_CONTEXT) +// { +// } + +// ~EglData() +// { +// } +// }; + +GLRenderer::GLRenderer(unsigned int viewWidth, unsigned viewHeight, tbm_surface_queue_h tbmSurfaceQueue) +: mViewWidth(viewWidth), + mViewHeight(viewHeight), + mTbmSurfaceQueue(tbmSurfaceQueue), + mGLInitCallback(NULL), + mGLDrawCallback(NULL), + mGLTerminateCallback(NULL), + // mEglData(NULL), + mSleepTime(DEFAULT_SLEEP_TIME), + mMode(RENDER_MODE::RENDER_MODE_ONDEMAND), + mRenderOnce(false), + mPauseThread(true), + mQuitThread(false), + mGraphics(), + mDisplayConnection(nullptr), + mColorDepth(COLOR_DEPTH_24), + 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) +{ +} + +bool GLRenderer::InitializeEGL() +{ + // Init Graphics + std::unique_ptr graphicsFactoryPtr = Utils::MakeUnique(mEnvironmentOptions); + auto graphicsFactory = *graphicsFactoryPtr.get(); + + mGraphics = std::unique_ptr(&graphicsFactory.Create()); + GraphicsInterface* graphics = mGraphics.get(); + EglGraphics* eglGraphics = static_cast(graphics); + eglGraphics->Initialize(mDepth, mStencil, false, mMSAA); + + 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) + // { + // eglImpl.SetGlesVersion(20); + // } + // else if(mGLESVersion == Dali::GlWindow::GlesVersion::VERSION_3_0) + // { + eglImpl.SetGlesVersion(30); + // } + + if(eglImpl.ChooseConfig(true, mColorDepth) == false) + { + DALI_LOG_ERROR("InitializeGraphics: Fail to choose config"); + + // 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); + // EGLNativeWindowType window = mWindowBase->CreateEglWindow(mPositionSize.width, mPositionSize.height); + mEGLSurface = eglImpl.CreateSurfaceWindow(mTbmSurfaceQueue, mColorDepth); + + return true; +} + +void GLRenderer::DeInitializeEGL() +{ + // if(mEglData->mEglContext != EGL_NO_CONTEXT) + // { + // eglDestroyContext(mEglData->mEglDisplay, mEglData->mEglContext); + // mEglData->mEglContext = EGL_NO_CONTEXT; + // } + + // if(mEglData->mEglSurface != EGL_NO_SURFACE) + // { + // eglDestroySurface(mEglData->mEglDisplay, mEglData->mEglSurface); + // mEglData->mEglSurface = EGL_NO_SURFACE; + // } + + // eglMakeCurrent(mEglData->mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + + // if(mEglData->mEglDisplay != EGL_NO_DISPLAY) + // { + // eglTerminate(mEglData->mEglDisplay); + // mEglData->mEglDisplay = EGL_NO_DISPLAY; + // } + + // if(mEglData->mNativeDisplay != NULL) + // { + // tbm_dummy_display_destroy(reinterpret_cast(mEglData->mNativeDisplay)); + // mEglData->mNativeDisplay = NULL; + // } + + // delete mEglData; + // mEglData = NULL; +} + +void GLRenderer::RegisterGLCallback(GLInit glInitCallback, GLDraw glDrawCallback, GLTerminate glTerminateCallback) +{ + if(glInitCallback == NULL || glDrawCallback == NULL || glTerminateCallback == NULL) + { + DALI_LOG_ERROR("GLImageRender Callback is not set glInitCallback [%p] glDrawCallback[%p] glTerminateCallback[%p]", + glInitCallback, + glDrawCallback, + glTerminateCallback); + return; + } + + mGLInitCallback = glInitCallback; + mGLDrawCallback = glDrawCallback; + mGLTerminateCallback = glTerminateCallback; +} + +void GLRenderer::SetRenderingMode(RENDER_MODE mode) +{ + if(mode == mMode) + { + return; + } + + //Notify GLRender thread. + Dali::ConditionalWait::ScopedLock updatelock(mConditionalWait); + if(mMode == RENDER_MODE::RENDER_MODE_CONTINUOUSLY) + { + mRenderOnce = false; + } + mMode = mode; + mConditionalWait.Notify(updatelock); +} + +void GLRenderer::RequestRender() +{ + if(mMode == RENDER_MODE::RENDER_MODE_CONTINUOUSLY) + { + return; + } + + //Notify GLRender thread. + Dali::ConditionalWait::ScopedLock updatelock(mConditionalWait); + mRenderOnce = true; + mConditionalWait.Notify(updatelock); +} + +void GLRenderer::Run() +{ + Dali::SetThreadName("GLViewRenderer"); + bool ret = InitializeEGL(); + if(ret == false) + { + DALI_LOG_ERROR("EGL Initilization Failed, Could not start GLRender Thread"); + return; + } + + bool callOnce = true; + bool initRet = false; + + while(1) + { + { + Dali::ConditionalWait::ScopedLock lock(mConditionalWait); + while(mPauseThread == true || + (mMode == RENDER_MODE::RENDER_MODE_ONDEMAND && mRenderOnce == false)) + { + mConditionalWait.Wait(lock); + } + } + + if(mQuitThread) + { + DALI_LOG_ERROR("Exiting GLRender thread"); + mGLTerminateCallback(); + return; + } + + auto startTime = std::chrono::steady_clock::now(); + + if(callOnce) + { + //Calling GLInit callback, only once. + initRet = mGLInitCallback(mViewWidth, mViewHeight); + callOnce = false; + } + + // Calling GLDraw callback, per frame depending on RenderMde set. + if(initRet == true) + { + mGLDrawCallback(); + } + + // eglSwapBuffers(mEglData->mEglDisplay, mEglData->mEglSurface); + GraphicsInterface* graphics = mGraphics.get(); + EglGraphics* eglGraphics = static_cast(graphics); + Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation(); + eglImpl->SwapBuffers(mEGLSurface); + + { + Dali::ConditionalWait::ScopedLock updateLock(mConditionalWait); + if(mRenderOnce == true) + { + mRenderOnce = false; + } + } + + // RenderingBehaviorManager::RequireRender(); + + auto endTime = std::chrono::steady_clock::now(); + auto elapsedTime = std::chrono::duration_cast(endTime - startTime); + if(elapsedTime < mSleepTime) + { + std::this_thread::sleep_for(mSleepTime - elapsedTime); + } + } + return; +} + +void GLRenderer::QuitRenderThread() +{ + mQuitThread = true; + // Set to come out Render Thread out of waiting condition. + Dali::ConditionalWait::ScopedLock updatelock(mConditionalWait); + mMode = RENDER_MODE::RENDER_MODE_CONTINUOUSLY; + mPauseThread = false; + mConditionalWait.Notify(updatelock); +} + +void GLRenderer::PauseRenderThread(bool pause) +{ + //Notify GLRender thread, If actor visibility is change + Dali::ConditionalWait::ScopedLock updatelock(mConditionalWait); + mPauseThread = pause; + mConditionalWait.Notify(updatelock); +} + +GLRenderer::~GLRenderer() +{ + DeInitializeEGL(); +} + +} // namespace Internal +} // namespace Toolkit +} // namespace Dali diff --git a/dali-toolkit/internal/controls/gl-view/gl-renderer.h b/dali-toolkit/internal/controls/gl-view/gl-renderer.h new file mode 100644 index 0000000000..375a83a623 --- /dev/null +++ b/dali-toolkit/internal/controls/gl-view/gl-renderer.h @@ -0,0 +1,103 @@ +/* + * Copyright 2019 by Samsung Electronics, Inc., + * + * This software is the confidential and proprietary information + * of Samsung Electronics, Inc. ("Confidential Information"). You + * shall not disclose such Confidential Information and shall use + * it only in accordance with the terms of the license agreement + * you entered into with Samsung. + * + */ + +// EXTERNAL INCLUDES +#include +#include +#include + +// #include +#include +#include +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Internal +{ +typedef bool (*GLInit)(unsigned, unsigned); +typedef void (*GLDraw)(); +typedef void (*GLTerminate)(); + +class GLRenderer : public Dali::Thread +{ +public: + enum class RENDER_MODE + { + RENDER_MODE_CONTINUOUSLY, + RENDER_MODE_ONDEMAND + }; + GLRenderer(unsigned int viewWidth, unsigned viewHeight, void* tbmSurfaceQueue); + + virtual ~GLRenderer(); + void RegisterGLCallback(GLInit glInitCallback, GLDraw glDrawCallback, GLTerminate glTerminateCallback); + void SetRenderingMode(RENDER_MODE mode); + void RequestRender(); + void QuitRenderThread(); + void PauseRenderThread(bool pause); + +protected: + virtual void Run(); + +private: + GLRenderer(const GLRenderer& obj) = delete; + GLRenderer operator=(const GLRenderer& obj) = delete; + + bool InitializeEGL(); + void DeInitializeEGL(); + +private: + unsigned mViewWidth; + unsigned mViewHeight; + + // tbm_surface_queue_h mTbmSurfaceQueue; + void* mTbmSurfaceQueue; + + GLInit mGLInitCallback; + GLDraw mGLDrawCallback; + GLTerminate mGLTerminateCallback; + + Dali::ConditionalWait mConditionalWait; + // EglData* mEglData; + + std::chrono::milliseconds mSleepTime; + RENDER_MODE mMode; + + bool mRenderOnce; + bool mPauseThread; + std::atomic_bool mQuitThread; + + std::unique_ptr mGraphics; ///< Graphics interface + std::unique_ptr mDisplayConnection; + ColorDepth mColorDepth; + + EnvironmentOptions mEnvironmentOptions; + std::unique_ptr mGLInitCallback; + std::unique_ptr mGLRenderFrameCallback; + std::unique_ptr mGLTerminateCallback; + CallbackBase* mGLRenderCallback; + // EGLSurface mEGLSurface; + // EGLContext mEGLContext; + void* mEGLSurface; + void* mEGLContext; + // Dali::GlWindow::GlesVersion mGLESVersion; + bool mInitCallback : 1; + bool mDepth : 1; + bool mStencil : 1; + bool mIsEGLInitialize : 1; + int mMSAA; +}; + +} // namespace Internal +} // namespace Toolkit +} // namespace Dali diff --git a/dali-toolkit/internal/controls/gl-view/gl-surface-view-impl.cpp b/dali-toolkit/internal/controls/gl-view/gl-surface-view-impl.cpp new file mode 100644 index 0000000000..4db99d3fcd --- /dev/null +++ b/dali-toolkit/internal/controls/gl-view/gl-surface-view-impl.cpp @@ -0,0 +1,268 @@ +// CLASS HEADER +#include "gl-surface-view-impl.h" +// #include + +// EXTERNAL INCLUDES +#include +#include +// #include +#include + +// INTERNAL INCLUDES +// #include "common-shader.h" +// #include "dali-ext-dlog.h" +// #include "misc.h" +// #include "renderer-utility.h" +// #include "rendering-behavior-manager.h" +#include +#include +#include +#include +#include +#include + +using namespace Dali; +using namespace Dali::Toolkit; + +const char* GL_SURFACE_VIEW_SHADER_VERT_GL = DALI_COMPOSE_SHADER( + attribute mediump vec2 aPosition; + varying mediump vec2 vTexCoord; + uniform highp mat4 uMvpMatrix; + uniform highp vec3 uSize; + varying mediump vec2 sTexCoordRect; + + void main() { + gl_Position = uMvpMatrix * vec4(aPosition * uSize.xy, 0.0, 1.0); + vTexCoord = aPosition + vec2(0.5); + }); + +const char* GL_SURFACE_VIEW_SHADER_FRAG_GL = DALI_COMPOSE_SHADER( + uniform lowp vec4 uColor; + varying mediump vec2 vTexCoord; + uniform samplerExternalOES sTexture; + + void main() { + gl_FragColor = texture2D(sTexture, vTexCoord) * uColor; + }); + +namespace Dali +{ +namespace Toolkit +{ +namespace Internal +{ +GLSurfaceView::GLSurfaceView(unsigned int viewWidth, unsigned int viewHeight) +: Control(ControlBehaviour(ACTOR_BEHAVIOUR_DEFAULT | DISABLE_STYLE_CHANGE_SIGNALS)), + mViewWidth(viewWidth), + mViewHeight(viewHeight), + mGLRenderer(NULL), + mTargetSurface(NULL) +{ + // Add callback to pause and resume thread when application paused or resumed + Dali::LifecycleController lifecycleController = Dali::LifecycleController::Get(); + lifecycleController.PauseSignal().Connect(this, &GLSurfaceView::OnApplicationPaused); + lifecycleController.ResumeSignal().Connect(this, &GLSurfaceView::OnApplicationResumed); +} + +GLSurfaceView::~GLSurfaceView() +{ + mGLRenderer->QuitRenderThread(); + mGLRenderer->Join(); + delete mGLRenderer; + mGLRenderer = NULL; + + mTargetSurface = NULL; +} + +Dali::Toolkit::GLSurfaceView GLSurfaceView::New(unsigned int viewWidth, unsigned int viewHeight) +{ + GLSurfaceView* impl = new GLSurfaceView(viewWidth, viewHeight); + Dali::Toolkit::GLSurfaceView handle = Dali::Toolkit::GLSurfaceView(*impl); + impl->Initialize(); + return handle; +} + +void GLSurfaceView::RegisterGLCallback(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback) +{ + mGLRenderer->RegisterGLCallback(initCallback, renderFrameCallback, terminateCallback); +} + +void GLSurfaceView::SetRenderingMode(Dali::Toolkit::GLSurfaceView::RENDER_MODE mode) +{ + mGLRenderer->SetRenderingMode(static_cast(mode)); +} + +void GLSurfaceView::RequestRender() +{ + mGLRenderer->RequestRender(); +} + +void GLSurfaceView::OnInitialize() +{ + //making sure that RBM is initialized in main thread + // RenderingBehaviorManager::RequireRender(); + CreateGLView(); +} + +Shader GLSurfaceView::CreateShader() +{ + // static const char* DEFAULT_SAMPLER_TYPENAME = "sampler2D"; + + if(mTargetSurface) + { + std::string fragmentShader; + + //Get custom fragment shader prefix + const char* fragmentPreFix = mTargetSurface->GetCustomFragmentPrefix(); + if(fragmentPreFix) + { + fragmentShader = fragmentPreFix; + fragmentShader += GL_SURFACE_VIEW_SHADER_FRAG_GL; + } + else + { + fragmentShader = GL_SURFACE_VIEW_SHADER_FRAG_GL; + } + + //Get custom sampler type name + // const char* customSamplerTypename = mTargetSurface->GetCustomSamplerTypename(); + // if(customSamplerTypename) + // { + // fragmentShader.replace(fragmentShader.find(DEFAULT_SAMPLER_TYPENAME), strlen(DEFAULT_SAMPLER_TYPENAME), customSamplerTypename); + // } + + return Shader::New(GL_SURFACE_VIEW_SHADER_VERT_GL, fragmentShader); + } + else + { + return Shader::New(GL_SURFACE_VIEW_SHADER_VERT_GL, GL_SURFACE_VIEW_SHADER_FRAG_GL); + } +} + +void GLSurfaceView::VisibilityChanged(Dali::Actor, bool visible, Dali::DevelActor::VisibilityChange::Type) +{ + if(Self().GetProperty(Actor::Property::CONNECTED_TO_SCENE) == true) + { + mGLRenderer->PauseRenderThread(!visible); + } +} + +void GLSurfaceView::OnApplicationResumed() +{ + if(Self().GetProperty(Actor::Property::CONNECTED_TO_SCENE) == true) + { + mGLRenderer->PauseRenderThread(!Self().GetProperty(Actor::Property::VISIBLE)); + } +} + +void GLSurfaceView::OnApplicationPaused() +{ + mGLRenderer->PauseRenderThread(true); +} + +void GLSurfaceView::OnSceneCallback(Actor actor) +// void GLSurfaceView::OnSceneCallback(Actor actor UNUSED) +{ + mGLRenderer->PauseRenderThread(!Self().GetProperty(Actor::Property::VISIBLE)); +} + +void GLSurfaceView::OffSceneCallback(Actor actor) +// void GLSurfaceView::OffSceneCallback(Actor actor UNUSED) +{ + mGLRenderer->PauseRenderThread(true); +} + +void GLSurfaceView::AddRenderer() +{ + Actor self = Self(); + + // Geometry geometry = RendererUtility::GetInstance()->GetGeometry(RendererUtility::GeometryType::Quad); + + // Shader shader = RendererUtility::GetInstance()->GetShader(RendererUtility::ShaderType::VideoImageView); + // if(!shader) + // { + // shader = CreateShader(); + // RendererUtility::GetInstance()->SaveShader(shader, RendererUtility::ShaderType::VideoImageView); + // } + Geometry geometry = VisualFactoryCache::CreateQuadGeometry(); + Shader shader = CreateShader(); + Renderer renderer = Renderer::New(geometry, shader); + + if(!mTargetSurface) + { + DALI_LOG_ERROR("Target Surface is NULL"); + return; + } + + Texture nativeTexture = Texture::New(*mTargetSurface); + TextureSet textureSet = TextureSet::New(); + textureSet.SetTexture(0u, nativeTexture); + + renderer.SetTextures(textureSet); + renderer.SetProperty(Dali::Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA, true); + + self.AddRenderer(renderer); +} + +// void GLSurfaceView::EnqueueDefaultTbmSurface(tbm_surface_queue_h tbmQueue) +// { +// if(tbm_surface_queue_can_dequeue(tbmQueue, 0)) +// { +// tbm_surface_h tbmSurface; +// if(tbm_surface_queue_dequeue(tbmQueue, &tbmSurface) != TBM_SURFACE_QUEUE_ERROR_NONE) +// { +// DALI_LOG_ERROR("Failed to dequeue a tbm_surface [%p]\n", this); +// return; +// } +// tbm_surface_info_s info; +// tbm_surface_map(tbmSurface, TBM_OPTION_WRITE, &info); +// memset(info.planes[0].ptr, 0x00, info.planes[0].size); +// tbm_surface_unmap(tbmSurface); +// tbm_surface_queue_enqueue(tbmQueue, tbmSurface); +// } +// } + +void GLSurfaceView::CreateGLView() +{ + DALI_LOG_ERROR("DKDK CreateGLView"); + + mTargetSurface = Dali::NativeImageSourceQueue::New(mViewWidth, mViewHeight, Dali::NativeImageSourceQueue::COLOR_DEPTH_DEFAULT); + if(!mTargetSurface) + { + DALI_LOG_ERROR("NativeImageSourceQueue is NULL"); + return; + } + + AddRenderer(); + + Actor self = Self(); + self.SetProperty(Actor::Property::SIZE, Vector2(mViewWidth, mViewHeight)); + + //Get the Tbm queue, created internally by NativeImageSourceQueue. + tbm_surface_queue_h tbmQueue = AnyCast(mTargetSurface->GetNativeImageSourceQueue()); + // void* tbmQueue = AnyCast(mTargetSurface->GetNativeImageSourceQueue()); + // void* tbmQueue = AnyCast(mTargetSurface->GetNativeImageSourceQueue()); + + if(!tbmQueue) + { + DALI_LOG_ERROR("Tbm Surface queue is NULL"); + return; + } + + // EnqueueDefaultTbmSurface(tbmQueue); + + //Create and Start Render Thread. + mGLRenderer = new GLRenderer(mViewWidth, mViewHeight, tbmQueue); + mGLRenderer->Start(); + + //Adding VisibilityChange Signal. + Dali::DevelActor::VisibilityChangedSignal(self).Connect(this, &GLSurfaceView::VisibilityChanged); + self.OnSceneSignal().Connect(this, &GLSurfaceView::OnSceneCallback); + self.OffSceneSignal().Connect(this, &GLSurfaceView::OffSceneCallback); +} + +} // namespace Internal + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/controls/gl-view/gl-surface-view-impl.h b/dali-toolkit/internal/controls/gl-view/gl-surface-view-impl.h new file mode 100644 index 0000000000..bd542d0863 --- /dev/null +++ b/dali-toolkit/internal/controls/gl-view/gl-surface-view-impl.h @@ -0,0 +1,109 @@ +#ifndef DALI_TOOLKIT_INTERNAL_GL_SURFACE_VIEW_H +#define DALI_TOOLKIT_INTERNAL_GL_SURFACE_VIEW_H + +/* + * Copyright 2019 by Samsung Electronics, Inc., + * + * This software is the confidential and proprietary information + * of Samsung Electronics, Inc. ("Confidential Information"). You + * shall not disclose such Confidential Information and shall use + * it only in accordance with the terms of the license agreement + * you entered into with Samsung. + * + */ + +// EXTERNAL INCLUDES +#include +#include +#include +#include +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ +namespace Toolkit +{ +class GLSurfaceView; + +namespace Internal +{ +class GLSurfaceView : public Dali::Toolkit::Internal::Control +{ +protected: + virtual ~GLSurfaceView(); + +public: + /** + * @copydoc Dali::Toolkit::GLSurfaceView::New() + */ + static Dali::Toolkit::GLSurfaceView New(unsigned int viewWidth, unsigned int viewHeight); + + GLSurfaceView(unsigned int viewWidth, unsigned int viewHeight); + + void RegisterGLCallback(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback); + + void SetRenderingMode(Dali::Toolkit::GLSurfaceView::RENDER_MODE mode); + + void RequestRender(); + +private: // From Control + /** + * @copydoc Toolkit::Control::OnInitialize() + */ + virtual void OnInitialize(); + +private: + GLSurfaceView(const GLSurfaceView& glSurfaceView); + + GLSurfaceView& operator=(const GLSurfaceView& glSurfaceView); + + void CreateGLView(); + + Dali::Shader CreateShader(); + + // void EnqueueDefaultTbmSurface(tbm_surface_queue_h tbmQueue); + + void VisibilityChanged(Dali::Actor, bool visible, Dali::DevelActor::VisibilityChange::Type); + + void OnApplicationPaused(); + + void OnApplicationResumed(); + + void OnSceneCallback(Dali::Actor actor); + + void OffSceneCallback(Dali::Actor actor); + + void AddRenderer(); + +private: + unsigned int mViewWidth; + unsigned int mViewHeight; + + GLRenderer* mGLRenderer; + Dali::NativeImageSourceQueuePtr mTargetSurface; +}; + +} // namespace Internal + +inline Dali::Toolkit::Internal::GLSurfaceView& GetImpl(Dali::Toolkit::GLSurfaceView& handle) +{ + DALI_ASSERT_ALWAYS(handle); + Dali::RefObject& impl = handle.GetImplementation(); + return static_cast(impl); +} + +inline const Dali::Toolkit::Internal::GLSurfaceView& GetImpl(const Dali::Toolkit::GLSurfaceView& handle) +{ + DALI_ASSERT_ALWAYS(handle); + const Dali::RefObject& impl = handle.GetImplementation(); + return static_cast(impl); +} + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_INTERNAL_GL_SURFACE_VIEW_H diff --git a/dali-toolkit/internal/controls/gl-view/gl-surface-view-thread.cpp b/dali-toolkit/internal/controls/gl-view/gl-surface-view-thread.cpp new file mode 100644 index 0000000000..726fdb0322 --- /dev/null +++ b/dali-toolkit/internal/controls/gl-view/gl-surface-view-thread.cpp @@ -0,0 +1,265 @@ +/* + * Copyright 2019 by Samsung Electronics, Inc., + * + * This software is the confidential and proprietary information + * of Samsung Electronics, Inc. ("Confidential Information"). You + * shall not disclose such Confidential Information and shall use + * it only in accordance with the terms of the license agreement + * you entered into with Samsung. + * + */ + +// CLASS HEADER +#include "gl-surface-view-thread.h" + +#include + +//EXTERNAL INCLUDES +#include +#include +#include +#include +#include +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Internal +{ +namespace +{ +const unsigned int DEFAULT_SLEEP_TIME = 16u; +} + +GLRenderer::GLRenderer(unsigned int viewWidth, unsigned viewHeight, tbm_surface_queue_h tbmSurfaceQueue) +: mSurface(nullptr), + mViewWidth(viewWidth), + mViewHeight(viewHeight), + mTbmSurfaceQueue(tbmSurfaceQueue), + // mGLInitCallback(NULL), + // mGLDrawCallback(NULL), + // mGLTerminateCallback(NULL), + mSleepTime(DEFAULT_SLEEP_TIME), + mMode(RENDER_MODE::RENDER_MODE_ONDEMAND), + mRenderOnce(false), + mPauseThread(true), + mQuitThread(false), + mColorDepth(Dali::NativeImageSourceQueue::COLOR_DEPTH_32), + // mGLInitCallback(), + // mGLRenderFrameCallback(), + // mGLTerminateCallback(), + // mInitCallback(false), + mDepth(false), + mStencil(false), + mIsEGLInitialize(false), + mMSAA(0) +{ + // bool ret = InitializeEGL(); + // if(ret == false) + // { + // DALI_LOG_ERROR("EGL Initilization Failed, Could not start GLRender Thread"); + // return; + // } +} + +bool GLRenderer::InitializeEGL() +{ + DALI_LOG_ERROR("DKDK InitializeEGL()"); + + // TODO: Check third parameter the translucent + mSurface = std::unique_ptr(CreateNativeSurface(SurfaceSize(mViewWidth, mViewHeight), mTbmSurfaceQueue, true)); + // mSurface.get()->SetAdaptor(Dali::Adaptor::Get()); + NativeRenderSurface* nativeSurface = dynamic_cast(mSurface.get()); + nativeSurface->SetGLView(true); + nativeSurface->InitializeGraphics(); + + DALI_LOG_ERROR("DKDK mTbmSurfaceQueue %p, mSurface %p", mTbmSurfaceQueue, mSurface.get()); + + return true; +} + +void GLRenderer::DeInitializeEGL() +{ +} + +void GLRenderer::RegisterGLCallback(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback) +{ + DALI_LOG_ERROR("DKDK GLRenderer::RegisterGLCallback"); + + if(initCallback == NULL || renderFrameCallback == NULL || terminateCallback == NULL) + { + DALI_LOG_ERROR("GLImageRender Callback is not set initCallback [%p] renderFrameCallback[%p] terminateCallback[%p]", + initCallback, + renderFrameCallback, + terminateCallback); + return; + } + + mGLInitCallback = std::unique_ptr(initCallback); + mGLRenderFrameCallback = std::unique_ptr(renderFrameCallback); + mGLTerminateCallback = std::unique_ptr(terminateCallback); +} + +NativeRenderSurface* GLRenderer::GetNativeRenderSurface() const +{ + return dynamic_cast(mSurface.get()); +} + +void GLRenderer::SetRenderingMode(RENDER_MODE mode) +{ + if(mode == mMode) + { + return; + } + + //Notify GLRender thread. + Dali::ConditionalWait::ScopedLock updatelock(mConditionalWait); + if(mMode == RENDER_MODE::RENDER_MODE_CONTINUOUSLY) + { + mRenderOnce = false; + } + mMode = mode; + mConditionalWait.Notify(updatelock); +} + +void GLRenderer::RequestRender() +{ + if(mMode == RENDER_MODE::RENDER_MODE_CONTINUOUSLY) + { + return; + } + + //Notify GLRender thread. + Dali::ConditionalWait::ScopedLock updatelock(mConditionalWait); + mRenderOnce = true; + mConditionalWait.Notify(updatelock); +} + +void GLRenderer::Run() +{ + Dali::SetThreadName("DKDKGLViewRenderer"); + DALI_LOG_ERROR("DKDK GLRenderer::Run()"); + // DALI_LOG_ERROR("initCallback [%p] renderFrameCallback[%p] terminateCallback[%p]", + // mGLInitCallback, + // mGLRenderFrameCallback, + // mGLTerminateCallback); + bool ret = InitializeEGL(); + if(ret == false) + { + DALI_LOG_ERROR("EGL Initilization Failed, Could not start GLRender Thread"); + return; + } + + bool callOnce = true; + bool initRet = false; + + while(1) + { + { + Dali::ConditionalWait::ScopedLock lock(mConditionalWait); + while(mPauseThread == true || + (mMode == RENDER_MODE::RENDER_MODE_ONDEMAND && mRenderOnce == false)) + { + mConditionalWait.Wait(lock); + } + } + + if(mQuitThread) + { + DALI_LOG_ERROR("Exiting GLRender thread"); + //TODO: check callback parameter + CallbackBase::Execute(*mGLTerminateCallback); + return; + } + + auto startTime = std::chrono::steady_clock::now(); + + if(callOnce) + { + //Calling GLInit callback, only once. + // initRet = mGLInitCallback(mViewWidth, mViewHeight); + //TODO: check callback parameter + + NativeRenderSurface* surface = GetNativeRenderSurface(); + + if(!surface) + { + return; + } + Rect rect; + surface->PreRender(false, std::vector>(), rect); + + CallbackBase::Execute(*mGLInitCallback); + + callOnce = false; + initRet = true; + } + + // Calling GLDraw callback, per frame depending on RenderMde set. + if(initRet == true) + { + NativeRenderSurface* surface = GetNativeRenderSurface(); + + if(!surface) + { + return; + } + // virtual bool PreRender(bool resizingSurface, const std::vector>& damagedRects, Rect& clippingRect) = 0; + Rect rect; + surface->PreRender(false, std::vector>(), rect); + //TODO: check callback parameter + CallbackBase::Execute(*mGLRenderFrameCallback); + + // virtual void PostRender(bool renderToFbo, bool replacingSurface, bool resizingSurface, const std::vector>& damagedRects) = 0; + + surface->PostRender(false, false, false, std::vector>()); + } + + { + Dali::ConditionalWait::ScopedLock updateLock(mConditionalWait); + if(mRenderOnce == true) + { + mRenderOnce = false; + } + } + + // RenderingBehaviorManager::RequireRender(); + + auto endTime = std::chrono::steady_clock::now(); + auto elapsedTime = std::chrono::duration_cast(endTime - startTime); + if(elapsedTime < mSleepTime) + { + std::this_thread::sleep_for(mSleepTime - elapsedTime); + } + } + return; +} + +void GLRenderer::QuitRenderThread() +{ + mQuitThread = true; + // Set to come out Render Thread out of waiting condition. + Dali::ConditionalWait::ScopedLock updatelock(mConditionalWait); + mMode = RENDER_MODE::RENDER_MODE_CONTINUOUSLY; + mPauseThread = false; + mConditionalWait.Notify(updatelock); +} + +void GLRenderer::PauseRenderThread(bool pause) +{ + //Notify GLRender thread, If actor visibility is change + Dali::ConditionalWait::ScopedLock updatelock(mConditionalWait); + mPauseThread = pause; + mConditionalWait.Notify(updatelock); +} + +GLRenderer::~GLRenderer() +{ + DeInitializeEGL(); +} + +} // namespace Internal +} // namespace Toolkit +} // namespace Dali diff --git a/dali-toolkit/internal/controls/gl-view/gl-surface-view-thread.h b/dali-toolkit/internal/controls/gl-view/gl-surface-view-thread.h new file mode 100644 index 0000000000..da4af96672 --- /dev/null +++ b/dali-toolkit/internal/controls/gl-view/gl-surface-view-thread.h @@ -0,0 +1,100 @@ +/* + * Copyright 2019 by Samsung Electronics, Inc., + * + * This software is the confidential and proprietary information + * of Samsung Electronics, Inc. ("Confidential Information"). You + * shall not disclose such Confidential Information and shall use + * it only in accordance with the terms of the license agreement + * you entered into with Samsung. + * + */ + +// EXTERNAL INCLUDES +#include +#include +#include +#include + +#include + +#include +#include + +// #include +#include +#include +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Internal +{ +typedef bool (*GLInit)(unsigned, unsigned); +typedef void (*GLDraw)(); +typedef void (*GLTerminate)(); + +class GLRenderer : public Dali::Thread +{ +public: + enum class RENDER_MODE + { + RENDER_MODE_CONTINUOUSLY, + RENDER_MODE_ONDEMAND + }; + GLRenderer(unsigned int viewWidth, unsigned viewHeight, tbm_surface_queue_h tbmSurfaceQueue); + + virtual ~GLRenderer(); + void RegisterGLCallback(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback); + void SetRenderingMode(RENDER_MODE mode); + void RequestRender(); + void QuitRenderThread(); + void PauseRenderThread(bool pause); + +protected: + virtual void Run(); + +private: + GLRenderer(const GLRenderer& obj) = delete; + GLRenderer operator=(const GLRenderer& obj) = delete; + + bool InitializeEGL(); + void DeInitializeEGL(); + + NativeRenderSurface* GetNativeRenderSurface() const; + +private: + std::unique_ptr mSurface; ///< The window rendering surface + + unsigned mViewWidth; + unsigned mViewHeight; + + // tbm_surface_queue_h mTbmSurfaceQueue; + tbm_surface_queue_h mTbmSurfaceQueue; + + Dali::ConditionalWait mConditionalWait; + // EglData* mEglData; + + std::chrono::milliseconds mSleepTime; + RENDER_MODE mMode; + + bool mRenderOnce; + bool mPauseThread; + std::atomic_bool mQuitThread; + + Dali::NativeImageSourceQueue::ColorDepth mColorDepth; + + std::unique_ptr mGLInitCallback; + std::unique_ptr mGLRenderFrameCallback; + std::unique_ptr mGLTerminateCallback; + bool mInitCallback : 1; + bool mDepth : 1; + bool mStencil : 1; + bool mIsEGLInitialize : 1; + int mMSAA; +}; + +} // namespace Internal +} // namespace Toolkit +} // namespace Dali diff --git a/dali-toolkit/internal/file.list b/dali-toolkit/internal/file.list index 1983a69f7f..8e33264cce 100644 --- a/dali-toolkit/internal/file.list +++ b/dali-toolkit/internal/file.list @@ -106,6 +106,8 @@ SET( toolkit_src_files ${toolkit_src_dir}/controls/tool-bar/tool-bar-impl.cpp ${toolkit_src_dir}/controls/tooltip/tooltip.cpp ${toolkit_src_dir}/controls/video-view/video-view-impl.cpp + ${toolkit_src_dir}/controls/gl-view/gl-surface-view-impl.cpp + ${toolkit_src_dir}/controls/gl-view/gl-surface-view-thread.cpp ${toolkit_src_dir}/controls/web-view/web-view-impl.cpp ${toolkit_src_dir}/accessibility-manager/accessibility-manager-impl.cpp diff --git a/dali-toolkit/public-api/controls/gl-view/gl-surface-view.cpp b/dali-toolkit/public-api/controls/gl-view/gl-surface-view.cpp new file mode 100644 index 0000000000..d862d1f576 --- /dev/null +++ b/dali-toolkit/public-api/controls/gl-view/gl-surface-view.cpp @@ -0,0 +1,78 @@ +/* + * Copyright 2019 by Samsung Electronics, Inc., + * + * This software is the confidential and proprietary information + * of Samsung Electronics, Inc. ("Confidential Information"). You + * shall not disclose such Confidential Information and shall use + * it only in accordance with the terms of the license agreement + * you entered into with Samsung. + * + */ + +// CLASS HEADER +#include "gl-surface-view.h" + +// INTERNAL INCLUDES +#include + +namespace Dali +{ +namespace Toolkit +{ +GLSurfaceView::GLSurfaceView() +{ +} + +GLSurfaceView::GLSurfaceView(const GLSurfaceView& glSurfaceView) +: Control(glSurfaceView) +{ +} + +GLSurfaceView& GLSurfaceView::operator=(const GLSurfaceView& glSurfaceView) +{ + if(&glSurfaceView != this) + { + Control::operator=(glSurfaceView); + } + + return *this; +} + +GLSurfaceView::~GLSurfaceView() +{ +} + +GLSurfaceView GLSurfaceView::New(unsigned int viewWidth, unsigned int viewHeight) +{ + return Internal::GLSurfaceView::New(viewWidth, viewHeight); +} + +void GLSurfaceView::RegisterGLCallback(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback) +{ + Dali::Toolkit::GetImpl(*this).RegisterGLCallback(initCallback, renderFrameCallback, terminateCallback); +} + +void GLSurfaceView::SetRenderingMode(RENDER_MODE mode) +{ + Dali::Toolkit::GetImpl(*this).SetRenderingMode(mode); +} + +void GLSurfaceView::RequestRender() +{ + Dali::Toolkit::GetImpl(*this).RequestRender(); +} + +GLSurfaceView::GLSurfaceView(Internal::GLSurfaceView& implementation) +: Control(implementation) +{ +} + +GLSurfaceView::GLSurfaceView(Dali::Internal::CustomActor* internal) +: Control(internal) +{ + VerifyCustomActorPointer(internal); +} + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/public-api/controls/gl-view/gl-surface-view.h b/dali-toolkit/public-api/controls/gl-view/gl-surface-view.h new file mode 100644 index 0000000000..3d9c5e60f0 --- /dev/null +++ b/dali-toolkit/public-api/controls/gl-view/gl-surface-view.h @@ -0,0 +1,115 @@ +#ifndef DALI_TOOLKIT_GL_SURFACE_VIEW_H +#define DALI_TOOLKIT_GL_SURFACE_VIEW_H + +// EXTERNAL INCLUDES +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Internal DALI_INTERNAL +{ +class GLSurfaceView; +} + +typedef bool (*GLInit)(unsigned, unsigned); +typedef void (*GLDraw)(); +typedef void (*GLTerminate)(); + +class DALI_IMPORT_API GLSurfaceView : public Dali::Toolkit::Control +{ +public: + enum class RENDER_MODE + { + RENDER_MODE_CONTINUOUSLY, + RENDER_MODE_ONDEMAND + }; + /** + * @brief Creates an initialized GLSurfaceView. + * @return A handle to a newly allocated Dali GLSurfaceView + * @param[in] viewWidth Framebuffer Width + * @param[in] viewHeight Framebuffer Height + * @note GLSurfaceView will not display anything + */ + static GLSurfaceView New(unsigned int viewWidth, unsigned int viewHeight); + + /** + * @brief Creates an uninitialized GLSurfaceView. + */ + GLSurfaceView(); + + /** + * @brief Destructor. + * + * This is non-virtual since derived Handle types must not contain data or virtual methods. + */ + ~GLSurfaceView(); + + /** + * @brief Copy constructor. + * + * @param[in] GLSurfaceView GLSurfaceView to copy. The copied GLSurfaceView will point at the same implementation + */ + GLSurfaceView(const GLSurfaceView& GLSurfaceView); + + /** + * @brief Assignment operator. + * + * @param[in] GLSurfaceView The GLSurfaceView to assign from + * @return The updated GLSurfaceView + */ + GLSurfaceView& operator=(const GLSurfaceView& GLSurfaceView); + + /** + * @brief sets GLInit and GLDraw callbacks + * GLInit is called only once after Egl initilization is completed. + * GLDraw is called per frame, depending on Rendering Mode set. + * GLTerminate is called only once, This callback can be by user for egl resource cleanup + * Both, user callbacks are called in GLSurfaceView thread. + * + * @param [in] GLInit callback + * @param [in] GLDraw callback + * @param [in] glTerminateCallback callback + */ + void RegisterGLCallback(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback); + + /** + * @brief Set the rendering mode + * When mode is RENDER_MODE_CONTINUOUSLY, the GLDraw callback is called repeatedly. + * When renderMode is RENDER_MODE_ONDEMAND, the GLDraw callback is called when requestRender() is called. + * Defaults to RENDER_MODE_ONDEMAND. + * + * @param [in] rendering mode. + */ + void SetRenderingMode(RENDER_MODE mode); + + /** + * @brief Request render frame on demand. + * This method is typically used when the render mode has been set to RENDER_MODE_ONDEMAND. + */ + void RequestRender(); + +public: // Not intended for application developers + /// @cond internal + /** + * @brief Creates a handle using the Toolkit::Internal implementation. + * + * @param[in] implementation The GLSurfaceView implementation + */ + DALI_INTERNAL GLSurfaceView(Internal::GLSurfaceView& implementation); + + /** + * @brief Allows the creation of this GLSurfaceView from an Internal::CustomActor pointer. + * + * @param[in] internal A pointer to the internal CustomActor + */ + DALI_INTERNAL GLSurfaceView(Dali::Internal::CustomActor* internal); + /// @endcond +}; + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_GL_SURFACE_VIEW_H diff --git a/dali-toolkit/public-api/file.list b/dali-toolkit/public-api/file.list index df039c8ed3..77954e2431 100644 --- a/dali-toolkit/public-api/file.list +++ b/dali-toolkit/public-api/file.list @@ -26,6 +26,7 @@ SET( public_api_src_files ${public_api_src_dir}/controls/text-controls/text-label.cpp ${public_api_src_dir}/controls/text-controls/text-field.cpp ${public_api_src_dir}/controls/video-view/video-view.cpp + ${public_api_src_dir}/controls/gl-view/gl-surface-view.cpp ${public_api_src_dir}/image-loader/image.cpp ${public_api_src_dir}/image-loader/async-image-loader.cpp ${public_api_src_dir}/image-loader/sync-image-loader.cpp @@ -127,6 +128,10 @@ SET( public_api_video_view_header_files ${public_api_src_dir}/controls/video-view/video-view.h ) +SET( public_api_gl_surface_view_header_files + ${public_api_src_dir}/controls/gl-view/gl-surface-view.h +) + SET( public_api_visuals_header_files ${public_api_src_dir}/visuals/border-visual-properties.h ${public_api_src_dir}/visuals/color-visual-properties.h @@ -160,5 +165,6 @@ SET( PUBLIC_API_HEADERS ${PUBLIC_API_HEADERS} ${public_api_focus_manager_header_files} ${public_api_text_header_files} ${public_api_video_view_header_files} + ${public_api_gl_surface_view_header_files} ${public_api_visuals_header_files} ) diff --git a/docs/content/example-code/CMakeLists.txt b/docs/content/example-code/CMakeLists.txt index 133ab593f9..dd45360ff7 100644 --- a/docs/content/example-code/CMakeLists.txt +++ b/docs/content/example-code/CMakeLists.txt @@ -2,7 +2,8 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) SET(PKG_LIST dali-core dali-adaptor - dali-toolkit) + dali-toolkit + libtbm) INCLUDE(FindPkgConfig) PKG_CHECK_MODULES(REQUIRED_PKGS REQUIRED ${PKG_LIST}) diff --git a/packaging/dali-toolkit.spec b/packaging/dali-toolkit.spec index 58a827792f..d102b6789c 100644 --- a/packaging/dali-toolkit.spec +++ b/packaging/dali-toolkit.spec @@ -16,6 +16,8 @@ BuildRequires: pkgconfig(dali2-core) BuildRequires: pkgconfig(dali2-adaptor) BuildRequires: gettext BuildRequires: pkgconfig(libtzplatform-config) +BuildRequires: pkgconfig(libtbm) + ############################# # profile setup