From 1a114a6a20202ef475db4f0b410c39c97d7f3515 Mon Sep 17 00:00:00 2001 From: Daekwang Ryu Date: Wed, 27 May 2020 15:18:13 +0900 Subject: [PATCH 01/16] Free an unnecessary variable anymore The parameter of app_get_id() has to be freed when it is not necessary anymore. Change-Id: Ic8a85286fa40031b405443876f794adabe2da81e --- dali/internal/adaptor/tizen-wayland/adaptor-impl-tizen.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/dali/internal/adaptor/tizen-wayland/adaptor-impl-tizen.cpp b/dali/internal/adaptor/tizen-wayland/adaptor-impl-tizen.cpp index fb0cddd..dda9e96 100755 --- a/dali/internal/adaptor/tizen-wayland/adaptor-impl-tizen.cpp +++ b/dali/internal/adaptor/tizen-wayland/adaptor-impl-tizen.cpp @@ -91,6 +91,7 @@ void Adaptor::GetAppId( std::string& appId ) if ( id ) { appId = id; + free( id ); } else { -- 2.7.4 From 7d019dfdc3cc881e188ae122600f41acb46de154 Mon Sep 17 00:00:00 2001 From: Heeyong Song Date: Fri, 22 May 2020 16:23:43 +0900 Subject: [PATCH 02/16] Delete multiple surfaces when the updated thread is destroyed Change-Id: I1d2f1431f1b4bb827691e28bfffba96c542eb227 --- .../adaptor/common/combined-update-render-controller.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/dali/internal/adaptor/common/combined-update-render-controller.cpp b/dali/internal/adaptor/common/combined-update-render-controller.cpp index 5c5840a..75d469c 100644 --- a/dali/internal/adaptor/common/combined-update-render-controller.cpp +++ b/dali/internal/adaptor/common/combined-update-render-controller.cpp @@ -796,11 +796,15 @@ void CombinedUpdateRenderController::UpdateRenderThread() // Inform core of context destruction mCore.ContextDestroyed(); - currentSurface = mAdaptorInterfaces.GetRenderSurfaceInterface(); - if( currentSurface ) + + WindowContainer windows; + mAdaptorInterfaces.GetWindowContainerInterface( windows ); + + // Destroy surfaces + for( auto&& window : windows ) { - currentSurface->DestroySurface(); - currentSurface = nullptr; + Dali::RenderSurfaceInterface* surface = window->GetSurface(); + surface->DestroySurface(); } // Shutdown EGL -- 2.7.4 From b2ebaf613fe04fce45fa18b4d1bec27277d7e7f5 Mon Sep 17 00:00:00 2001 From: Heeyong Song Date: Tue, 28 Apr 2020 14:34:50 +0900 Subject: [PATCH 03/16] Add a thread mode In case of ThreadMode::RUN_IF_REQUESTED, the update thread runs when the application requests rendering. Change-Id: I8aac3fcd7fb802b0b8d5259fe40ecf14f7b905c3 --- dali/internal/adaptor/common/adaptor-impl.cpp | 19 ++++++++- dali/internal/adaptor/common/adaptor-impl.h | 2 + .../common/combined-update-render-controller.cpp | 49 +++++++++++++++++++--- .../common/combined-update-render-controller.h | 4 +- .../adaptor/common/thread-controller-interface.h | 9 +++- dali/internal/system/common/thread-controller.cpp | 4 +- dali/internal/system/common/thread-controller.h | 3 +- 7 files changed, 78 insertions(+), 12 deletions(-) diff --git a/dali/internal/adaptor/common/adaptor-impl.cpp b/dali/internal/adaptor/common/adaptor-impl.cpp index 737845d..a48eb5f 100755 --- a/dali/internal/adaptor/common/adaptor-impl.cpp +++ b/dali/internal/adaptor/common/adaptor-impl.cpp @@ -199,7 +199,7 @@ void Adaptor::Initialize( GraphicsFactory& graphicsFactory, Dali::Configuration: mDisplayConnection = Dali::DisplayConnection::New( *mGraphics, defaultWindow->GetSurface()->GetSurfaceType() ); - mThreadController = new ThreadController( *this, *mEnvironmentOptions ); + mThreadController = new ThreadController( *this, *mEnvironmentOptions, mThreadMode ); // Should be called after Core creation if( mEnvironmentOptions->GetPanGestureLoggingLevel() ) @@ -1030,7 +1030,21 @@ void Adaptor::NotifyLanguageChanged() void Adaptor::RenderOnce() { - RequestUpdateOnce(); + if( mThreadController ) + { + UpdateMode updateMode; + if( mThreadMode == ThreadMode::NORMAL ) + { + updateMode = UpdateMode::NORMAL; + } + else + { + updateMode = UpdateMode::FORCE_RENDER; + + ProcessCoreEvents(); + } + mThreadController->RequestUpdateOnce( updateMode ); + } } const LogFactoryInterface& Adaptor::GetLogFactory() @@ -1141,6 +1155,7 @@ Adaptor::Adaptor(Dali::Integration::SceneHolder window, Dali::Adaptor& adaptor, mSystemTracer(), mObjectProfiler( nullptr ), mSocketFactory(), + mThreadMode( ThreadMode::NORMAL ), mEnvironmentOptionsOwned( environmentOptions ? false : true /* If not provided then we own the object */ ), mUseRemoteSurface( false ) { diff --git a/dali/internal/adaptor/common/adaptor-impl.h b/dali/internal/adaptor/common/adaptor-impl.h index 9e4c079..31fd83a 100755 --- a/dali/internal/adaptor/common/adaptor-impl.h +++ b/dali/internal/adaptor/common/adaptor-impl.h @@ -76,6 +76,7 @@ class LifeCycleObserver; class ObjectProfiler; class SceneHolder; class ConfigurationManager; +enum class ThreadMode; /** * Implementation of the Adaptor class. @@ -685,6 +686,7 @@ private: // Data SystemTrace mSystemTracer; ///< System tracer ObjectProfiler* mObjectProfiler; ///< Tracks object lifetime for profiling SocketFactory mSocketFactory; ///< Socket factory + ThreadMode mThreadMode; ///< The thread mode const bool mEnvironmentOptionsOwned:1; ///< Whether we own the EnvironmentOptions (and thus, need to delete it) bool mUseRemoteSurface:1; ///< whether the remoteSurface is used or not diff --git a/dali/internal/adaptor/common/combined-update-render-controller.cpp b/dali/internal/adaptor/common/combined-update-render-controller.cpp index 75d469c..0e20903 100644 --- a/dali/internal/adaptor/common/combined-update-render-controller.cpp +++ b/dali/internal/adaptor/common/combined-update-render-controller.cpp @@ -89,7 +89,7 @@ const unsigned int MAXIMUM_UPDATE_REQUESTS = 2; // EVENT THREAD /////////////////////////////////////////////////////////////////////////////////////////////////// -CombinedUpdateRenderController::CombinedUpdateRenderController( AdaptorInternalServices& adaptorInterfaces, const EnvironmentOptions& environmentOptions ) +CombinedUpdateRenderController::CombinedUpdateRenderController( AdaptorInternalServices& adaptorInterfaces, const EnvironmentOptions& environmentOptions, ThreadMode threadMode ) : mFpsTracker( environmentOptions ), mUpdateStatusLogger( environmentOptions ), mEventThreadSemaphore(), @@ -109,6 +109,7 @@ CombinedUpdateRenderController::CombinedUpdateRenderController( AdaptorInternalS mDefaultHalfFrameNanoseconds( 0u ), mUpdateRequestCount( 0u ), mRunning( FALSE ), + mThreadMode( threadMode ), mUpdateRenderRunCount( 0 ), mDestroyUpdateRenderThread( FALSE ), mUpdateRenderThreadCanSleep( FALSE ), @@ -289,7 +290,7 @@ void CombinedUpdateRenderController::RequestUpdateOnce( UpdateMode updateMode ) ++mUpdateRequestCount; } - if( IsUpdateRenderThreadPaused() ) + if( IsUpdateRenderThreadPaused() || updateMode == UpdateMode::FORCE_RENDER ) { LOG_EVENT_TRACE; @@ -418,9 +419,31 @@ void CombinedUpdateRenderController::AddSurface( Dali::RenderSurfaceInterface* s void CombinedUpdateRenderController::RunUpdateRenderThread( int numberOfCycles, AnimationProgression animationProgression, UpdateMode updateMode ) { ConditionalWait::ScopedLock lock( mUpdateRenderThreadWaitCondition ); - mUpdateRenderRunCount = numberOfCycles; + + switch( mThreadMode ) + { + case ThreadMode::NORMAL: + { + mUpdateRenderRunCount = numberOfCycles; + mUseElapsedTimeAfterWait = ( animationProgression == AnimationProgression::USE_ELAPSED_TIME ); + break; + } + case ThreadMode::RUN_IF_REQUESTED: + { + if( updateMode != UpdateMode::FORCE_RENDER ) + { + // Render only if the update mode is FORCE_RENDER which means the application requests it. + // We don't want to awake the update thread. + return; + } + + mUpdateRenderRunCount++; // Increase the update request count + mUseElapsedTimeAfterWait = TRUE; // The elapsed time should be used. We want animations to proceed. + break; + } + } + mUpdateRenderThreadCanSleep = FALSE; - mUseElapsedTimeAfterWait = ( animationProgression == AnimationProgression::USE_ELAPSED_TIME ); mUploadWithoutRendering = ( updateMode == UpdateMode::SKIP_RENDER ); LOG_COUNTER_EVENT( "mUpdateRenderRunCount: %d, mUseElapsedTimeAfterWait: %d", mUpdateRenderRunCount, mUseElapsedTimeAfterWait ); mUpdateRenderThreadWaitCondition.Notify( lock ); @@ -442,6 +465,12 @@ void CombinedUpdateRenderController::StopUpdateRenderThread() bool CombinedUpdateRenderController::IsUpdateRenderThreadPaused() { ConditionalWait::ScopedLock lock( mUpdateRenderThreadWaitCondition ); + + if( mThreadMode == ThreadMode::RUN_IF_REQUESTED ) + { + return !mRunning || mUpdateRenderThreadCanSleep; + } + return ( mUpdateRenderRunCount != CONTINUOUS ) || // Report paused if NOT continuously running mUpdateRenderThreadCanSleep; // Report paused if sleeping } @@ -562,7 +591,7 @@ void CombinedUpdateRenderController::UpdateRenderThread() uint64_t currentFrameStartTime = 0; TimeService::GetNanoseconds( currentFrameStartTime ); - const uint64_t timeSinceLastFrame = currentFrameStartTime - lastFrameTime; + uint64_t timeSinceLastFrame = currentFrameStartTime - lastFrameTime; // Optional FPS Tracking when continuously rendering if( useElapsedTime && mFpsTracker.Enabled() ) @@ -609,6 +638,16 @@ void CombinedUpdateRenderController::UpdateRenderThread() float frameDelta = 0.0f; if( useElapsedTime ) { + if( mThreadMode == ThreadMode::RUN_IF_REQUESTED ) + { + extraFramesDropped = 0; + while( timeSinceLastFrame >= mDefaultFrameDurationNanoseconds ) + { + timeSinceLastFrame -= mDefaultFrameDurationNanoseconds; + extraFramesDropped++; + } + } + // If using the elapsed time, then calculate frameDelta as a multiple of mDefaultFrameDelta noOfFramesSinceLastUpdate += extraFramesDropped; diff --git a/dali/internal/adaptor/common/combined-update-render-controller.h b/dali/internal/adaptor/common/combined-update-render-controller.h index 54cc67d..965479e 100644 --- a/dali/internal/adaptor/common/combined-update-render-controller.h +++ b/dali/internal/adaptor/common/combined-update-render-controller.h @@ -80,7 +80,7 @@ public: /** * Constructor */ - CombinedUpdateRenderController( AdaptorInternalServices& adaptorInterfaces, const EnvironmentOptions& environmentOptions ); + CombinedUpdateRenderController( AdaptorInternalServices& adaptorInterfaces, const EnvironmentOptions& environmentOptions, ThreadMode threadMode ); /** * Non virtual destructor. Not intended as base class. @@ -367,6 +367,8 @@ private: unsigned int mUpdateRequestCount; ///< Count of update-requests we have received to ensure we do not go to sleep too early. unsigned int mRunning; ///< Read and set on the event-thread only to state whether we are running. + ThreadMode mThreadMode; ///< Whether the thread runs continuously or runs when it is requested. + // // NOTE: cannot use booleans as these are used from multiple threads, must use variable with machine word size for atomic read/write // diff --git a/dali/internal/adaptor/common/thread-controller-interface.h b/dali/internal/adaptor/common/thread-controller-interface.h index 6b9055b..efeb819 100644 --- a/dali/internal/adaptor/common/thread-controller-interface.h +++ b/dali/internal/adaptor/common/thread-controller-interface.h @@ -34,7 +34,14 @@ namespace Adaptor enum class UpdateMode { NORMAL, ///< Update and render - SKIP_RENDER ///< Update and resource upload but no rendering + SKIP_RENDER, ///< Update and resource upload but no rendering + FORCE_RENDER ///< Force update and render +}; + +enum class ThreadMode +{ + NORMAL, ///< The thread runs continuously + RUN_IF_REQUESTED ///< The threads runs when it is requested }; /** diff --git a/dali/internal/system/common/thread-controller.cpp b/dali/internal/system/common/thread-controller.cpp index a9054ec..31a5a24 100644 --- a/dali/internal/system/common/thread-controller.cpp +++ b/dali/internal/system/common/thread-controller.cpp @@ -32,14 +32,14 @@ namespace Internal namespace Adaptor { -ThreadController::ThreadController( AdaptorInternalServices& adaptorInterfaces, const EnvironmentOptions& environmentOptions ) +ThreadController::ThreadController( AdaptorInternalServices& adaptorInterfaces, const EnvironmentOptions& environmentOptions, ThreadMode threadMode ) : mThreadControllerInterface( NULL ) { switch( environmentOptions.GetThreadingMode() ) { case ThreadingMode::COMBINED_UPDATE_RENDER: { - mThreadControllerInterface = new CombinedUpdateRenderController( adaptorInterfaces, environmentOptions ); + mThreadControllerInterface = new CombinedUpdateRenderController( adaptorInterfaces, environmentOptions, threadMode ); break; } } diff --git a/dali/internal/system/common/thread-controller.h b/dali/internal/system/common/thread-controller.h index c4f3961..d51e57d 100644 --- a/dali/internal/system/common/thread-controller.h +++ b/dali/internal/system/common/thread-controller.h @@ -34,6 +34,7 @@ namespace Adaptor { enum class UpdateMode; +enum class ThreadMode; class AdaptorInternalServices; class EnvironmentOptions; @@ -49,7 +50,7 @@ public: /** * Constructor */ - ThreadController( AdaptorInternalServices& adaptorInterfaces, const EnvironmentOptions& environmentOptions ); + ThreadController( AdaptorInternalServices& adaptorInterfaces, const EnvironmentOptions& environmentOptions, ThreadMode threadMode ); /** * Non virtual destructor. Not intended as base class. -- 2.7.4 From c398715c18cdaf20493e6aded77b30e22ed6b0d3 Mon Sep 17 00:00:00 2001 From: Wonsik Jung Date: Tue, 2 Jun 2020 11:09:23 +0900 Subject: [PATCH 04/16] Update window's geometry to ecore_wl2. When the ecore wl2 window is resized or changed position then the window is hidden, the window's position and size is not updated by the Tizen Display Server. Because wayland protocol is destroyed by window's hidden. To fix that, window's geometry is updated again before window is shown. Change-Id: Iafa6a7ae5509c54f2e11bd6bd3ca8e0d23a1439b --- .../tizen-wayland/ecore-wl2/window-base-ecore-wl2.cpp | 15 +++++++++++++++ .../tizen-wayland/ecore-wl2/window-base-ecore-wl2.h | 3 +++ 2 files changed, 18 insertions(+) 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 89fae58..dbd8aa6 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 @@ -688,6 +688,8 @@ WindowBaseEcoreWl2::WindowBaseEcoreWl2( Dali::PositionSize positionSize, Any sur mBrightness( 0 ), mBrightnessChangeState( 0 ), mBrightnessChangeDone( true ), + mVisible( true ), + mWindowPositionSize( positionSize ), mOwnSurface( false ), mMoveResizeSerial( 0 ), mLastSubmittedMoveResizeSerial( 0 ) @@ -949,6 +951,9 @@ void WindowBaseEcoreWl2::OnRotation( void* data, int type, void* event ) rotationEvent.height = ev->w; } + mWindowPositionSize.width = rotationEvent.width; + mWindowPositionSize.height = rotationEvent.height; + mRotationSignal.Emit( rotationEvent ); } } @@ -1521,16 +1526,19 @@ bool WindowBaseEcoreWl2::IsEglWindowRotationSupported() void WindowBaseEcoreWl2::Move( PositionSize positionSize ) { + mWindowPositionSize = positionSize; ecore_wl2_window_position_set( mEcoreWindow, positionSize.x, positionSize.y ); } void WindowBaseEcoreWl2::Resize( PositionSize positionSize ) { + mWindowPositionSize = positionSize; ecore_wl2_window_geometry_set( mEcoreWindow, positionSize.x, positionSize.y, positionSize.width, positionSize.height ); } void WindowBaseEcoreWl2::MoveResize( PositionSize positionSize ) { + mWindowPositionSize = positionSize; ecore_wl2_window_sync_geometry_set( mEcoreWindow, ++mMoveResizeSerial, positionSize.x, positionSize.y, positionSize.width, positionSize.height ); } @@ -1580,11 +1588,18 @@ void WindowBaseEcoreWl2::SetAcceptFocus( bool accept ) void WindowBaseEcoreWl2::Show() { + if( !mVisible ) + { + ecore_wl2_window_geometry_set( mEcoreWindow, mWindowPositionSize.x, mWindowPositionSize.y, mWindowPositionSize.width, mWindowPositionSize.height ); + } + mVisible = true; + ecore_wl2_window_show( mEcoreWindow ); } void WindowBaseEcoreWl2::Hide() { + mVisible = false; ecore_wl2_window_hide( mEcoreWindow ); } 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 c7a7240..f429435 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 @@ -496,6 +496,9 @@ private: uint32_t mBrightnessChangeState; bool mBrightnessChangeDone; + bool mVisible:1; + Dali::PositionSize mWindowPositionSize; + bool mOwnSurface; volatile uint32_t mMoveResizeSerial; -- 2.7.4 From 5167c1e4978ea61ffc8c3f74c15595b97662d347 Mon Sep 17 00:00:00 2001 From: Wonsik Jung Date: Tue, 2 Jun 2020 15:21:21 +0900 Subject: [PATCH 05/16] DALi Version 1.5.14 Change-Id: I2a694e23d32a43a58eba993458e54670a3373302 --- 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 5a65498..28b3ebd 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 = 13; +const unsigned int ADAPTOR_MICRO_VERSION = 14; const char * const ADAPTOR_BUILD_DATE = __DATE__ " " __TIME__; #ifdef DEBUG_ENABLED diff --git a/packaging/dali-adaptor.spec b/packaging/dali-adaptor.spec index c5a2b63..acc28db 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.13 +Version: 1.5.14 Release: 1 Group: System/Libraries License: Apache-2.0 and BSD-3-Clause and MIT -- 2.7.4 From d95e058075b693420f96b803425a14f994929d43 Mon Sep 17 00:00:00 2001 From: Heeyong Song Date: Tue, 19 May 2020 17:32:25 +0900 Subject: [PATCH 06/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 07/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 08/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 09/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 10/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 11/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 12/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 13/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 14/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 15/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 bcc548aaa80f4401d414d9cde92550b57a8c569b Mon Sep 17 00:00:00 2001 From: "Seungho, Baek" Date: Wed, 10 Jun 2020 16:04:07 +0900 Subject: [PATCH 16/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