From d95e058075b693420f96b803425a14f994929d43 Mon Sep 17 00:00:00 2001 From: Heeyong Song Date: Tue, 19 May 2020 17:32:25 +0900 Subject: [PATCH 01/16] Call PostRender method of the surface if needed Change-Id: Ic5651f52dfa42b08a4bc514af765188310f8f863 --- .../dali-test-suite-utils/test-application.cpp | 17 +++++++++++++---- .../dali-test-suite-utils/test-application.h | 1 + .../common/combined-update-render-controller.cpp | 11 ++++++++--- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-application.cpp b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-application.cpp index f85f14d..e8c0d12 100644 --- a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-application.cpp +++ b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-application.cpp @@ -188,9 +188,13 @@ bool TestApplication::Render( uint32_t intervalMilliseconds, const char* locatio { DoUpdate( intervalMilliseconds, location ); + // Reset the status + mRenderStatus.SetNeedsUpdate( false ); + mRenderStatus.SetNeedsPostRender( false ); + mCore->PreRender( mRenderStatus, false /*do not force clear*/, false /*do not skip rendering*/ ); - mCore->RenderScene( mScene, true /*render the off-screen buffers*/); - mCore->RenderScene( mScene, false /*render the surface*/); + mCore->RenderScene( mRenderStatus, mScene, true /*render the off-screen buffers*/); + mCore->RenderScene( mRenderStatus, mScene, false /*render the surface*/); mCore->PostRender( false /*do not skip rendering*/ ); mFrame++; @@ -214,12 +218,17 @@ bool TestApplication::GetRenderNeedsUpdate() return mRenderStatus.NeedsUpdate(); } +bool TestApplication::GetRenderNeedsPostRender() +{ + return mRenderStatus.NeedsPostRender(); +} + bool TestApplication::RenderOnly( ) { // Update Time values mCore->PreRender( mRenderStatus, false /*do not force clear*/, false /*do not skip rendering*/ ); - mCore->RenderScene( mScene, true /*render the off-screen buffers*/); - mCore->RenderScene( mScene, false /*render the surface*/); + mCore->RenderScene( mRenderStatus, mScene, true /*render the off-screen buffers*/); + mCore->RenderScene( mRenderStatus, mScene, false /*render the surface*/); mCore->PostRender( false /*do not skip rendering*/ ); mFrame++; diff --git a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-application.h b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-application.h index a922e23..e96f759 100644 --- a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-application.h +++ b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-application.h @@ -74,6 +74,7 @@ public: bool RenderOnly( ); void ResetContext(); bool GetRenderNeedsUpdate(); + bool GetRenderNeedsPostRender(); uint32_t Wait( uint32_t durationToWait ); static void EnableLogging( bool enabled ) { diff --git a/dali/internal/adaptor/common/combined-update-render-controller.cpp b/dali/internal/adaptor/common/combined-update-render-controller.cpp index 0e20903..b310671 100644 --- a/dali/internal/adaptor/common/combined-update-render-controller.cpp +++ b/dali/internal/adaptor/common/combined-update-render-controller.cpp @@ -741,18 +741,23 @@ void CombinedUpdateRenderController::UpdateRenderThread() if ( scene && windowSurface ) { + Integration::RenderStatus windowRenderStatus; + windowSurface->InitializeGraphics(); // Render off-screen frame buffers first if any - mCore.RenderScene( scene, true ); + mCore.RenderScene( windowRenderStatus, scene, true ); // Switch to the EGL context of the surface windowSurface->PreRender( surfaceResized ); // Switch GL context // Render the surface - mCore.RenderScene( scene, false ); + mCore.RenderScene( windowRenderStatus, scene, false ); - windowSurface->PostRender( false, false, surfaceResized ); // Swap Buffer + if( windowRenderStatus.NeedsPostRender() ) + { + windowSurface->PostRender( false, false, surfaceResized ); // Swap Buffer + } } } } -- 2.7.4 From 7e12b804069b4baedfbd6588cd238b4d5406e680 Mon Sep 17 00:00:00 2001 From: Joogab Yun Date: Mon, 8 Jun 2020 19:10:06 +0900 Subject: [PATCH 02/16] DALi Version 1.5.15 Change-Id: I3b8b0f9bb1d4d3ff852a88d552e9f030f7f845ab --- dali/public-api/dali-adaptor-version.cpp | 2 +- packaging/dali-adaptor.spec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dali/public-api/dali-adaptor-version.cpp b/dali/public-api/dali-adaptor-version.cpp index 28b3ebd..d89bb3f 100644 --- a/dali/public-api/dali-adaptor-version.cpp +++ b/dali/public-api/dali-adaptor-version.cpp @@ -28,7 +28,7 @@ namespace Dali const unsigned int ADAPTOR_MAJOR_VERSION = 1; const unsigned int ADAPTOR_MINOR_VERSION = 5; -const unsigned int ADAPTOR_MICRO_VERSION = 14; +const unsigned int ADAPTOR_MICRO_VERSION = 15; const char * const ADAPTOR_BUILD_DATE = __DATE__ " " __TIME__; #ifdef DEBUG_ENABLED diff --git a/packaging/dali-adaptor.spec b/packaging/dali-adaptor.spec index acc28db..7a83814 100644 --- a/packaging/dali-adaptor.spec +++ b/packaging/dali-adaptor.spec @@ -17,7 +17,7 @@ Name: dali-adaptor Summary: The DALi Tizen Adaptor -Version: 1.5.14 +Version: 1.5.15 Release: 1 Group: System/Libraries License: Apache-2.0 and BSD-3-Clause and MIT -- 2.7.4 From 62b1236eb4b8dea02d1c6e6d952a904de83ddd5f Mon Sep 17 00:00:00 2001 From: Heeyong Song Date: Mon, 8 Jun 2020 18:41:09 +0900 Subject: [PATCH 03/16] Throw an exception if the Adaptor is not instantiated Change-Id: I707c2d351d4c28cfb05954cdd6d59c08269d8024 --- dali/internal/adaptor/common/adaptor.cpp | 4 ++++ dali/internal/system/linux/timer-impl-ecore.cpp | 8 ++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/dali/internal/adaptor/common/adaptor.cpp b/dali/internal/adaptor/common/adaptor.cpp index e77dea8..9551d82 100755 --- a/dali/internal/adaptor/common/adaptor.cpp +++ b/dali/internal/adaptor/common/adaptor.cpp @@ -107,21 +107,25 @@ void Adaptor::Stop() bool Adaptor::AddIdle( CallbackBase* callback, bool hasReturnValue ) { + DALI_ASSERT_ALWAYS( IsAvailable() && "Adaptor not instantiated" ); return mImpl->AddIdle( callback, hasReturnValue, false ); } bool Adaptor::AddWindow( Dali::Integration::SceneHolder childWindow, const std::string& childWindowName, const std::string& childWindowClassName, bool childWindowMode ) { + DALI_ASSERT_ALWAYS( IsAvailable() && "Adaptor not instantiated" ); return mImpl->AddWindow( childWindow, childWindowName, childWindowClassName, childWindowMode ); } void Adaptor::RemoveIdle( CallbackBase* callback ) { + DALI_ASSERT_ALWAYS( IsAvailable() && "Adaptor not instantiated" ); mImpl->RemoveIdle( callback ); } void Adaptor::ProcessIdle() { + DALI_ASSERT_ALWAYS( IsAvailable() && "Adaptor not instantiated" ); mImpl->ProcessIdle(); } diff --git a/dali/internal/system/linux/timer-impl-ecore.cpp b/dali/internal/system/linux/timer-impl-ecore.cpp index fde050d..7ebea28 100644 --- a/dali/internal/system/linux/timer-impl-ecore.cpp +++ b/dali/internal/system/linux/timer-impl-ecore.cpp @@ -81,7 +81,7 @@ Timer::~Timer() void Timer::Start() { // Timer should be used in the event thread - DALI_ASSERT_DEBUG( Adaptor::IsAvailable() ); + DALI_ASSERT_ALWAYS( Adaptor::IsAvailable() ); if(mImpl->mId != NULL) { @@ -94,7 +94,7 @@ void Timer::Start() void Timer::Stop() { // Timer should be used in the event thread - DALI_ASSERT_DEBUG( Adaptor::IsAvailable() ); + DALI_ASSERT_ALWAYS( Adaptor::IsAvailable() ); ResetTimerData(); } @@ -102,7 +102,7 @@ void Timer::Stop() void Timer::Pause() { // Timer should be used in the event thread - DALI_ASSERT_DEBUG( Adaptor::IsAvailable() ); + DALI_ASSERT_ALWAYS( Adaptor::IsAvailable() ); if( mImpl->mId != NULL ) { @@ -113,7 +113,7 @@ void Timer::Pause() void Timer::Resume() { // Timer should be used in the event thread - DALI_ASSERT_DEBUG( Adaptor::IsAvailable() ); + DALI_ASSERT_ALWAYS( Adaptor::IsAvailable() ); if( mImpl->mId != NULL ) { -- 2.7.4 From 0e9c6d5b7970bf6f385efa3c9b2173cce83c3da0 Mon Sep 17 00:00:00 2001 From: neostom432 Date: Tue, 16 Jun 2020 02:15:02 +0900 Subject: [PATCH 04/16] DALi Version 1.5.16 Change-Id: I7380bcff70ae49949edf1fc1283e88533206fd16 --- dali/public-api/dali-adaptor-version.cpp | 2 +- packaging/dali-adaptor.spec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dali/public-api/dali-adaptor-version.cpp b/dali/public-api/dali-adaptor-version.cpp index d89bb3f..e5ef10f 100644 --- a/dali/public-api/dali-adaptor-version.cpp +++ b/dali/public-api/dali-adaptor-version.cpp @@ -28,7 +28,7 @@ namespace Dali const unsigned int ADAPTOR_MAJOR_VERSION = 1; const unsigned int ADAPTOR_MINOR_VERSION = 5; -const unsigned int ADAPTOR_MICRO_VERSION = 15; +const unsigned int ADAPTOR_MICRO_VERSION = 16; const char * const ADAPTOR_BUILD_DATE = __DATE__ " " __TIME__; #ifdef DEBUG_ENABLED diff --git a/packaging/dali-adaptor.spec b/packaging/dali-adaptor.spec index 7a83814..706b1fd 100644 --- a/packaging/dali-adaptor.spec +++ b/packaging/dali-adaptor.spec @@ -17,7 +17,7 @@ Name: dali-adaptor Summary: The DALi Tizen Adaptor -Version: 1.5.15 +Version: 1.5.16 Release: 1 Group: System/Libraries License: Apache-2.0 and BSD-3-Clause and MIT -- 2.7.4 From 31b3e92ff29394d14bcf9ff95b8a1e33173fd784 Mon Sep 17 00:00:00 2001 From: "huiyu.eun" Date: Tue, 16 Jun 2020 15:44:24 +0900 Subject: [PATCH 05/16] Change unsetenv to setenv unsetenv("AUL_LOADER_INIT") -> setenv("AUL_LOADER_INIT", "0", "1") Change-Id: If5420fc0a3baed766f03486ae14571bdd3d87212 Signed-off-by: huiyu.eun --- dali/internal/adaptor/tizen-wayland/framework-tizen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dali/internal/adaptor/tizen-wayland/framework-tizen.cpp b/dali/internal/adaptor/tizen-wayland/framework-tizen.cpp index c440eeb..1a05da1 100644 --- a/dali/internal/adaptor/tizen-wayland/framework-tizen.cpp +++ b/dali/internal/adaptor/tizen-wayland/framework-tizen.cpp @@ -401,7 +401,7 @@ struct Framework::Impl if(getenv("AUL_LOADER_INIT")) { - unsetenv("AUL_LOADER_INIT"); + setenv("AUL_LOADER_INIT", "0", 1); ecore_shutdown(); } } -- 2.7.4 From 6fca3747046705fdbebd72f6fe7f86aada43d707 Mon Sep 17 00:00:00 2001 From: Heeyong Song Date: Thu, 18 Jun 2020 15:42:22 +0900 Subject: [PATCH 06/16] Fix feedback sound API mm_sound_play_keysound() should be use with mm_sound_stop_keysound(). Change-Id: I4197a848508e12f880b30bded19d8c918b1af7bb --- plugins/dali-feedback.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/dali-feedback.cpp b/plugins/dali-feedback.cpp index c53935f..68dcc04 100644 --- a/plugins/dali-feedback.cpp +++ b/plugins/dali-feedback.cpp @@ -82,7 +82,7 @@ int DaliFeedback::PlaySound( const std::string& fileName ) void DaliFeedback::StopSound( int handle ) { - int errorCode = mm_sound_stop_sound( handle ); + int errorCode = mm_sound_stop_keysound( NULL ); if( errorCode < 0 ) { DEBUG_PRINTF( "StopSound() handle = %d failed with error code = %d\n", handle, errorCode); -- 2.7.4 From af634906664f835cd54f971dfe4bdf07216acb91 Mon Sep 17 00:00:00 2001 From: Joogab Yun Date: Wed, 17 Jun 2020 16:13:03 +0900 Subject: [PATCH 07/16] The advance of the letters is too narrow. So, remove the floor. Change-Id: Iae4c426819d7002ad1e4c7aab74818a3ef82aa30 --- dali/internal/text/text-abstraction/shaping-impl.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/dali/internal/text/text-abstraction/shaping-impl.cpp b/dali/internal/text/text-abstraction/shaping-impl.cpp index b785c02..da78f59 100755 --- a/dali/internal/text/text-abstraction/shaping-impl.cpp +++ b/dali/internal/text/text-abstraction/shaping-impl.cpp @@ -249,10 +249,10 @@ struct Shaping::Plugin const GlyphIndex index = rtlIndex + j; mIndices.PushBack( glyphInfo[index].codepoint ); - mAdvance.PushBack( floor( glyphPositions[index].x_advance * FROM_266 ) ); + mAdvance.PushBack( glyphPositions[index].x_advance * FROM_266 ); mCharacterMap.PushBack( glyphInfo[index].cluster ); - mOffset.PushBack( floor( glyphPositions[index].x_offset * FROM_266 ) ); - mOffset.PushBack( floor( glyphPositions[index].y_offset * FROM_266 ) ); + mOffset.PushBack( glyphPositions[index].x_offset * FROM_266 ); + mOffset.PushBack( glyphPositions[index].y_offset * FROM_266 ); } i += numberOfGlyphsInCluster; @@ -260,10 +260,10 @@ struct Shaping::Plugin else { mIndices.PushBack( glyphInfo[i].codepoint ); - mAdvance.PushBack( floor( glyphPositions[i].x_advance * FROM_266 ) ); + mAdvance.PushBack( glyphPositions[i].x_advance * FROM_266 ); mCharacterMap.PushBack( glyphInfo[i].cluster ); - mOffset.PushBack( floor( glyphPositions[i].x_offset * FROM_266 ) ); - mOffset.PushBack( floor( glyphPositions[i].y_offset * FROM_266 ) ); + mOffset.PushBack( glyphPositions[i].x_offset * FROM_266 ); + mOffset.PushBack( glyphPositions[i].y_offset * FROM_266 ); ++i; } -- 2.7.4 From aa35ce5329eb4bc15b19d919f6ce7d0ceb64be7a Mon Sep 17 00:00:00 2001 From: Anton Obzhirov Date: Tue, 14 Apr 2020 16:00:16 +0100 Subject: [PATCH 08/16] Partial update implementation, first phase. Change-Id: I222a1972d5727f6e01bb941b08339c38aad1546a --- .../dali-test-suite-utils/test-application.cpp | 38 ++- .../dali-test-suite-utils/test-application.h | 6 +- .../src/dali-adaptor/utc-Dali-Window.cpp | 18 ++ dali/devel-api/adaptor-framework/window-devel.cpp | 5 + dali/devel-api/adaptor-framework/window-devel.h | 15 +- .../adaptor-framework/render-surface-interface.h | 7 +- .../adaptor-framework/scene-holder-impl.cpp | 15 ++ dali/internal/adaptor/common/adaptor-impl.cpp | 3 +- .../common/combined-update-render-controller.cpp | 25 +- .../common/combined-update-render-controller.h | 2 + dali/internal/graphics/common/graphics-interface.h | 14 +- dali/internal/graphics/gles/egl-graphics.cpp | 13 +- dali/internal/graphics/gles/egl-graphics.h | 10 + dali/internal/graphics/gles/egl-implementation.cpp | 293 ++++++++++++++++++++- dali/internal/graphics/gles/egl-implementation.h | 48 +++- .../internal/system/common/environment-options.cpp | 18 +- dali/internal/system/common/environment-options.h | 6 + .../internal/system/common/environment-variables.h | 2 + dali/internal/window-system/common/window-impl.cpp | 106 ++++++++ dali/internal/window-system/common/window-impl.h | 5 + .../window-system/common/window-render-surface.cpp | 21 +- .../window-system/common/window-render-surface.h | 4 +- .../native-render-surface-ecore-wl.cpp | 22 +- .../tizen-wayland/native-render-surface-ecore-wl.h | 4 +- .../ubuntu-x11/pixmap-render-surface-ecore-x.cpp | 4 +- .../ubuntu-x11/pixmap-render-surface-ecore-x.h | 4 +- 26 files changed, 664 insertions(+), 44 deletions(-) diff --git a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-application.cpp b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-application.cpp index e8c0d12..b2a3fb9 100644 --- a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-application.cpp +++ b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-application.cpp @@ -26,13 +26,15 @@ TestApplication::TestApplication( uint32_t surfaceWidth, uint32_t surfaceHeight, uint32_t horizontalDpi, uint32_t verticalDpi, - bool initialize ) + bool initialize, + bool enablePartialUpdate ) : mCore( NULL ), mSurfaceWidth( surfaceWidth ), mSurfaceHeight( surfaceHeight ), mFrame( 0u ), mDpi{ horizontalDpi, verticalDpi }, - mLastVSyncTime(0u) + mLastVSyncTime(0u), + mPartialUpdateEnabled(enablePartialUpdate) { if( initialize ) { @@ -59,7 +61,8 @@ void TestApplication::CreateCore() mGlContextHelperAbstraction, Integration::RenderToFrameBuffer::FALSE, Integration::DepthBufferAvailable::TRUE, - Integration::StencilBufferAvailable::TRUE ); + Integration::StencilBufferAvailable::TRUE, + mPartialUpdateEnabled ? Integration::PartialUpdateAvailable::TRUE : Integration::PartialUpdateAvailable::FALSE ); mCore->ContextCreated(); @@ -193,8 +196,8 @@ bool TestApplication::Render( uint32_t intervalMilliseconds, const char* locatio mRenderStatus.SetNeedsPostRender( false ); mCore->PreRender( mRenderStatus, false /*do not force clear*/, false /*do not skip rendering*/ ); - mCore->RenderScene( mRenderStatus, mScene, true /*render the off-screen buffers*/); - mCore->RenderScene( mRenderStatus, mScene, false /*render the surface*/); + mCore->RenderScene( mRenderStatus, mScene, true /*render the off-screen buffers*/ ); + mCore->RenderScene( mRenderStatus, mScene, false /*render the surface*/ ); mCore->PostRender( false /*do not skip rendering*/ ); mFrame++; @@ -202,6 +205,27 @@ bool TestApplication::Render( uint32_t intervalMilliseconds, const char* locatio return mStatus.KeepUpdating() || mRenderStatus.NeedsUpdate(); } +bool TestApplication::PreRenderWithPartialUpdate(uint32_t intervalMilliseconds, const char* location, std::vector>& damagedRects) +{ + DoUpdate(intervalMilliseconds, location); + + mCore->PreRender(mRenderStatus, false /*do not force clear*/, false /*do not skip rendering*/ ); + mCore->PreRender(mScene, damagedRects); + + return mStatus.KeepUpdating() || mRenderStatus.NeedsUpdate(); +} + +bool TestApplication::RenderWithPartialUpdate(std::vector>& damagedRects, Rect& clippingRect) +{ + mCore->RenderScene(mRenderStatus, mScene, true /*render the off-screen buffers*/, clippingRect); + mCore->RenderScene(mRenderStatus, mScene, false /*render the surface*/, clippingRect); + mCore->PostRender(false /*do not skip rendering*/); + + mFrame++; + + return mStatus.KeepUpdating() || mRenderStatus.NeedsUpdate(); +} + uint32_t TestApplication::GetUpdateStatus() { return mStatus.KeepUpdating(); @@ -227,8 +251,8 @@ bool TestApplication::RenderOnly( ) { // Update Time values mCore->PreRender( mRenderStatus, false /*do not force clear*/, false /*do not skip rendering*/ ); - mCore->RenderScene( mRenderStatus, mScene, true /*render the off-screen buffers*/); - mCore->RenderScene( mRenderStatus, mScene, false /*render the surface*/); + mCore->RenderScene( mRenderStatus, mScene, true /*render the off-screen buffers*/ ); + mCore->RenderScene( mRenderStatus, mScene, false /*render the surface*/ ); mCore->PostRender( false /*do not skip rendering*/ ); mFrame++; diff --git a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-application.h b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-application.h index e96f759..1df0743 100644 --- a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-application.h +++ b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-application.h @@ -51,7 +51,8 @@ public: uint32_t surfaceHeight = DEFAULT_SURFACE_HEIGHT, uint32_t horizontalDpi = DEFAULT_HORIZONTAL_DPI, uint32_t verticalDpi = DEFAULT_VERTICAL_DPI, - bool initialize = true ); + bool initialize = true, + bool enablePartialUpdate = false ); void Initialize(); void CreateCore(); @@ -69,6 +70,8 @@ public: void ProcessEvent(const Integration::Event& event); void SendNotification(); bool Render( uint32_t intervalMilliseconds = DEFAULT_RENDER_INTERVAL, const char* location=NULL ); + bool PreRenderWithPartialUpdate(uint32_t intervalMilliseconds, const char* location, std::vector>& damagedRects); + bool RenderWithPartialUpdate(std::vector>& damagedRects, Rect& clippingRect); uint32_t GetUpdateStatus(); bool UpdateOnly( uint32_t intervalMilliseconds = DEFAULT_RENDER_INTERVAL ); bool RenderOnly( ); @@ -108,6 +111,7 @@ protected: struct { uint32_t x; uint32_t y; } mDpi; uint32_t mLastVSyncTime; + bool mPartialUpdateEnabled; static bool mLoggingEnabled; }; diff --git a/automated-tests/src/dali-adaptor/utc-Dali-Window.cpp b/automated-tests/src/dali-adaptor/utc-Dali-Window.cpp index 4b14df2..cb7de36 100644 --- a/automated-tests/src/dali-adaptor/utc-Dali-Window.cpp +++ b/automated-tests/src/dali-adaptor/utc-Dali-Window.cpp @@ -16,6 +16,7 @@ */ #include +#include #include #include @@ -412,3 +413,20 @@ int UtcDaliWindowFocusChangedSignalN(void) END_TEST; } + +int UtcDaliWindowPartialUpdate(void) +{ + Dali::Window window; + try + { + std::vector> damagedAreas; + DevelWindow::SetDamagedAreas(window, damagedAreas); + DALI_TEST_CHECK( false ); // Should not reach here! + } + catch( ... ) + { + DALI_TEST_CHECK( true ); + } + + END_TEST; +} diff --git a/dali/devel-api/adaptor-framework/window-devel.cpp b/dali/devel-api/adaptor-framework/window-devel.cpp index b9fadbb..44e9801 100755 --- a/dali/devel-api/adaptor-framework/window-devel.cpp +++ b/dali/devel-api/adaptor-framework/window-devel.cpp @@ -148,6 +148,11 @@ int32_t GetNativeId( Window window ) return GetImplementation( window ).GetNativeId(); } +void SetDamagedAreas(Window window, std::vector>& areas) +{ + GetImplementation(window).SetDamagedAreas(areas); +} + } // namespace DevelWindow } // namespace Dali diff --git a/dali/devel-api/adaptor-framework/window-devel.h b/dali/devel-api/adaptor-framework/window-devel.h index 958b940..1eb3501 100755 --- a/dali/devel-api/adaptor-framework/window-devel.h +++ b/dali/devel-api/adaptor-framework/window-devel.h @@ -2,7 +2,7 @@ #define DALI_WINDOW_DEVEL_H /* - * Copyright (c) 2019 Samsung Electronics Co., Ltd. + * 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. @@ -18,7 +18,10 @@ * */ +// EXTERNAL INCLUDES + // INTERNAL INCLUDES +#include #include namespace Dali @@ -250,6 +253,16 @@ DALI_ADAPTOR_API void SetAvailableOrientations( Window window, const Dali::Vecto */ DALI_ADAPTOR_API int32_t GetNativeId( Window window ); +/** + * @brief Sets damaged areas of the window. + * + * This API is for setting static damaged areas of the window for partial update. + * + * @param[in] window The window instance + * @param[in] areas The damaged areas list to set + */ +DALI_ADAPTOR_API void SetDamagedAreas(Window window, std::vector>& areas); + } // namespace DevelWindow } // namespace Dali diff --git a/dali/integration-api/adaptor-framework/render-surface-interface.h b/dali/integration-api/adaptor-framework/render-surface-interface.h index 25ad128..e148662 100644 --- a/dali/integration-api/adaptor-framework/render-surface-interface.h +++ b/dali/integration-api/adaptor-framework/render-surface-interface.h @@ -20,6 +20,7 @@ // EXTERNAL INCLUDES #include +#include #include #include #include @@ -136,9 +137,10 @@ public: * If the operation fails, then Core::Render should not be called until there is * a surface to render onto. * @param[in] resizingSurface True if the surface is being resized + * @param[in] damagedRects List of damaged rects this render pass * @return True if the operation is successful, False if the operation failed */ - virtual bool PreRender( bool resizingSurface ) = 0; + virtual bool PreRender( bool resizingSurface, const std::vector>& damagedRects, Rect& clippingRect ) = 0; /** * @brief Invoked by render thread after Core::Render @@ -146,7 +148,8 @@ public: * @param[in] replacingSurface True if the surface is being replaced. * @param[in] resizingSurface True if the surface is being resized. */ - virtual void PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface ) = 0; + virtual void PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface, const std::vector>& damagedRects ) = 0; + /** * @brief Invoked by render thread when the thread should be stop */ diff --git a/dali/integration-api/adaptor-framework/scene-holder-impl.cpp b/dali/integration-api/adaptor-framework/scene-holder-impl.cpp index 7162a1c..5bbe94b 100644 --- a/dali/integration-api/adaptor-framework/scene-holder-impl.cpp +++ b/dali/integration-api/adaptor-framework/scene-holder-impl.cpp @@ -31,6 +31,7 @@ // INTERNAL INCLUDES #include #include +#include #include #include @@ -208,6 +209,13 @@ void SceneHolder::SurfaceResized() { PositionSize surfacePositionSize = mSurface->GetPositionSize(); mScene.SurfaceResized( static_cast( surfacePositionSize.width ), static_cast( surfacePositionSize.height ) ); + + GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface(); + EglGraphics* eglGraphics = static_cast(&graphics); + if (eglGraphics) + { + eglGraphics->SetFullSwapNextFrame(); + } } Dali::RenderSurfaceInterface* SceneHolder::GetSurface() const @@ -220,6 +228,13 @@ void SceneHolder::SetBackgroundColor( const Vector4& color ) if( mScene ) { mScene.SetBackgroundColor( color ); + + GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface(); + EglGraphics* eglGraphics = static_cast(&graphics); + if (eglGraphics) + { + eglGraphics->SetFullSwapNextFrame(); + } } } diff --git a/dali/internal/adaptor/common/adaptor-impl.cpp b/dali/internal/adaptor/common/adaptor-impl.cpp index a48eb5f..58f9c85 100755 --- a/dali/internal/adaptor/common/adaptor-impl.cpp +++ b/dali/internal/adaptor/common/adaptor-impl.cpp @@ -181,7 +181,8 @@ void Adaptor::Initialize( GraphicsFactory& graphicsFactory, Dali::Configuration: eglContextHelperImpl, ( 0u != mEnvironmentOptions->GetRenderToFboInterval() ) ? Integration::RenderToFrameBuffer::TRUE : Integration::RenderToFrameBuffer::FALSE, mGraphics->GetDepthBufferRequired(), - mGraphics->GetStencilBufferRequired() ); + mGraphics->GetStencilBufferRequired(), + mGraphics->GetPartialUpdateRequired() ); defaultWindow->SetAdaptor( Get() ); diff --git a/dali/internal/adaptor/common/combined-update-render-controller.cpp b/dali/internal/adaptor/common/combined-update-render-controller.cpp index b310671..b514cb6 100644 --- a/dali/internal/adaptor/common/combined-update-render-controller.cpp +++ b/dali/internal/adaptor/common/combined-update-render-controller.cpp @@ -745,18 +745,35 @@ void CombinedUpdateRenderController::UpdateRenderThread() windowSurface->InitializeGraphics(); + // clear previous frame damaged render items rects, buffer history is tracked on surface level + mDamagedRects.clear(); + + // If user damaged areas are not set + if (!eglImpl.DamageAreasSet()) + { + // Collect damage rects + mCore.PreRender( scene, mDamagedRects ); + } + // Render off-screen frame buffers first if any mCore.RenderScene( windowRenderStatus, scene, true ); - // Switch to the EGL context of the surface - windowSurface->PreRender( surfaceResized ); // Switch GL context + Rect clippingRect; // Empty for fbo rendering + + // Switch to the EGL context of the surface, merge damaged areas for previous frames + windowSurface->PreRender( surfaceResized, mDamagedRects, clippingRect ); // Switch GL context + + if (clippingRect.IsEmpty()) + { + mDamagedRects.clear(); + } // Render the surface - mCore.RenderScene( windowRenderStatus, scene, false ); + mCore.RenderScene( windowRenderStatus, scene, false, clippingRect ); if( windowRenderStatus.NeedsPostRender() ) { - windowSurface->PostRender( false, false, surfaceResized ); // Swap Buffer + windowSurface->PostRender( false, false, surfaceResized, mDamagedRects ); // Swap Buffer with damage } } } diff --git a/dali/internal/adaptor/common/combined-update-render-controller.h b/dali/internal/adaptor/common/combined-update-render-controller.h index 965479e..8dfd4eb 100644 --- a/dali/internal/adaptor/common/combined-update-render-controller.h +++ b/dali/internal/adaptor/common/combined-update-render-controller.h @@ -391,6 +391,8 @@ private: volatile unsigned int mUploadWithoutRendering; ///< Will be set to upload the resource only (with no rendering) volatile unsigned int mFirstFrameAfterResume; ///< Will be set to check the first frame after resume (for log) + + std::vector> mDamagedRects; ///< Keeps collected damaged render items rects for one render pass }; } // namespace Adaptor diff --git a/dali/internal/graphics/common/graphics-interface.h b/dali/internal/graphics/common/graphics-interface.h index 93c1b2f..4404fab 100644 --- a/dali/internal/graphics/common/graphics-interface.h +++ b/dali/internal/graphics/common/graphics-interface.h @@ -42,8 +42,9 @@ public: * Constructor */ GraphicsInterface() -: mDepthBufferRequired( Integration::DepthBufferAvailable::FALSE ), - mStencilBufferRequired( Integration::StencilBufferAvailable::FALSE ) + : mDepthBufferRequired( Integration::DepthBufferAvailable::FALSE ), + mStencilBufferRequired( Integration::StencilBufferAvailable::FALSE ), + mPartialUpdateRequired( Integration::PartialUpdateAvailable::FALSE ) { }; @@ -81,11 +82,20 @@ public: return mStencilBufferRequired; }; + /** + * Get whether the stencil buffer is required + * @return TRUE if the stencil buffer is required + */ + Integration::PartialUpdateAvailable GetPartialUpdateRequired() + { + return mPartialUpdateRequired; + }; protected: Integration::DepthBufferAvailable mDepthBufferRequired; ///< Whether the depth buffer is required Integration::StencilBufferAvailable mStencilBufferRequired; ///< Whether the stencil buffer is required + Integration::PartialUpdateAvailable mPartialUpdateRequired; ///< Whether the partial update is required }; } // Adaptor diff --git a/dali/internal/graphics/gles/egl-graphics.cpp b/dali/internal/graphics/gles/egl-graphics.cpp index 406e69c..e13ce0b 100644 --- a/dali/internal/graphics/gles/egl-graphics.cpp +++ b/dali/internal/graphics/gles/egl-graphics.cpp @@ -62,6 +62,7 @@ void EglGraphics::Initialize( EnvironmentOptions* environmentOptions ) mDepthBufferRequired = static_cast< Integration::DepthBufferAvailable >( environmentOptions->DepthBufferRequired() ); mStencilBufferRequired = static_cast< Integration::StencilBufferAvailable >( environmentOptions->StencilBufferRequired() ); + mPartialUpdateRequired = static_cast< Integration::PartialUpdateAvailable >( environmentOptions->PartialUpdateRequired() ); mMultiSamplingLevel = environmentOptions->GetMultiSamplingLevel(); @@ -72,7 +73,7 @@ void EglGraphics::Initialize( EnvironmentOptions* environmentOptions ) EglInterface* EglGraphics::Create() { - mEglImplementation = Utils::MakeUnique< EglImplementation >( mMultiSamplingLevel, mDepthBufferRequired, mStencilBufferRequired ); + mEglImplementation = Utils::MakeUnique< EglImplementation >( mMultiSamplingLevel, mDepthBufferRequired, mStencilBufferRequired, mPartialUpdateRequired ); mEglImageExtensions = Utils::MakeUnique< EglImageExtensions >( mEglImplementation.get() ); mEglSync->Initialize( mEglImplementation.get() ); // The sync impl needs the EglDisplay @@ -128,6 +129,16 @@ EglImageExtensions* EglGraphics::GetImageExtensions() return mEglImageExtensions.get(); } +void EglGraphics::SetDamagedAreas(std::vector>& areas) +{ + mEglImplementation->SetDamageAreas(areas); +} + +void EglGraphics::SetFullSwapNextFrame() +{ + mEglImplementation->SetFullSwapNextFrame(); +} + } // Adaptor } // Internal } // Dali diff --git a/dali/internal/graphics/gles/egl-graphics.h b/dali/internal/graphics/gles/egl-graphics.h index 8ee45bc..410395c 100644 --- a/dali/internal/graphics/gles/egl-graphics.h +++ b/dali/internal/graphics/gles/egl-graphics.h @@ -126,6 +126,16 @@ public: EglImageExtensions* GetImageExtensions(); /** + * Sets fixed damaged areas for partial rendering. This overrides automatic partial rendering. + */ + void SetDamagedAreas( std::vector>& areas ); + + /** + * Instructs egl implementation to do full swap regardless of stored data, resets the data. + */ + void SetFullSwapNextFrame(); + + /** * @copydoc Dali::Internal::Adaptor::GraphicsInterface::Destroy() */ void Destroy() override; diff --git a/dali/internal/graphics/gles/egl-implementation.cpp b/dali/internal/graphics/gles/egl-implementation.cpp index 38851f9..3710dd1 100755 --- a/dali/internal/graphics/gles/egl-implementation.cpp +++ b/dali/internal/graphics/gles/egl-implementation.cpp @@ -63,7 +63,8 @@ namespace Adaptor EglImplementation::EglImplementation( int multiSamplingLevel, Integration::DepthBufferAvailable depthBufferRequired, - Integration::StencilBufferAvailable stencilBufferRequired ) + Integration::StencilBufferAvailable stencilBufferRequired , + Integration::PartialUpdateAvailable partialUpdateRequired ) : mContextAttribs(), mEglNativeDisplay( 0 ), mEglNativeWindow( 0 ), @@ -81,9 +82,14 @@ EglImplementation::EglImplementation( int multiSamplingLevel, mIsWindow( true ), mDepthBufferRequired( depthBufferRequired == Integration::DepthBufferAvailable::TRUE ), mStencilBufferRequired( stencilBufferRequired == Integration::StencilBufferAvailable::TRUE ), + mPartialUpdateRequired( partialUpdateRequired == Integration::PartialUpdateAvailable::TRUE ), mIsSurfacelessContextSupported( false ), mIsKhrCreateContextSupported( false ), - mSwapBufferCountAfterResume( 0 ) + mSwapBufferCountAfterResume( 0 ), + mEglSetDamageRegionKHR( 0 ), + mEglSwapBuffersWithDamageKHR( 0 ), + mBufferAge( 0 ), + mFullSwapNextFrame( true ) { } @@ -169,6 +175,18 @@ bool EglImplementation::CreateContext() DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_SHADING_LANGUAGE_VERSION : %s***\n", glGetString(GL_SHADING_LANGUAGE_VERSION)); DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** Supported Extensions ***\n%s\n\n", glGetString(GL_EXTENSIONS)); + mEglSetDamageRegionKHR = reinterpret_cast(eglGetProcAddress("eglSetDamageRegionKHR")); + if (!mEglSetDamageRegionKHR) + { + DALI_LOG_ERROR("Coudn't find eglSetDamageRegionKHR!\n"); + mPartialUpdateRequired = false; + } + mEglSwapBuffersWithDamageKHR = reinterpret_cast(eglGetProcAddress("eglSwapBuffersWithDamageKHR")); + if (!mEglSwapBuffersWithDamageKHR) + { + DALI_LOG_ERROR("Coudn't find eglSwapBuffersWithDamageKHR!\n"); + mPartialUpdateRequired = false; + } return true; } @@ -190,6 +208,18 @@ bool EglImplementation::CreateWindowContext( EGLContext& eglContext ) mEglWindowContexts.push_back( eglContext ); + mEglSetDamageRegionKHR = reinterpret_cast(eglGetProcAddress("eglSetDamageRegionKHR")); + if (!mEglSetDamageRegionKHR) + { + DALI_LOG_ERROR("Coudn't find eglSetDamageRegionKHR!\n"); + mPartialUpdateRequired = false; + } + mEglSwapBuffersWithDamageKHR = reinterpret_cast(eglGetProcAddress("eglSwapBuffersWithDamageKHR")); + if (!mEglSwapBuffersWithDamageKHR) + { + DALI_LOG_ERROR("Coudn't find eglSwapBuffersWithDamageKHR!\n"); + mPartialUpdateRequired = false; + } return true; } @@ -321,7 +351,266 @@ void EglImplementation::SwapBuffers( EGLSurface& eglSurface ) } #endif //DALI_PROFILE_UBUNTU + // DALI_LOG_ERROR("EglImplementation::SwapBuffers()\n"); eglSwapBuffers( mEglDisplay, eglSurface ); + mFullSwapNextFrame = false; + +#ifndef DALI_PROFILE_UBUNTU + if( mSwapBufferCountAfterResume < THRESHOLD_SWAPBUFFER_COUNT ) + { + DALI_LOG_RELEASE_INFO( "EglImplementation::SwapBuffers finished.\n" ); + mSwapBufferCountAfterResume++; + } +#endif //DALI_PROFILE_UBUNTU + } +} + +EGLint EglImplementation::GetBufferAge(EGLSurface& eglSurface) const +{ + EGLint age = 0; + eglQuerySurface(mEglDisplay, eglSurface, EGL_BUFFER_AGE_EXT, &age); + if (age < 0) + { + DALI_LOG_ERROR("eglQuerySurface(%d)\n", eglGetError()); + age = 0; + } + + // 0 - invalid buffer + // 1, 2, 3 + if (age > 3) + { + DALI_LOG_ERROR("EglImplementation::GetBufferAge() buffer age %d > 3\n", age); + age = 0; // shoudn't be more than 3 back buffers, if there is just reset, I don't want to add extra history level + } + + return age; +} + +bool EglImplementation::DamageAreasSet() const +{ + return (mDamagedAreas.size() ? true : false); +} + +void EglImplementation::SetDamageAreas( std::vector>& damagedAreas ) +{ + mFullSwapNextFrame = true; + mDamagedAreas = damagedAreas; +} + +void EglImplementation::SetFullSwapNextFrame() +{ + mFullSwapNextFrame = true; +} + +void mergeRects(Rect& mergingRect, const std::vector>& rects) +{ + uint32_t i = 0; + if (mergingRect.IsEmpty()) + { + for (;i < rects.size(); i++) + { + if (!rects[i].IsEmpty()) + { + mergingRect = rects[i]; + break; + } + } + } + + for (;i < rects.size(); i++) + { + mergingRect.Merge(rects[i]); + } +} + +void insertRects(std::list>>& damagedRectsList, const std::vector>& damagedRects) +{ + damagedRectsList.push_front(damagedRects); + if (damagedRectsList.size() > 4) // past triple buffers + current + { + damagedRectsList.pop_back(); + } +} + +void EglImplementation::SetDamage( EGLSurface& eglSurface, const std::vector>& damagedRects, Rect& clippingRect ) +{ + if (!mPartialUpdateRequired) + { + return; + } + + if (eglSurface != EGL_NO_SURFACE) // skip if using surfaceless context + { + EGLint width = 0; + EGLint height = 0; + eglQuerySurface(mEglDisplay, eglSurface, EGL_WIDTH, &width); + eglQuerySurface(mEglDisplay, eglSurface, EGL_HEIGHT, &height); + Rect surfaceRect(0, 0, width, height); + + mSurfaceRect = surfaceRect; + + if (mFullSwapNextFrame) + { + mBufferAge = 0; + insertRects(mBufferDamagedRects, std::vector>(1, surfaceRect)); + clippingRect = Rect(); + return; + } + + EGLint bufferAge = GetBufferAge(eglSurface); + if (mDamagedAreas.size()) + { + mBufferAge = bufferAge; + if (bufferAge == 0) + { + // Buffer age is reset + clippingRect = Rect(); + return; + } + + mergeRects(clippingRect, mDamagedAreas); + } + else + { + // Buffer age 0 means the back buffer in invalid and requires full swap + if (!damagedRects.size() || bufferAge != mBufferAge || bufferAge == 0) + { + // No damage or buffer is out of order or buffer age is reset + mBufferAge = bufferAge; + insertRects(mBufferDamagedRects, std::vector>(1, surfaceRect)); + clippingRect = Rect(); + return; + } + + // We push current frame damaged rects here, zero index for current frame + mBufferAge = bufferAge; + insertRects(mBufferDamagedRects, damagedRects); + + // Merge damaged rects into clipping rect + auto bufferDamagedRects = mBufferDamagedRects.begin(); + while (bufferAge-- >= 0 && bufferDamagedRects != mBufferDamagedRects.end()) + { + const std::vector>& rects = *bufferDamagedRects++; + mergeRects(clippingRect, rects); + } + } + + if (!clippingRect.Intersect(surfaceRect) || clippingRect.Area() > surfaceRect.Area() * 0.8) + { + // clipping area too big or doesn't intersect surface rect + clippingRect = Rect(); + return; + } + + // DALI_LOG_ERROR("eglSetDamageRegionKHR(%d, %d, %d, %d)\n", clippingRect.x, clippingRect.y, clippingRect.width, clippingRect.height); + EGLBoolean result = mEglSetDamageRegionKHR(mEglDisplay, eglSurface, reinterpret_cast(&clippingRect), 1); + if (result == EGL_FALSE) + { + DALI_LOG_ERROR("eglSetDamageRegionKHR(%d)\n", eglGetError()); + } + } +} + +void EglImplementation::SwapBuffers(EGLSurface& eglSurface, const std::vector>& damagedRects) +{ + if (eglSurface != EGL_NO_SURFACE ) // skip if using surfaceless context + { + if (!mPartialUpdateRequired || mFullSwapNextFrame || mBufferAge == 0 || !damagedRects.size()) + { + SwapBuffers(eglSurface); + return; + } + +#ifndef DALI_PROFILE_UBUNTU + if( mSwapBufferCountAfterResume < THRESHOLD_SWAPBUFFER_COUNT ) + { + DALI_LOG_RELEASE_INFO( "EglImplementation::SwapBuffers started.\n" ); + } +#endif //DALI_PROFILE_UBUNTU + + if (mDamagedAreas.size()) + { + // DALI_LOG_ERROR("EglImplementation::SwapBuffers(%d)\n", mDamagedAreas.size()); + EGLBoolean result = mEglSwapBuffersWithDamageKHR(mEglDisplay, eglSurface, reinterpret_cast(mDamagedAreas.data()), mDamagedAreas.size()); + if (result == EGL_FALSE) + { + DALI_LOG_ERROR("eglSwapBuffersWithDamageKHR(%d)\n", eglGetError()); + } + +#ifndef DALI_PROFILE_UBUNTU + if( mSwapBufferCountAfterResume < THRESHOLD_SWAPBUFFER_COUNT ) + { + DALI_LOG_RELEASE_INFO( "EglImplementation::SwapBuffers finished.\n" ); + mSwapBufferCountAfterResume++; + } +#endif //DALI_PROFILE_UBUNTU + return; + } + + // current frame damaged rects were pushed by EglImplementation::SetDamage() to 0 index. + EGLint bufferAge = mBufferAge; + mCombinedDamagedRects.clear(); + + // Combine damaged rects from previous frames (beginning from bufferAge index) with the current frame (0 index) + auto bufferDamagedRects = mBufferDamagedRects.begin(); + while (bufferAge-- >= 0 && bufferDamagedRects != mBufferDamagedRects.end()) + { + const std::vector>& rects = *bufferDamagedRects++; + mCombinedDamagedRects.insert(mCombinedDamagedRects.end(), rects.begin(), rects.end()); + } + + // Merge intersecting rects, form an array of non intersecting rects to help driver a bit + // Could be optional and can be removed, needs to be checked with and without on platform + const int n = mCombinedDamagedRects.size(); + for (int i = 0; i < n-1; i++) + { + if (mCombinedDamagedRects[i].IsEmpty()) + { + continue; + } + + for (int j = i+1; j < n; j++) + { + if (mCombinedDamagedRects[j].IsEmpty()) + { + continue; + } + + if (mCombinedDamagedRects[i].Intersects(mCombinedDamagedRects[j])) + { + mCombinedDamagedRects[i].Merge(mCombinedDamagedRects[j]); + mCombinedDamagedRects[j].width = 0; + mCombinedDamagedRects[j].height = 0; + } + } + } + + int j = 0; + for (int i = 0; i < n; i++) + { + if (!mCombinedDamagedRects[i].IsEmpty()) + { + mCombinedDamagedRects[j++] = mCombinedDamagedRects[i]; + } + } + + if (j != 0) + { + mCombinedDamagedRects.resize(j); + } + + if (!mCombinedDamagedRects.size() || (mCombinedDamagedRects[0].Area() > mSurfaceRect.Area() * 0.8)) + { + SwapBuffers(eglSurface); + return; + } + + // DALI_LOG_ERROR("EglImplementation::SwapBuffers(%d)\n", mCombinedDamagedRects.size()); + EGLBoolean result = mEglSwapBuffersWithDamageKHR(mEglDisplay, eglSurface, reinterpret_cast(mCombinedDamagedRects.data()), mCombinedDamagedRects.size()); + if (result == EGL_FALSE) + { + DALI_LOG_ERROR("eglSwapBuffersWithDamageKHR(%d)\n", eglGetError()); + } #ifndef DALI_PROFILE_UBUNTU if( mSwapBufferCountAfterResume < THRESHOLD_SWAPBUFFER_COUNT ) diff --git a/dali/internal/graphics/gles/egl-implementation.h b/dali/internal/graphics/gles/egl-implementation.h index efb9754..b505352 100644 --- a/dali/internal/graphics/gles/egl-implementation.h +++ b/dali/internal/graphics/gles/egl-implementation.h @@ -19,9 +19,13 @@ */ // EXTERNAL INCLUDES +#include +#include + #include #include #include +#include #include // INTERNAL INCLUDES @@ -46,10 +50,12 @@ public: * @param[in] multiSamplingLevel The Multi-sampling level required * @param[in] depthBufferRequired Whether the depth buffer is required * @param[in] stencilBufferRequired Whether the stencil buffer is required + * @param[in] partialUpdatedRequired Whether the partial update is required */ EglImplementation( int multiSamplingLevel, Integration::DepthBufferAvailable depthBufferRequired, - Integration::StencilBufferAvailable stencilBufferRequired ); + Integration::StencilBufferAvailable stencilBufferRequired, + Integration::PartialUpdateAvailable partialUpdateRequired ); /** * Destructor @@ -124,6 +130,36 @@ public: virtual void SwapBuffers( EGLSurface& eglSurface ); /** + * Gets current back buffer age + */ + EGLint GetBufferAge( EGLSurface& eglSurface ) const; + + /** + * Gets if user set damaged areas + */ + bool DamageAreasSet() const; + + /** + * Sets damaged areas, overrides auto calculated ones + */ + void SetDamageAreas( std::vector>& damagedArea ); + + /** + * Forces full surface swap next frame, resets current partial update state. + */ + void SetFullSwapNextFrame(); + + /** + * Performs an OpenGL set damage command with damaged rects + */ + virtual void SetDamage( EGLSurface& eglSurface, const std::vector>& damagedRects, Rect& clippingRect ); + + /** + * Performs an OpenGL swap buffers command with damaged rects + */ + virtual void SwapBuffers( EGLSurface& eglSurface, const std::vector>& damagedRects ); + + /** * Performs an OpenGL copy buffers command */ virtual void CopyBuffers( EGLSurface& eglSurface ); @@ -246,10 +282,20 @@ private: bool mIsWindow; bool mDepthBufferRequired; bool mStencilBufferRequired; + bool mPartialUpdateRequired; bool mIsSurfacelessContextSupported; bool mIsKhrCreateContextSupported; uint32_t mSwapBufferCountAfterResume; + PFNEGLSETDAMAGEREGIONKHRPROC mEglSetDamageRegionKHR; + PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC mEglSwapBuffersWithDamageKHR; + + EGLint mBufferAge; + std::list>> mBufferDamagedRects; + std::vector> mCombinedDamagedRects; + std::vector> mDamagedAreas; + Rect mSurfaceRect; + bool mFullSwapNextFrame; }; } // namespace Adaptor diff --git a/dali/internal/system/common/environment-options.cpp b/dali/internal/system/common/environment-options.cpp index 7fea428..1d00be7 100644 --- a/dali/internal/system/common/environment-options.cpp +++ b/dali/internal/system/common/environment-options.cpp @@ -42,6 +42,7 @@ const unsigned int DEFAULT_STATISTICS_LOG_FREQUENCY = 2; const int DEFAULT_MULTI_SAMPLING_LEVEL = -1; const bool DEFAULT_DEPTH_BUFFER_REQUIRED_SETTING = true; const bool DEFAULT_STENCIL_BUFFER_REQUIRED_SETTING = true; +const bool DEFAULT_PARTIAL_UPDATE_REQUIRED_SETTING = false; unsigned int GetIntegerEnvironmentVariable( const char* variable, unsigned int defaultValue ) { @@ -130,7 +131,8 @@ EnvironmentOptions::EnvironmentOptions() mThreadingMode( ThreadingMode::COMBINED_UPDATE_RENDER ), mGlesCallAccumulate( false ), mDepthBufferRequired( DEFAULT_DEPTH_BUFFER_REQUIRED_SETTING ), - mStencilBufferRequired( DEFAULT_STENCIL_BUFFER_REQUIRED_SETTING ) + mStencilBufferRequired( DEFAULT_STENCIL_BUFFER_REQUIRED_SETTING ), + mPartialUpdateRequired( DEFAULT_PARTIAL_UPDATE_REQUIRED_SETTING ) { ParseEnvironmentOptions(); } @@ -391,6 +393,11 @@ bool EnvironmentOptions::StencilBufferRequired() const return mStencilBufferRequired; } +bool EnvironmentOptions::PartialUpdateRequired() const +{ + return mPartialUpdateRequired; +} + void EnvironmentOptions::ParseEnvironmentOptions() { // get logging options @@ -660,6 +667,15 @@ void EnvironmentOptions::ParseEnvironmentOptions() mStencilBufferRequired = false; } } + + int partialUpdateRequired( -1 ); + if( GetIntegerEnvironmentVariable( DALI_ENV_ENABLE_PARTIAL_UPDATE, partialUpdateRequired ) ) + { + if( partialUpdateRequired > 0 ) + { + mPartialUpdateRequired = true; + } + } } } // Adaptor diff --git a/dali/internal/system/common/environment-options.h b/dali/internal/system/common/environment-options.h index f72ebdd..4d4b458 100644 --- a/dali/internal/system/common/environment-options.h +++ b/dali/internal/system/common/environment-options.h @@ -316,6 +316,11 @@ public: */ bool StencilBufferRequired() const; + /** + * @return Whether the partial update is required. + */ + bool PartialUpdateRequired() const; + /// Deleted copy constructor. EnvironmentOptions( const EnvironmentOptions& ) = delete; @@ -383,6 +388,7 @@ private: // Data bool mGlesCallAccumulate; ///< Whether or not to accumulate gles call statistics bool mDepthBufferRequired; ///< Whether the depth buffer is required bool mStencilBufferRequired; ///< Whether the stencil buffer is required + bool mPartialUpdateRequired; ///< Whether the partial update is required std::unique_ptr mTraceManager; ///< TraceManager }; diff --git a/dali/internal/system/common/environment-variables.h b/dali/internal/system/common/environment-variables.h index ca1a9c8..1be9185 100644 --- a/dali/internal/system/common/environment-variables.h +++ b/dali/internal/system/common/environment-variables.h @@ -128,6 +128,8 @@ namespace Adaptor #define DALI_ENV_DISABLE_STENCIL_BUFFER "DALI_DISABLE_STENCIL_BUFFER" +#define DALI_ENV_ENABLE_PARTIAL_UPDATE "DALI_ENABLE_PARTIAL_UPDATE" + #define DALI_ENV_WEB_ENGINE_NAME "DALI_WEB_ENGINE_NAME" #define DALI_ENV_DPI_HORIZONTAL "DALI_DPI_HORIZONTAL" diff --git a/dali/internal/window-system/common/window-impl.cpp b/dali/internal/window-system/common/window-impl.cpp index b21ca77..15be716 100755 --- a/dali/internal/window-system/common/window-impl.cpp +++ b/dali/internal/window-system/common/window-impl.cpp @@ -32,6 +32,7 @@ // INTERNAL HEADERS #include +#include #include #include #include @@ -188,18 +189,42 @@ std::string Window::GetClassName() const void Window::Raise() { mWindowBase->Raise(); + + GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface(); + EglGraphics* eglGraphics = static_cast(&graphics); + if (eglGraphics) + { + eglGraphics->SetFullSwapNextFrame(); + } + DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Raise() \n", this, mNativeWindowId ); } void Window::Lower() { mWindowBase->Lower(); + + GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface(); + EglGraphics* eglGraphics = static_cast(&graphics); + if (eglGraphics) + { + eglGraphics->SetFullSwapNextFrame(); + } + DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Lower() \n", this, mNativeWindowId ); } void Window::Activate() { mWindowBase->Activate(); + + GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface(); + EglGraphics* eglGraphics = static_cast(&graphics); + if (eglGraphics) + { + eglGraphics->SetFullSwapNextFrame(); + } + DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Activate() \n", this, mNativeWindowId ); } @@ -412,6 +437,13 @@ void Window::Show() mVisibilityChangedSignal.Emit( handle, true ); } + GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface(); + EglGraphics* eglGraphics = static_cast(&graphics); + if (eglGraphics) + { + eglGraphics->SetFullSwapNextFrame(); + } + DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Show(): iconified = %d, visible = %d\n", this, mNativeWindowId, mIconified, mVisible ); } @@ -430,6 +462,14 @@ void Window::Hide() mVisibilityChangedSignal.Emit( handle, false ); } + + GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface(); + EglGraphics* eglGraphics = static_cast(&graphics); + if (eglGraphics) + { + eglGraphics->SetFullSwapNextFrame(); + } + DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Hide(): iconified = %d, visible = %d\n", this, mNativeWindowId, mIconified, mVisible ); } @@ -478,6 +518,13 @@ void Window::SetInputRegion( const Rect< int >& inputRegion ) { mWindowBase->SetInputRegion( inputRegion ); + GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface(); + EglGraphics* eglGraphics = static_cast(&graphics); + if (eglGraphics) + { + eglGraphics->SetFullSwapNextFrame(); + } + DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::SetInputRegion: x = %d, y = %d, w = %d, h = %d\n", inputRegion.x, inputRegion.y, inputRegion.width, inputRegion.height ); } @@ -589,6 +636,13 @@ void Window::SetSize( Dali::Window::WindowSize size ) mAdaptor->SurfaceResizeComplete( mSurface.get(), newSize ); } + + GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface(); + EglGraphics* eglGraphics = static_cast(&graphics); + if (eglGraphics) + { + eglGraphics->SetFullSwapNextFrame(); + } } Dali::Window::WindowSize Window::GetSize() const @@ -609,6 +663,13 @@ void Window::SetPosition( Dali::Window::WindowPosition position ) PositionSize oldRect = mSurface->GetPositionSize(); mWindowSurface->MoveResize( PositionSize( position.GetX(), position.GetY(), oldRect.width, oldRect.height ) ); + + GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface(); + EglGraphics* eglGraphics = static_cast(&graphics); + if (eglGraphics) + { + eglGraphics->SetFullSwapNextFrame(); + } } Dali::Window::WindowPosition Window::GetPosition() const @@ -647,6 +708,13 @@ void Window::SetPositionSize( PositionSize positionSize ) mResizeSignal.Emit( handle, newSize ); mAdaptor->SurfaceResizeComplete( mSurface.get(), newSize ); } + + GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface(); + EglGraphics* eglGraphics = static_cast(&graphics); + if (eglGraphics) + { + eglGraphics->SetFullSwapNextFrame(); + } } Dali::Layer Window::GetRootLayer() const @@ -711,6 +779,13 @@ void Window::OnIconifyChanged( bool iconified ) DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Deiconified: visible = %d\n", this, mNativeWindowId, mVisible ); } + + GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface(); + EglGraphics* eglGraphics = static_cast(&graphics); + if (eglGraphics) + { + eglGraphics->SetFullSwapNextFrame(); + } } void Window::OnFocusChanged( bool focusIn ) @@ -718,6 +793,13 @@ void Window::OnFocusChanged( bool focusIn ) Dali::Window handle( this ); mFocusChangedSignal.Emit( focusIn ); mFocusChangeSignal.Emit( handle, focusIn ); + + GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface(); + EglGraphics* eglGraphics = static_cast(&graphics); + if (eglGraphics) + { + eglGraphics->SetFullSwapNextFrame(); + } } void Window::OnOutputTransformed() @@ -784,6 +866,13 @@ void Window::OnPause() { mEventHandler->Pause(); } + + GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface(); + EglGraphics* eglGraphics = static_cast(&graphics); + if (eglGraphics) + { + eglGraphics->SetFullSwapNextFrame(); + } } void Window::OnResume() @@ -792,6 +881,13 @@ void Window::OnResume() { mEventHandler->Resume(); } + + GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface(); + EglGraphics* eglGraphics = static_cast(&graphics); + if (eglGraphics) + { + eglGraphics->SetFullSwapNextFrame(); + } } void Window::RecalculateTouchPosition( Integration::Point& point ) @@ -915,6 +1011,16 @@ int32_t Window::GetNativeId() const return mWindowBase->GetNativeWindowId(); } +void Window::SetDamagedAreas(std::vector>& areas) +{ + GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface(); + EglGraphics* eglGraphics = static_cast(&graphics); + if (eglGraphics) + { + eglGraphics->SetDamagedAreas(areas); + } +} + } // Adaptor } // Internal diff --git a/dali/internal/window-system/common/window-impl.h b/dali/internal/window-system/common/window-impl.h index ca1d3bf..3a877ae 100755 --- a/dali/internal/window-system/common/window-impl.h +++ b/dali/internal/window-system/common/window-impl.h @@ -359,6 +359,11 @@ public: */ void SetAvailableOrientations( const Dali::Vector& orientations ); + /** + * @copydoc Dali::DevelWindow::SetDamagedAreas() + */ + void SetDamagedAreas(std::vector>& areas); + public: // Dali::Internal::Adaptor::SceneHolder /** diff --git a/dali/internal/window-system/common/window-render-surface.cpp b/dali/internal/window-system/common/window-render-surface.cpp index c95d508..dfaefa4 100644 --- a/dali/internal/window-system/common/window-render-surface.cpp +++ b/dali/internal/window-system/common/window-render-surface.cpp @@ -352,10 +352,12 @@ void WindowRenderSurface::StartRender() { } -bool WindowRenderSurface::PreRender( bool resizingSurface ) +bool WindowRenderSurface::PreRender( bool resizingSurface, const std::vector>& damagedRects, Rect& clippingRect ) { MakeContextCurrent(); + auto eglGraphics = static_cast(mGraphics); + if( resizingSurface ) { // Window rotate or screen rotate @@ -386,19 +388,24 @@ bool WindowRenderSurface::PreRender( bool resizingSurface ) DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PreRender: Set resize\n" ); } + + if (eglGraphics) + { + Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation(); + eglImpl.SetFullSwapNextFrame(); + } } - auto eglGraphics = static_cast(mGraphics); - if ( eglGraphics ) + if (eglGraphics) { - GlImplementation& mGLES = eglGraphics->GetGlesInterface(); - mGLES.PreRender(); + Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation(); + eglImpl.SetDamage( mEGLSurface, damagedRects, clippingRect ); } return true; } -void WindowRenderSurface::PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface ) +void WindowRenderSurface::PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface, const std::vector>& damagedRects ) { // Inform the gl implementation that rendering has finished before informing the surface auto eglGraphics = static_cast(mGraphics); @@ -438,7 +445,7 @@ void WindowRenderSurface::PostRender( bool renderToFbo, bool replacingSurface, b } Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation(); - eglImpl.SwapBuffers( mEGLSurface ); + eglImpl.SwapBuffers( mEGLSurface, damagedRects ); if( mRenderNotification ) { diff --git a/dali/internal/window-system/common/window-render-surface.h b/dali/internal/window-system/common/window-render-surface.h index f8160b8..bc03611 100644 --- a/dali/internal/window-system/common/window-render-surface.h +++ b/dali/internal/window-system/common/window-render-surface.h @@ -156,12 +156,12 @@ public: // from Dali::RenderSurfaceInterface /** * @copydoc Dali::RenderSurfaceInterface::PreRender() */ - virtual bool PreRender( bool resizingSurface ) override; + virtual bool PreRender( bool resizingSurface, const std::vector>& damagedRects, Rect& clippingRect ) override; /** * @copydoc Dali::RenderSurfaceInterface::PostRender() */ - virtual void PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface ); + virtual void PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface, const std::vector>& damagedRects ) override; /** * @copydoc Dali::RenderSurfaceInterface::StopRender() diff --git a/dali/internal/window-system/tizen-wayland/native-render-surface-ecore-wl.cpp b/dali/internal/window-system/tizen-wayland/native-render-surface-ecore-wl.cpp index 3ef4f68..48069c7 100644 --- a/dali/internal/window-system/tizen-wayland/native-render-surface-ecore-wl.cpp +++ b/dali/internal/window-system/tizen-wayland/native-render-surface-ecore-wl.cpp @@ -216,20 +216,30 @@ void NativeRenderSurfaceEcoreWl::StartRender() { } -bool NativeRenderSurfaceEcoreWl::PreRender( bool ) +bool NativeRenderSurfaceEcoreWl::PreRender( bool resizingSurface, const std::vector>& damagedRects, Rect& clippingRect ) { - // nothing to do for pixmaps + auto eglGraphics = static_cast(mGraphics); + if (eglGraphics) + { + Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation(); + if (resizingSurface) + { + eglImpl.SetFullSwapNextFrame(); + } + + eglImpl.SetDamage(mEGLSurface, damagedRects, clippingRect); + } + return true; } -void NativeRenderSurfaceEcoreWl::PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface ) +void NativeRenderSurfaceEcoreWl::PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface, const std::vector>& damagedRects ) { auto eglGraphics = static_cast(mGraphics); - if ( eglGraphics ) + if (eglGraphics) { Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation(); - - eglImpl.SwapBuffers( mEGLSurface ); + eglImpl.SwapBuffers( mEGLSurface, damagedRects ); } if( mThreadSynchronization ) diff --git a/dali/internal/window-system/tizen-wayland/native-render-surface-ecore-wl.h b/dali/internal/window-system/tizen-wayland/native-render-surface-ecore-wl.h index e3a33ba..bfca63c 100644 --- a/dali/internal/window-system/tizen-wayland/native-render-surface-ecore-wl.h +++ b/dali/internal/window-system/tizen-wayland/native-render-surface-ecore-wl.h @@ -116,12 +116,12 @@ public: // from Dali::RenderSurfaceInterface /** * @copydoc Dali::RenderSurfaceInterface::PreRender() */ - virtual bool PreRender( bool resizingSurface ) override; + virtual bool PreRender( bool resizingSurface, const std::vector>& damagedRects, Rect& clippingRect ) override; /** * @copydoc Dali::RenderSurfaceInterface::PostRender() */ - virtual void PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface ); + virtual void PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface, const std::vector>& damagedRects ) override; /** * @copydoc Dali::RenderSurfaceInterface::StopRender() diff --git a/dali/internal/window-system/ubuntu-x11/pixmap-render-surface-ecore-x.cpp b/dali/internal/window-system/ubuntu-x11/pixmap-render-surface-ecore-x.cpp index 2e93140..527f5cc 100644 --- a/dali/internal/window-system/ubuntu-x11/pixmap-render-surface-ecore-x.cpp +++ b/dali/internal/window-system/ubuntu-x11/pixmap-render-surface-ecore-x.cpp @@ -220,13 +220,13 @@ void PixmapRenderSurfaceEcoreX::StartRender() { } -bool PixmapRenderSurfaceEcoreX::PreRender( bool ) +bool PixmapRenderSurfaceEcoreX::PreRender( bool, const std::vector>&, Rect& ) { // Nothing to do for pixmaps return true; } -void PixmapRenderSurfaceEcoreX::PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface ) +void PixmapRenderSurfaceEcoreX::PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface, const std::vector>& damagedRects ) { auto eglGraphics = static_cast(mGraphics); diff --git a/dali/internal/window-system/ubuntu-x11/pixmap-render-surface-ecore-x.h b/dali/internal/window-system/ubuntu-x11/pixmap-render-surface-ecore-x.h index 034fee6..ebedfef 100644 --- a/dali/internal/window-system/ubuntu-x11/pixmap-render-surface-ecore-x.h +++ b/dali/internal/window-system/ubuntu-x11/pixmap-render-surface-ecore-x.h @@ -114,12 +114,12 @@ public: // from Dali::RenderSurfaceInterface /** * @copydoc Dali::RenderSurfaceInterface::PreRender() */ - virtual bool PreRender( bool resizingSurface ) override; + virtual bool PreRender( bool resizingSurface, const std::vector>& damagedRects, Rect& clippingRect ) override; /** * @copydoc Dali::RenderSurfaceInterface::PostRender() */ - virtual void PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface ) override; + virtual void PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface, const std::vector>& damagedRects ) override; /** * @copydoc Dali::RenderSurfaceInterface::StopRender() -- 2.7.4 From 4461208a8cf11f6c1765cc0fd81a8c46c0cd9b8d Mon Sep 17 00:00:00 2001 From: Sunghyun Kim Date: Mon, 22 Jun 2020 17:33:09 +0900 Subject: [PATCH 09/16] DALi Version 1.5.17 Change-Id: Ided273236003f8c233c282275d26259bfce35d8c --- dali/public-api/dali-adaptor-version.cpp | 2 +- packaging/dali-adaptor.spec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dali/public-api/dali-adaptor-version.cpp b/dali/public-api/dali-adaptor-version.cpp index e5ef10f..0fce620 100644 --- a/dali/public-api/dali-adaptor-version.cpp +++ b/dali/public-api/dali-adaptor-version.cpp @@ -28,7 +28,7 @@ namespace Dali const unsigned int ADAPTOR_MAJOR_VERSION = 1; const unsigned int ADAPTOR_MINOR_VERSION = 5; -const unsigned int ADAPTOR_MICRO_VERSION = 16; +const unsigned int ADAPTOR_MICRO_VERSION = 17; const char * const ADAPTOR_BUILD_DATE = __DATE__ " " __TIME__; #ifdef DEBUG_ENABLED diff --git a/packaging/dali-adaptor.spec b/packaging/dali-adaptor.spec index 706b1fd..6523580 100644 --- a/packaging/dali-adaptor.spec +++ b/packaging/dali-adaptor.spec @@ -17,7 +17,7 @@ Name: dali-adaptor Summary: The DALi Tizen Adaptor -Version: 1.5.16 +Version: 1.5.17 Release: 1 Group: System/Libraries License: Apache-2.0 and BSD-3-Clause and MIT -- 2.7.4 From 589ec1d7fa9d28ddd347b86bef3a730cecebc047 Mon Sep 17 00:00:00 2001 From: "huiyu.eun" Date: Mon, 25 Nov 2019 17:58:43 +0900 Subject: [PATCH 10/16] Add Component Application Structure Add Component Application Structure Change-Id: I6d37796b495db417f81d0cd14dd66818c0d69ba4 Signed-off-by: huiyu.eun --- build/tizen/deps-check.cmake | 7 ++ build/tizen/profiles/common-profile.cmake | 7 ++ build/tizen/profiles/ivi-profile.cmake | 7 ++ build/tizen/profiles/mobile-profile.cmake | 6 + build/tizen/profiles/tv-profile.cmake | 7 ++ build/tizen/profiles/wearable-profile.cmake | 7 ++ .../adaptor-framework/component-application.h | 127 +++++++++++++++++++++ dali/devel-api/file.list | 2 +- dali/internal/adaptor/common/framework.h | 13 ++- dali/internal/adaptor/file.list | 5 +- .../tizen-wayland/component-application-impl.cpp | 53 +++++++++ .../tizen-wayland/component-application-impl.h | 111 ++++++++++++++++++ .../tizen-wayland/component-application.cpp | 53 +++++++++ .../adaptor/tizen-wayland/framework-tizen.cpp | 121 ++++++++++++++++---- dali/public-api/file.list | 2 +- packaging/dali-adaptor.spec | 6 +- 16 files changed, 505 insertions(+), 29 deletions(-) create mode 100644 dali/devel-api/adaptor-framework/component-application.h create mode 100644 dali/internal/adaptor/tizen-wayland/component-application-impl.cpp create mode 100644 dali/internal/adaptor/tizen-wayland/component-application-impl.h create mode 100644 dali/internal/adaptor/tizen-wayland/component-application.cpp diff --git a/build/tizen/deps-check.cmake b/build/tizen/deps-check.cmake index b496dd9..ac5382a 100644 --- a/build/tizen/deps-check.cmake +++ b/build/tizen/deps-check.cmake @@ -89,6 +89,7 @@ CHECK_MODULE_AND_SET( CAPI_SYSTEM_INFO capi-system-info [] ) CHECK_MODULE_AND_SET( CAPI_SYSTEM_SENSOR capi-system-sensor capi_system_sensor_support ) CHECK_MODULE_AND_SET( CAPI_SYSTEM_SYSTEM_SETTINGS capi-system-system-settings [] ) CHECK_MODULE_AND_SET( CAPI_APPFW_APPLICATION capi-appfw-application [] ) +CHECK_MODULE_AND_SET( COMPONENT_BASED_CORE_BASE component-based-core-base [] ) CHECK_MODULE_AND_SET( ELEMENTARY elementary [] ) CHECK_MODULE_AND_SET( BUNDLE bundle [] ) @@ -211,6 +212,10 @@ ELSE() SET( cachePath /home/owner ) ENDIF() +IF( enable_appfw ) + ADD_DEFINITIONS( -DUSE_APPFW -DCOMPONENT_APPLICATION_SUPPORT) +ENDIF() + ####################################################### ADD_DEFINITIONS( -DDALI_PROFILE_${enable_profile}) @@ -330,6 +335,7 @@ IF( enable_appfw ) ${CAPI_APPFW_WIDGET_BASE_CFLAGS} ${ECORE_IMF_CFLAGS} ${FRIBIDI_CFLAGS} + ${COMPONENT_BASED_CORE_BASE_CFLAGS} ) SET( DALI_LDFLAGS ${DALI_LDFLAGS} @@ -344,6 +350,7 @@ IF( enable_appfw ) ${CAPI_APPFW_WIDGET_BASE_LDFLAGS} ${ECORE_IMF_LDFLAGS} ${FRIBIDI_LDFLAGS} + ${COMPONENT_BASED_CORE_BASE_LDFLAGS} ) ELSE() SET( DALI_CFLAGS ${DALI_CFLAGS} diff --git a/build/tizen/profiles/common-profile.cmake b/build/tizen/profiles/common-profile.cmake index 2c18ce0..bdc26ff 100644 --- a/build/tizen/profiles/common-profile.cmake +++ b/build/tizen/profiles/common-profile.cmake @@ -65,3 +65,10 @@ IF( ENABLE_TRACE ) ${adaptor_trace_tizen_src_files} ) ENDIF() + +IF( COMPONENT_APPLICATION_SUPPORT ) + SET( SOURCES ${SOURCES} + ${adaptor_adaptor_component_application_src_files} + ) +ENDIF() + diff --git a/build/tizen/profiles/ivi-profile.cmake b/build/tizen/profiles/ivi-profile.cmake index 765a1ea..77d540c 100644 --- a/build/tizen/profiles/ivi-profile.cmake +++ b/build/tizen/profiles/ivi-profile.cmake @@ -66,3 +66,10 @@ IF( ENABLE_TRACE ) ${adaptor_trace_tizen_src_files} ) ENDIF() + +IF( COMPONENT_APPLICATION_SUPPORT ) + SET( SOURCES ${SOURCES} + ${adaptor_adaptor_component_application_src_files} + ) +ENDIF() + diff --git a/build/tizen/profiles/mobile-profile.cmake b/build/tizen/profiles/mobile-profile.cmake index 38cc849..0ba3e35 100644 --- a/build/tizen/profiles/mobile-profile.cmake +++ b/build/tizen/profiles/mobile-profile.cmake @@ -66,3 +66,9 @@ IF( ENABLE_TRACE ) ) ENDIF() +IF( COMPONENT_APPLICATION_SUPPORT ) + SET( SOURCES ${SOURCES} + ${adaptor_adaptor_component_application_src_files} + ) +ENDIF() + diff --git a/build/tizen/profiles/tv-profile.cmake b/build/tizen/profiles/tv-profile.cmake index fbaa533..ff4b008 100644 --- a/build/tizen/profiles/tv-profile.cmake +++ b/build/tizen/profiles/tv-profile.cmake @@ -65,3 +65,10 @@ IF( ENABLE_TRACE ) ${adaptor_trace_tizen_src_files} ) ENDIF() + +IF( COMPONENT_APPLICATION_SUPPORT ) + SET( SOURCES ${SOURCES} + ${adaptor_adaptor_component_application_src_files} + ) +ENDIF() + diff --git a/build/tizen/profiles/wearable-profile.cmake b/build/tizen/profiles/wearable-profile.cmake index 3682664..7d5b1b4 100644 --- a/build/tizen/profiles/wearable-profile.cmake +++ b/build/tizen/profiles/wearable-profile.cmake @@ -67,3 +67,10 @@ IF( ENABLE_TRACE ) ${adaptor_trace_tizen_src_files} ) ENDIF() + +IF( COMPONENT_APPLICATION_SUPPORT ) + SET( SOURCES ${SOURCES} + ${adaptor_adaptor_component_application_src_files} + ) +ENDIF() + diff --git a/dali/devel-api/adaptor-framework/component-application.h b/dali/devel-api/adaptor-framework/component-application.h new file mode 100644 index 0000000..1f23b2f --- /dev/null +++ b/dali/devel-api/adaptor-framework/component-application.h @@ -0,0 +1,127 @@ +#ifndef DALI_COMPONENT_APPLICATION_H +#define DALI_COMPONENT_APPLICATION_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. + * + */ + +// INTERNAL INCLUDES +#include + +namespace Dali +{ +namespace Internal DALI_INTERNAL +{ + +namespace Adaptor +{ +class ComponentApplication; +} + +} + +/** + * @brief An ComponentApplication class object should be created by every component-based application + * that wishes to use Dali. + * + * Component application draw multiple UI applications based on frame components. + * component application can draw multiple UIs in one process. + * + * It provides a means for initializing the + * resources required by the Dali::Core. + * + * The ComponentApplication class emits several signals which the user can + * connect to. The user should not create any Dali objects in the main + * function and instead should connect to the Init signal of the + * ComponentApplication and create the Dali Widget object in the connected callback. + * + */ +class DALI_ADAPTOR_API ComponentApplication : public Application +{ +public: + typedef Signal< Any () > CreateSignalType; + +public: + /** + * @brief This is the constructor for component applications without an argument list. + * @return A handle to the ComponentApplication + */ + static ComponentApplication New( ); + + /** + * @brief This is the constructor for component applications. + * + * @param[in,out] argc A pointer to the number of arguments + * @param[in,out] argv A pointer to the argument list + * @return A handle to the ComponentApplication + */ + static ComponentApplication New( int* argc, char **argv[] ); + + /** + * @brief This is the constructor for component applications with a stylesheet + * + * @param[in,out] argc A pointer to the number of arguments + * @param[in,out] argv A pointer to the argument list + * @param[in] stylesheet The path to user defined theme file + * @return A handle to the ComponentApplication + */ + static ComponentApplication New( int* argc, char **argv[], const std::string& stylesheet ); + + /** + * @brief The default constructor. + */ + ComponentApplication() = default; + + /** + * @brief Copy Constructor. + * + * @param[in] componentApplication Handle to an object + */ + ComponentApplication( const ComponentApplication& componentApplication ) = default; + + /** + * @brief Assignment operator. + * + * @param[in] componentApplication Handle to an object + * @return A reference to this + */ + ComponentApplication& operator=( const ComponentApplication& componentApplication ) = default; + + /** + * @brief Destructor + */ + ~ComponentApplication() = default; + + /** + * @brief The user should connect to this signal to determine when they should initialize + * their application. + * The callback function is called before the main loop of the application starts. + * @return The signal to connect to + */ + CreateSignalType& CreateSignal(); + +public: + /// @cond internal + /** + * @brief Internal constructor. + */ + explicit DALI_INTERNAL ComponentApplication(Internal::Adaptor::ComponentApplication* componentApplication); + /// @endcond +}; +} // namespace Dali + +#endif // DALI_COMPONENT_APPLICATION_H + diff --git a/dali/devel-api/file.list b/dali/devel-api/file.list index 33c3ab3..b7e8f1f 100755 --- a/dali/devel-api/file.list +++ b/dali/devel-api/file.list @@ -84,6 +84,7 @@ SET( devel_api_adaptor_framework_header_files ${adaptor_devel_api_dir}/adaptor-framework/key-devel.h ${adaptor_devel_api_dir}/adaptor-framework/thread-settings.h ${adaptor_devel_api_dir}/adaptor-framework/window-devel.h + ${adaptor_devel_api_dir}/adaptor-framework/component-application.h ) @@ -117,4 +118,3 @@ SET( text_abstraction_header_files ${adaptor_devel_api_dir}/text-abstraction/text-renderer.h ${adaptor_devel_api_dir}/text-abstraction/text-renderer-layout-helper.h ) - diff --git a/dali/internal/adaptor/common/framework.h b/dali/internal/adaptor/common/framework.h index d95388c..e4b172b 100644 --- a/dali/internal/adaptor/common/framework.h +++ b/dali/internal/adaptor/common/framework.h @@ -28,6 +28,9 @@ // INTERNAL INCLUDES #include #include +#ifdef COMPONENT_APPLICATION_SUPPORT +#include +#endif namespace Dali { @@ -54,7 +57,8 @@ public: { NORMAL, ///< normal appFramework WATCH, ///< watch appFramework - WIDGET ///< widget appFramework + WIDGET, ///< widget appFramework + COMPONENT ///< component appFramework }; /** @@ -141,6 +145,13 @@ public: * Invoked when the platform surface is destroyed. */ virtual void OnSurfaceDestroyed( Any newSurface ) {} + +#ifdef COMPONENT_APPLICATION_SUPPORT + /** + * Invoked when the component application is created. + */ + virtual Any OnCreate() { return nullptr; } +#endif }; public: diff --git a/dali/internal/adaptor/file.list b/dali/internal/adaptor/file.list index defd518..cf5b02c 100644 --- a/dali/internal/adaptor/file.list +++ b/dali/internal/adaptor/file.list @@ -48,4 +48,7 @@ SET( adaptor_adaptor_windows_src_files ${adaptor_adaptor_dir}/windows/framework-win.cpp ) - +SET( adaptor_adaptor_component_application_src_files + ${adaptor_adaptor_dir}/tizen-wayland/component-application.cpp + ${adaptor_adaptor_dir}/tizen-wayland/component-application-impl.cpp +) diff --git a/dali/internal/adaptor/tizen-wayland/component-application-impl.cpp b/dali/internal/adaptor/tizen-wayland/component-application-impl.cpp new file mode 100644 index 0000000..bf3855c --- /dev/null +++ b/dali/internal/adaptor/tizen-wayland/component-application-impl.cpp @@ -0,0 +1,53 @@ +/* + * 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 + +namespace Dali +{ + +namespace Internal +{ + +namespace Adaptor +{ +ComponentApplicationPtr ComponentApplication::New( + int* argc, + char **argv[], + const std::string& stylesheet, + Dali::Application::WINDOW_MODE windowMode) +{ + ComponentApplicationPtr application ( new ComponentApplication (argc, argv, stylesheet, windowMode ) ); + return application; +} + +ComponentApplication::ComponentApplication( int* argc, char** argv[], const std::string& stylesheet, Dali::Application::WINDOW_MODE windowMode ) +: Application(argc, argv, stylesheet, windowMode, PositionSize(), Framework::COMPONENT) +{ +} + +Any ComponentApplication::OnCreate() +{ + return mCreateSignal.Emit(); +} + +} // namespace Adaptor + +} // namespace Internal + +} // namespace Dali diff --git a/dali/internal/adaptor/tizen-wayland/component-application-impl.h b/dali/internal/adaptor/tizen-wayland/component-application-impl.h new file mode 100644 index 0000000..cd7e6c2 --- /dev/null +++ b/dali/internal/adaptor/tizen-wayland/component-application-impl.h @@ -0,0 +1,111 @@ +#ifndef DALI_INTERNAL_COMPONENT_APPLICATION_H +#define DALI_INTERNAL_COMPONENT_APPLICATION_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. + * + */ + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ +class Adaptor; + +namespace Internal +{ + +namespace Adaptor +{ + +class ComponentApplication; +typedef IntrusivePtr ComponentApplicationPtr; + +/** + * Implementation of the ComponentApplication class. + */ +class ComponentApplication : public Application +{ +public: + typedef Dali::ComponentApplication::CreateSignalType CreateSignal; + +public: + /** + * Create a new component application + * @param[in] argc A pointer to the number of arguments + * @param[in] argv A pointer to the argument list + * @param[in] stylesheet The path to user defined theme file + * @param[in] windowMode A member of WINDOW_MODE + * @return A handle to the ComponentApplication + */ + static ComponentApplicationPtr New( int* argc, char **argv[], const std::string& stylesheet, WINDOW_MODE windowMode ); + + /** + * @brief The default constructor. + */ + ComponentApplication( int* argc, char **argv[], const std::string& stylesheet, WINDOW_MODE windowMode ); + + /** + * @brief Undefined copy constructor. + */ + ComponentApplication( const ComponentApplication& ) = default; + + /** + * @brief Destructor + */ + virtual ~ComponentApplication() = default; + + /** + *@brief Undefined assignment operator. + */ + ComponentApplication& operator=( const ComponentApplication& ) = delete; + +public: // From Framework::Observer + /** + * Called when the framework is Component Application Created. + */ + virtual Any OnCreate(); + +public: + CreateSignal mCreateSignal; +}; + +inline ComponentApplication& GetImplementation(Dali::ComponentApplication& application) +{ + DALI_ASSERT_ALWAYS(application && "application handle is empty"); + + BaseObject& handle = application.GetBaseObject(); + + return static_cast(handle); +} + +inline const ComponentApplication& GetImplementation(const Dali::ComponentApplication& application) +{ + DALI_ASSERT_ALWAYS(application && "application handle is empty"); + + const BaseObject& handle = application.GetBaseObject(); + + return static_cast(handle); +} + + +} // namespace Adaptor + +} // namespace Internal + +} // namespace Dali +#endif diff --git a/dali/internal/adaptor/tizen-wayland/component-application.cpp b/dali/internal/adaptor/tizen-wayland/component-application.cpp new file mode 100644 index 0000000..c1e0761 --- /dev/null +++ b/dali/internal/adaptor/tizen-wayland/component-application.cpp @@ -0,0 +1,53 @@ +/* + * 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 + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +ComponentApplication ComponentApplication::New() +{ + return New( NULL, NULL ); +} + +ComponentApplication ComponentApplication::New( int* argc, char **argv[] ) +{ + return New( argc, argv, "" ); +} + +ComponentApplication ComponentApplication::New( int* argc, char **argv[], const std::string& stylesheet ) +{ + Internal::Adaptor::ComponentApplicationPtr internal = Internal::Adaptor::ComponentApplication::New( argc, argv, stylesheet, TRANSPARENT ); + return ComponentApplication(internal.Get()); +} + +ComponentApplication::CreateSignalType& ComponentApplication::CreateSignal() +{ + return Internal::Adaptor::GetImplementation(*this).mCreateSignal; +} + +ComponentApplication::ComponentApplication(Internal::Adaptor::ComponentApplication* implementation) +: Application(implementation) +{ +} + +} // namespace Dali diff --git a/dali/internal/adaptor/tizen-wayland/framework-tizen.cpp b/dali/internal/adaptor/tizen-wayland/framework-tizen.cpp index 1a05da1..d4236cf 100644 --- a/dali/internal/adaptor/tizen-wayland/framework-tizen.cpp +++ b/dali/internal/adaptor/tizen-wayland/framework-tizen.cpp @@ -41,6 +41,10 @@ #include #endif // TIZEN_PLATFORM_CONFIG_SUPPORTED +#ifdef COMPONENT_APPLICATION_SUPPORT +#include +#endif + #include // INTERNAL INCLUDES @@ -222,35 +226,60 @@ struct Framework::Impl int AppMain() { int ret; - - if (mApplicationType == NORMAL) - { - ret = AppNormalMain(); - } - else if(mApplicationType == WIDGET) + switch ( mApplicationType ) { - ret = AppWidgetMain(); - } - else - { - ret = AppWatchMain(); + case NORMAL: + { + ret = AppNormalMain(); + break; + } + case WIDGET: + { + ret = AppWidgetMain(); + break; + } + case WATCH: + { + ret = AppWatchMain(); + break; + } +#ifdef COMPONENT_APPLICATION_SUPPORT + case COMPONENT: + { + ret = AppComponentMain(); + break; + } +#endif } return ret; } void AppExit() { - if (mApplicationType == NORMAL) - { - AppNormalExit(); - } - else if(mApplicationType == WIDGET) + switch ( mApplicationType ) { - AppWidgetExit(); - } - else - { - AppWatchExit(); + case NORMAL: + { + AppNormalExit(); + break; + } + case WIDGET: + { + AppWidgetExit(); + break; + } + case WATCH: + { + AppWatchExit(); + break; + } +#ifdef COMPONENT_APPLICATION_SUPPORT + case COMPONENT: + { + AppComponentExit(); + break; + } +#endif } } @@ -697,6 +726,56 @@ struct Framework::Impl #endif } +#ifdef COMPONENT_APPLICATION_SUPPORT + int AppComponentMain() + { + int ret; + + /*Crate component_based_app_base_lifecycle_callback*/ + component_based_app_base_lifecycle_callback_s callback; + callback.init = AppInit; + callback.run = AppRun; + callback.exit = AppExit; + callback.create = ComponentAppCreate; + callback.terminate = ComponentAppTerminate; + callback.fini = ComponentAppFinish; + + return component_based_app_base_main(*mFramework->mArgc, *mFramework->mArgv, &callback, mFramework);; + } + + static void* ComponentAppCreate( void *data ) + { + Framework* framework = static_cast(data); + Observer *observer = &framework->mObserver; + observer->OnInit(); + + return Dali::AnyCast( observer->OnCreate() ); + } + + static void ComponentAppTerminate( void *data ) + { + Observer *observer = &static_cast(data)->mObserver; + observer->OnTerminate(); + } + + static void ComponentAppFinish( void *data ) + { + ecore_shutdown(); + + if(getenv("AUL_LOADER_INIT")) + { + setenv("AUL_LOADER_INIT", "0", 1); + ecore_shutdown(); + } + } + + void AppComponentExit() + { + component_based_app_base_exit(); + } + +#endif + private: // Undefined Impl( const Impl& impl ); diff --git a/dali/public-api/file.list b/dali/public-api/file.list index 71866f1..e4d3ac3 100644 --- a/dali/public-api/file.list +++ b/dali/public-api/file.list @@ -54,4 +54,4 @@ SET( adaptor_dali_wearable_header_file SET( public_dali_watch_header_files ${adaptor_public_api_dir}/watch/watch-application.h ${adaptor_public_api_dir}/watch/watch-time.h -) \ No newline at end of file +) diff --git a/packaging/dali-adaptor.spec b/packaging/dali-adaptor.spec index 6523580..0e7a469 100644 --- a/packaging/dali-adaptor.spec +++ b/packaging/dali-adaptor.spec @@ -103,6 +103,7 @@ BuildRequires: pkgconfig(capi-system-system-settings) # for feedback plugin BuildRequires: pkgconfig(mm-sound) BuildRequires: pkgconfig(feedback) +BuildRequires: pkgconfig(component-based-core-base) # for multiprofile Requires: %{name}-compat = %{version}-%{release} @@ -277,10 +278,6 @@ cmake_flags+=" -DCMAKE_BUILD_TYPE=Debug" cmake_flags+=" -DENABLE_TRACE=ON" %endif -%if 0%{?enable_appfw} -cmake_flags+=" -DUSE_APPFW" -%endif - libtoolize --force cd %{_builddir}/%{name}-%{version}/build/tizen @@ -300,6 +297,7 @@ cmake_flags+=" -DCMAKE_INSTALL_INCLUDEDIR=%{_includedir}" cmake_flags+=" -DENABLE_TIZEN_MAJOR_VERSION=%{tizen_version_major}" cmake_flags+=" -DENABLE_FEEDBACK=YES" cmake_flags+=" -DENABLE_APPFW=YES" +cmake_flags+=" -DCOMPONENT_APPLICATION_SUPPORT=YES" # Set up the build via Cmake ####################################################################### -- 2.7.4 From f5b4a7d0dcf0f95ea57931d7f891842e8c238c88 Mon Sep 17 00:00:00 2001 From: "Seungho, Baek" Date: Thu, 25 Jun 2020 11:22:36 +0900 Subject: [PATCH 11/16] Change target share directory from dali to dali-legacy Change-Id: Ie8ec3ef95b572487347c25d5cd80f078ab756509 Signed-off-by: Seungho, Baek --- build/tizen/deps-check.cmake | 4 ++-- packaging/dali-adaptor.spec | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/tizen/deps-check.cmake b/build/tizen/deps-check.cmake index ac5382a..f22ceef 100644 --- a/build/tizen/deps-check.cmake +++ b/build/tizen/deps-check.cmake @@ -185,13 +185,13 @@ ENDIF() IF( DEFINED ENV{DALI_DATA_RW_DIR} ) SET( dataReadWriteDir $ENV{DALI_DATA_RW_DIR} ) ELSE() - SET( dataReadWriteDir ${CMAKE_INSTALL_PREFIX}/share/dali/ ) + SET( dataReadWriteDir ${CMAKE_INSTALL_PREFIX}/share/dali-legacy/ ) ENDIF() IF( DEFINED ENV{DALI_DATA_RO_DIR} ) SET( dataReadOnlyDir $ENV{DALI_DATA_RO_DIR} ) ELSE() - SET( dataReadOnlyDir ${CMAKE_INSTALL_PREFIX}/share/dali/ ) + SET( dataReadOnlyDir ${CMAKE_INSTALL_PREFIX}/share/dali-legacy/ ) ENDIF() IF( DEFINED ENV{TIZEN_PLATFORM_CONFIG_SUPPORTED} ) diff --git a/packaging/dali-adaptor.spec b/packaging/dali-adaptor.spec index 0e7a469..ddc0189 100644 --- a/packaging/dali-adaptor.spec +++ b/packaging/dali-adaptor.spec @@ -234,8 +234,8 @@ Feedback plugin to play haptic and audio feedback for Dali #Use TZ_PATH when tizen version is 3.x or greater -%define dali_data_rw_dir %TZ_SYS_RO_SHARE/dali/ -%define dali_data_ro_dir %TZ_SYS_RO_SHARE/dali/ +%define dali_data_rw_dir %TZ_SYS_RO_SHARE/dali-legacy/ +%define dali_data_ro_dir %TZ_SYS_RO_SHARE/dali-legacy/ %define font_preloaded_path %TZ_SYS_RO_SHARE/fonts/ %define font_downloaded_path %TZ_SYS_SHARE/fonts/ %define font_application_path %TZ_SYS_RO_SHARE/app_fonts/ -- 2.7.4 From bcc548aaa80f4401d414d9cde92550b57a8c569b Mon Sep 17 00:00:00 2001 From: "Seungho, Baek" Date: Wed, 10 Jun 2020 16:04:07 +0900 Subject: [PATCH 12/16] Support WebP format - Make animated-image-loading interface for gif and webp. - Animated WebP requires WEBP_DEMUX_ABI_VERSION 0x0107 or later Change-Id: I5331163e2b0d68a6ef7cb5a06d6e59a5140ffca9 Signed-off-by: Seungho, Baek --- .../src/dali-adaptor/utc-Dali-GifLoading.cpp | 60 +++-- build/tizen/CMakeLists.txt | 8 +- .../adaptor-framework/animated-image-loading.cpp | 91 +++++++ .../adaptor-framework/animated-image-loading.h | 150 +++++++++++ dali/devel-api/file.list | 4 +- .../imaging/common/animated-image-loading-impl.h | 118 ++++++++ .../imaging/common}/gif-loading.cpp | 45 ++-- .../imaging/common}/gif-loading.h | 60 ++--- dali/internal/imaging/common/webp-loading.cpp | 297 +++++++++++++++++++++ dali/internal/imaging/common/webp-loading.h | 121 +++++++++ dali/internal/imaging/file.list | 2 + packaging/dali-adaptor.spec | 4 + 12 files changed, 871 insertions(+), 89 deletions(-) create mode 100644 dali/devel-api/adaptor-framework/animated-image-loading.cpp create mode 100644 dali/devel-api/adaptor-framework/animated-image-loading.h create mode 100644 dali/internal/imaging/common/animated-image-loading-impl.h rename dali/{devel-api/adaptor-framework => internal/imaging/common}/gif-loading.cpp (97%) mode change 100755 => 100644 rename dali/{devel-api/adaptor-framework => internal/imaging/common}/gif-loading.h (62%) mode change 100755 => 100644 create mode 100644 dali/internal/imaging/common/webp-loading.cpp create mode 100644 dali/internal/imaging/common/webp-loading.h diff --git a/automated-tests/src/dali-adaptor/utc-Dali-GifLoading.cpp b/automated-tests/src/dali-adaptor/utc-Dali-GifLoading.cpp index 6a4fa87..b87ce8e 100755 --- a/automated-tests/src/dali-adaptor/utc-Dali-GifLoading.cpp +++ b/automated-tests/src/dali-adaptor/utc-Dali-GifLoading.cpp @@ -18,7 +18,7 @@ #include #include #include -#include +#include using namespace Dali; @@ -50,38 +50,57 @@ void VerifyLoad( std::vector& pixelDataList, Dali::Vector pixelDataList; Dali::Vector frameDelayList; - std::unique_ptr gifLoading = GifLoading::New( gGif_100_None, true ); - bool succeed = gifLoading->LoadAllFrames( pixelDataList, frameDelayList ); + Dali::AnimatedImageLoading animatedImageLoading = Dali::AnimatedImageLoading::New( gGif_100_None, true ); + bool succeed = animatedImageLoading.LoadNextNFrames( 0u, animatedImageLoading.GetImageCount(), pixelDataList ); + frameDelayList.Clear(); + frameDelayList.Resize( animatedImageLoading.GetImageCount(), 0 ); + for( uint32_t i = 0; i < animatedImageLoading.GetImageCount(); ++i ) + { + frameDelayList[i] = animatedImageLoading.GetFrameInterval( i ); + } // Check that the loading succeed DALI_TEST_CHECK( succeed ); VerifyLoad( pixelDataList, frameDelayList, 5u, 100u, 100u, 1000u ); pixelDataList.clear(); - gifLoading = GifLoading::New( gGif_100_Prev, true ); - succeed = gifLoading->LoadAllFrames( pixelDataList, frameDelayList ); + animatedImageLoading = Dali::AnimatedImageLoading::New( gGif_100_Prev, true ); + succeed = animatedImageLoading.LoadNextNFrames( 0u, animatedImageLoading.GetImageCount(), pixelDataList ); + frameDelayList.Clear(); + frameDelayList.Resize( animatedImageLoading.GetImageCount(), 0 ); + for( uint32_t i = 0; i < animatedImageLoading.GetImageCount(); ++i ) + { + frameDelayList[i] = animatedImageLoading.GetFrameInterval( i ); + } + // Check that the loading succeed DALI_TEST_CHECK( succeed ); VerifyLoad( pixelDataList, frameDelayList, 5u, 100u, 100u, 1000u ); pixelDataList.clear(); - gifLoading = GifLoading::New( gGif_100_Bgnd, true ); - succeed = gifLoading->LoadAllFrames( pixelDataList, frameDelayList ); + animatedImageLoading = Dali::AnimatedImageLoading::New( gGif_100_Bgnd, true ); + succeed = animatedImageLoading.LoadNextNFrames( 0u, animatedImageLoading.GetImageCount(), pixelDataList ); + frameDelayList.Clear(); + frameDelayList.Resize( animatedImageLoading.GetImageCount(), 0 ); + for( uint32_t i = 0; i < animatedImageLoading.GetImageCount(); ++i ) + { + frameDelayList[i] = animatedImageLoading.GetFrameInterval( i ); + } // Check that the loading succeed DALI_TEST_CHECK( succeed ); @@ -90,28 +109,27 @@ int UtcDaliGifLoadingP(void) END_TEST; } -int UtcDaliGifLoadingN(void) +int UtcDaliAnimatedImageLoadingN(void) { std::vector pixelDataList; Dali::Vector frameDelayList; - std::unique_ptr gifLoading = GifLoading::New( gGifNonExist, true ); - bool succeed = gifLoading->LoadAllFrames( pixelDataList, frameDelayList ); + Dali::AnimatedImageLoading animatedImageLoading = Dali::AnimatedImageLoading::New( gGifNonExist, true ); + bool succeed = animatedImageLoading.LoadNextNFrames( 0u, animatedImageLoading.GetImageCount(), pixelDataList ); // Check that the loading failed DALI_TEST_CHECK( !succeed ); // Check that both pixelDataList and frameDelayList are empty DALI_TEST_EQUALS( pixelDataList.size(), 0u, TEST_LOCATION ); - DALI_TEST_EQUALS( frameDelayList.Size(), 0u, TEST_LOCATION ); END_TEST; } -int UtcDaliGifLoadingGetImageSizeP(void) +int UtcDaliAnimatedImageLoadingGetImageSizeP(void) { - std::unique_ptr gifLoading = GifLoading::New( gGif_100_None, true ); - ImageDimensions imageSize = gifLoading->GetImageSize(); + Dali::AnimatedImageLoading animatedImageLoading = Dali::AnimatedImageLoading::New( gGif_100_None, true ); + ImageDimensions imageSize = animatedImageLoading.GetImageSize(); // Check that the image size is [100, 100] DALI_TEST_EQUALS( imageSize.GetWidth(), 100u, TEST_LOCATION ); @@ -120,12 +138,12 @@ int UtcDaliGifLoadingGetImageSizeP(void) END_TEST; } -int UtcDaliGifLoadingGetImageSizeN(void) +int UtcDaliAnimatedImageLoadingGetImageSizeN(void) { - std::unique_ptr gifLoading = GifLoading::New( gGifNonExist, true ); - ImageDimensions imageSize = gifLoading->GetImageSize(); + Dali::AnimatedImageLoading animatedImageLoading = Dali::AnimatedImageLoading::New( gGifNonExist, true ); + ImageDimensions imageSize = animatedImageLoading.GetImageSize(); - // Check that it returns zero size when the gif is not valid + // Check that it returns zero size when the animated image is not valid DALI_TEST_EQUALS( imageSize.GetWidth(), 0u, TEST_LOCATION ); DALI_TEST_EQUALS( imageSize.GetHeight(), 0u, TEST_LOCATION ); diff --git a/build/tizen/CMakeLists.txt b/build/tizen/CMakeLists.txt index 7c56a82..a83d807 100644 --- a/build/tizen/CMakeLists.txt +++ b/build/tizen/CMakeLists.txt @@ -176,11 +176,13 @@ IF( UNIX ) ENDIF() ENDIF() +SET( REQUIRED_LIBS ${REQUIRED_LIBS} webp webpdemux ) + TARGET_LINK_LIBRARIES( ${name} ${DALI_LDFLAGS} - ${REQUIRED_LIBS} - ${OPTIONAL_LIBS} - ${COVERAGE} + ${REQUIRED_LIBS} + ${OPTIONAL_LIBS} + ${COVERAGE} ) SET_TARGET_PROPERTIES( ${name} diff --git a/dali/devel-api/adaptor-framework/animated-image-loading.cpp b/dali/devel-api/adaptor-framework/animated-image-loading.cpp new file mode 100644 index 0000000..f2a9afa --- /dev/null +++ b/dali/devel-api/adaptor-framework/animated-image-loading.cpp @@ -0,0 +1,91 @@ +/* + * 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 + +// INTERNAL HEADER +#include +#include +#include + +namespace Dali +{ + +AnimatedImageLoading::AnimatedImageLoading() +{ +} + +AnimatedImageLoading AnimatedImageLoading::New( const std::string& url, bool isLocalResource ) +{ + + const std::size_t urlSize = url.length(); + + Internal::Adaptor::AnimatedImageLoadingPtr internal = NULL; + if(urlSize >= 4){ // Avoid throwing out_of_range or failing silently if exceptions are turned-off on the compare(). (http://www.cplusplus.com/reference/string/string/compare/) + if( !url.compare( urlSize - 4, 4, ".gif" ) + || !url.compare( urlSize - 4, 4, ".GIF" ) ) + { + internal = Internal::Adaptor::GifLoading::New( url, isLocalResource ); + } + } + if(urlSize >= 5){ // Avoid throwing out_of_range or failing silently if exceptions are turned-off on the compare(). (http://www.cplusplus.com/reference/string/string/compare/) + if( !url.compare( urlSize - 5, 5, ".webp" ) + || !url.compare( urlSize - 5, 5, ".WEBP" ) ) + { + internal = Internal::Adaptor::WebPLoading::New( url, isLocalResource ); + } + } + + return AnimatedImageLoading( internal.Get() ); +} + +AnimatedImageLoading AnimatedImageLoading::DownCast( BaseHandle handle ) +{ + return AnimatedImageLoading( dynamic_cast< Internal::Adaptor::AnimatedImageLoading* >( handle.GetObjectPtr() ) ); +} + +AnimatedImageLoading::~AnimatedImageLoading() +{ +} + +bool AnimatedImageLoading::LoadNextNFrames( uint32_t frameStartIndex, int count, std::vector& pixelData ) +{ + return GetImplementation( *this ).LoadNextNFrames( frameStartIndex, count, pixelData ); +} + +ImageDimensions AnimatedImageLoading::GetImageSize() const +{ + return GetImplementation( *this ).GetImageSize(); +} + +uint32_t AnimatedImageLoading::GetImageCount() const +{ + return GetImplementation( *this ).GetImageCount(); +} + +uint32_t AnimatedImageLoading::GetFrameInterval( uint32_t frameIndex ) const +{ + return GetImplementation( *this ).GetFrameInterval( frameIndex ); +} + +AnimatedImageLoading::AnimatedImageLoading( Internal::Adaptor::AnimatedImageLoading* internal ) +: BaseHandle( internal ) +{ +} + +} // namespace Dali diff --git a/dali/devel-api/adaptor-framework/animated-image-loading.h b/dali/devel-api/adaptor-framework/animated-image-loading.h new file mode 100644 index 0000000..7c0a69b --- /dev/null +++ b/dali/devel-api/adaptor-framework/animated-image-loading.h @@ -0,0 +1,150 @@ +#ifndef DALI_ANIMATED_IMAGE_LOADING_H +#define DALI_ANIMATED_IMAGE_LOADING_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 + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +class PixelData; +typedef Dali::Uint16Pair ImageDimensions; + +/** + * @addtogroup dali_adaptor_framework + * @{ + */ + +namespace Internal DALI_INTERNAL +{ +namespace Adaptor +{ +class AnimatedImageLoading; +} +} + +/** + * Class to manage loading frames of an animated image in small chunks. Lazy initializes only when + * data is actually needed. + * Note, once the Animated Image has loaded, the undecoded data will reside in memory until this object + * is released. (This is to speed up frame loads, which would otherwise have to re-acquire the + * data from disk) + */ +class DALI_ADAPTOR_API AnimatedImageLoading : public BaseHandle +{ +public: + + /** + * Create a GifLoading with the given url and resourceType. + * @param[in] url The url of the animated image to load + * @param[in] isLocalResource The true or false whether this is a local resource. + * @return A newly created GifLoading. + */ + static AnimatedImageLoading New( const std::string& url, bool isLocalResource ); + + /** + * @brief Constructor + */ + AnimatedImageLoading(); + + /** + * @brief Downcast an Object handle to Capture handle. + * + * If handle points to a Capture object the downcast produces valid + * handle. If not the returned handle is left uninitialized. + * + * @param[in] handle to An object. + * @return handle to a Capture object or an uninitialized handle. + */ + static AnimatedImageLoading DownCast( BaseHandle handle ); + + + /** + * @brief Copy constructor. + * + * @param[in] copy The AnimatedImageLoading to copy + */ + AnimatedImageLoading(const AnimatedImageLoading& copy) = default; + + /** + * @brief Assignment operator + * + * @param[in] rhs The AnimatedImageLoading to copy + * @return A reference to this + */ + AnimatedImageLoading& operator=(const AnimatedImageLoading& rhs) = default; + + /** + * @brief Destructor + */ + ~AnimatedImageLoading(); + + /** + * @brief Load the next N Frames of the animated image. + * + * @note This function will load the entire animated image into memory if not already loaded. + * @param[in] frameStartIndex The frame counter to start from. Will usually be the next frame + * after the previous invocation of this method, or 0 to start. + * @param[in] count The number of frames to load + * @param[out] pixelData The vector in which to return the frame data + * @return True if the frame data was successfully loaded + */ + bool LoadNextNFrames( uint32_t frameStartIndex, int count, std::vector& pixelData ); + + /** + * @brief Get the size of a animated image. + * + * @return The width and height in pixels of the animated image. + */ + ImageDimensions GetImageSize() const; + + /** + * @brief Get the number of frames in this animated image. + */ + uint32_t GetImageCount() const; + + /** + * @brief Get the frame interval of the frame index + * + * @note The frame is needed to be loaded before this function is called. + * + * @return The time interval of the frame(microsecond). + */ + uint32_t GetFrameInterval( uint32_t frameIndex ) const; + +public: // Not intended for application developers + /// @cond internal + /** + * @brief This constructor is used by New() methods. + * + * @param[in] internal A pointer to a newly allocated Dali resource. + */ + explicit DALI_INTERNAL AnimatedImageLoading( Internal::Adaptor::AnimatedImageLoading* internal ); + /// @endcond +}; + +} // namespace Dali + +#endif // DALI_ANIMATED_IMAGE_LOADING_H diff --git a/dali/devel-api/file.list b/dali/devel-api/file.list index b7e8f1f..789939d 100755 --- a/dali/devel-api/file.list +++ b/dali/devel-api/file.list @@ -2,6 +2,7 @@ SET( devel_api_src_files ${adaptor_devel_api_dir}/adaptor-framework/accessibility-adaptor.cpp + ${adaptor_devel_api_dir}/adaptor-framework/animated-image-loading.cpp ${adaptor_devel_api_dir}/adaptor-framework/application-devel.cpp ${adaptor_devel_api_dir}/adaptor-framework/bitmap-saver.cpp ${adaptor_devel_api_dir}/adaptor-framework/clipboard.cpp @@ -14,7 +15,6 @@ SET( devel_api_src_files ${adaptor_devel_api_dir}/adaptor-framework/file-loader.cpp ${adaptor_devel_api_dir}/adaptor-framework/file-stream.cpp ${adaptor_devel_api_dir}/adaptor-framework/image-loading.cpp - ${adaptor_devel_api_dir}/adaptor-framework/gif-loading.cpp ${adaptor_devel_api_dir}/adaptor-framework/input-method-context.cpp ${adaptor_devel_api_dir}/adaptor-framework/input-method-options.cpp ${adaptor_devel_api_dir}/adaptor-framework/native-image-source-devel.cpp @@ -42,6 +42,7 @@ SET( devel_api_adaptor_framework_header_files ${adaptor_devel_api_dir}/adaptor-framework/accessibility-action-handler.h ${adaptor_devel_api_dir}/adaptor-framework/accessibility-gesture-handler.h ${adaptor_devel_api_dir}/adaptor-framework/accessibility-gesture-event.h + ${adaptor_devel_api_dir}/adaptor-framework/animated-image-loading.h ${adaptor_devel_api_dir}/adaptor-framework/application-devel.h ${adaptor_devel_api_dir}/adaptor-framework/atspi-accessibility.h ${adaptor_devel_api_dir}/adaptor-framework/bitmap-saver.h @@ -59,7 +60,6 @@ SET( devel_api_adaptor_framework_header_files ${adaptor_devel_api_dir}/adaptor-framework/image-loader-input.h ${adaptor_devel_api_dir}/adaptor-framework/image-loader-plugin.h ${adaptor_devel_api_dir}/adaptor-framework/image-loading.h - ${adaptor_devel_api_dir}/adaptor-framework/gif-loading.h ${adaptor_devel_api_dir}/adaptor-framework/input-method-context.h ${adaptor_devel_api_dir}/adaptor-framework/input-method-options.h ${adaptor_devel_api_dir}/adaptor-framework/keyboard.h diff --git a/dali/internal/imaging/common/animated-image-loading-impl.h b/dali/internal/imaging/common/animated-image-loading-impl.h new file mode 100644 index 0000000..759eb09 --- /dev/null +++ b/dali/internal/imaging/common/animated-image-loading-impl.h @@ -0,0 +1,118 @@ +#ifndef DALI_INTERNAL_ANIMATED_IMAGE_LOADING_IMPL_H +#define DALI_INTERNAL_ANIMATED_IMAGE_LOADING_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 +#include +#include + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ +class PixelData; +typedef Dali::Uint16Pair ImageDimensions; + +namespace Internal +{ + +namespace Adaptor +{ + +class AnimatedImageLoading; +typedef IntrusivePtr AnimatedImageLoadingPtr; + +/** + * Class interface for animated image loading. + * Each loading classes for animated image file format(e.g., gif and webp) needs to inherit this interface + */ +class AnimatedImageLoading : public BaseObject +{ +public: + + /** + * @copydoc Dali::AnimatedImageLoading::New() + */ + static AnimatedImageLoadingPtr New( const std::string& url, bool isLocalResource ); + + AnimatedImageLoading() = default; + + // Moveable but not copyable + AnimatedImageLoading( const AnimatedImageLoading& ); + AnimatedImageLoading& operator=( const AnimatedImageLoading& ); + AnimatedImageLoading( AnimatedImageLoading&& ) = default; + AnimatedImageLoading& operator=( AnimatedImageLoading&& ) = default; + + /** + * @brief Destructor + */ + virtual ~AnimatedImageLoading() = default; + + /** + * @copydoc Dali::AnimatedImageLoading::LoadNextNFrames() + */ + virtual bool LoadNextNFrames( uint32_t frameStartIndex, int count, std::vector& pixelData ) = 0; + + /** + * @copydoc Dali::AnimatedImageLoading::GetImageSize() + */ + virtual ImageDimensions GetImageSize() const = 0; + + /** + * @copydoc Dali::AnimatedImageLoading::GetImageCount() + */ + virtual uint32_t GetImageCount() const = 0; + + /** + * @copydoc Dali::AnimatedImageLoading::LoadFrameDelays() + */ + virtual uint32_t GetFrameInterval( uint32_t frameIndex ) const = 0; +}; + +} // namespace Adaptor + +} // namespace Internal + +// Helpers for api forwarding methods + +inline Internal::Adaptor::AnimatedImageLoading& GetImplementation( Dali::AnimatedImageLoading& handle) +{ + DALI_ASSERT_ALWAYS( handle && "AnimatedImageLoading handle is empty" ); + + BaseObject& object = handle.GetBaseObject(); + + return static_cast< Internal::Adaptor::AnimatedImageLoading& >( object ); +} + +inline const Internal::Adaptor::AnimatedImageLoading& GetImplementation( const Dali::AnimatedImageLoading& handle ) +{ + DALI_ASSERT_ALWAYS( handle && "AnimatedImageLoading handle is empty" ); + + const BaseObject& object = handle.GetBaseObject(); + + return static_cast< const Internal::Adaptor::AnimatedImageLoading& >( object ); +} + +} // namespace Dali + +#endif // DALI_INTERNAL_ANIMATED_IMAGE_LOADING_IMPL_H diff --git a/dali/devel-api/adaptor-framework/gif-loading.cpp b/dali/internal/imaging/common/gif-loading.cpp old mode 100755 new mode 100644 similarity index 97% rename from dali/devel-api/adaptor-framework/gif-loading.cpp rename to dali/internal/imaging/common/gif-loading.cpp index e49fbc8..187d91c --- a/dali/devel-api/adaptor-framework/gif-loading.cpp +++ b/dali/internal/imaging/common/gif-loading.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 Samsung Electronics Co., Ltd. + * 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. @@ -18,7 +18,7 @@ */ // CLASS HEADER -#include +#include // EXTERNAL INCLUDES #include @@ -45,6 +45,12 @@ namespace Dali { +namespace Internal +{ + +namespace Adaptor +{ + namespace { #if defined(DEBUG_ENABLED) @@ -1232,9 +1238,9 @@ public: ImageProperties imageProperties; }; -std::unique_ptr GifLoading::New( const std::string &url, bool isLocalResource ) +AnimatedImageLoadingPtr GifLoading::New( const std::string &url, bool isLocalResource ) { - return std::unique_ptr( new GifLoading( url, isLocalResource ) ); + return AnimatedImageLoadingPtr( new GifLoading( url, isLocalResource ) ); } GifLoading::GifLoading( const std::string &url, bool isLocalResource ) @@ -1248,7 +1254,7 @@ GifLoading::~GifLoading() delete mImpl; } -bool GifLoading::LoadNextNFrames( int frameStartIndex, int count, std::vector &pixelData ) +bool GifLoading::LoadNextNFrames( uint32_t frameStartIndex, int count, std::vector &pixelData ) { int error; bool ret = false; @@ -1278,36 +1284,23 @@ bool GifLoading::LoadNextNFrames( int frameStartIndex, int count, std::vector &pixelData, Dali::Vector &frameDelays ) -{ - if( LoadFrameDelays( frameDelays ) ) - { - return LoadNextNFrames( 0, mImpl->loaderInfo.animated.frameCount, pixelData ); - } - return false; -} - -ImageDimensions GifLoading::GetImageSize() +ImageDimensions GifLoading::GetImageSize() const { return ImageDimensions( mImpl->imageProperties.w, mImpl->imageProperties.h ); } -int GifLoading::GetImageCount() +uint32_t GifLoading::GetImageCount() const { return mImpl->loaderInfo.animated.frameCount; } -bool GifLoading::LoadFrameDelays( Dali::Vector &frameDelays ) +uint32_t GifLoading::GetFrameInterval( uint32_t frameIndex ) const { - frameDelays.Clear(); + return mImpl->loaderInfo.animated.frames[frameIndex].info.delay * 10; +} - for( auto &&elem : mImpl->loaderInfo.animated.frames ) - { - // Read frame delay time, multiply 10 to change time unit to milliseconds - frameDelays.PushBack( elem.info.delay * 10 ); - } +} // namespace Adaptor - return true; -} +} // namespace Internal -} // namespace Dali +} // namespace Dali \ No newline at end of file diff --git a/dali/devel-api/adaptor-framework/gif-loading.h b/dali/internal/imaging/common/gif-loading.h old mode 100755 new mode 100644 similarity index 62% rename from dali/devel-api/adaptor-framework/gif-loading.h rename to dali/internal/imaging/common/gif-loading.h index 6143f15..4ee7565 --- a/dali/devel-api/adaptor-framework/gif-loading.h +++ b/dali/internal/imaging/common/gif-loading.h @@ -2,7 +2,7 @@ #define DALI_INTERNAL_GIF_LOADING_H /* - * Copyright (c) 2019 Samsung Electronics Co., Ltd. + * 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. @@ -27,11 +27,16 @@ // INTERNAL INCLUDES #include +#include namespace Dali { -class PixelData; -typedef Dali::Uint16Pair ImageDimensions; + +namespace Internal +{ + +namespace Adaptor +{ /** * Class to manage loading frames of an animated gif in small chunks. Lazy initializes only when @@ -40,7 +45,7 @@ typedef Dali::Uint16Pair ImageDimensions; * is released. (This is to speed up frame loads, which would otherwise have to re-acquire the * data from disk) */ -class DALI_ADAPTOR_API GifLoading +class GifLoading: public Internal::Adaptor::AnimatedImageLoading { public: @@ -50,7 +55,7 @@ public: * @param[in] isLocalResource The true or false whether this is a local resource. * @return A newly created GifLoading. */ - static std::unique_ptr New( const std::string& url, bool isLocalResource ); + static AnimatedImageLoadingPtr New( const std::string& url, bool isLocalResource ); /** * @brief Constructor @@ -61,17 +66,10 @@ public: */ GifLoading( const std::string& url, bool isLocalResource ); - // Moveable but not copyable - - GifLoading( const GifLoading& ) = delete; - GifLoading& operator=( const GifLoading& ) = delete; - GifLoading( GifLoading&& ) = default; - GifLoading& operator=( GifLoading&& ) = default; - /** * @brief Destructor */ - ~GifLoading(); + ~GifLoading() override; /** * @brief Load the next N Frames of the gif. @@ -83,50 +81,38 @@ public: * @param[out] pixelData The vector in which to return the frame data * @return True if the frame data was successfully loaded */ - bool LoadNextNFrames( int frameStartIndex, int count, std::vector& pixelData ); - - /** - * @brief Load all frames of an animated gif file. - * - * @note This function will load the entire gif into memory if not already loaded. - * - * @param[out] pixelData The loaded pixel data for each frame. - * @param[out] frameDelays The loaded delay time for each frame. - * - * @return True if the loading succeeded, false otherwise. - */ - bool LoadAllFrames( std::vector& pixelData, Dali::Vector& frameDelays ); + bool LoadNextNFrames( uint32_t frameStartIndex, int count, std::vector& pixelData ) override; /** * @brief Get the size of a gif image. * - * @note This function will load the entire gif into memory if not already loaded. - * * @return The width and height in pixels of the gif image. */ - ImageDimensions GetImageSize(); + ImageDimensions GetImageSize() const override; /** * @brief Get the number of frames in this gif. - * - * @note This function will load the entire gif into memory if not already loaded. */ - int GetImageCount(); + uint32_t GetImageCount() const override; /** - * @brief Load the frame delay counts into the provided array. + * @brief Get the frame interval of the frame index * - * @note This function will load the entire gif into memory if not already loaded. - * @param[in] frameDelays a vector to write the frame delays into - * @return true if the frame delays were successfully loaded + * @note The frame is needed to be loaded before this function is called. + * + * @return The time interval of the frame(microsecond). */ - bool LoadFrameDelays( Dali::Vector& frameDelays ); + uint32_t GetFrameInterval( uint32_t frameIndex ) const override; private: struct Impl; Impl* mImpl; }; +} // namespace Adaptor + +} // namespace Internal + } // namespace Dali #endif // DALI_INTERNAL_GIF_LOADING_H diff --git a/dali/internal/imaging/common/webp-loading.cpp b/dali/internal/imaging/common/webp-loading.cpp new file mode 100644 index 0000000..78e2e11 --- /dev/null +++ b/dali/internal/imaging/common/webp-loading.cpp @@ -0,0 +1,297 @@ +/* + * 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 +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +typedef unsigned char WebPByteType; + +namespace Dali +{ + +namespace Internal +{ + +namespace Adaptor +{ + +namespace +{ + +#if defined(DEBUG_ENABLED) +Debug::Filter *gWebPLoadingLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_GIF_LOADING" ); +#endif + +constexpr size_t MAXIMUM_DOWNLOAD_IMAGE_SIZE = 50 * 1024 * 1024; + +} + +struct WebPLoading::Impl +{ +public: + Impl( const std::string& url, bool isLocalResource ) + : mUrl( url ), + mLoadingFrame( 0 ) + { +#if WEBP_DEMUX_ABI_VERSION > 0x0101 + if( ReadWebPInformation( isLocalResource ) ) + { + WebPAnimDecoderOptions webPAnimDecoderOptions; + WebPAnimDecoderOptionsInit( &webPAnimDecoderOptions ); + webPAnimDecoderOptions.color_mode = MODE_RGBA; + mWebPAnimDecoder = WebPAnimDecoderNew( &mWebPData, &webPAnimDecoderOptions ); + WebPAnimDecoderGetInfo( mWebPAnimDecoder, &mWebPAnimInfo ); + mTimeStamp.assign( mWebPAnimInfo.frame_count, 0 ); + } +#endif + } + + bool ReadWebPInformation( bool isLocalResource ) + { +#if WEBP_DEMUX_ABI_VERSION > 0x0101 + WebPDataInit( &mWebPData ); + if( isLocalResource ) + { + Internal::Platform::FileReader fileReader( mUrl ); + FILE *fp = fileReader.GetFile(); + if( fp == NULL ) + { + return false; + } + + if( fseek( fp, 0, SEEK_END ) <= -1 ) + { + return false; + } + + mWebPData.size = ftell( fp ); + if( ( ! fseek( fp, 0, SEEK_SET ) ) ) + { + unsigned char *WebPDataBuffer; + WebPDataBuffer = reinterpret_cast( malloc(sizeof( WebPByteType ) * mWebPData.size ) ); + mWebPData.size = fread( WebPDataBuffer, sizeof( WebPByteType ), mWebPData.size, fp ); + mWebPData.bytes = WebPDataBuffer; + } + else + { + return false; + } + } + else + { + // remote file + bool succeeded; + Dali::Vector dataBuffer; + size_t dataSize; + + succeeded = TizenPlatform::Network::DownloadRemoteFileIntoMemory( mUrl, dataBuffer, dataSize, MAXIMUM_DOWNLOAD_IMAGE_SIZE ); + if( succeeded ) + { + size_t blobSize = dataBuffer.Size(); + if( blobSize > 0U ) + { + // Open a file handle on the memory buffer: + Dali::Internal::Platform::FileReader fileReader( dataBuffer, blobSize ); + FILE * const fp = fileReader.GetFile(); + if ( NULL != fp ) + { + if( ( ! fseek( fp, 0, SEEK_SET ) ) ) + { + unsigned char *WebPDataBuffer; + WebPDataBuffer = reinterpret_cast( malloc(sizeof( WebPByteType ) * blobSize ) ); + mWebPData.size = fread( WebPDataBuffer, sizeof( WebPByteType ), mWebPData.size, fp ); + mWebPData.bytes = WebPDataBuffer; + } + else + { + DALI_LOG_ERROR( "Error seeking within file\n" ); + } + } + else + { + DALI_LOG_ERROR( "Error reading file\n" ); + } + } + } + } + return true; +#else + return false; +#endif + } + + // Moveable but not copyable + + Impl( const Impl& ) = delete; + Impl& operator=( const Impl& ) = delete; + Impl( Impl&& ) = default; + Impl& operator=( Impl&& ) = default; + + ~Impl() + { +#if WEBP_DEMUX_ABI_VERSION > 0x0101 + if( &mWebPData != NULL ) + { + free( (void*)mWebPData.bytes ); + mWebPData.bytes = nullptr; + WebPDataInit( &mWebPData ); + } + if( mWebPAnimDecoder ) + { + WebPAnimDecoderDelete(mWebPAnimDecoder); + } +#endif + } + + std::string mUrl; + std::vector mTimeStamp; + uint32_t mLoadingFrame; + +#if WEBP_DEMUX_ABI_VERSION > 0x0101 + WebPData mWebPData; + WebPAnimDecoder* mWebPAnimDecoder; + WebPAnimInfo mWebPAnimInfo; +#endif +}; + +AnimatedImageLoadingPtr WebPLoading::New( const std::string &url, bool isLocalResource ) +{ +#if WEBP_DEMUX_ABI_VERSION <= 0x0101 + DALI_LOG_ERROR( "The system do not support Animated WebP format.\n" ); +#endif + return AnimatedImageLoadingPtr( new WebPLoading( url, isLocalResource ) ); +} + +WebPLoading::WebPLoading( const std::string &url, bool isLocalResource ) +: mImpl( new WebPLoading::Impl( url, isLocalResource ) ) +{ +} + +WebPLoading::~WebPLoading() +{ + delete mImpl; +} + +bool WebPLoading::LoadNextNFrames( uint32_t frameStartIndex, int count, std::vector &pixelData ) +{ +#if WEBP_DEMUX_ABI_VERSION > 0x0101 + if( frameStartIndex >= mImpl->mWebPAnimInfo.frame_count ) + { + return false; + } + + DALI_LOG_INFO( gWebPLoadingLogFilter, Debug::Concise, "LoadNextNFrames( frameStartIndex:%d, count:%d )\n", frameStartIndex, count ); + + if( mImpl->mLoadingFrame > frameStartIndex ) + { + mImpl->mLoadingFrame = 0; + WebPAnimDecoderReset( mImpl->mWebPAnimDecoder ); + } + + for( ; mImpl->mLoadingFrame < frameStartIndex ; ++mImpl->mLoadingFrame ) + { + uint8_t* frameBuffer; + int timestamp; + WebPAnimDecoderGetNext( mImpl->mWebPAnimDecoder, &frameBuffer, ×tamp ); + mImpl->mTimeStamp[mImpl->mLoadingFrame] = timestamp; + } + + for( int i = 0; i < count; ++i ) + { + const int bufferSize = mImpl->mWebPAnimInfo.canvas_width * mImpl->mWebPAnimInfo.canvas_height * sizeof( uint32_t ); + uint8_t* frameBuffer; + int timestamp; + WebPAnimDecoderGetNext( mImpl->mWebPAnimDecoder, &frameBuffer, ×tamp ); + + auto pixelBuffer = new uint8_t[ bufferSize ]; + memcpy( pixelBuffer, frameBuffer, bufferSize ); + mImpl->mTimeStamp[mImpl->mLoadingFrame] = timestamp; + + if( pixelBuffer ) + { + pixelData.push_back( Dali::PixelData::New( pixelBuffer, bufferSize, + mImpl->mWebPAnimInfo.canvas_width, mImpl->mWebPAnimInfo.canvas_height, + Dali::Pixel::RGBA8888, Dali::PixelData::DELETE_ARRAY) ); + } + + mImpl->mLoadingFrame++; + if( mImpl->mLoadingFrame >= mImpl->mWebPAnimInfo.frame_count ) + { + mImpl->mLoadingFrame = 0; + WebPAnimDecoderReset( mImpl->mWebPAnimDecoder ); + } + } + + return true; +#else + return false; +#endif +} + +ImageDimensions WebPLoading::GetImageSize() const +{ +#if WEBP_DEMUX_ABI_VERSION > 0x0101 + return ImageDimensions( mImpl->mWebPAnimInfo.canvas_width, mImpl->mWebPAnimInfo.canvas_height ); +#else + return ImageDimensions(); +#endif +} + +uint32_t WebPLoading::GetImageCount() const +{ +#if WEBP_DEMUX_ABI_VERSION > 0x0101 + return mImpl->mWebPAnimInfo.frame_count; +#else + return 0u; +#endif +} + +uint32_t WebPLoading::GetFrameInterval( uint32_t frameIndex ) const +{ + if( frameIndex >= GetImageCount() ) + { + return 0u; + } + else + { + if( frameIndex > 0 ) + { + return mImpl->mTimeStamp[frameIndex] - mImpl->mTimeStamp[frameIndex - 1]; + } + return mImpl->mTimeStamp[frameIndex]; + } +} + +} // namespace Adaptor + +} // namespace Internal + +} // namespace Dali \ No newline at end of file diff --git a/dali/internal/imaging/common/webp-loading.h b/dali/internal/imaging/common/webp-loading.h new file mode 100644 index 0000000..01bd4e3 --- /dev/null +++ b/dali/internal/imaging/common/webp-loading.h @@ -0,0 +1,121 @@ +#ifndef DALI_INTERNAL_WEBP_LOADING_H +#define DALI_INTERNAL_WEBP_LOADING_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 + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ +class PixelData; +typedef Dali::Uint16Pair ImageDimensions; + +namespace Internal +{ + +namespace Adaptor +{ + +/** + * Class to manage loading frames of an animated webp in small chunks. Lazy initializes only when + * data is actually needed. + * Note, once the WEBP has loaded, the undecoded data will reside in memory until this object + * is released. (This is to speed up frame loads, which would otherwise have to re-acquire the + * data from disk) + */ +class WebPLoading: public Internal::Adaptor::AnimatedImageLoading +{ +public: + + /** + * Create a WebPLoading with the given url and resourceType. + * @param[in] url The url of the webp image to load + * @param[in] isLocalResource The true or false whether this is a local resource. + * @return A newly created WebPLoading. + */ + static AnimatedImageLoadingPtr New( const std::string& url, bool isLocalResource ); + + /** + * @brief Constructor + * + * Construct a Loader with the given URL + * @param[in] url The url of the webp image to load + * @param[in] isLocalResource The true or false whether this is a local resource. + */ + WebPLoading( const std::string& url, bool isLocalResource ); + + + /** + * @brief Destructor + */ + ~WebPLoading() override; + + /** + * @brief Load the next N Frames of the webp. + * + * @note This function will load the entire webp into memory if not already loaded. + * @param[in] frameStartIndex The frame counter to start from. Will usually be the next frame + * after the previous invocation of this method, or 0 to start. + * @param[in] count The number of frames to load + * @param[out] pixelData The vector in which to return the frame data + * @return True if the frame data was successfully loaded + */ + bool LoadNextNFrames( uint32_t frameStartIndex, int count, std::vector& pixelData ) override; + + /** + * @brief Get the size of a webp image. + * + * @return The width and height in pixels of the webp image. + */ + ImageDimensions GetImageSize() const override; + + /** + * @brief Get the number of frames in this webp. + */ + uint32_t GetImageCount() const override; + + /** + * @brief Get the frame interval of the frame index + * + * @note The frame is needed to be loaded before this function is called. + * + * @return The time interval of the frame(microsecond). + */ + uint32_t GetFrameInterval( uint32_t frameIndex ) const override; + +private: + struct Impl; + Impl* mImpl; +}; + +} // namespace Adaptor + +} // namespace Internal + +} // namespace Dali + +#endif // DALI_INTERNAL_WEBP_LOADING_H diff --git a/dali/internal/imaging/file.list b/dali/internal/imaging/file.list index 6558e96..c91ffcf 100644 --- a/dali/internal/imaging/file.list +++ b/dali/internal/imaging/file.list @@ -18,6 +18,8 @@ SET( adaptor_imaging_common_src_files ${adaptor_imaging_dir}/common/loader-png.cpp ${adaptor_imaging_dir}/common/loader-wbmp.cpp ${adaptor_imaging_dir}/common/pixel-manipulation.cpp + ${adaptor_imaging_dir}/common/gif-loading.cpp + ${adaptor_imaging_dir}/common/webp-loading.cpp ) # module: imaging, backend: tizen diff --git a/packaging/dali-adaptor.spec b/packaging/dali-adaptor.spec index 0e7a469..6d7bafc 100644 --- a/packaging/dali-adaptor.spec +++ b/packaging/dali-adaptor.spec @@ -56,6 +56,10 @@ BuildRequires: pkgconfig BuildRequires: gawk BuildRequires: cmake BuildRequires: giflib-devel +BuildRequires: pkgconfig(libwebp) +BuildRequires: pkgconfig(libwebpdecoder) +BuildRequires: pkgconfig(libwebpdemux) +BuildRequires: pkgconfig(libwebpmux) BuildRequires: pkgconfig(fontconfig) BuildRequires: libjpeg-turbo-devel BuildRequires: pkgconfig(vconf) -- 2.7.4 From b2b2447230b78d870dba9e11961a01fa9b03a09c Mon Sep 17 00:00:00 2001 From: Victor Cebollada Date: Mon, 22 Jun 2020 15:02:23 +0100 Subject: [PATCH 13/16] Fixed MS Windows min, max compile error. Change-Id: I96d60fce295aae527313c24dd480b069466b21b3 Signed-off-by: Victor Cebollada --- dali/internal/graphics/common/egl-include.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dali/internal/graphics/common/egl-include.h b/dali/internal/graphics/common/egl-include.h index d0d1cad..6e744cf 100644 --- a/dali/internal/graphics/common/egl-include.h +++ b/dali/internal/graphics/common/egl-include.h @@ -16,6 +16,9 @@ #undef CopyMemory #undef CreateWindow +#undef min +#undef max + #include #endif // EGL_INCLUDE_H -- 2.7.4 From 95abef3d0976b9e12f22cfa45509bbe8b3c86974 Mon Sep 17 00:00:00 2001 From: "Seungho, Baek" Date: Mon, 6 Jul 2020 17:54:01 +0900 Subject: [PATCH 14/16] DALi Version 1.5.18 Change-Id: I51de1ebd2bfa155460f4d1ab9655f0346ed3b3a4 Signed-off-by: Seungho, Baek --- dali/public-api/dali-adaptor-version.cpp | 2 +- packaging/dali-adaptor.spec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dali/public-api/dali-adaptor-version.cpp b/dali/public-api/dali-adaptor-version.cpp index 0fce620..b829bda 100644 --- a/dali/public-api/dali-adaptor-version.cpp +++ b/dali/public-api/dali-adaptor-version.cpp @@ -28,7 +28,7 @@ namespace Dali const unsigned int ADAPTOR_MAJOR_VERSION = 1; const unsigned int ADAPTOR_MINOR_VERSION = 5; -const unsigned int ADAPTOR_MICRO_VERSION = 17; +const unsigned int ADAPTOR_MICRO_VERSION = 18; const char * const ADAPTOR_BUILD_DATE = __DATE__ " " __TIME__; #ifdef DEBUG_ENABLED diff --git a/packaging/dali-adaptor.spec b/packaging/dali-adaptor.spec index 0026bca..ed41061 100644 --- a/packaging/dali-adaptor.spec +++ b/packaging/dali-adaptor.spec @@ -17,7 +17,7 @@ Name: dali-adaptor Summary: The DALi Tizen Adaptor -Version: 1.5.17 +Version: 1.5.18 Release: 1 Group: System/Libraries License: Apache-2.0 and BSD-3-Clause and MIT -- 2.7.4 From e08d1616cb7db94588feae8a8ddcfed25dccd137 Mon Sep 17 00:00:00 2001 From: Heeyong Song Date: Tue, 16 Jun 2020 11:42:02 +0900 Subject: [PATCH 15/16] Support a frame rendered / presented callback Change-Id: Ie6dfe10a1349c1c4c50ebf8b4005835b67b53c57 --- dali/devel-api/adaptor-framework/window-devel.cpp | 10 +++ dali/devel-api/adaptor-framework/window-devel.h | 35 ++++++++ .../adaptor-framework/render-surface-interface.h | 17 ++++ .../adaptor-framework/scene-holder-impl.cpp | 20 ++++- .../adaptor-framework/scene-holder-impl.h | 32 +++++++ .../android/file-descriptor-monitor-android.cpp | 2 +- .../system/common/file-descriptor-monitor.h | 2 +- dali/internal/system/common/trigger-event.cpp | 2 +- dali/internal/system/common/trigger-event.h | 3 +- .../system/linux/file-descriptor-monitor-ecore.cpp | 4 +- .../window-system/android/window-base-android.cpp | 10 +++ .../window-system/android/window-base-android.h | 10 +++ dali/internal/window-system/common/window-base.h | 12 +++ .../window-system/common/window-render-surface.cpp | 100 +++++++++++++++++++++ .../window-system/common/window-render-surface.h | 47 ++++++++++ .../ecore-wl/window-base-ecore-wl.cpp | 10 +++ .../tizen-wayland/ecore-wl/window-base-ecore-wl.h | 10 +++ .../ecore-wl2/window-base-ecore-wl2.cpp | 10 +++ .../ecore-wl2/window-base-ecore-wl2.h | 10 +++ .../ubuntu-x11/window-base-ecore-x.cpp | 10 +++ .../window-system/ubuntu-x11/window-base-ecore-x.h | 10 +++ .../window-system/windows/window-base-win.cpp | 10 +++ .../window-system/windows/window-base-win.h | 10 +++ 23 files changed, 378 insertions(+), 8 deletions(-) diff --git a/dali/devel-api/adaptor-framework/window-devel.cpp b/dali/devel-api/adaptor-framework/window-devel.cpp index 44e9801..7d046ec 100755 --- a/dali/devel-api/adaptor-framework/window-devel.cpp +++ b/dali/devel-api/adaptor-framework/window-devel.cpp @@ -153,6 +153,16 @@ void SetDamagedAreas(Window window, std::vector>& areas) GetImplementation(window).SetDamagedAreas(areas); } +void AddFrameRenderedCallback( Window window, std::unique_ptr< CallbackBase > callback, int32_t frameId ) +{ + GetImplementation( window ).AddFrameRenderedCallback( std::move( callback ), frameId ); +} + +void AddFramePresentedCallback( Window window, std::unique_ptr< CallbackBase > callback, int32_t frameId ) +{ + GetImplementation( window ).AddFramePresentedCallback( std::move( callback ), frameId ); +} + } // namespace DevelWindow } // namespace Dali diff --git a/dali/devel-api/adaptor-framework/window-devel.h b/dali/devel-api/adaptor-framework/window-devel.h index 1eb3501..3c97559 100755 --- a/dali/devel-api/adaptor-framework/window-devel.h +++ b/dali/devel-api/adaptor-framework/window-devel.h @@ -19,6 +19,7 @@ */ // EXTERNAL INCLUDES +#include // INTERNAL INCLUDES #include @@ -263,6 +264,40 @@ DALI_ADAPTOR_API int32_t GetNativeId( Window window ); */ DALI_ADAPTOR_API void SetDamagedAreas(Window window, std::vector>& areas); +/** + * @brief Adds a callback that is called when the frame rendering is done by the graphics driver. + * + * @param[in] window The window instance + * @param[in] callback The function to call + * @param[in] frameId The Id to specify the frame. It will be passed when the callback is called. + * + * @note A callback of the following type may be used: + * @code + * void MyFunction( int frameId ); + * @endcode + * This callback will be deleted once it is called. + * + * @note Ownership of the callback is passed onto this class. + */ +DALI_ADAPTOR_API void AddFrameRenderedCallback( Window window, std::unique_ptr< CallbackBase > callback, int32_t frameId ); + +/** + * @brief Adds a callback that is called when the frame is displayed on the display. + * + * @param[in] window The window instance + * @param[in] callback The function to call + * @param[in] frameId The Id to specify the frame. It will be passed when the callback is called. + * + * @note A callback of the following type may be used: + * @code + * void MyFunction( int frameId ); + * @endcode + * This callback will be deleted once it is called. + * + * @note Ownership of the callback is passed onto this class. + */ +DALI_ADAPTOR_API void AddFramePresentedCallback( Window window, std::unique_ptr< CallbackBase > callback, int32_t frameId ); + } // namespace DevelWindow } // namespace Dali diff --git a/dali/integration-api/adaptor-framework/render-surface-interface.h b/dali/integration-api/adaptor-framework/render-surface-interface.h index e148662..6de1182 100644 --- a/dali/integration-api/adaptor-framework/render-surface-interface.h +++ b/dali/integration-api/adaptor-framework/render-surface-interface.h @@ -31,6 +31,11 @@ namespace Dali class DisplayConnection; class ThreadSynchronizationInterface; +namespace Integration +{ +class Scene; +} + namespace Internal { namespace Adaptor @@ -77,6 +82,7 @@ public: : mAdaptor( nullptr ), mGraphics( nullptr ), mDisplayConnection( nullptr ), + mScene( nullptr ), mDepthBufferRequired( Integration::DepthBufferAvailable::FALSE ), mStencilBufferRequired( Integration::StencilBufferAvailable::FALSE ) {} @@ -206,6 +212,16 @@ public: mDisplayConnection = &displayConnection; } + /** + * @brief Sets a Scene that is rendered on this surface. + * @param scene The Scene object + */ + void SetScene( Dali::Integration::Scene& scene ) + { + // This will be changed to use the WeakHandle later. + mScene = &scene; + } + private: /** @@ -223,6 +239,7 @@ protected: Dali::Internal::Adaptor::AdaptorInternalServices* mAdaptor; Dali::Internal::Adaptor::GraphicsInterface* mGraphics; Dali::DisplayConnection* mDisplayConnection; + Dali::Integration::Scene* mScene; private: diff --git a/dali/integration-api/adaptor-framework/scene-holder-impl.cpp b/dali/integration-api/adaptor-framework/scene-holder-impl.cpp index 5bbe94b..e296ea1 100644 --- a/dali/integration-api/adaptor-framework/scene-holder-impl.cpp +++ b/dali/integration-api/adaptor-framework/scene-holder-impl.cpp @@ -48,7 +48,7 @@ namespace { #if defined(DEBUG_ENABLED) -Integration::Log::Filter* gTouchEventLogFilter = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_ADAPTOR_EVENTS_TOUCH"); +Debug::Filter* gSceneHolderLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_SCENE_HOLDER" ); #endif // Copied from x server @@ -201,6 +201,7 @@ void SceneHolder::SetSurface(Dali::RenderSurfaceInterface* surface) mScene.SetDpi( Vector2( static_cast( dpiHorizontal ), static_cast( dpiVertical ) ) ); mSurface->SetAdaptor( *mAdaptor ); + mSurface->SetScene( mScene ); OnSurfaceSet( surface ); } @@ -272,6 +273,7 @@ void SceneHolder::SetAdaptor(Dali::Adaptor& adaptor) mScene.SetDpi( Vector2( static_cast( dpiHorizontal ), static_cast( dpiVertical ) ) ); mSurface->SetAdaptor( *mAdaptor ); + mSurface->SetScene( mScene ); } OnAdaptorSet( adaptor ); @@ -305,7 +307,7 @@ void SceneHolder::FeedTouchPoint( Dali::Integration::Point& point, int timeStamp Integration::TouchEventCombiner::EventDispatchType type = mCombiner.GetNextTouchEvent(point, timeStamp, touchEvent, hoverEvent); if( type != Integration::TouchEventCombiner::DispatchNone ) { - DALI_LOG_INFO( gTouchEventLogFilter, Debug::General, "%d: Device %d: Button state %d (%.2f, %.2f)\n", timeStamp, point.GetDeviceId(), point.GetState(), point.GetScreenPosition().x, point.GetScreenPosition().y ); + DALI_LOG_INFO( gSceneHolderLogFilter, Debug::Verbose, "%d: Device %d: Button state %d (%.2f, %.2f)\n", timeStamp, point.GetDeviceId(), point.GetState(), point.GetScreenPosition().x, point.GetScreenPosition().y ); // Signals can be emitted while processing core events, and the scene holder could be deleted in the signal callback. // Keep the handle alive until the core events are processed. @@ -357,6 +359,20 @@ void SceneHolder::FeedKeyEvent( Dali::Integration::KeyEvent& keyEvent ) mAdaptor->ProcessCoreEvents(); } +void SceneHolder::AddFrameRenderedCallback( std::unique_ptr< CallbackBase > callback, int32_t frameId ) +{ + mScene.AddFrameRenderedCallback( std::move( callback ), frameId ); + + DALI_LOG_INFO( gSceneHolderLogFilter, Debug::General, "SceneHolder::AddFrameRenderedCallback:: Added [%d]\n", frameId ); +} + +void SceneHolder::AddFramePresentedCallback( std::unique_ptr< CallbackBase > callback, int32_t frameId ) +{ + mScene.AddFramePresentedCallback( std::move( callback ), frameId ); + + DALI_LOG_INFO( gSceneHolderLogFilter, Debug::General, "SceneHolder::AddFramePresentedCallback:: Added [%d]\n", frameId ); +} + Dali::Integration::SceneHolder SceneHolder::Get( Dali::Actor actor ) { SceneHolder* sceneHolderImpl = nullptr; diff --git a/dali/integration-api/adaptor-framework/scene-holder-impl.h b/dali/integration-api/adaptor-framework/scene-holder-impl.h index 3a830f9..38560cf 100644 --- a/dali/integration-api/adaptor-framework/scene-holder-impl.h +++ b/dali/integration-api/adaptor-framework/scene-holder-impl.h @@ -171,6 +171,38 @@ public: void FeedKeyEvent( Dali::Integration::KeyEvent& keyEvent ); /** + * @brief Adds a callback that is called when the frame rendering is done by the graphics driver. + * + * @param[in] callback The function to call + * @param[in] frameId The Id to specify the frame. It will be passed when the callback is called. + * + * @note A callback of the following type may be used: + * @code + * void MyFunction( int frameId ); + * @endcode + * This callback will be deleted once it is called. + * + * @note Ownership of the callback is passed onto this class. + */ + void AddFrameRenderedCallback( std::unique_ptr< CallbackBase > callback, int32_t frameId ); + + /** + * @brief Adds a callback that is called when the frame rendering is done by the graphics driver. + * + * @param[in] callback The function to call + * @param[in] frameId The Id to specify the frame. It will be passed when the callback is called. + * + * @note A callback of the following type may be used: + * @code + * void MyFunction( int frameId ); + * @endcode + * This callback will be deleted once it is called. + * + * @note Ownership of the callback is passed onto this class. + */ + void AddFramePresentedCallback( std::unique_ptr< CallbackBase > callback, int32_t frameId ); + + /** * @copydoc Dali::Integration::SceneHolder::Get() */ static Dali::Integration::SceneHolder Get( Dali::Actor actor ); diff --git a/dali/internal/system/android/file-descriptor-monitor-android.cpp b/dali/internal/system/android/file-descriptor-monitor-android.cpp index 9bbfb01..b15b339 100644 --- a/dali/internal/system/android/file-descriptor-monitor-android.cpp +++ b/dali/internal/system/android/file-descriptor-monitor-android.cpp @@ -85,7 +85,7 @@ struct FileDescriptorMonitor::Impl // if there is an event, execute the callback if( type != FileDescriptorMonitor::FD_NO_EVENT ) { - CallbackBase::Execute( *impl->mCallback, static_cast< FileDescriptorMonitor::EventType >( type ) ); + CallbackBase::Execute( *impl->mCallback, static_cast< FileDescriptorMonitor::EventType >( type ), impl->mFileDescriptor ); } return 1; // Continue receiving callbacks diff --git a/dali/internal/system/common/file-descriptor-monitor.h b/dali/internal/system/common/file-descriptor-monitor.h index dafd064..a6aa316 100644 --- a/dali/internal/system/common/file-descriptor-monitor.h +++ b/dali/internal/system/common/file-descriptor-monitor.h @@ -66,7 +66,7 @@ public: * mFileDescriptorMonitor = new FileDescriptorMonitor( myFd, MakeCallback( this, &MyClass::FdCallback ), FileDescriptorMonitor::FD_READABLE ); * } * - * void MyClass::FdCallback( EventType event ) + * void MyClass::FdCallback( EventType event, int fileDescriptor ) * { * if( event & FileDescriptorMonitor::FD_ERROR) * { diff --git a/dali/internal/system/common/trigger-event.cpp b/dali/internal/system/common/trigger-event.cpp index 005f5ec..78044b4 100644 --- a/dali/internal/system/common/trigger-event.cpp +++ b/dali/internal/system/common/trigger-event.cpp @@ -90,7 +90,7 @@ void TriggerEvent::Trigger() } } -void TriggerEvent::Triggered( FileDescriptorMonitor::EventType eventBitMask ) +void TriggerEvent::Triggered( FileDescriptorMonitor::EventType eventBitMask, int fileDescriptor ) { if( !( eventBitMask & FileDescriptorMonitor::FD_READABLE ) ) { diff --git a/dali/internal/system/common/trigger-event.h b/dali/internal/system/common/trigger-event.h index 09ef23d..04e7835 100644 --- a/dali/internal/system/common/trigger-event.h +++ b/dali/internal/system/common/trigger-event.h @@ -80,8 +80,9 @@ private: /** * @brief Called when our event file descriptor has been written to. * @param[in] eventBitMask bit mask of events that occured on the file descriptor + * @param[in] fileDescriptor The file descriptor */ - void Triggered( FileDescriptorMonitor::EventType eventBitMask ); + void Triggered( FileDescriptorMonitor::EventType eventBitMask, int fileDescriptor ); private: diff --git a/dali/internal/system/linux/file-descriptor-monitor-ecore.cpp b/dali/internal/system/linux/file-descriptor-monitor-ecore.cpp index 88e9de3..83d63f4 100644 --- a/dali/internal/system/linux/file-descriptor-monitor-ecore.cpp +++ b/dali/internal/system/linux/file-descriptor-monitor-ecore.cpp @@ -72,7 +72,7 @@ struct FileDescriptorMonitor::Impl if( ecore_main_fd_handler_active_get( handler, ECORE_FD_ERROR) ) { - CallbackBase::Execute( *impl->mCallback, FileDescriptorMonitor::FD_ERROR); + CallbackBase::Execute( *impl->mCallback, FileDescriptorMonitor::FD_ERROR, impl->mFileDescriptor ); DALI_LOG_ERROR("ECORE_FD_ERROR occurred on %d\n", impl->mFileDescriptor); return ECORE_CALLBACK_CANCEL; @@ -97,7 +97,7 @@ struct FileDescriptorMonitor::Impl // if there is an event, execute the callback if( type != FileDescriptorMonitor::FD_NO_EVENT ) { - CallbackBase::Execute( *impl->mCallback, static_cast< FileDescriptorMonitor::EventType >(type ) ); + CallbackBase::Execute( *impl->mCallback, static_cast< FileDescriptorMonitor::EventType >(type ), impl->mFileDescriptor ); } return ECORE_CALLBACK_RENEW; diff --git a/dali/internal/window-system/android/window-base-android.cpp b/dali/internal/window-system/android/window-base-android.cpp index b894fa0..fa75f42 100644 --- a/dali/internal/window-system/android/window-base-android.cpp +++ b/dali/internal/window-system/android/window-base-android.cpp @@ -343,6 +343,16 @@ void WindowBaseAndroid::SetParent( WindowBase* parentWinBase ) { } +int WindowBaseAndroid::CreateFrameRenderedSyncFence() +{ + return -1; +} + +int WindowBaseAndroid::CreateFramePresentedSyncFence() +{ + return -1; +} + } // namespace Adaptor } // namespace Internal diff --git a/dali/internal/window-system/android/window-base-android.h b/dali/internal/window-system/android/window-base-android.h index 86e8ddc..e970b7a 100644 --- a/dali/internal/window-system/android/window-base-android.h +++ b/dali/internal/window-system/android/window-base-android.h @@ -352,6 +352,16 @@ public: */ virtual void SetParent( WindowBase* parentWinBase ) override; + /** + * @copydoc Dali::Internal::Adaptor::WindowBase::CreateFrameRenderedSyncFence() + */ + virtual int CreateFrameRenderedSyncFence() override; + + /** + * @copydoc Dali::Internal::Adaptor::WindowBase::CreateFramePresentedSyncFence() + */ + virtual int CreateFramePresentedSyncFence() override; + private: /** diff --git a/dali/internal/window-system/common/window-base.h b/dali/internal/window-system/common/window-base.h index 9871611..a5daaa2 100644 --- a/dali/internal/window-system/common/window-base.h +++ b/dali/internal/window-system/common/window-base.h @@ -335,6 +335,18 @@ public: */ virtual void SetParent( WindowBase* parentWinBase ) = 0; + /** + * @brief Create a sync fence that can tell the frame is rendered by the graphics driver. + * @return The file descriptor that tells when it is rendered. + */ + virtual int CreateFrameRenderedSyncFence() = 0; + + /** + * @brief Create a sync fence that can tell the frame is presented by the display server. + * @return The file descriptor that tells when it is presented. + */ + virtual int CreateFramePresentedSyncFence() = 0; + // Signals /** diff --git a/dali/internal/window-system/common/window-render-surface.cpp b/dali/internal/window-system/common/window-render-surface.cpp index dfaefa4..9c60476 100644 --- a/dali/internal/window-system/common/window-render-surface.cpp +++ b/dali/internal/window-system/common/window-render-surface.cpp @@ -60,11 +60,13 @@ WindowRenderSurface::WindowRenderSurface( Dali::PositionSize positionSize, Any s mThreadSynchronization( NULL ), mRenderNotification( NULL ), mRotationTrigger( NULL ), + mFrameRenderedTrigger(), mGraphics( nullptr ), mEGLSurface( nullptr ), mEGLContext( nullptr ), mColorDepth( isTransparent ? COLOR_DEPTH_32 : COLOR_DEPTH_24 ), mOutputTransformedSignal(), + mFrameCallbackInfoContainer(), mRotationAngle( 0 ), mScreenRotationAngle( 0 ), mOwnSurface( false ), @@ -354,6 +356,63 @@ void WindowRenderSurface::StartRender() bool WindowRenderSurface::PreRender( bool resizingSurface, const std::vector>& damagedRects, Rect& clippingRect ) { + Dali::Integration::Scene::FrameCallbackContainer callbacks; + + if( mScene ) + { + mScene->GetFrameRenderedCallback( callbacks ); + if( !callbacks.empty() ) + { + int frameRenderedSync = mWindowBase->CreateFrameRenderedSyncFence(); + if( frameRenderedSync != -1 ) + { + DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PreRender: CreateFrameRenderedSyncFence [%d]\n", frameRenderedSync ); + + mFrameCallbackInfoContainer.push_back( std::unique_ptr< FrameCallbackInfo >( new FrameCallbackInfo( callbacks, frameRenderedSync ) ) ); + + if( !mFrameRenderedTrigger ) + { + mFrameRenderedTrigger = std::unique_ptr< TriggerEventInterface >( TriggerEventFactory::CreateTriggerEvent( MakeCallback( this, &WindowRenderSurface::ProcessFrameCallback ), + TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER ) ); + } + mFrameRenderedTrigger->Trigger(); + } + else + { + DALI_LOG_ERROR( "WindowRenderSurface::PreRender: CreateFrameRenderedSyncFence is failed\n" ); + } + + // Clear callbacks + callbacks.clear(); + } + + mScene->GetFramePresentedCallback( callbacks ); + if( !callbacks.empty() ) + { + int framePresentedSync = mWindowBase->CreateFramePresentedSyncFence(); + if( framePresentedSync != -1 ) + { + DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PreRender: CreateFramePresentedSyncFence [%d]\n", framePresentedSync ); + + mFrameCallbackInfoContainer.push_back( std::unique_ptr< FrameCallbackInfo >( new FrameCallbackInfo( callbacks, framePresentedSync ) ) ); + + if( !mFrameRenderedTrigger ) + { + mFrameRenderedTrigger = std::unique_ptr< TriggerEventInterface >( TriggerEventFactory::CreateTriggerEvent( MakeCallback( this, &WindowRenderSurface::ProcessFrameCallback ), + TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER ) ); + } + mFrameRenderedTrigger->Trigger(); + } + else + { + DALI_LOG_ERROR( "WindowRenderSurface::PreRender: CreateFramePresentedSyncFence is failed\n" ); + } + + // Clear callbacks + callbacks.clear(); + } + } + MakeContextCurrent(); auto eglGraphics = static_cast(mGraphics); @@ -526,6 +585,47 @@ void WindowRenderSurface::ProcessRotationRequest() } } +void WindowRenderSurface::ProcessFrameCallback() +{ + for( auto&& iter : mFrameCallbackInfoContainer ) + { + if( !iter->fileDescriptorMonitor ) + { + iter->fileDescriptorMonitor = std::unique_ptr< FileDescriptorMonitor >( new FileDescriptorMonitor( iter->fileDescriptor, + MakeCallback( this, &WindowRenderSurface::OnFileDescriptorEventDispatched ), FileDescriptorMonitor::FD_READABLE ) ); + + DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::ProcessFrameCallback: Add handler [%d]\n", iter->fileDescriptor ); + } + } +} + +void WindowRenderSurface::OnFileDescriptorEventDispatched( FileDescriptorMonitor::EventType eventBitMask, int fileDescriptor ) +{ + if( !( eventBitMask & FileDescriptorMonitor::FD_READABLE ) ) + { + DALI_LOG_ERROR( "WindowRenderSurface::OnFileDescriptorEventDispatched: file descriptor error [%d]\n", eventBitMask ); + close( fileDescriptor ); + return; + } + + DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::OnFileDescriptorEventDispatched: Frame rendered [%d]\n", fileDescriptor ); + + auto frameCallbackInfo = std::find_if( mFrameCallbackInfoContainer.begin(), mFrameCallbackInfoContainer.end(), + [fileDescriptor]( std::unique_ptr< FrameCallbackInfo >& callbackInfo ) + { + return callbackInfo->fileDescriptor == fileDescriptor; + } ); + if( frameCallbackInfo != mFrameCallbackInfoContainer.end() ) + { + // Call the connected callback + for( auto&& iter : ( *frameCallbackInfo )->callbacks ) + { + CallbackBase::Execute( *( iter.first ), iter.second ); + } + mFrameCallbackInfoContainer.erase( frameCallbackInfo ); + } +} + } // namespace Adaptor } // namespace internal diff --git a/dali/internal/window-system/common/window-render-surface.h b/dali/internal/window-system/common/window-render-surface.h index bc03611..6f982e4 100644 --- a/dali/internal/window-system/common/window-render-surface.h +++ b/dali/internal/window-system/common/window-render-surface.h @@ -21,11 +21,14 @@ // EXTERNAL INCLUDES #include #include +#include +#include // INTERNAL INCLUDES #include #include #include +#include namespace Dali { @@ -215,6 +218,18 @@ private: */ void ProcessRotationRequest(); + /** + * @brief Used as the callback for the frame rendered / presented. + */ + void ProcessFrameCallback(); + + /** + * @brief Called when our event file descriptor has been written to. + * @param[in] eventBitMask bit mask of events that occured on the file descriptor + * @param[in] fileDescriptor The file descriptor + */ + void OnFileDescriptorEventDispatched( FileDescriptorMonitor::EventType eventBitMask, int fileDescriptor ); + protected: // Undefined @@ -223,6 +238,36 @@ protected: // Undefined WindowRenderSurface& operator=(const WindowRenderSurface& rhs) = delete; +private: + + struct FrameCallbackInfo + { + FrameCallbackInfo( Dali::Integration::Scene::FrameCallbackContainer& callbackList, int fd ) + : callbacks(), + fileDescriptorMonitor(), + fileDescriptor( fd ) + { + // Transfer owership of the CallbackBase + for( auto&& iter : callbackList ) + { + callbacks.push_back( std::make_pair( std::move( iter.first ), iter.second ) ); + } + } + + ~FrameCallbackInfo() + { + // Delete FileDescriptorMonitor before close fd. + fileDescriptorMonitor.release(); + close( fileDescriptor ); + } + + Dali::Integration::Scene::FrameCallbackContainer callbacks; + std::unique_ptr< FileDescriptorMonitor > fileDescriptorMonitor; + int fileDescriptor; + }; + + using FrameCallbackInfoContainer = std::vector< std::unique_ptr< FrameCallbackInfo > >; + private: // Data EglInterface* mEGL; @@ -232,11 +277,13 @@ private: // Data ThreadSynchronizationInterface* mThreadSynchronization; TriggerEventInterface* mRenderNotification; ///< Render notification trigger TriggerEventInterface* mRotationTrigger; + std::unique_ptr< TriggerEventInterface > mFrameRenderedTrigger; GraphicsInterface* mGraphics; ///< Graphics interface EGLSurface mEGLSurface; EGLContext mEGLContext; ColorDepth mColorDepth; ///< Color depth of surface (32 bit or 24 bit) OutputSignalType mOutputTransformedSignal; + FrameCallbackInfoContainer mFrameCallbackInfoContainer; int mRotationAngle; int mScreenRotationAngle; bool mOwnSurface; ///< Whether we own the surface (responsible for deleting it) diff --git a/dali/internal/window-system/tizen-wayland/ecore-wl/window-base-ecore-wl.cpp b/dali/internal/window-system/tizen-wayland/ecore-wl/window-base-ecore-wl.cpp index 509ddd4..ac6879d 100644 --- a/dali/internal/window-system/tizen-wayland/ecore-wl/window-base-ecore-wl.cpp +++ b/dali/internal/window-system/tizen-wayland/ecore-wl/window-base-ecore-wl.cpp @@ -2146,6 +2146,16 @@ void WindowBaseEcoreWl::SetParent( WindowBase* parentWinBase ) ecore_wl_window_parent_set( mEcoreWindow, ecoreParent ); } +int WindowBaseEcoreWl::CreateFrameRenderedSyncFence() +{ + return -1; +} + +int WindowBaseEcoreWl::CreateFramePresentedSyncFence() +{ + return -1; +} + } // namespace Adaptor } // namespace Internal diff --git a/dali/internal/window-system/tizen-wayland/ecore-wl/window-base-ecore-wl.h b/dali/internal/window-system/tizen-wayland/ecore-wl/window-base-ecore-wl.h index 5811b5c..d9116e1 100644 --- a/dali/internal/window-system/tizen-wayland/ecore-wl/window-base-ecore-wl.h +++ b/dali/internal/window-system/tizen-wayland/ecore-wl/window-base-ecore-wl.h @@ -419,6 +419,16 @@ public: */ virtual void SetParent( WindowBase* parentWinBase ) override; + /** + * @copydoc Dali::Internal::Adaptor::WindowBase::CreateFrameRenderedSyncFence() + */ + virtual int CreateFrameRenderedSyncFence() override; + + /** + * @copydoc Dali::Internal::Adaptor::WindowBase::CreateFramePresentedSyncFence() + */ + virtual int CreateFramePresentedSyncFence() override; + private: /** diff --git a/dali/internal/window-system/tizen-wayland/ecore-wl2/window-base-ecore-wl2.cpp b/dali/internal/window-system/tizen-wayland/ecore-wl2/window-base-ecore-wl2.cpp index dbd8aa6..754fa5a 100755 --- a/dali/internal/window-system/tizen-wayland/ecore-wl2/window-base-ecore-wl2.cpp +++ b/dali/internal/window-system/tizen-wayland/ecore-wl2/window-base-ecore-wl2.cpp @@ -2367,6 +2367,16 @@ void WindowBaseEcoreWl2::SetParent( WindowBase* parentWinBase ) ecore_wl2_window_parent_set( mEcoreWindow, ecoreParent ); } +int WindowBaseEcoreWl2::CreateFrameRenderedSyncFence() +{ + return wl_egl_window_tizen_create_commit_sync_fd( mEglWindow ); +} + +int WindowBaseEcoreWl2::CreateFramePresentedSyncFence() +{ + return wl_egl_window_tizen_create_presentation_sync_fd( mEglWindow ); +} + } // namespace Adaptor } // namespace Internal diff --git a/dali/internal/window-system/tizen-wayland/ecore-wl2/window-base-ecore-wl2.h b/dali/internal/window-system/tizen-wayland/ecore-wl2/window-base-ecore-wl2.h index f429435..dad079d 100644 --- a/dali/internal/window-system/tizen-wayland/ecore-wl2/window-base-ecore-wl2.h +++ b/dali/internal/window-system/tizen-wayland/ecore-wl2/window-base-ecore-wl2.h @@ -441,6 +441,16 @@ public: */ virtual void SetParent( WindowBase* parentWinBase ) override; + /** + * @copydoc Dali::Internal::Adaptor::WindowBase::CreateFrameRenderedSyncFence() + */ + virtual int CreateFrameRenderedSyncFence() override; + + /** + * @copydoc Dali::Internal::Adaptor::WindowBase::CreateFramePresentedSyncFence() + */ + virtual int CreateFramePresentedSyncFence() override; + private: /** diff --git a/dali/internal/window-system/ubuntu-x11/window-base-ecore-x.cpp b/dali/internal/window-system/ubuntu-x11/window-base-ecore-x.cpp index ab67b43..ecc9e07 100755 --- a/dali/internal/window-system/ubuntu-x11/window-base-ecore-x.cpp +++ b/dali/internal/window-system/ubuntu-x11/window-base-ecore-x.cpp @@ -909,6 +909,16 @@ void WindowBaseEcoreX::SetParent( WindowBase* parentWinBase ) } } +int WindowBaseEcoreX::CreateFrameRenderedSyncFence() +{ + return -1; +} + +int WindowBaseEcoreX::CreateFramePresentedSyncFence() +{ + return -1; +} + } // namespace Adaptor } // namespace Internal diff --git a/dali/internal/window-system/ubuntu-x11/window-base-ecore-x.h b/dali/internal/window-system/ubuntu-x11/window-base-ecore-x.h index 8ab7080..bdbe0a8 100644 --- a/dali/internal/window-system/ubuntu-x11/window-base-ecore-x.h +++ b/dali/internal/window-system/ubuntu-x11/window-base-ecore-x.h @@ -353,6 +353,16 @@ public: */ virtual void SetParent( WindowBase* parentWinBase ) override; + /** + * @copydoc Dali::Internal::Adaptor::WindowBase::CreateFrameRenderedSyncFence() + */ + virtual int CreateFrameRenderedSyncFence() override; + + /** + * @copydoc Dali::Internal::Adaptor::WindowBase::CreateFramePresentedSyncFence() + */ + virtual int CreateFramePresentedSyncFence() override; + private: /** diff --git a/dali/internal/window-system/windows/window-base-win.cpp b/dali/internal/window-system/windows/window-base-win.cpp index c968bea..7697790 100755 --- a/dali/internal/window-system/windows/window-base-win.cpp +++ b/dali/internal/window-system/windows/window-base-win.cpp @@ -567,6 +567,16 @@ void WindowBaseWin::SetParent( WindowBase* parentWinBase ) } +int WindowBaseWin::CreateFrameRenderedSyncFence() +{ + return -1; +} + +int WindowBaseWin::CreateFramePresentedSyncFence() +{ + return -1; +} + } // namespace Adaptor } // namespace Internal diff --git a/dali/internal/window-system/windows/window-base-win.h b/dali/internal/window-system/windows/window-base-win.h index c0a17dc..48c0560 100755 --- a/dali/internal/window-system/windows/window-base-win.h +++ b/dali/internal/window-system/windows/window-base-win.h @@ -341,6 +341,16 @@ public: */ virtual void SetParent( WindowBase* parentWinBase ) override; + /** + * @copydoc Dali::Internal::Adaptor::WindowBase::CreateFrameRenderedSyncFence() + */ + virtual int CreateFrameRenderedSyncFence() override; + + /** + * @copydoc Dali::Internal::Adaptor::WindowBase::CreateFramePresentedSyncFence() + */ + virtual int CreateFramePresentedSyncFence() override; + private: /** -- 2.7.4 From e9eaa30a00149c298f11de8cb2f23e4e7e4123c8 Mon Sep 17 00:00:00 2001 From: Richard Huang Date: Fri, 26 Jun 2020 11:52:29 +0100 Subject: [PATCH 16/16] Try to get default EGL display connection if it fails to get native display connection Change-Id: I1a633fd2244fdafb793eb761caad1887ebca32ae --- dali/internal/graphics/gles/egl-implementation.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/dali/internal/graphics/gles/egl-implementation.cpp b/dali/internal/graphics/gles/egl-implementation.cpp index 3710dd1..f8149c4 100755 --- a/dali/internal/graphics/gles/egl-implementation.cpp +++ b/dali/internal/graphics/gles/egl-implementation.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 Samsung Electronics Co., Ltd. + * 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. @@ -104,12 +104,18 @@ bool EglImplementation::InitializeGles( EGLNativeDisplayType display, bool isOwn { mEglNativeDisplay = display; - //@todo see if we can just EGL_DEFAULT_DISPLAY instead - mEglDisplay = eglGetDisplay(mEglNativeDisplay); - EGLint error = eglGetError(); + // Try to get the display connection for the native display first + mEglDisplay = eglGetDisplay( mEglNativeDisplay ); + + if( mEglDisplay == EGL_NO_DISPLAY ) + { + // If failed, try to get the default display connection + mEglDisplay = eglGetDisplay( EGL_DEFAULT_DISPLAY ); + } - if( mEglDisplay == NULL && error != EGL_SUCCESS ) + if( mEglDisplay == EGL_NO_DISPLAY ) { + // Still failed to get a display connection throw Dali::DaliException( "", "OpenGL ES is not supported"); } -- 2.7.4