From: Victor Cebollada Date: Thu, 12 Oct 2017 15:36:42 +0000 (+0100) Subject: [4.0] Render to Frame Buffer Object. X-Git-Tag: accepted/tizen/4.0/unified/20171121.061728~7^2 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-adaptor.git;a=commitdiff_plain;h=62911dcd069b5cfebc0f2589621cd1620e570997 [4.0] Render to Frame Buffer Object. * A new feature has been added to dali-core/dali-adaptor to measure the performance above 60 fps avoiding the vsync. It renders the frames into a Frame Buffer Object. However, is possible to render into the default Frame Buffer every certain number of frames. * Usage: $ DALI_FPS_TRACKING=1 DALI_RENDER_TO_FBO=30 path_to_DALi_app Will render into the Frame Buffer Object 29 frames of 30, the 30th will be rendered into the Frame Buffer. Will show as well the FPS. Change-Id: I3a56078e5ec97ffda781a1242576dda25d148110 Signed-off-by: Victor Cebollada (cherry picked from commit 1a38e92ed83c0392dbd17c8047b13c9fc8ca1b06) --- diff --git a/adaptors/base/combined-update-render/combined-update-render-controller.cpp b/adaptors/base/combined-update-render/combined-update-render-controller.cpp index 2b3ed58..9bb5bdc 100644 --- a/adaptors/base/combined-update-render/combined-update-render-controller.cpp +++ b/adaptors/base/combined-update-render/combined-update-render-controller.cpp @@ -400,6 +400,10 @@ void CombinedUpdateRenderController::UpdateRenderThread() uint64_t timeToSleepUntil = 0; int extraFramesDropped = 0; + const unsigned int renderToFboInterval = mEnvironmentOptions.GetRenderToFboInterval(); + const bool renderToFboEnabled = 0u != renderToFboInterval; + unsigned int frameCount = 0u; + while( UpdateRenderReady( useElapsedTime, updateRequired, timeToSleepUntil ) ) { LOG_UPDATE_RENDER_TRACE; @@ -437,6 +441,9 @@ void CombinedUpdateRenderController::UpdateRenderThread() // RESIZE SURFACE ////////////////////////////// + const bool isRenderingToFbo = renderToFboEnabled && ( ( 0u == frameCount ) || ( 0u != frameCount % renderToFboInterval ) ); + ++frameCount; + // The resizing will be applied in the next loop bool surfaceResized = ShouldSurfaceBeResized(); if( DALI_UNLIKELY( surfaceResized ) ) @@ -467,7 +474,12 @@ void CombinedUpdateRenderController::UpdateRenderThread() Integration::UpdateStatus updateStatus; AddPerformanceMarker( PerformanceInterface::UPDATE_START ); - mCore.Update( frameDelta, currentTime, nextFrameTime, updateStatus ); + mCore.Update( frameDelta, + currentTime, + nextFrameTime, + updateStatus, + renderToFboEnabled, + isRenderingToFbo ); AddPerformanceMarker( PerformanceInterface::UPDATE_END ); unsigned int keepUpdatingStatus = updateStatus.KeepUpdating(); @@ -497,7 +509,7 @@ void CombinedUpdateRenderController::UpdateRenderThread() if( renderStatus.NeedsPostRender() ) { - mRenderHelper.PostRender(); + mRenderHelper.PostRender( isRenderingToFbo ); } // Trigger event thread to request Update/Render thread to sleep if update not required @@ -549,8 +561,12 @@ void CombinedUpdateRenderController::UpdateRenderThread() } } - // Sleep until at least the the default frame duration has elapsed. This will return immediately if the specified end-time has already passed. - TimeService::SleepUntil( timeToSleepUntil ); + // Render to FBO is intended to measure fps above 60 so sleep is not wanted. + if( 0u == renderToFboInterval ) + { + // Sleep until at least the the default frame duration has elapsed. This will return immediately if the specified end-time has already passed. + TimeService::SleepUntil( timeToSleepUntil ); + } } // Inform core of context destruction & shutdown EGL diff --git a/adaptors/base/environment-options.cpp b/adaptors/base/environment-options.cpp index db6660c..7d2d354 100644 --- a/adaptors/base/environment-options.cpp +++ b/adaptors/base/environment-options.cpp @@ -103,14 +103,15 @@ EnvironmentOptions::EnvironmentOptions() mPanMinimumDistance(-1), mPanMinimumEvents(-1), mGlesCallTime( 0 ), - mWindowWidth( 0 ), - mWindowHeight( 0 ), + mWindowWidth( 0u ), + mWindowHeight( 0u ), mThreadingMode( ThreadingMode::COMBINED_UPDATE_RENDER ), - mRenderRefreshRate( 1 ), + mRenderRefreshRate( 1u ), mGlesCallAccumulate( false ), mMultiSamplingLevel( DEFAULT_MULTI_SAMPLING_LEVEL ), mMaxTextureSize( 0 ), mIndicatorVisibleMode( -1 ), + mRenderToFboInterval( 0u ), mLogFunction( NULL ) { ParseEnvironmentOptions(); @@ -272,6 +273,11 @@ int EnvironmentOptions::GetIndicatorVisibleMode() const return mIndicatorVisibleMode; } +unsigned int EnvironmentOptions::GetRenderToFboInterval() const +{ + return mRenderToFboInterval; +} + bool EnvironmentOptions::PerformanceServerRequired() const { return ( ( GetPerformanceStatsLoggingOptions() > 0) || @@ -437,6 +443,8 @@ void EnvironmentOptions::ParseEnvironmentOptions() mIndicatorVisibleMode = indicatorVisibleMode; } } + + mRenderToFboInterval = GetIntegerEnvironmentVariable( DALI_RENDER_TO_FBO, 0u ); } } // Adaptor diff --git a/adaptors/base/environment-options.h b/adaptors/base/environment-options.h index 2d2300d..080850e 100644 --- a/adaptors/base/environment-options.h +++ b/adaptors/base/environment-options.h @@ -1,5 +1,5 @@ -#ifndef __DALI_INTERNAL_ADAPTOR_ENVIRONMENT_OPTIONS_H__ -#define __DALI_INTERNAL_ADAPTOR_ENVIRONMENT_OPTIONS_H__ +#ifndef DALI_INTERNAL_ADAPTOR_ENVIRONMENT_OPTIONS_H +#define DALI_INTERNAL_ADAPTOR_ENVIRONMENT_OPTIONS_H /* * Copyright (c) 2017 Samsung Electronics Co., Ltd. @@ -217,6 +217,13 @@ public: */ int GetIndicatorVisibleMode() const; + /** + * @brief Retrieves the interval of frames to be rendered into the Frame Buffer Object and the Frame Buffer. + * + * @return The number of frames that are going to be rendered into the Frame Buffer Object but the last one which is going to be rendered into the Frame Buffer. + */ + unsigned int GetRenderToFboInterval() const; + private: // Internal /** @@ -255,6 +262,7 @@ private: // Data int mMultiSamplingLevel; ///< The number of samples required in multisample buffers unsigned int mMaxTextureSize; ///< The maximum texture size that GL can handle int mIndicatorVisibleMode; ///< Indicator visible mode + unsigned int mRenderToFboInterval; ///< The number of frames that are going to be rendered into the Frame Buffer Object but the last one which is going to be rendered into the Frame Buffer. Dali::Integration::Log::LogFunction mLogFunction; @@ -270,4 +278,4 @@ private: // Data } // Internal } // Dali -#endif // __DALI_INTERNAL_ADAPTOR_ENVIRONMENT_OPTIONS_H__ +#endif // DALI_INTERNAL_ADAPTOR_ENVIRONMENT_OPTIONS_H diff --git a/adaptors/base/environment-variables.h b/adaptors/base/environment-variables.h index 72b4834..234ce3c 100644 --- a/adaptors/base/environment-variables.h +++ b/adaptors/base/environment-variables.h @@ -1,5 +1,5 @@ -#ifndef __DALI_INTERNAL_ADAPTOR_ENVIRONMENT_VARIABLES_H__ -#define __DALI_INTERNAL_ADAPTOR_ENVIRONMENT_VARIABLES_H__ +#ifndef DALI_INTERNAL_ADAPTOR_ENVIRONMENT_VARIABLES_H +#define DALI_INTERNAL_ADAPTOR_ENVIRONMENT_VARIABLES_H /* * Copyright (c) 2017 Samsung Electronics Co., Ltd. @@ -99,10 +99,12 @@ namespace Adaptor #define DALI_ENV_INDICATOR_VISIBLE_MODE "DALI_INDICATOR_VISIBLE_MODE" +#define DALI_RENDER_TO_FBO "DALI_RENDER_TO_FBO" + } // namespace Adaptor } // namespace Internal } // namespace Dali -#endif // __DALI_INTERNAL_ADAPTOR_ENVIRONMENT_VARIABLES_H__ +#endif // DALI_INTERNAL_ADAPTOR_ENVIRONMENT_VARIABLES_H diff --git a/adaptors/base/render-helper.cpp b/adaptors/base/render-helper.cpp index c77d2c9..1276078 100644 --- a/adaptors/base/render-helper.cpp +++ b/adaptors/base/render-helper.cpp @@ -155,15 +155,23 @@ bool RenderHelper::PreRender() return true; } -void RenderHelper::PostRender() +void RenderHelper::PostRender( bool renderToFbo ) { // Inform the gl implementation that rendering has finished before informing the surface mGLES.PostRender(); - if( mSurface ) + if( renderToFbo ) + { + mGLES.Flush(); + mGLES.Finish(); + } + else { - // Inform the surface that rendering this frame has finished. - mSurface->PostRender( *mEGL, mGLES, mDisplayConnection, mSurfaceReplaced, mSurfaceResized ); + if( mSurface ) + { + // Inform the surface that rendering this frame has finished. + mSurface->PostRender( *mEGL, mGLES, mDisplayConnection, mSurfaceReplaced, mSurfaceResized ); + } } mSurfaceReplaced = false; mSurfaceResized = false; diff --git a/adaptors/base/render-helper.h b/adaptors/base/render-helper.h index 5d26d16..4e12afe 100644 --- a/adaptors/base/render-helper.h +++ b/adaptors/base/render-helper.h @@ -1,5 +1,5 @@ -#ifndef __DALI_INTERNAL_RENDER_HELPER_H__ -#define __DALI_INTERNAL_RENDER_HELPER_H__ +#ifndef DALI_INTERNAL_RENDER_HELPER_H +#define DALI_INTERNAL_RENDER_HELPER_H /* * Copyright (c) 2017 Samsung Electronics Co., Ltd. @@ -128,8 +128,10 @@ public: * Called after core has rendered the scene * * @note Called from render thread + * + * @param[in] renderToFbo Whether to render to a Frame Buffer Object. */ - void PostRender(); + void PostRender( bool renderToFbo ); private: @@ -156,4 +158,4 @@ private: // Data } // namespace Dali -#endif // __DALI_INTERNAL_RENDER_HELPER_H__ +#endif // DALI_INTERNAL_RENDER_HELPER_H diff --git a/adaptors/common/adaptor-impl.cpp b/adaptors/common/adaptor-impl.cpp index c0a6699..0c7c4e4 100644 --- a/adaptors/common/adaptor-impl.cpp +++ b/adaptors/common/adaptor-impl.cpp @@ -144,7 +144,13 @@ void Adaptor::Initialize( Dali::Configuration::ContextLoss configuration ) EglSyncImplementation* eglSyncImpl = mEglFactory->GetSyncImplementation(); - mCore = Integration::Core::New( *this, *mPlatformAbstraction, *mGLES, *eglSyncImpl, *mGestureManager, dataRetentionPolicy ); + mCore = Integration::Core::New( *this, + *mPlatformAbstraction, + *mGLES, + *eglSyncImpl, + *mGestureManager, + dataRetentionPolicy , + 0u != mEnvironmentOptions->GetRenderToFboInterval() ); const unsigned int timeInterval = mEnvironmentOptions->GetObjectProfilerInterval(); if( 0u < timeInterval ) 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 6636676..54a69bb 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 @@ -62,13 +62,13 @@ void TestApplication::Initialize() // We always need the first update! mStatus.keepUpdating = Integration::KeepUpdating::STAGE_KEEP_RENDERING; - mCore = Dali::Integration::Core::New( - mRenderController, - mPlatformAbstraction, - mGlAbstraction, - mGlSyncAbstraction, - mGestureManager, - mDataRetentionPolicy); + mCore = Dali::Integration::Core::New( mRenderController, + mPlatformAbstraction, + mGlAbstraction, + mGlSyncAbstraction, + mGestureManager, + mDataRetentionPolicy, + false ); mCore->ContextCreated(); mCore->SurfaceResized( mSurfaceWidth, mSurfaceHeight ); @@ -171,7 +171,7 @@ void TestApplication::DoUpdate( unsigned int intervalMilliseconds, const char* l unsigned int nextVSyncTime = mLastVSyncTime + intervalMilliseconds; float elapsedSeconds = intervalMilliseconds / 1e3f; - mCore->Update( elapsedSeconds, mLastVSyncTime, nextVSyncTime, mStatus ); + mCore->Update( elapsedSeconds, mLastVSyncTime, nextVSyncTime, mStatus, false, false ); GetRenderController().Initialize();