From 79881246746f65474b24ea4fe14151ccef8df3f4 Mon Sep 17 00:00:00 2001 From: Richard Huang Date: Thu, 20 Feb 2020 10:55:01 +0000 Subject: [PATCH] Remove RenderSurface from Core Change-Id: I416d7b5613634b6d32f9531c5ad15ba3ca62a5d2 --- automated-tests/src/dali-internal/CMakeLists.txt | 1 - automated-tests/src/dali/CMakeLists.txt | 1 - .../dali-test-suite-utils/test-application.cpp | 18 +- .../dali/dali-test-suite-utils/test-application.h | 2 - .../test-gl-context-helper-abstraction.h | 8 +- .../dali-test-suite-utils/test-render-surface.cpp | 115 ---- .../dali-test-suite-utils/test-render-surface.h | 155 ------ automated-tests/src/dali/utc-Dali-RenderTask.cpp | 6 +- automated-tests/src/dali/utc-Dali-Scene.cpp | 201 +------ build/tizen/CMakeLists.txt | 1 - dali/integration-api/core.cpp | 20 +- dali/integration-api/core.h | 35 +- dali/integration-api/file.list | 1 - .../gl-context-helper-abstraction.h | 9 +- dali/integration-api/render-surface.h | 203 ------- dali/integration-api/scene.cpp | 19 +- dali/integration-api/scene.h | 25 +- dali/internal/common/core-impl.cpp | 27 +- dali/internal/common/core-impl.h | 18 +- dali/internal/event/common/scene-impl.cpp | 111 ++-- dali/internal/event/common/scene-impl.h | 46 +- .../internal/event/rendering/frame-buffer-impl.cpp | 72 +-- dali/internal/event/rendering/frame-buffer-impl.h | 30 +- dali/internal/file.list | 4 +- .../render/common/render-instruction-container.cpp | 45 +- .../render/common/render-instruction-container.h | 26 +- dali/internal/render/common/render-instruction.cpp | 3 +- dali/internal/render/common/render-instruction.h | 5 +- dali/internal/render/common/render-manager.cpp | 596 ++++++++++----------- dali/internal/render/common/render-manager.h | 70 ++- dali/internal/render/gl-resources/context.cpp | 6 +- dali/internal/render/gl-resources/context.h | 18 +- ...re-frame-buffer.cpp => render-frame-buffer.cpp} | 28 +- .../render/renderers/render-frame-buffer.h | 53 +- .../renderers/render-surface-frame-buffer.cpp | 137 ----- .../render/renderers/render-surface-frame-buffer.h | 156 ------ .../render/renderers/render-texture-frame-buffer.h | 127 ----- dali/internal/update/common/scene-graph-scene.cpp | 82 +++ dali/internal/update/common/scene-graph-scene.h | 94 ++++ .../manager/render-instruction-processor.cpp | 11 +- .../update/manager/render-instruction-processor.h | 6 +- .../update/manager/render-task-processor.cpp | 13 +- .../update/manager/render-task-processor.h | 4 +- dali/internal/update/manager/update-manager.cpp | 67 ++- dali/internal/update/manager/update-manager.h | 61 ++- .../render-tasks/scene-graph-render-task.cpp | 18 +- .../update/render-tasks/scene-graph-render-task.h | 19 +- 47 files changed, 999 insertions(+), 1774 deletions(-) delete mode 100644 automated-tests/src/dali/dali-test-suite-utils/test-render-surface.cpp delete mode 100644 automated-tests/src/dali/dali-test-suite-utils/test-render-surface.h delete mode 100644 dali/integration-api/render-surface.h rename dali/internal/render/renderers/{render-texture-frame-buffer.cpp => render-frame-buffer.cpp} (81%) delete mode 100644 dali/internal/render/renderers/render-surface-frame-buffer.cpp delete mode 100644 dali/internal/render/renderers/render-surface-frame-buffer.h delete mode 100644 dali/internal/render/renderers/render-texture-frame-buffer.h create mode 100644 dali/internal/update/common/scene-graph-scene.cpp create mode 100644 dali/internal/update/common/scene-graph-scene.h diff --git a/automated-tests/src/dali-internal/CMakeLists.txt b/automated-tests/src/dali-internal/CMakeLists.txt index 5c6a868..c23ab7d 100644 --- a/automated-tests/src/dali-internal/CMakeLists.txt +++ b/automated-tests/src/dali-internal/CMakeLists.txt @@ -26,7 +26,6 @@ LIST(APPEND TC_SOURCES ../dali/dali-test-suite-utils/test-native-image.cpp ../dali/dali-test-suite-utils/test-platform-abstraction.cpp ../dali/dali-test-suite-utils/test-render-controller.cpp - ../dali/dali-test-suite-utils/test-render-surface.cpp ../dali/dali-test-suite-utils/test-trace-call-stack.cpp ) diff --git a/automated-tests/src/dali/CMakeLists.txt b/automated-tests/src/dali/CMakeLists.txt index 6db6c25..8eabe80 100644 --- a/automated-tests/src/dali/CMakeLists.txt +++ b/automated-tests/src/dali/CMakeLists.txt @@ -125,7 +125,6 @@ LIST(APPEND TC_SOURCES dali-test-suite-utils/test-native-image.cpp dali-test-suite-utils/test-platform-abstraction.cpp dali-test-suite-utils/test-render-controller.cpp - dali-test-suite-utils/test-render-surface.cpp dali-test-suite-utils/test-trace-call-stack.cpp ) diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-application.cpp b/automated-tests/src/dali/dali-test-suite-utils/test-application.cpp index f5d670d..f85f14d 100644 --- a/automated-tests/src/dali/dali-test-suite-utils/test-application.cpp +++ b/automated-tests/src/dali/dali-test-suite-utils/test-application.cpp @@ -27,8 +27,7 @@ TestApplication::TestApplication( uint32_t surfaceWidth, uint32_t horizontalDpi, uint32_t verticalDpi, bool initialize ) -: mRenderSurface( NULL ), - mCore( NULL ), +: mCore( NULL ), mSurfaceWidth( surfaceWidth ), mSurfaceHeight( surfaceHeight ), mFrame( 0u ), @@ -75,8 +74,7 @@ void TestApplication::CreateCore() void TestApplication::CreateScene() { - mRenderSurface = new TestRenderSurface( Dali::PositionSize( 0, 0, mSurfaceWidth, mSurfaceHeight ) ); - mScene = Dali::Integration::Scene::New( *mRenderSurface ); + mScene = Dali::Integration::Scene::New( Size( static_cast( mSurfaceWidth ), static_cast( mSurfaceHeight ) ) ); mScene.SetDpi( Vector2( static_cast( mDpi.x ), static_cast( mDpi.y ) ) ); } @@ -89,7 +87,6 @@ void TestApplication::InitializeCore() TestApplication::~TestApplication() { Dali::Integration::Log::UninstallLogFunction(); - delete mRenderSurface; delete mCore; } @@ -190,7 +187,11 @@ void TestApplication::DoUpdate( uint32_t intervalMilliseconds, const char* locat bool TestApplication::Render( uint32_t intervalMilliseconds, const char* location ) { DoUpdate( intervalMilliseconds, location ); - mCore->Render( mRenderStatus, false /*do not force clear*/, false /*do not skip rendering*/ ); + + 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->PostRender( false /*do not skip rendering*/ ); mFrame++; @@ -216,7 +217,10 @@ bool TestApplication::GetRenderNeedsUpdate() bool TestApplication::RenderOnly( ) { // Update Time values - mCore->Render( mRenderStatus, false /*do not force clear*/, false /*do not skip rendering*/ ); + 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->PostRender( false /*do not skip rendering*/ ); mFrame++; diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-application.h b/automated-tests/src/dali/dali-test-suite-utils/test-application.h index 2606a56..a922e23 100644 --- a/automated-tests/src/dali/dali-test-suite-utils/test-application.h +++ b/automated-tests/src/dali/dali-test-suite-utils/test-application.h @@ -24,7 +24,6 @@ #include "test-gl-abstraction.h" #include "test-gl-context-helper-abstraction.h" #include "test-render-controller.h" -#include "test-render-surface.h" #include #include #include @@ -95,7 +94,6 @@ protected: TestGlAbstraction mGlAbstraction; TestGlSyncAbstraction mGlSyncAbstraction; TestGlContextHelperAbstraction mGlContextHelperAbstraction; - TestRenderSurface* mRenderSurface; Integration::UpdateStatus mStatus; Integration::RenderStatus mRenderStatus; diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-gl-context-helper-abstraction.h b/automated-tests/src/dali/dali-test-suite-utils/test-gl-context-helper-abstraction.h index 0442f0d..ce150d1 100644 --- a/automated-tests/src/dali/dali-test-suite-utils/test-gl-context-helper-abstraction.h +++ b/automated-tests/src/dali/dali-test-suite-utils/test-gl-context-helper-abstraction.h @@ -2,7 +2,7 @@ #define TEST_GL_CONTEXT_HELPER_ABSTRACTION_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. @@ -46,12 +46,6 @@ public: virtual void MakeSurfacelessContextCurrent() {}; /** - * @brief Switch to the GL context of the specific render surface - * @param[in] surface The render surface - */ - virtual void MakeContextCurrent( Integration::RenderSurface* surface ) {}; - - /** * @brief Clear the GL context */ virtual void MakeContextNull() {}; diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-render-surface.cpp b/automated-tests/src/dali/dali-test-suite-utils/test-render-surface.cpp deleted file mode 100644 index 332d77e..0000000 --- a/automated-tests/src/dali/dali-test-suite-utils/test-render-surface.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2019 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test-render-surface.h" - -namespace Dali -{ - -TestRenderSurface::TestRenderSurface( Dali::PositionSize positionSize ) -: mPositionSize( positionSize ), - mBackgroundColor() -{ -} - -TestRenderSurface::~TestRenderSurface() -{ -} - -Dali::PositionSize TestRenderSurface::GetPositionSize() const -{ - return mPositionSize; -}; - -void TestRenderSurface::GetDpi( unsigned int& dpiHorizontal, unsigned int& dpiVertical ) -{ - dpiHorizontal = dpiVertical = 96; -}; - -void TestRenderSurface::InitializeGraphics() -{ -} - -void TestRenderSurface::CreateSurface() -{ -} - -void TestRenderSurface::DestroySurface() -{ -} - -bool TestRenderSurface::ReplaceGraphicsSurface() -{ - return false; -} - -void TestRenderSurface::MoveResize( Dali::PositionSize positionSize ) -{ - mPositionSize = positionSize; -} - -void TestRenderSurface::StartRender() -{ -} - -bool TestRenderSurface::PreRender( bool resizingSurface ) -{ - return true; -} - -void TestRenderSurface::PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface ) -{ -} - -void TestRenderSurface::StopRender() -{ -} - -void TestRenderSurface::ReleaseLock() -{ -} - -Dali::Integration::RenderSurface::Type TestRenderSurface::GetSurfaceType() -{ - return WINDOW_RENDER_SURFACE; -} - -void TestRenderSurface::MakeContextCurrent() -{ -} - -Integration::DepthBufferAvailable TestRenderSurface::GetDepthBufferRequired() -{ - return Integration::DepthBufferAvailable::TRUE; -} - -Integration::StencilBufferAvailable TestRenderSurface::GetStencilBufferRequired() -{ - return Integration::StencilBufferAvailable::TRUE; -} - -void TestRenderSurface::SetBackgroundColor( Vector4 color ) -{ - mBackgroundColor = color; -} - -Vector4 TestRenderSurface::GetBackgroundColor() -{ - return mBackgroundColor; -} - -} // Namespace dali diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-render-surface.h b/automated-tests/src/dali/dali-test-suite-utils/test-render-surface.h deleted file mode 100644 index fba89c2..0000000 --- a/automated-tests/src/dali/dali-test-suite-utils/test-render-surface.h +++ /dev/null @@ -1,155 +0,0 @@ -#ifndef TEST_REENDER_SURFACE_H -#define TEST_REENDER_SURFACE_H - -/* - * Copyright (c) 2019 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 -{ - -/** - * Concrete implementation of the RenderSurface class. - */ -class DALI_CORE_API TestRenderSurface : public Dali::Integration::RenderSurface -{ -public: - - /** - * @copydoc Dali::Integration::RenderSurface::RenderSurface - */ - TestRenderSurface( Dali::PositionSize positionSize ); - - /** - * @copydoc Dali::Integration::RenderSurface::~RenderSurface - */ - virtual ~TestRenderSurface(); - - /** - * @copydoc Dali::Integration::RenderSurface::GetPositionSize - */ - virtual Dali::PositionSize GetPositionSize() const; - - /** - * @copydoc Dali::Integration::RenderSurface::GetDpi - */ - virtual void GetDpi( unsigned int& dpiHorizontal, unsigned int& dpiVertical ); - - /** - * @copydoc Dali::Integration::RenderSurface::InitializeGraphics - */ - virtual void InitializeGraphics(); - - /** - * @copydoc Dali::Integration::RenderSurface::CreateSurface - */ - virtual void CreateSurface(); - - /** - * @copydoc Dali::Integration::RenderSurface::DestroySurface - */ - virtual void DestroySurface(); - - /** - * @copydoc Dali::Integration::RenderSurface::ReplaceGraphicsSurface - */ - virtual bool ReplaceGraphicsSurface(); - - /** - * @copydoc Dali::Integration::RenderSurface::MoveResize - */ - virtual void MoveResize( Dali::PositionSize positionSize ); - - /** - * @copydoc Dali::Integration::RenderSurface::StartRender - */ - virtual void StartRender(); - - /** - * @copydoc Dali::Integration::RenderSurface::PreRender - */ - virtual bool PreRender( bool resizingSurface ); - - /** - * @copydoc Dali::Integration::RenderSurface::PostRender - */ - virtual void PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface ); - - /** - * @copydoc Dali::Integration::RenderSurface::StopRender - */ - virtual void StopRender(); - - /** - * @copydoc Dali::Integration::RenderSurface::ReleaseLock - */ - virtual void ReleaseLock(); - - /** - * @copydoc Dali::Integration::RenderSurface::GetSurfaceType - */ - virtual Dali::Integration::RenderSurface::Type GetSurfaceType(); - - /** - * @copydoc Dali::Integration::RenderSurface::MakeContextCurrent - */ - virtual void MakeContextCurrent(); - - /** - * @copydoc Dali::Integration::RenderSurface::GetDepthBufferRequired - */ - virtual Integration::DepthBufferAvailable GetDepthBufferRequired(); - - /** - * @copydoc Dali::Integration::RenderSurface::GetStencilBufferRequired - */ - virtual Integration::StencilBufferAvailable GetStencilBufferRequired(); - - /** - * @copydoc Dali::Integration::RenderSurface::SetBackgroundColor - */ - virtual void SetBackgroundColor( Vector4 color ); - - /** - * @copydoc Dali::Integration::RenderSurface::GetBackgroundColor - */ - virtual Vector4 GetBackgroundColor(); - -private: - - /** - * @brief Undefined copy constructor. RenderSurface cannot be copied - */ - TestRenderSurface( const TestRenderSurface& rhs ); - - /** - * @brief Undefined assignment operator. RenderSurface cannot be copied - */ - TestRenderSurface& operator=( const TestRenderSurface& rhs ); - -private: - - Dali::PositionSize mPositionSize; - Vector4 mBackgroundColor; ///< The background color of the surface -}; - -} // Dali - -#endif diff --git a/automated-tests/src/dali/utc-Dali-RenderTask.cpp b/automated-tests/src/dali/utc-Dali-RenderTask.cpp index 4bd248e..e5ea26b 100644 --- a/automated-tests/src/dali/utc-Dali-RenderTask.cpp +++ b/automated-tests/src/dali/utc-Dali-RenderTask.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. @@ -1183,9 +1183,9 @@ int UtcDaliRenderTaskGetFrameBufferN(void) RenderTask task = taskList.GetTask( 0u ); - // A scene creates frame buffer by default + // By default render-tasks do not render off-screen FrameBuffer frameBuffer = task.GetFrameBuffer(); - DALI_TEST_CHECK( frameBuffer ); + DALI_TEST_CHECK( !frameBuffer ); END_TEST; } diff --git a/automated-tests/src/dali/utc-Dali-Scene.cpp b/automated-tests/src/dali/utc-Dali-Scene.cpp index b439957..fd790b9 100644 --- a/automated-tests/src/dali/utc-Dali-Scene.cpp +++ b/automated-tests/src/dali/utc-Dali-Scene.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. @@ -142,8 +142,7 @@ struct TouchFunctor if ( signalData.createNewScene ) { - TestRenderSurface* surface = new TestRenderSurface( PositionSize( 0.0f, 0.0f, 480.0f, 800.0f ) ); // This is a leak, but we need to keep the surface alive till the end - Dali::Integration::Scene scene = Dali::Integration::Scene::New( *surface ); + Dali::Integration::Scene scene = Dali::Integration::Scene::New( Size( 480.0f, 800.0f ) ); DALI_TEST_CHECK( scene ); signalData.newSceneCreated = true; @@ -407,8 +406,7 @@ int UtcDaliSceneDiscard(void) tet_infoline("Testing Dali::Scene::Discard"); // Create a new Scene - TestRenderSurface surface( PositionSize( 0.0f, 0.0f, 480.0f, 800.0f ) ); - Dali::Integration::Scene scene = Dali::Integration::Scene::New( surface ); + Dali::Integration::Scene scene = Dali::Integration::Scene::New( Size( 480.0f, 800.0f ) ); DALI_TEST_CHECK( scene ); // One reference of scene kept here and the other one kept in the Core @@ -478,8 +476,7 @@ int UtcDaliSceneRootLayerAndSceneAlignment(void) TestApplication application; // Create a Scene - TestRenderSurface surface( PositionSize( 0.0f, 0.0f, 480.0f, 800.0f ) ); - Dali::Integration::Scene scene = Dali::Integration::Scene::New( surface ); + Dali::Integration::Scene scene = Dali::Integration::Scene::New( Size( 480.0f, 800.0f ) ); DALI_TEST_CHECK( scene ); // One reference of scene kept here and the other one kept in the Core @@ -514,8 +511,7 @@ int UtcDaliSceneRootLayerAndSceneAlignment(void) DALI_TEST_CHECK( rootLayer.GetBaseObject().ReferenceCount() == 1 ); // Create a new Scene while the root layer of the deleted scene is still alive - TestRenderSurface surface2( PositionSize( 0.0f, 0.0f, 480.0f, 800.0f ) ); - Dali::Integration::Scene newScene = Dali::Integration::Scene::New( surface2 ); + Dali::Integration::Scene newScene = Dali::Integration::Scene::New( Size( 480.0f, 800.0f ) ); DALI_TEST_CHECK( newScene ); // Render and notify. @@ -536,43 +532,6 @@ int UtcDaliSceneRootLayerAndSceneAlignment(void) END_TEST; } -int UtcDaliSceneDeleteSurface(void) -{ - TestApplication application; - - // Create the render surface for the scene - TestRenderSurface* renderSurface = new TestRenderSurface( Dali::PositionSize( 0, 0, 480.0f, 800.0f ) ); - - // Create a Scene - Dali::Integration::Scene scene = Dali::Integration::Scene::New( *renderSurface ); - DALI_TEST_CHECK( scene ); - - // Render and notify. - application.SendNotification(); - application.Render(0); - - // Add a renderable actor to the scene - auto actor = CreateRenderableActor(); - scene.Add( actor ); - - // Render and notify. - application.SendNotification(); - application.Render(0); - - // Notify the Core that the render surface will be deleted. - application.GetCore().SurfaceDeleted( renderSurface ); - - // Delete the render surface - delete renderSurface; - renderSurface = nullptr; - - // Render and notify. - application.SendNotification(); - application.Render(0); - - END_TEST; -} - int UtcDaliSceneEventProcessingFinishedP(void) { TestApplication application; @@ -916,79 +875,6 @@ int UtcDaliSceneSignalWheelEventP(void) END_TEST; } -int UtcDaliSceneEnsureEmptySceneCleared(void) -{ - tet_infoline( "Ensure we clear the newly added window" ); - - TestApplication application; - - auto& glAbstraction = application.GetGlAbstraction(); - auto clearCountBefore = glAbstraction.GetClearCountCalled(); - - application.SendNotification(); - application.Render(); - - // No actor, no rendering at all - DALI_TEST_EQUALS( glAbstraction.GetClearCountCalled(), clearCountBefore, TEST_LOCATION ); - DALI_TEST_EQUALS( glAbstraction.GetLastClearColor(), Color::TRANSPARENT, TEST_LOCATION ); - - // Need to create a renderable as we don't start rendering until we have at least one - // We don't need to add this to any scene - auto actor = CreateRenderableActor(); - - application.SendNotification(); - application.Render(); - - // Default background color - DALI_TEST_EQUALS( glAbstraction.GetClearCountCalled(), clearCountBefore + 1, TEST_LOCATION ); - DALI_TEST_EQUALS( glAbstraction.GetLastClearColor(), Color::BLACK, TEST_LOCATION ); - - // Create a new scene and set the background colors of both the new and the main scenes - auto defaultScene = application.GetScene(); - defaultScene.SetBackgroundColor( Color::WHITE ); - - application.SendNotification(); - application.Render(); - - DALI_TEST_EQUALS( glAbstraction.GetClearCountCalled(), clearCountBefore + 2, TEST_LOCATION ); - DALI_TEST_EQUALS( glAbstraction.GetLastClearColor(), Color::WHITE, TEST_LOCATION ); - - TestRenderSurface surface( PositionSize( 0.0f, 0.0f, 480.0f, 800.0f ) ); - auto newScene = Integration::Scene::New( surface ); - newScene.SetBackgroundColor( Color::RED ); - - application.SendNotification(); - application.Render(); - - // + 2 clear for 2 scenes - DALI_TEST_EQUALS( glAbstraction.GetClearCountCalled(), clearCountBefore + 4, TEST_LOCATION ); - DALI_TEST_EQUALS( glAbstraction.GetLastClearColor(), Color::RED, TEST_LOCATION ); - - // Add the actor to the main scene - defaultScene.Add( actor ); - - application.SendNotification(); - application.Render(); - - // + 2 clear for 2 scenes - DALI_TEST_EQUALS( glAbstraction.GetClearCountCalled(), clearCountBefore + 6, TEST_LOCATION ); - DALI_TEST_EQUALS( glAbstraction.GetLastClearColor(), Color::RED, TEST_LOCATION ); - - // Add another scene and set its background color, ensure we clear it to the appropriate color - // + 3 clear for 3 scenes - TestRenderSurface surface2( PositionSize( 0.0f, 0.0f, 480.0f, 800.0f ) ); - auto thirdScene = Integration::Scene::New( surface2 ); - thirdScene.SetBackgroundColor( Color::BLUE ); - - application.SendNotification(); - application.Render(); - - DALI_TEST_EQUALS( glAbstraction.GetClearCountCalled(), clearCountBefore + 9, TEST_LOCATION ); - DALI_TEST_EQUALS( glAbstraction.GetLastClearColor(), Color::BLUE, TEST_LOCATION ); - - END_TEST; -} - int UtcDaliSceneSurfaceResizedDefaultScene(void) { tet_infoline( "Ensure resizing of the surface is handled properly" ); @@ -996,18 +882,16 @@ int UtcDaliSceneSurfaceResizedDefaultScene(void) TestApplication application; auto defaultScene = application.GetScene(); - Integration::RenderSurface* defaultSurface = defaultScene.GetSurface(); - DALI_TEST_CHECK( defaultSurface ); + DALI_TEST_CHECK( defaultScene ); - // Ensure stage size matches the surface size + // Ensure stage size matches the scene size auto stage = Stage::GetCurrent(); - DALI_TEST_EQUALS( stage.GetSize(), Vector2( defaultSurface->GetPositionSize().width, defaultSurface->GetPositionSize().height ), TEST_LOCATION ); + DALI_TEST_EQUALS( stage.GetSize(), defaultScene.GetSize(), TEST_LOCATION ); - // Resize the surface and inform the scene accordingly + // Resize the scene Vector2 newSize( 1000.0f, 2000.0f ); DALI_TEST_CHECK( stage.GetSize() != newSize ); - defaultSurface->MoveResize( PositionSize( 0, 0, newSize.width, newSize.height ) ); - defaultScene.SurfaceResized(); + defaultScene.SurfaceResized( newSize.width, newSize.height ); DALI_TEST_EQUALS( stage.GetSize(), newSize, TEST_LOCATION ); DALI_TEST_EQUALS( defaultScene.GetSize(), newSize, TEST_LOCATION ); @@ -1040,19 +924,17 @@ int UtcDaliSceneSurfaceResizedDefaultSceneViewport(void) glAbstraction.ResetViewportCallStack(); auto defaultScene = application.GetScene(); - Integration::RenderSurface* defaultSurface = defaultScene.GetSurface(); - DALI_TEST_CHECK( defaultSurface ); + DALI_TEST_CHECK( defaultScene ); - // Ensure stage size matches the surface size + // Ensure stage size matches the scene size auto stage = Stage::GetCurrent(); - DALI_TEST_EQUALS( stage.GetSize(), Vector2( defaultSurface->GetPositionSize().width, defaultSurface->GetPositionSize().height ), TEST_LOCATION ); + DALI_TEST_EQUALS( stage.GetSize(), defaultScene.GetSize(), TEST_LOCATION ); - // Resize the surface and inform the scene accordingly + // Resize the scene Vector2 newSize( 1000.0f, 2000.0f ); std::string viewportParams( "0, 0, 1000, 2000" ); // to match newSize DALI_TEST_CHECK( stage.GetSize() != newSize ); - defaultSurface->MoveResize( PositionSize( 0, 0, newSize.width, newSize.height ) ); - defaultScene.SurfaceResized(); + defaultScene.SurfaceResized( newSize.width, newSize.height ); DALI_TEST_EQUALS( stage.GetSize(), newSize, TEST_LOCATION ); DALI_TEST_EQUALS( defaultScene.GetSize(), newSize, TEST_LOCATION ); @@ -1114,18 +996,16 @@ int UtcDaliSceneSurfaceResizedMultipleRenderTasks(void) DALI_TEST_EQUALS( initialHeight, testHeight, TEST_LOCATION ); auto defaultScene = application.GetScene(); - Integration::RenderSurface* defaultSurface = defaultScene.GetSurface(); - DALI_TEST_CHECK( defaultSurface ); + DALI_TEST_CHECK( defaultScene ); - // Ensure stage size matches the surface size - DALI_TEST_EQUALS( stage.GetSize(), Vector2( defaultSurface->GetPositionSize().width, defaultSurface->GetPositionSize().height ), TEST_LOCATION ); + // Ensure stage size matches the scene size + DALI_TEST_EQUALS( stage.GetSize(), defaultScene.GetSize(), TEST_LOCATION ); - // Resize the surface and inform the scene accordingly - Vector2 newSize( 800.0f, 480.0f ); - std::string viewportParams( "0, 0, 800, 480" ); // to match newSize + // Resize the scene + Vector2 newSize( 1000.0f, 2000.0f ); + std::string viewportParams( "0, 0, 1000, 2000" ); // to match newSize DALI_TEST_CHECK( stage.GetSize() != newSize ); - defaultSurface->MoveResize( PositionSize( 0, 0, newSize.width, newSize.height ) ); - defaultScene.SurfaceResized(); + defaultScene.SurfaceResized( newSize.width, newSize.height ); DALI_TEST_EQUALS( stage.GetSize(), newSize, TEST_LOCATION ); DALI_TEST_EQUALS( defaultScene.GetSize(), newSize, TEST_LOCATION ); @@ -1154,8 +1034,7 @@ int UtcDaliSceneSurfaceResizedAdditionalScene(void) TestApplication application; Vector2 originalSurfaceSize( 500.0f, 1000.0f ); - TestRenderSurface surface( PositionSize( 0.0f, 0.0f, originalSurfaceSize.width, originalSurfaceSize.height ) ); - auto scene = Integration::Scene::New( surface ); + auto scene = Integration::Scene::New( Size( originalSurfaceSize.width, originalSurfaceSize.height ) ); // Ensure stage size does NOT match the surface size auto stage = Stage::GetCurrent(); @@ -1166,8 +1045,7 @@ int UtcDaliSceneSurfaceResizedAdditionalScene(void) // Resize the surface and inform the scene accordingly Vector2 newSize( 1000.0f, 2000.0f ); DALI_TEST_CHECK( stage.GetSize() != newSize ); - surface.MoveResize( PositionSize( 0, 0, newSize.width, newSize.height ) ); - scene.SurfaceResized(); + scene.SurfaceResized( newSize.width, newSize.height ); // Ensure the stage hasn't been resized DALI_TEST_EQUALS( stage.GetSize(), stageSize, TEST_LOCATION ); @@ -1176,34 +1054,6 @@ int UtcDaliSceneSurfaceResizedAdditionalScene(void) END_TEST; } -int UtcDaliSceneSetSurface(void) -{ - tet_infoline( "Scene::SetSurface test" ); - - TestApplication application; - - // Create a scene with a surface and ensure the size and surface is set correctly on the scene - Vector2 surfaceSize( 480.0f, 800.0f ); - TestRenderSurface surface( PositionSize( 0.0f, 0.0f, surfaceSize.width, surfaceSize.height ) ); - auto scene = Integration::Scene::New( surface ); - DALI_TEST_EQUALS( scene.GetSize(), surfaceSize, TEST_LOCATION ); - DALI_TEST_CHECK( scene.GetSurface() == &surface ); - - // Create a new surface and set that on the scene - Vector2 newSurfaceSize( 1000.0f, 1000.0f ); - TestRenderSurface newSurface( PositionSize( 0.0f, 0.0f, newSurfaceSize.width, newSurfaceSize.height ) ); - scene.SetSurface( newSurface ); - DALI_TEST_EQUALS( scene.GetSize(), newSurfaceSize, TEST_LOCATION ); - DALI_TEST_CHECK( scene.GetSurface() == &newSurface ); - - // Ensure setting the same surface again doesn't have any side effects - scene.SetSurface( newSurface ); - DALI_TEST_EQUALS( scene.GetSize(), newSurfaceSize, TEST_LOCATION ); - DALI_TEST_CHECK( scene.GetSurface() == &newSurface ); - - END_TEST; -} - int UtcDaliSceneKeyEventGeneratedSignalP(void) { TestApplication application; @@ -1280,8 +1130,7 @@ int UtcDaliSceneEnsureReplacedSurfaceKeepsClearColor(void) DALI_TEST_EQUALS( glAbstraction.GetClearCountCalled(), clearCountBefore + 1, TEST_LOCATION ); DALI_TEST_EQUALS( glAbstraction.GetLastClearColor(), Color::BLUE, TEST_LOCATION ); - TestRenderSurface surface( PositionSize( 0.0f, 0.0f, 480.0f, 800.0f ) ); - defaultScene.SetSurface( surface ); + defaultScene.SurfaceReplaced(); application.SendNotification(); application.Render(); diff --git a/build/tizen/CMakeLists.txt b/build/tizen/CMakeLists.txt index 94dbedb..367446c 100644 --- a/build/tizen/CMakeLists.txt +++ b/build/tizen/CMakeLists.txt @@ -330,7 +330,6 @@ IF( ENABLE_LINK_TEST ) ${DALI_TEST_SUITE_DIR}/test-application.cpp ${DALI_TEST_SUITE_DIR}/test-platform-abstraction.cpp ${DALI_TEST_SUITE_DIR}/test-render-controller.cpp - ${DALI_TEST_SUITE_DIR}/test-render-surface.cpp ${DALI_TEST_SUITE_DIR}/test-gl-abstraction.cpp ${DALI_TEST_SUITE_DIR}/test-gl-sync-abstraction.cpp ${DALI_TEST_SUITE_DIR}/test-trace-call-stack.cpp diff --git a/dali/integration-api/core.cpp b/dali/integration-api/core.cpp index 30e1cba..d15cd28 100644 --- a/dali/integration-api/core.cpp +++ b/dali/integration-api/core.cpp @@ -17,7 +17,6 @@ // CLASS HEADER #include -#include // INTERNAL INCLUDES #include @@ -87,11 +86,6 @@ void Core::RecoverFromContextLoss() mImpl->RecoverFromContextLoss(); } -void Core::SurfaceDeleted( Integration::RenderSurface* surface ) -{ - mImpl->SurfaceDeleted(surface); -} - void Core::SceneCreated() { mImpl->SceneCreated(); @@ -117,9 +111,19 @@ void Core::Update( float elapsedSeconds, uint32_t lastVSyncTimeMilliseconds, uin mImpl->Update( elapsedSeconds, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds, status, renderToFboEnabled, isRenderingToFbo ); } -void Core::Render( RenderStatus& status, bool forceClear, bool uploadOnly ) +void Core::PreRender( RenderStatus& status, bool forceClear, bool uploadOnly ) +{ + mImpl->PreRender( status, forceClear, uploadOnly ); +} + +void Core::RenderScene( Integration::Scene& scene, bool renderToFbo ) +{ + mImpl->RenderScene( scene, renderToFbo ); +} + +void Core::PostRender( bool uploadOnly ) { - mImpl->Render( status, forceClear, uploadOnly ); + mImpl->PostRender( uploadOnly ); } void Core::RegisterProcessor( Processor& processor ) diff --git a/dali/integration-api/core.h b/dali/integration-api/core.h index e242cfe..f2a9f7a 100644 --- a/dali/integration-api/core.h +++ b/dali/integration-api/core.h @@ -46,7 +46,7 @@ class GlContextHelperAbstraction; class PlatformAbstraction; class Processor; class RenderController; -class RenderSurface; +class Scene; struct Event; struct TouchData; @@ -283,13 +283,6 @@ public: */ void RecoverFromContextLoss(); - /** - * Notify the Core that the GL surface has been deleted. - * Multi-threading note: this method should be called from the main thread - * @param[in] surface The deleted surface - */ - void SurfaceDeleted( Integration::RenderSurface* surface ); - // Core Lifecycle /** @@ -345,14 +338,36 @@ public: bool isRenderingToFbo ); /** - * Render the next frame. This method should be preceded by a call up Update. + * This is called before rendering any scene in the next frame. This method should be preceded + * by a call up Update. * Multi-threading note: this method should be called from a dedicated rendering thread. * @pre The GL context must have been created, and made current. * @param[out] status showing whether update is required to run. * @param[in] forceClear force the Clear on the framebuffer even if nothing is rendered. * @param[in] uploadOnly uploadOnly Upload the resource only without rendering. */ - void Render( RenderStatus& status, bool forceClear, bool uploadOnly ); + void PreRender( RenderStatus& status, bool forceClear, bool uploadOnly ); + + /** + * Render a scene in the next frame. This method should be preceded by a call up PreRender. + * This method should be called twice. The first pass to render off-screen frame buffers if any, + * and the second pass to render the surface. + * Multi-threading note: this method should be called from a dedicated rendering thread. + * @pre The GL context must have been created, and made current. + * @param[in] scene The scene to be rendered. + * @param[in] renderToFbo True to render off-screen frame buffers only if any, and False to render the surface only. + */ + void RenderScene( Integration::Scene& scene, bool renderToFbo ); + + + /** + * This is called after rendering all the scenes in the next frame. This method should be + * followed by a call up RenderScene. + * Multi-threading note: this method should be called from a dedicated rendering thread. + * @pre The GL context must have been created, and made current. + * @param[in] uploadOnly uploadOnly Upload the resource only without rendering. + */ + void PostRender( bool uploadOnly ); /** * @brief Register a processor diff --git a/dali/integration-api/file.list b/dali/integration-api/file.list index a6d44bf..940771c 100644 --- a/dali/integration-api/file.list +++ b/dali/integration-api/file.list @@ -44,7 +44,6 @@ SET( platform_abstraction_header_files ${platform_abstraction_src_dir}/lockless-buffer.h ${platform_abstraction_src_dir}/render-task-list-integ.h ${platform_abstraction_src_dir}/scene.h - ${platform_abstraction_src_dir}/render-surface.h ) diff --git a/dali/integration-api/gl-context-helper-abstraction.h b/dali/integration-api/gl-context-helper-abstraction.h index 7e425f9..91b1dcc 100644 --- a/dali/integration-api/gl-context-helper-abstraction.h +++ b/dali/integration-api/gl-context-helper-abstraction.h @@ -2,7 +2,7 @@ #define DALI_INTEGRATION_GL_CONTEXT_HELPER_ABSTRACTION_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. @@ -20,7 +20,6 @@ // INTERNAL INCLUDES #include -#include namespace Dali { @@ -46,12 +45,6 @@ public: virtual void MakeSurfacelessContextCurrent() = 0; /** - * @brief Switch to the GL context of the specific render surface - * @param[in] surface The render surface - */ - virtual void MakeContextCurrent( Integration::RenderSurface* surface ) = 0; - - /** * @brief Clear the GL context */ virtual void MakeContextNull() = 0; diff --git a/dali/integration-api/render-surface.h b/dali/integration-api/render-surface.h deleted file mode 100644 index 2270fc2..0000000 --- a/dali/integration-api/render-surface.h +++ /dev/null @@ -1,203 +0,0 @@ -#ifndef DALI_RENDER_SURFACE_H -#define DALI_RENDER_SURFACE_H - -/* - * Copyright (c) 2019 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 - -namespace Dali -{ - -class DisplayConnection; -class ThreadSynchronizationInterface; - -namespace Internal -{ - -namespace Adaptor -{ - -class GraphicsInterface; - -} // namespace Adaptor - -} // namespace Internal - -/** - * @brief The position and size of the render surface. - */ -typedef Dali::Rect PositionSize; - -namespace Integration -{ - -class GlAbstraction; - -/** - * @brief Interface for a render surface onto which Dali draws. - * - * Dali::Adaptor requires a render surface to draw on to. This is - * usually a window in the native windowing system, or some other - * mapped pixel buffer. - * - * Dali::Application will automatically create a render surface using a window. - * - * The implementation of the factory method below should choose an appropriate - * implementation of RenderSurface for the given platform - */ - -class DALI_CORE_API RenderSurface -{ -public: - - enum Type - { - WINDOW_RENDER_SURFACE, - PIXMAP_RENDER_SURFACE, - NATIVE_RENDER_SURFACE - }; - - /** - * @brief Constructor - * Inlined as this is a pure abstract interface - */ - RenderSurface() {} - - /** - * @brief Virtual Destructor. - * Inlined as this is a pure abstract interface - */ - virtual ~RenderSurface() {} - - /** - * @brief Return the size and position of the surface. - * @return The position and size - */ - virtual PositionSize GetPositionSize() const = 0; - - /** - * @brief Get DPI - * @param[out] dpiHorizontal set to the horizontal dpi - * @param[out] dpiVertical set to the vertical dpi - */ - virtual void GetDpi( unsigned int& dpiHorizontal, unsigned int& dpiVertical ) = 0; - - /** - * @brief InitializeGraphics the platform specific graphics surface interfaces - */ - virtual void InitializeGraphics() = 0; - - /** - * @brief Creates the Surface - */ - virtual void CreateSurface() = 0; - - /** - * @brief Destroys the Surface - */ - virtual void DestroySurface() = 0; - - /** - * @brief Replace the Surface - * @return true if context was lost - */ - virtual bool ReplaceGraphicsSurface() = 0; - - /** - * @brief Resizes the underlying surface. - * @param[in] The dimensions of the new position - */ - virtual void MoveResize( Dali::PositionSize positionSize ) = 0; - - /** - * @brief Called when Render thread has started - */ - virtual void StartRender() = 0; - - /** - * @brief Invoked by render thread before Core::Render - * 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 - * @return True if the operation is successful, False if the operation failed - */ - virtual bool PreRender( bool resizingSurface ) = 0; - - /** - * @brief Invoked by render thread after Core::Render - * @param[in] renderToFbo True if render to FBO. - * @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; - - /** - * @brief Invoked by render thread when the thread should be stop - */ - virtual void StopRender() = 0; - - /** - * @brief Invoked by Event Thread when the compositor lock should be released and rendering should resume. - */ - virtual void ReleaseLock() = 0; - - /** - * @brief Gets the surface type - */ - virtual RenderSurface::Type GetSurfaceType() = 0; - - /** - * @brief Makes the graphics context current - */ - virtual void MakeContextCurrent() = 0; - - /** - * @brief Gets whether the depth buffer is required - * @return TRUE if the depth buffer is required - */ - virtual Integration::DepthBufferAvailable GetDepthBufferRequired() = 0; - - /** - * @brief Gets whether the stencil buffer is required - * @return TRUE if the stencil buffer is required - */ - virtual Integration::StencilBufferAvailable GetStencilBufferRequired() = 0; - -private: - - /** - * @brief Undefined copy constructor. RenderSurface cannot be copied - */ - RenderSurface( const RenderSurface& rhs ) = delete; - - /** - * @brief Undefined assignment operator. RenderSurface cannot be copied - */ - RenderSurface& operator=( const RenderSurface& rhs ) = delete; -}; - -} // namespace Integration - -} // namespace Dali - -#endif // DALI_RENDER_SURFACE_H diff --git a/dali/integration-api/scene.cpp b/dali/integration-api/scene.cpp index 8fef6db..c8bc91b 100644 --- a/dali/integration-api/scene.cpp +++ b/dali/integration-api/scene.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. @@ -29,9 +29,9 @@ namespace Dali namespace Integration { -Scene Scene::New( Integration::RenderSurface& surface ) +Scene Scene::New( Size size ) { - Internal::ScenePtr internal = Internal::Scene::New( surface ); + Internal::ScenePtr internal = Internal::Scene::New( size ); return Scene( internal.Get() ); } @@ -119,19 +119,14 @@ Layer Scene::GetLayer( uint32_t depth ) const return GetImplementation(*this).GetLayer( depth ); } -void Scene::SetSurface( Integration::RenderSurface& surface ) +void Scene::SurfaceResized( float width, float height ) { - GetImplementation(*this).SetSurface( surface ); + GetImplementation( *this ).SurfaceResized( width, height ); } -void Scene::SurfaceResized() +void Scene::SurfaceReplaced() { - GetImplementation( *this ).SurfaceResized(); -} - -Integration::RenderSurface* Scene::GetSurface() const -{ - return GetImplementation(*this).GetSurface(); + GetImplementation( *this ).SurfaceReplaced(); } void Scene::Discard() diff --git a/dali/integration-api/scene.h b/dali/integration-api/scene.h index dca7cbc..9211ae1 100755 --- a/dali/integration-api/scene.h +++ b/dali/integration-api/scene.h @@ -2,7 +2,7 @@ #define DALI_SCENE_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. @@ -41,7 +41,6 @@ namespace Internal DALI_INTERNAL namespace Integration { -class RenderSurface; struct Event; /** @@ -62,11 +61,11 @@ public: /** * @brief Create an initialized Scene handle. * - * @param[in] surface Binds this rendering surface to this scene + * @param[in] size The size of the set surface for this scene * * @return a handle to a newly allocated Dali resource. */ - static Scene New( Integration::RenderSurface& surface ); + static Scene New( Size size ); /** * @brief Downcast an Object handle to Scene handle. @@ -196,23 +195,17 @@ public: Layer GetLayer( uint32_t depth ) const; /** - * @brief Binds the rendering surface to the scene - * - * @return The root layer - */ - void SetSurface( Integration::RenderSurface& surface ); - - /** * @brief Informs the scene that the set surface has been resized. + * + * @param[in] width The new width of the set surface + * @param[in] height The new height of the set surface */ - void SurfaceResized(); + void SurfaceResized( float width, float height ); /** - * @brief Gets the rendering surface bound to the scene - * - * @return The render surface + * @brief Informs the scene that the surface has been replaced. */ - Integration::RenderSurface* GetSurface() const; + void SurfaceReplaced(); /** * @brief Discards this Scene from the Core. diff --git a/dali/internal/common/core-impl.cpp b/dali/internal/common/core-impl.cpp index 43f2a2a..f1c6cd4 100644 --- a/dali/internal/common/core-impl.cpp +++ b/dali/internal/common/core-impl.cpp @@ -27,7 +27,6 @@ #include #include #include -#include #include #include @@ -193,18 +192,6 @@ void Core::ContextDestroyed() mRenderManager->ContextDestroyed(); } -void Core::SurfaceDeleted( Integration::RenderSurface* surface ) -{ - for( auto scene : mScenes ) - { - if( scene->GetSurface() == surface ) - { - scene->SurfaceDeleted(); - break; - } - } -} - void Core::Update( float elapsedSeconds, uint32_t lastVSyncTimeMilliseconds, uint32_t nextVSyncTimeMilliseconds, Integration::UpdateStatus& status, bool renderToFboEnabled, bool isRenderingToFbo ) { // set the time delta so adaptor can easily print FPS with a release build with 0 as @@ -229,9 +216,19 @@ void Core::Update( float elapsedSeconds, uint32_t lastVSyncTimeMilliseconds, uin // Any message to update will wake it up anyways } -void Core::Render( RenderStatus& status, bool forceClear, bool uploadOnly ) +void Core::PreRender( RenderStatus& status, bool forceClear, bool uploadOnly ) +{ + mRenderManager->PreRender( status, forceClear, uploadOnly ); +} + +void Core::RenderScene( Integration::Scene& scene, bool renderToFbo ) +{ + mRenderManager->RenderScene( scene, renderToFbo ); +} + +void Core::PostRender( bool uploadOnly ) { - mRenderManager->Render( status, forceClear, uploadOnly ); + mRenderManager->PostRender( uploadOnly ); } void Core::SceneCreated() diff --git a/dali/internal/common/core-impl.h b/dali/internal/common/core-impl.h index ba38092..9272e16 100644 --- a/dali/internal/common/core-impl.h +++ b/dali/internal/common/core-impl.h @@ -44,7 +44,6 @@ class GlSyncAbstraction; class GlContextHelperAbstraction; class UpdateStatus; class RenderStatus; -class RenderSurface; struct Event; struct TouchData; } @@ -120,11 +119,6 @@ public: void RecoverFromContextLoss(); /** - * @copydoc Dali::Integration::Core::SurfaceDeleted(Integration::RenderSurface*) - */ - void SurfaceDeleted( Integration::RenderSurface* surface ); - - /** * @copydoc Dali::Integration::Core::SetMinimumFrameTimeInterval(uint32_t) */ void SetMinimumFrameTimeInterval(uint32_t interval); @@ -137,7 +131,17 @@ public: /** * @copydoc Dali::Integration::Core::Render() */ - void Render( Integration::RenderStatus& status, bool forceClear, bool uploadOnly ); + void PreRender( Integration::RenderStatus& status, bool forceClear, bool uploadOnly ); + + /** + * @copydoc Dali::Integration::Core::RenderScene() + */ + void RenderScene( Integration::Scene& scene, bool renderToFbo ); + + /** + * @copydoc Dali::Integration::Core::Render() + */ + void PostRender( bool uploadOnly ); /** * @copydoc Dali::Integration::Core::SceneCreated() diff --git a/dali/internal/event/common/scene-impl.cpp b/dali/internal/event/common/scene-impl.cpp index 69b0724..2cc2cdc 100644 --- a/dali/internal/event/common/scene-impl.cpp +++ b/dali/internal/event/common/scene-impl.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. @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -48,18 +49,18 @@ const Vector4 DEFAULT_BACKGROUND_COLOR(0.0f, 0.0f, 0.0f, 1.0f); // Default backg } //Unnamed namespace -ScenePtr Scene::New( Integration::RenderSurface& surface ) +ScenePtr Scene::New( Size size ) { ScenePtr scene = new Scene; // Second-phase construction - scene->Initialize( surface ); + scene->Initialize( size ); return scene; } Scene::Scene() -: mSurface( nullptr ), +: mSceneObject( nullptr ), mSize(), // Don't set the proper value here, this will be set when the surface is set later mDpi(), mBackgroundColor( DEFAULT_BACKGROUND_COLOR ), @@ -70,6 +71,12 @@ Scene::Scene() Scene::~Scene() { + if( EventThreadServices::IsCoreRunning() && mSceneObject ) + { + ThreadLocalStorage* tls = ThreadLocalStorage::GetInternal(); + RemoveSceneMessage( tls->GetUpdateManager(), *mSceneObject ); + } + if( mDefaultCamera ) { // its enough to release the handle so the object is released @@ -89,16 +96,11 @@ Scene::~Scene() mRenderTaskList.Reset(); } - if ( mFrameBuffer ) - { - mFrameBuffer.Reset(); - } - // No need to discard this Scene from Core, as Core stores an intrusive_ptr to this scene // When this destructor is called, the scene has either already been removed from Core or Core has already been destroyed } -void Scene::Initialize( Integration::RenderSurface& surface ) +void Scene::Initialize( Size size ) { ThreadLocalStorage* tls = ThreadLocalStorage::GetInternal(); @@ -124,9 +126,7 @@ void Scene::Initialize( Integration::RenderSurface& surface ) // Create the default camera actor first; this is needed by the RenderTaskList // The default camera attributes and position is such that children of the default layer, // can be positioned at (0,0) and be at the top-left of the viewport. - const PositionSize positionSize = surface.GetPositionSize(); - const Vector2 surfaceSize( static_cast< float >( positionSize.width ), static_cast< float >( positionSize.height ) ); - mDefaultCamera = CameraActor::New( surfaceSize ); + mDefaultCamera = CameraActor::New( size ); mDefaultCamera->SetParentOrigin(ParentOrigin::CENTER); Add(*(mDefaultCamera.Get())); @@ -136,8 +136,12 @@ void Scene::Initialize( Integration::RenderSurface& surface ) // Create the default render-task mRenderTaskList->CreateTask( mRootLayer.Get(), mDefaultCamera.Get() ); - // Set the surface - SetSurface( surface ); + SurfaceResized( size.width, size.height ); + + // Create scene graph object + mSceneObject = new SceneGraph::Scene(); + OwnerPointer< SceneGraph::Scene > transferOwnership( const_cast< SceneGraph::Scene* >( mSceneObject ) ); + AddSceneMessage( updateManager, transferOwnership ); } void Scene::Add(Actor& actor) @@ -200,68 +204,39 @@ Actor& Scene::GetDefaultRootActor() return *mRootLayer; } -void Scene::SetSurface( Integration::RenderSurface& surface ) +void Scene::SurfaceResized( float width, float height ) { - if( mSurface != &surface ) + if( ( fabsf( mSize.width - width ) > Math::MACHINE_EPSILON_1 ) || ( fabsf( mSize.height - height ) > Math::MACHINE_EPSILON_1 ) ) { - mSurface = &surface; + Rect< int32_t > newSize( 0, 0, static_cast< int32_t >( width ), static_cast< int32_t >( height ) ); // truncated - RenderTaskPtr defaultRenderTask = mRenderTaskList->GetTask( 0u ); - - mFrameBuffer = Dali::Internal::FrameBuffer::New( surface, Dali::FrameBuffer::Attachment::NONE ); - defaultRenderTask->SetFrameBuffer( mFrameBuffer ); + mSize.width = width; + mSize.height = height; - SurfaceResized(); - } -} - -void Scene::SurfaceResized() -{ - if( mSurface ) - { - const PositionSize surfacePositionSize = mSurface->GetPositionSize(); - const float fWidth = static_cast< float >( surfacePositionSize.width ); - const float fHeight = static_cast< float >( surfacePositionSize.height ); + // Calculates the aspect ratio, near and far clipping planes, field of view and camera Z position. + mDefaultCamera->SetPerspectiveProjection( mSize ); - if( ( fabsf( mSize.width - fWidth ) > Math::MACHINE_EPSILON_1 ) || ( fabsf( mSize.height - fHeight ) > Math::MACHINE_EPSILON_1 ) ) - { - Rect< int32_t > newSize( 0, 0, static_cast< int32_t >( surfacePositionSize.width ), static_cast< int32_t >( surfacePositionSize.height ) ); // truncated + mRootLayer->SetSize( mSize.width, mSize.height ); - mSize.width = fWidth; - mSize.height = fHeight; - - // Calculates the aspect ratio, near and far clipping planes, field of view and camera Z position. - mDefaultCamera->SetPerspectiveProjection( mSize ); - - mRootLayer->SetSize( mSize.width, mSize.height ); - - ThreadLocalStorage* tls = ThreadLocalStorage::GetInternal(); - SceneGraph::UpdateManager& updateManager = tls->GetUpdateManager(); - SetDefaultSurfaceRectMessage( updateManager, newSize ); + ThreadLocalStorage* tls = ThreadLocalStorage::GetInternal(); + SceneGraph::UpdateManager& updateManager = tls->GetUpdateManager(); + SetDefaultSurfaceRectMessage( updateManager, newSize ); - // set default render-task viewport parameters - RenderTaskPtr defaultRenderTask = mRenderTaskList->GetTask( 0u ); - defaultRenderTask->SetViewport( newSize ); - defaultRenderTask->GetFrameBuffer()->SetSize( static_cast( newSize.width ), static_cast( newSize.height ) ); - } + // set default render-task viewport parameters + RenderTaskPtr defaultRenderTask = mRenderTaskList->GetTask( 0u ); + defaultRenderTask->SetViewport( newSize ); } } -void Scene::SurfaceDeleted() +void Scene::SurfaceReplaced() { - mSurface = nullptr; - if ( mFrameBuffer ) + if ( mSceneObject ) { - // The frame buffer doesn't have a valid render surface any more. - mFrameBuffer->MarkSurfaceAsInvalid(); + ThreadLocalStorage* tls = ThreadLocalStorage::GetInternal(); + SurfaceReplacedMessage( tls->GetUpdateManager(), *mSceneObject ); } } -Integration::RenderSurface* Scene::GetSurface() const -{ - return mSurface; -} - void Scene::Discard() { if( ThreadLocalStorage::Created() ) @@ -301,11 +276,8 @@ void Scene::SetBackgroundColor( const Vector4& color ) { mBackgroundColor = color; - if( mSurface ) - { - mRenderTaskList->GetTask( 0u )->SetClearColor( color ); - mRenderTaskList->GetTask( 0u )->SetClearEnabled( true ); - } + mRenderTaskList->GetTask( 0u )->SetClearColor( color ); + mRenderTaskList->GetTask( 0u )->SetClearEnabled( true ); } Vector4 Scene::GetBackgroundColor() const @@ -313,6 +285,11 @@ Vector4 Scene::GetBackgroundColor() const return mBackgroundColor; } +SceneGraph::Scene* Scene::GetSceneObject() const +{ + return mSceneObject; +} + void Scene::EmitKeyEventSignal(const KeyEvent& event) { if ( !mKeyEventSignal.Empty() ) diff --git a/dali/internal/event/common/scene-impl.h b/dali/internal/event/common/scene-impl.h index 01766df..99a3e50 100644 --- a/dali/internal/event/common/scene-impl.h +++ b/dali/internal/event/common/scene-impl.h @@ -2,7 +2,7 @@ #define DALI_INTERNAL_SCENE_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. @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -42,6 +41,11 @@ struct Event; namespace Internal { +namespace SceneGraph +{ +class Scene; +} + class EventProcessor; class Layer; class LayerList; @@ -62,7 +66,7 @@ public: /** * @copydoc Dali::Integration::Scene::New */ - static ScenePtr New( Integration::RenderSurface& surface ); + static ScenePtr New( Size size ); /** * virtual destructor @@ -115,19 +119,17 @@ public: Dali::Layer GetLayer(uint32_t depth) const; /** - * @copydoc Dali::Integration::Scene::SetSurface - */ - void SetSurface( Integration::RenderSurface& surface ); - - /** * Notify the surface has been resized. + * + * @param[in] width The new width of the set surface + * @param[in] height The new height of the set surface */ - void SurfaceResized(); + void SurfaceResized( float width, float height ); /** - * Notify the surface has been deleted. + * @copydoc Dali::Integration::Scene::SurfaceReplaced */ - void SurfaceDeleted(); + void SurfaceReplaced(); /** * @copydoc Dali::Integration::Scene::Discard @@ -135,12 +137,6 @@ public: void Discard(); /** - * Retrieve the render surface the scene is binded to. - * @return The render surface. - */ - Integration::RenderSurface* GetSurface() const; - - /** * Retrieve the ordered list of on-scene layers. * @return The layer-list. */ @@ -181,6 +177,13 @@ public: Vector4 GetBackgroundColor() const; /** + * @brief Get the Scene scene graph object + * + * @return the Scene scene graph object + */ + SceneGraph::Scene* GetSceneObject() const; + + /** * Used by the EventProcessor to emit key event signals. * @param[in] event The key event. */ @@ -267,8 +270,10 @@ private: /** * Second-phase constructor. + * + * @param[in] size The size of the set surface */ - void Initialize( Integration::RenderSurface& surface ); + void Initialize( Size size ); // Undefined Scene(const Scene&) = delete; @@ -277,7 +282,7 @@ private: Scene& operator=(const Scene& rhs) = delete; private: - Integration::RenderSurface* mSurface; + Internal::SceneGraph::Scene* mSceneObject; Size mSize; @@ -295,9 +300,6 @@ private: // The list of render-tasks IntrusivePtr mRenderTaskList; - // The frame buffer - FrameBufferPtr mFrameBuffer; - bool mDepthTreeDirty:1; ///< True if the depth tree needs recalculating EventProcessor mEventProcessor; diff --git a/dali/internal/event/rendering/frame-buffer-impl.cpp b/dali/internal/event/rendering/frame-buffer-impl.cpp index 1703fd7..e26b0ee 100644 --- a/dali/internal/event/rendering/frame-buffer-impl.cpp +++ b/dali/internal/event/rendering/frame-buffer-impl.cpp @@ -21,9 +21,6 @@ // INTERNAL INCLUDES #include #include -#include -#include -#include namespace Dali { @@ -37,14 +34,6 @@ FrameBufferPtr FrameBuffer::New( uint32_t width, uint32_t height, Mask attachmen return frameBuffer; } -FrameBufferPtr FrameBuffer::New( Dali::Integration::RenderSurface& renderSurface, Mask attachments ) -{ - Dali::PositionSize positionSize = renderSurface.GetPositionSize(); - FrameBufferPtr frameBuffer( new FrameBuffer( positionSize.width, positionSize.height, attachments ) ); - frameBuffer->Initialize( &renderSurface ); - return frameBuffer; -} - Render::FrameBuffer* FrameBuffer::GetRenderObject() const { return mRenderObject; @@ -57,25 +46,13 @@ FrameBuffer::FrameBuffer( uint32_t width, uint32_t height, Mask attachments ) mWidth( width ), mHeight( height ), mAttachments( attachments ), - mColorAttachmentCount( 0 ), - mIsSurfaceBacked( false ) + mColorAttachmentCount( 0 ) { } -void FrameBuffer::Initialize( Integration::RenderSurface* renderSurface ) +void FrameBuffer::Initialize() { - mIsSurfaceBacked = ( renderSurface != nullptr ); - - // If render surface backed, create a different scene object - // Make Render::FrameBuffer as a base class, and implement Render::TextureFrameBuffer & Render::WindowFrameBuffer - if ( mIsSurfaceBacked ) - { - mRenderObject = new Render::SurfaceFrameBuffer( renderSurface ); - } - else - { - mRenderObject = new Render::TextureFrameBuffer( mWidth, mHeight, mAttachments ); - } + mRenderObject = new Render::FrameBuffer( mWidth, mHeight, mAttachments ); OwnerPointer< Render::FrameBuffer > transferOwnership( mRenderObject ); AddFrameBuffer( mEventThreadServices.GetUpdateManager(), transferOwnership ); @@ -83,54 +60,33 @@ void FrameBuffer::Initialize( Integration::RenderSurface* renderSurface ) void FrameBuffer::AttachColorTexture( TexturePtr texture, uint32_t mipmapLevel, uint32_t layer ) { - if ( mIsSurfaceBacked ) + if( ( texture->GetWidth() / ( 1u << mipmapLevel ) != mWidth ) || + ( texture->GetHeight() / ( 1u << mipmapLevel ) != mHeight ) ) { - DALI_LOG_ERROR( "Attempted to attach color texture to a render surface backed FrameBuffer \n" ); + DALI_LOG_ERROR( "Failed to attach color texture to FrameBuffer: Size mismatch \n" ); + } + else if ( mColorAttachmentCount >= Dali::DevelFrameBuffer::MAX_COLOR_ATTACHMENTS ) + { + DALI_LOG_ERROR( "Failed to attach color texture to FrameBuffer: Exceeded maximum supported color attachments.\n" ); } else { - if( ( texture->GetWidth() / ( 1u << mipmapLevel ) != mWidth ) || - ( texture->GetHeight() / ( 1u << mipmapLevel ) != mHeight ) ) - { - DALI_LOG_ERROR( "Failed to attach color texture to FrameBuffer: Size mismatch \n" ); - } - else if ( mColorAttachmentCount >= Dali::DevelFrameBuffer::MAX_COLOR_ATTACHMENTS ) - { - DALI_LOG_ERROR( "Failed to attach color texture to FrameBuffer: Exceeded maximum supported color attachments.\n" ); - } - else - { - mColor[mColorAttachmentCount] = texture; - ++mColorAttachmentCount; + mColor[mColorAttachmentCount] = texture; + ++mColorAttachmentCount; - AttachColorTextureToFrameBuffer( mEventThreadServices.GetUpdateManager(), *mRenderObject, texture->GetRenderObject(), mipmapLevel, layer ); - } + AttachColorTextureToFrameBuffer( mEventThreadServices.GetUpdateManager(), *mRenderObject, texture->GetRenderObject(), mipmapLevel, layer ); } } Texture* FrameBuffer::GetColorTexture(uint8_t index) const { - return ( mIsSurfaceBacked || index >= mColorAttachmentCount ) ? nullptr : mColor[index].Get(); + return ( index >= mColorAttachmentCount ) ? nullptr : mColor[index].Get(); } void FrameBuffer::SetSize( uint32_t width, uint32_t height ) { mWidth = width; mHeight = height; - - if( mRenderObject->IsSurfaceBacked() ) - { - SetFrameBufferSizeMessage( mEventThreadServices.GetUpdateManager(), static_cast( mRenderObject ), width, height ); - } -} - -void FrameBuffer::MarkSurfaceAsInvalid() -{ - if ( mIsSurfaceBacked ) - { - Render::SurfaceFrameBuffer* renderObject = static_cast( mRenderObject ); - renderObject->MarkSurfaceAsInvalid(); - } } FrameBuffer::~FrameBuffer() diff --git a/dali/internal/event/rendering/frame-buffer-impl.h b/dali/internal/event/rendering/frame-buffer-impl.h index e30c285..9913b4d 100644 --- a/dali/internal/event/rendering/frame-buffer-impl.h +++ b/dali/internal/event/rendering/frame-buffer-impl.h @@ -29,11 +29,7 @@ namespace Dali { - -namespace Integration -{ -class RenderSurface; -} +using Mask = Dali::FrameBuffer::Attachment::Mask; namespace Internal { @@ -62,15 +58,6 @@ public: static FrameBufferPtr New( uint32_t width, uint32_t height, Mask attachments ); /** - * @brief Create a new FrameBuffer - * - * @param[in] renderSurface The render surface - * @param[in] attachments The attachments comprising the format of the FrameBuffer (bit-mask) - * @return A smart-pointer to the newly allocated Texture. - */ - static FrameBufferPtr New( Dali::Integration::RenderSurface& renderSurface, Mask attachments ); - - /** * A reference counted object may only be deleted by calling Unreference() */ virtual ~FrameBuffer(); @@ -99,16 +86,6 @@ public: */ void SetSize( uint32_t width, uint32_t height ); - /** - * @brief Mark the render surface as invalid - * - * The render surface is maked as invalid when it is deleted. - * - * @note Only for FrameBuffer backed by a render surface. - * @return True if the FrameBuffer is backed by a render surface - */ - void MarkSurfaceAsInvalid(); - private: // implementation /** @@ -122,7 +99,7 @@ private: // implementation /** * Second stage initialization of the Texture */ - void Initialize( Integration::RenderSurface* renderSurface = nullptr ); + void Initialize(); protected: @@ -142,9 +119,6 @@ private: // data uint32_t mHeight; Mask mAttachments; ///< Bit-mask of type FrameBuffer::Attachment::Mask uint8_t mColorAttachmentCount; - - bool mIsSurfaceBacked:1; - }; } // namespace Internal diff --git a/dali/internal/file.list b/dali/internal/file.list index 969d49a..cfa282d 100644 --- a/dali/internal/file.list +++ b/dali/internal/file.list @@ -112,8 +112,7 @@ SET( internal_src_files ${internal_src_dir}/render/gl-resources/gl-call-debug.cpp ${internal_src_dir}/render/gl-resources/gpu-buffer.cpp ${internal_src_dir}/render/queue/render-queue.cpp - ${internal_src_dir}/render/renderers/render-texture-frame-buffer.cpp - ${internal_src_dir}/render/renderers/render-surface-frame-buffer.cpp + ${internal_src_dir}/render/renderers/render-frame-buffer.cpp ${internal_src_dir}/render/renderers/render-geometry.cpp ${internal_src_dir}/render/renderers/render-property-buffer.cpp ${internal_src_dir}/render/renderers/render-renderer.cpp @@ -134,6 +133,7 @@ SET( internal_src_files ${internal_src_dir}/update/common/scene-graph-buffers.cpp ${internal_src_dir}/update/common/scene-graph-connection-change-propagator.cpp ${internal_src_dir}/update/common/scene-graph-property-notification.cpp + ${internal_src_dir}/update/common/scene-graph-scene.cpp ${internal_src_dir}/update/common/uniform-map.cpp ${internal_src_dir}/update/controllers/render-message-dispatcher.cpp ${internal_src_dir}/update/controllers/scene-controller-impl.cpp diff --git a/dali/internal/render/common/render-instruction-container.cpp b/dali/internal/render/common/render-instruction-container.cpp index da899a9..4389f2f 100644 --- a/dali/internal/render/common/render-instruction-container.cpp +++ b/dali/internal/render/common/render-instruction-container.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 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. @@ -31,58 +31,45 @@ namespace SceneGraph { RenderInstructionContainer::RenderInstructionContainer() +: mInstructions{} { - // array initialisation in ctor initializer list not supported until C++ 11 - mIndex[ 0 ] = 0u; - mIndex[ 1 ] = 0u; } RenderInstructionContainer::~RenderInstructionContainer() { - // OwnerContainer deletes the instructions } void RenderInstructionContainer::ResetAndReserve( BufferIndex bufferIndex, uint32_t capacityRequired ) { - mIndex[ bufferIndex ] = 0u; - uint32_t oldcapacity = static_cast( mInstructions[ bufferIndex ].Capacity() ); // uint32_t is large enough in practice - if( oldcapacity < capacityRequired ) + // Only re-allocate if necessary. + if( mInstructions.size() < capacityRequired ) { - mInstructions[ bufferIndex ].Reserve( capacityRequired ); - // add N new elements - for( ; oldcapacity < capacityRequired; ++oldcapacity ) - { - mInstructions[ bufferIndex ].PushBack( new RenderInstruction ); - } + mInstructions.reserve( capacityRequired ); } - // Note that we may have spare elements in the list, we don't remove them as that would - // decrease the capacity of our container and lead to possibly reallocating, which we hate - // RenderInstruction holds a lot of data so we keep them and recycle instead of new & delete + + mInstructions.clear(); } uint32_t RenderInstructionContainer::Count( BufferIndex bufferIndex ) { - // mIndex contains the number of instructions that have been really prepared and updated - // (from UpdateManager through GetNextInstruction) - return mIndex[ bufferIndex ]; + return static_cast( mInstructions.size() ); } -RenderInstruction& RenderInstructionContainer::GetNextInstruction( BufferIndex bufferIndex ) +RenderInstruction& RenderInstructionContainer::At( BufferIndex bufferIndex, uint32_t index ) { - // At protects against running out of space - return At( bufferIndex, mIndex[ bufferIndex ]++ ); + DALI_ASSERT_DEBUG( index < mInstructions.size() ); + + return *mInstructions[ index ]; } -RenderInstruction& RenderInstructionContainer::At( BufferIndex bufferIndex, uint32_t index ) +void RenderInstructionContainer::PushBack( BufferIndex bufferIndex, RenderInstruction* renderInstruction ) { - DALI_ASSERT_DEBUG( index < mInstructions[ bufferIndex ].Count() ); - - return *mInstructions[ bufferIndex ][ index ]; + mInstructions.push_back( renderInstruction ); } -void RenderInstructionContainer::DiscardCurrentInstruction( BufferIndex bufferIndex ) +void RenderInstructionContainer::DiscardCurrentInstruction( BufferIndex updateBufferIndex ) { - mIndex[ bufferIndex ]--; + mInstructions.pop_back(); } } // namespace SceneGraph diff --git a/dali/internal/render/common/render-instruction-container.h b/dali/internal/render/common/render-instruction-container.h index 11e7451..cfc8aa7 100644 --- a/dali/internal/render/common/render-instruction-container.h +++ b/dali/internal/render/common/render-instruction-container.h @@ -2,7 +2,7 @@ #define DALI_INTERNAL_SCENE_GRAPH_RENDER_INSTRUCTION_CONTAINER_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. @@ -19,6 +19,7 @@ */ // INTERNAL INCLUDES +#include #include #include @@ -33,7 +34,8 @@ namespace SceneGraph class RenderInstruction; /** - * Class to encapsulate double buffered render instruction data + * Class to hold ordered list of current frame's render instructions. + * Does not own the instructions. */ class RenderInstructionContainer { @@ -64,29 +66,27 @@ public: uint32_t Count( BufferIndex bufferIndex ); /** - * Get a reference to the next instruction + * Get a reference to the instruction at index * @param bufferIndex to use + * @param index to use */ - RenderInstruction& GetNextInstruction( BufferIndex bufferIndex ); + RenderInstruction& At( BufferIndex bufferIndex, uint32_t index ); /** - * Get a reference to the instruction at index + * Add an instruction to the end of the container * @param bufferIndex to use - * @param index to use */ - RenderInstruction& At( BufferIndex bufferIndex, uint32_t index ); + void PushBack( BufferIndex index, RenderInstruction* renderInstruction ); /** - * Discard the current container index - * @param bufferIndex to reset + * Discard an instruction from the end of the container + * @param bufferIndex to use */ - void DiscardCurrentInstruction( BufferIndex bufferIndex ); + void DiscardCurrentInstruction( BufferIndex updateBufferIndex ); private: - unsigned int mIndex[ 2 ]; ///< count of the elements that have been added - typedef OwnerContainer< RenderInstruction* > InstructionContainer; - InstructionContainer mInstructions[ 2 ]; /// Double buffered instruction lists + std::vector mInstructions; }; diff --git a/dali/internal/render/common/render-instruction.cpp b/dali/internal/render/common/render-instruction.cpp index 4eb7a40..164a9af 100644 --- a/dali/internal/render/common/render-instruction.cpp +++ b/dali/internal/render/common/render-instruction.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 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. @@ -39,6 +39,7 @@ RenderInstruction::RenderInstruction() mIsClearColorSet( false ), mIgnoreRenderToFbo( false ), mFrameBuffer( 0 ), + mContext( 0 ), mCamera( 0 ), mNextFreeRenderList( 0 ) { diff --git a/dali/internal/render/common/render-instruction.h b/dali/internal/render/common/render-instruction.h index 8605288..1152321 100644 --- a/dali/internal/render/common/render-instruction.h +++ b/dali/internal/render/common/render-instruction.h @@ -2,7 +2,7 @@ #define DALI_INTERNAL_SCENE_GRAPH_RENDER_INSTRUCTION_H /* - * Copyright (c) 2017 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. @@ -24,6 +24,7 @@ #include #include #include +#include namespace Dali { @@ -148,6 +149,8 @@ public: // Data Render::FrameBuffer* mFrameBuffer; + Context* mContext; ///< The context holding the GL state of rendering + private: // Data Camera* mCamera; ///< camera that is used diff --git a/dali/internal/render/common/render-manager.cpp b/dali/internal/render/common/render-manager.cpp index a1b527b..24c310f 100644 --- a/dali/internal/render/common/render-manager.cpp +++ b/dali/internal/render/common/render-manager.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. @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -39,12 +40,11 @@ #include #include #include -#include -#include #include #include #include #include +#include namespace Dali { @@ -72,13 +72,12 @@ struct RenderManager::Impl Integration::GlContextHelperAbstraction& glContextHelperAbstraction, Integration::DepthBufferAvailable depthBufferAvailableParam, Integration::StencilBufferAvailable stencilBufferAvailableParam ) - : context( glAbstraction, &surfaceContextContainer ), + : context( glAbstraction, &sceneContextContainer ), currentContext( &context ), glAbstraction( glAbstraction ), glSyncAbstraction( glSyncAbstraction ), glContextHelperAbstraction( glContextHelperAbstraction ), renderQueue(), - instructions(), renderAlgorithms(), frameCount( 0u ), renderBufferIndex( SceneGraphBuffers::INITIAL_UPDATE_BUFFER_INDEX ), @@ -113,15 +112,26 @@ struct RenderManager::Impl mRenderTrackers.EraseObject( renderTracker ); } - Context* CreateSurfaceContext() + Context* CreateSceneContext() { - surfaceContextContainer.PushBack( new Context( glAbstraction ) ); - return surfaceContextContainer[ surfaceContextContainer.Count() - 1 ]; + sceneContextContainer.push_back( new Context( glAbstraction ) ); + return sceneContextContainer[ sceneContextContainer.size() - 1 ]; } - void DestroySurfaceContext( Context* surfaceContext ) + void DestroySceneContext( Context* sceneContext ) { - surfaceContextContainer.EraseObject( surfaceContext ); + auto iter = std::find( sceneContextContainer.begin(), sceneContextContainer.end(), sceneContext ); + if( iter != sceneContextContainer.end() ) + { + sceneContextContainer.erase( iter ); + } + } + + Context* ReplaceSceneContext( Context* oldSceneContext ) + { + Context* newContext = new Context( glAbstraction ); + std::replace( sceneContextContainer.begin(), sceneContextContainer.end(), oldSceneContext, newContext ); + return newContext; } void UpdateTrackers() @@ -136,15 +146,14 @@ struct RenderManager::Impl // programs are owned by context at the moment. Context context; ///< Holds the GL state of the share resource context Context* currentContext; ///< Holds the GL state of the current context for rendering - OwnerContainer< Context* > surfaceContextContainer; ///< List of owned contexts holding the GL state per surface + std::vector< Context* > sceneContextContainer; ///< List of owned contexts holding the GL state per scene Integration::GlAbstraction& glAbstraction; ///< GL abstraction Integration::GlSyncAbstraction& glSyncAbstraction; ///< GL sync abstraction Integration::GlContextHelperAbstraction& glContextHelperAbstraction; ///< GL context helper abstraction RenderQueue renderQueue; ///< A message queue for receiving messages from the update-thread. - // Render instructions describe what should be rendered during RenderManager::Render() - // Owned by RenderManager. Update manager updates instructions for the next frame while we render the current one - RenderInstructionContainer instructions; + std::vector< SceneGraph::Scene* > sceneContainer; ///< List of pointers to the scene graph objects of the scenes + Render::RenderAlgorithms renderAlgorithms; ///< The RenderAlgorithms object is used to action the renders required by a RenderInstruction uint32_t frameCount; ///< The current frame count @@ -234,6 +243,12 @@ void RenderManager::ContextDestroyed() { renderer->GlContextDestroyed(); } + + // inform scenes + for( auto&& scene : mImpl->sceneContainer ) + { + scene->GlContextDestroyed(); + } } void RenderManager::SetShaderSaver( ShaderSaver& upstream ) @@ -241,11 +256,6 @@ void RenderManager::SetShaderSaver( ShaderSaver& upstream ) mImpl->programController.SetShaderSaver( upstream ); } -RenderInstructionContainer& RenderManager::GetRenderInstructionContainer() -{ - return mImpl->instructions; -} - void RenderManager::SetDefaultSurfaceRect(const Rect& rect) { mImpl->defaultSurfaceRect = rect; @@ -323,14 +333,7 @@ void RenderManager::AddFrameBuffer( OwnerPointer< Render::FrameBuffer >& frameBu { Render::FrameBuffer* frameBufferPtr = frameBuffer.Release(); mImpl->frameBufferContainer.PushBack( frameBufferPtr ); - if ( frameBufferPtr->IsSurfaceBacked() ) - { - frameBufferPtr->Initialize( *mImpl->CreateSurfaceContext() ); - } - else - { - frameBufferPtr->Initialize( mImpl->context ); - } + frameBufferPtr->Initialize( mImpl->context ); } void RenderManager::RemoveFrameBuffer( Render::FrameBuffer* frameBuffer ) @@ -343,29 +346,40 @@ void RenderManager::RemoveFrameBuffer( Render::FrameBuffer* frameBuffer ) if ( iter == frameBuffer ) { frameBuffer->Destroy( mImpl->context ); - - if ( frameBuffer->IsSurfaceBacked() ) - { - auto surfaceFrameBuffer = static_cast( frameBuffer ); - mImpl->DestroySurfaceContext( surfaceFrameBuffer->GetContext() ); - } - mImpl->frameBufferContainer.Erase( &iter ); // frameBuffer found; now destroy it break; } } } +void RenderManager::InitializeScene( SceneGraph::Scene* scene ) +{ + scene->Initialize( *mImpl->CreateSceneContext() ); + mImpl->sceneContainer.push_back( scene ); +} -void RenderManager::AttachColorTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::Texture* texture, uint32_t mipmapLevel, uint32_t layer ) +void RenderManager::UninitializeScene( SceneGraph::Scene* scene ) { - if ( !frameBuffer->IsSurfaceBacked() ) + mImpl->DestroySceneContext( scene->GetContext() ); + + auto iter = std::find( mImpl->sceneContainer.begin(), mImpl->sceneContainer.end(), scene ); + if( iter != mImpl->sceneContainer.end() ) { - auto textureFrameBuffer = static_cast( frameBuffer ); - textureFrameBuffer->AttachColorTexture( mImpl->context, texture, mipmapLevel, layer ); + mImpl->sceneContainer.erase( iter ); } } +void RenderManager::SurfaceReplaced( SceneGraph::Scene* scene ) +{ + Context* newContext = mImpl->ReplaceSceneContext( scene->GetContext() ); + scene->Initialize( *newContext ); +} + +void RenderManager::AttachColorTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::Texture* texture, uint32_t mipmapLevel, uint32_t layer ) +{ + frameBuffer->AttachColorTexture( mImpl->context, texture, mipmapLevel, layer ); +} + void RenderManager::AddPropertyBuffer( OwnerPointer< Render::PropertyBuffer >& propertyBuffer ) { mImpl->propertyBufferContainer.PushBack( propertyBuffer.Release() ); @@ -451,7 +465,7 @@ ProgramCache* RenderManager::GetProgramCache() return &(mImpl->programController); } -void RenderManager::Render( Integration::RenderStatus& status, bool forceClear, bool uploadOnly ) +void RenderManager::PreRender( Integration::RenderStatus& status, bool forceClear, bool uploadOnly ) { DALI_PRINT_RENDER_START( mImpl->renderBufferIndex ); @@ -464,7 +478,12 @@ void RenderManager::Render( Integration::RenderStatus& status, bool forceClear, // Process messages queued during previous update mImpl->renderQueue.ProcessMessages( mImpl->renderBufferIndex ); - const uint32_t count = mImpl->instructions.Count( mImpl->renderBufferIndex ); + uint32_t count = 0u; + for( uint32_t i = 0; i < mImpl->sceneContainer.size(); ++i ) + { + count += mImpl->sceneContainer[i]->GetRenderInstructions().Count( mImpl->renderBufferIndex ); + } + const bool haveInstructions = count > 0u; DALI_LOG_INFO( gLogFilter, Debug::General, @@ -499,220 +518,167 @@ void RenderManager::Render( Integration::RenderStatus& status, bool forceClear, } // Upload the geometries - for( uint32_t i = 0; i < count; ++i ) + for( uint32_t i = 0; i < mImpl->sceneContainer.size(); ++i ) { - RenderInstruction& instruction = mImpl->instructions.At( mImpl->renderBufferIndex, i ); - - const Matrix* viewMatrix = instruction.GetViewMatrix( mImpl->renderBufferIndex ); - const Matrix* projectionMatrix = instruction.GetProjectionMatrix( mImpl->renderBufferIndex ); + RenderInstructionContainer& instructions = mImpl->sceneContainer[i]->GetRenderInstructions(); + for ( uint32_t j = 0; j < instructions.Count( mImpl->renderBufferIndex ); ++j ) + { + RenderInstruction& instruction = instructions.At( mImpl->renderBufferIndex, j ); - DALI_ASSERT_DEBUG( viewMatrix ); - DALI_ASSERT_DEBUG( projectionMatrix ); + const Matrix* viewMatrix = instruction.GetViewMatrix( mImpl->renderBufferIndex ); + const Matrix* projectionMatrix = instruction.GetProjectionMatrix( mImpl->renderBufferIndex ); - if( viewMatrix && projectionMatrix ) - { - const RenderListContainer::SizeType renderListCount = instruction.RenderListCount(); + DALI_ASSERT_DEBUG( viewMatrix ); + DALI_ASSERT_DEBUG( projectionMatrix ); - // Iterate through each render list. - for( RenderListContainer::SizeType index = 0; index < renderListCount; ++index ) + if( viewMatrix && projectionMatrix ) { - const RenderList* renderList = instruction.GetRenderList( index ); + const RenderListContainer::SizeType renderListCount = instruction.RenderListCount(); - if( renderList && !renderList->IsEmpty() ) + // Iterate through each render list. + for( RenderListContainer::SizeType index = 0; index < renderListCount; ++index ) { - const std::size_t itemCount = renderList->Count(); - for( uint32_t itemIndex = 0u; itemIndex < itemCount; ++itemIndex ) + const RenderList* renderList = instruction.GetRenderList( index ); + + if( renderList && !renderList->IsEmpty() ) { - const RenderItem& item = renderList->GetItem( itemIndex ); - if( DALI_LIKELY( item.mRenderer ) ) + const std::size_t itemCount = renderList->Count(); + for( uint32_t itemIndex = 0u; itemIndex < itemCount; ++itemIndex ) { - item.mRenderer->Upload( *mImpl->currentContext ); + const RenderItem& item = renderList->GetItem( itemIndex ); + if( DALI_LIKELY( item.mRenderer ) ) + { + item.mRenderer->Upload( *mImpl->currentContext ); + } } } } } } } + } +} - if ( !uploadOnly ) - { - for( uint32_t i = 0; i < count; ++i ) - { - RenderInstruction& instruction = mImpl->instructions.At( mImpl->renderBufferIndex, i ); - DoRender( instruction ); - } +void RenderManager::RenderScene( Integration::Scene& scene, bool renderToFbo ) +{ + Internal::Scene& sceneInternal = GetImplementation( scene ); + SceneGraph::Scene* sceneObject = sceneInternal.GetSceneObject(); - if ( mImpl->currentContext->IsSurfacelessContextSupported() ) - { - mImpl->glContextHelperAbstraction.MakeSurfacelessContextCurrent(); - } + uint32_t count = sceneObject->GetRenderInstructions().Count( mImpl->renderBufferIndex ); - GLenum attachments[] = { GL_DEPTH, GL_STENCIL }; - mImpl->context.InvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments); - for ( auto&& context : mImpl->surfaceContextContainer ) - { - context->InvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments); - } - } + for( uint32_t i = 0; i < count; ++i ) + { + RenderInstruction& instruction = sceneObject->GetRenderInstructions().At( mImpl->renderBufferIndex, i ); - //Notify RenderGeometries that rendering has finished - for ( auto&& iter : mImpl->geometryContainer ) + if ( ( renderToFbo && !instruction.mFrameBuffer ) || ( !renderToFbo && instruction.mFrameBuffer ) ) { - iter->OnRenderFinished(); + continue; // skip } - } - else - { - DALI_LOG_RELEASE_INFO( "RenderManager::Render: Skip rendering [%d, %d, %d]\n", haveInstructions, mImpl->lastFrameWasRendered, forceClear ); - } - - mImpl->UpdateTrackers(); - - // If this frame was rendered due to instructions existing, we mark this so we know to clear the next frame. - mImpl->lastFrameWasRendered = haveInstructions; - - /** - * The rendering has finished; swap to the next buffer. - * Ideally the update has just finished using this buffer; otherwise the render thread - * should block until the update has finished. - */ - mImpl->renderBufferIndex = (0 != mImpl->renderBufferIndex) ? 0 : 1; - DALI_PRINT_RENDER_END(); -} + Rect viewportRect; + Vector4 clearColor; -void RenderManager::DoRender( RenderInstruction& instruction ) -{ - Rect viewportRect; - Vector4 clearColor; - - if ( instruction.mIsClearColorSet ) - { - clearColor = instruction.mClearColor; - } - else - { - clearColor = Dali::RenderTask::DEFAULT_CLEAR_COLOR; - } + if ( instruction.mIsClearColorSet ) + { + clearColor = instruction.mClearColor; + } + else + { + clearColor = Dali::RenderTask::DEFAULT_CLEAR_COLOR; + } - Rect surfaceRect = mImpl->defaultSurfaceRect; - Integration::DepthBufferAvailable depthBufferAvailable = mImpl->depthBufferAvailable; - Integration::StencilBufferAvailable stencilBufferAvailable = mImpl->stencilBufferAvailable; + Rect surfaceRect = mImpl->defaultSurfaceRect; + Integration::DepthBufferAvailable depthBufferAvailable = mImpl->depthBufferAvailable; + Integration::StencilBufferAvailable stencilBufferAvailable = mImpl->stencilBufferAvailable; - Render::SurfaceFrameBuffer* surfaceFrameBuffer = nullptr; - if ( instruction.mFrameBuffer != 0 ) - { - if ( instruction.mFrameBuffer->IsSurfaceBacked() ) + if ( instruction.mFrameBuffer ) { - surfaceFrameBuffer = static_cast( instruction.mFrameBuffer ); - - if ( !surfaceFrameBuffer->IsSurfaceValid() ) + // offscreen buffer + if ( mImpl->currentContext != &mImpl->context ) { - // Skip rendering the frame buffer if the render surface becomes invalid - return; - } + // Switch to shared context for off-screen buffer + mImpl->currentContext = &mImpl->context; + if ( mImpl->currentContext->IsSurfacelessContextSupported() ) + { + mImpl->glContextHelperAbstraction.MakeSurfacelessContextCurrent(); + } + + // Clear the current cached program when the context is switched + mImpl->programController.ClearCurrentProgram(); + } + } + else + { if ( mImpl->currentContext->IsSurfacelessContextSupported() ) { - Context* surfaceContext = surfaceFrameBuffer->GetContext(); - if ( mImpl->currentContext != surfaceContext ) + if ( mImpl->currentContext != sceneObject->GetContext() ) { // Switch the correct context if rendering to a surface - mImpl->currentContext = surfaceContext; - surfaceFrameBuffer->MakeContextCurrent(); + mImpl->currentContext = sceneObject->GetContext(); // Clear the current cached program when the context is switched mImpl->programController.ClearCurrentProgram(); } } - surfaceRect = Rect( 0, 0, static_cast( surfaceFrameBuffer->GetWidth() ), static_cast( surfaceFrameBuffer->GetHeight() ) ); - } - else - { - // Switch to shared context for off-screen buffer - mImpl->currentContext = &mImpl->context; - - if ( mImpl->currentContext->IsSurfacelessContextSupported() ) - { - mImpl->glContextHelperAbstraction.MakeSurfacelessContextCurrent(); - } + surfaceRect = Rect( 0, 0, static_cast( scene.GetSize().width ), static_cast( scene.GetSize().height ) ); } - } - - DALI_ASSERT_DEBUG( mImpl->currentContext->IsGlContextCreated() ); - // reset the program matrices for all programs once per frame - // this ensures we will set view and projection matrix once per program per camera - mImpl->programController.ResetProgramMatrices(); + DALI_ASSERT_DEBUG( mImpl->currentContext->IsGlContextCreated() ); - if( instruction.mFrameBuffer ) - { - instruction.mFrameBuffer->Bind( *mImpl->currentContext ); + // reset the program matrices for all programs once per frame + // this ensures we will set view and projection matrix once per program per camera + mImpl->programController.ResetProgramMatrices(); - if ( !instruction.mFrameBuffer->IsSurfaceBacked() ) + if( instruction.mFrameBuffer ) { + instruction.mFrameBuffer->Bind( *mImpl->currentContext ); + // For each offscreen buffer, update the dependency list with the new texture id used by this frame buffer. - Render::TextureFrameBuffer* textureFrameBuffer = static_cast( instruction.mFrameBuffer ); - for (unsigned int i0 = 0, i1 = textureFrameBuffer->GetColorAttachmentCount(); i0 < i1; ++i0) + for (unsigned int i0 = 0, i1 = instruction.mFrameBuffer->GetColorAttachmentCount(); i0 < i1; ++i0) { - mImpl->textureDependencyList.PushBack( textureFrameBuffer->GetTextureId(i0) ); + mImpl->textureDependencyList.PushBack( instruction.mFrameBuffer->GetTextureId(i0) ); } } - } - else - { - mImpl->currentContext->BindFramebuffer( GL_FRAMEBUFFER, 0u ); - } - - if ( surfaceFrameBuffer ) - { - mImpl->currentContext->Viewport( surfaceRect.x, - surfaceRect.y, - surfaceRect.width, - surfaceRect.height ); - } + else + { + mImpl->currentContext->BindFramebuffer( GL_FRAMEBUFFER, 0u ); + } - // Clear the entire color, depth and stencil buffers for the default framebuffer, if required. - // It is important to clear all 3 buffers when they are being used, for performance on deferred renderers - // e.g. previously when the depth & stencil buffers were NOT cleared, it caused the DDK to exceed a "vertex count limit", - // and then stall. That problem is only noticeable when rendering a large number of vertices per frame. - GLbitfield clearMask = GL_COLOR_BUFFER_BIT; + if ( !instruction.mFrameBuffer ) + { + mImpl->currentContext->Viewport( surfaceRect.x, + surfaceRect.y, + surfaceRect.width, + surfaceRect.height ); + } - mImpl->currentContext->ColorMask( true ); + // Clear the entire color, depth and stencil buffers for the default framebuffer, if required. + // It is important to clear all 3 buffers when they are being used, for performance on deferred renderers + // e.g. previously when the depth & stencil buffers were NOT cleared, it caused the DDK to exceed a "vertex count limit", + // and then stall. That problem is only noticeable when rendering a large number of vertices per frame. + GLbitfield clearMask = GL_COLOR_BUFFER_BIT; - if( depthBufferAvailable == Integration::DepthBufferAvailable::TRUE ) - { - mImpl->currentContext->DepthMask( true ); - clearMask |= GL_DEPTH_BUFFER_BIT; - } + mImpl->currentContext->ColorMask( true ); - if( stencilBufferAvailable == Integration::StencilBufferAvailable::TRUE) - { - mImpl->currentContext->ClearStencil( 0 ); - mImpl->currentContext->StencilMask( 0xFF ); // 8 bit stencil mask, all 1's - clearMask |= GL_STENCIL_BUFFER_BIT; - } + if( depthBufferAvailable == Integration::DepthBufferAvailable::TRUE ) + { + mImpl->currentContext->DepthMask( true ); + clearMask |= GL_DEPTH_BUFFER_BIT; + } - if( !instruction.mIgnoreRenderToFbo && ( instruction.mFrameBuffer != 0 ) ) - { - if ( instruction.mFrameBuffer->IsSurfaceBacked() ) // Surface rendering + if( stencilBufferAvailable == Integration::StencilBufferAvailable::TRUE) { - if ( instruction.mIsViewportSet ) - { - // For glViewport the lower-left corner is (0,0) - // For glViewport the lower-left corner is (0,0) - const int32_t y = ( surfaceRect.height - instruction.mViewport.height ) - instruction.mViewport.y; - viewportRect.Set( instruction.mViewport.x, y, instruction.mViewport.width, instruction.mViewport.height ); - } - else - { - viewportRect = surfaceRect; - } + mImpl->currentContext->ClearStencil( 0 ); + mImpl->currentContext->StencilMask( 0xFF ); // 8 bit stencil mask, all 1's + clearMask |= GL_STENCIL_BUFFER_BIT; } - else // Offscreen buffer rendering + + if( !instruction.mIgnoreRenderToFbo && ( instruction.mFrameBuffer != 0 ) ) { + // Offscreen buffer rendering if ( instruction.mIsViewportSet ) { // For glViewport the lower-left corner is (0,0) @@ -724,154 +690,186 @@ void RenderManager::DoRender( RenderInstruction& instruction ) viewportRect.Set( 0, 0, instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight() ); } } - } - else // No Offscreen frame buffer rendering - { - // Check whether a viewport is specified, otherwise the full surface size is used - if ( instruction.mFrameBuffer != 0 ) + else // No Offscreen frame buffer rendering { + // Check whether a viewport is specified, otherwise the full surface size is used if ( instruction.mIsViewportSet ) { // For glViewport the lower-left corner is (0,0) - const int32_t y = ( instruction.mFrameBuffer->GetHeight() - instruction.mViewport.height ) - instruction.mViewport.y; + const int32_t y = ( surfaceRect.height - instruction.mViewport.height ) - instruction.mViewport.y; viewportRect.Set( instruction.mViewport.x, y, instruction.mViewport.width, instruction.mViewport.height ); } else { - viewportRect.Set( 0, 0, instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight() ); + viewportRect = surfaceRect; } } - else - { - viewportRect = surfaceRect; - } - } - - bool clearFullFrameRect = true; - if( instruction.mFrameBuffer != 0 ) - { - Viewport frameRect( 0, 0, instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight() ); - clearFullFrameRect = ( frameRect == viewportRect ); - } - else - { - clearFullFrameRect = ( surfaceRect == viewportRect ); - } - - mImpl->currentContext->Viewport(viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height); - - if( instruction.mIsClearColorSet ) - { - mImpl->currentContext->ClearColor( clearColor.r, - clearColor.g, - clearColor.b, - clearColor.a ); - if( !clearFullFrameRect ) + bool clearFullFrameRect = true; + if( instruction.mFrameBuffer != 0 ) { - mImpl->currentContext->SetScissorTest( true ); - mImpl->currentContext->Scissor( viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height ); - mImpl->currentContext->Clear( clearMask, Context::FORCE_CLEAR ); - mImpl->currentContext->SetScissorTest( false ); + Viewport frameRect( 0, 0, instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight() ); + clearFullFrameRect = ( frameRect == viewportRect ); } else { - mImpl->currentContext->SetScissorTest( false ); - mImpl->currentContext->Clear( clearMask, Context::FORCE_CLEAR ); + clearFullFrameRect = ( surfaceRect == viewportRect ); } - } - - // Clear the list of bound textures - mImpl->boundTextures.Clear(); - - mImpl->renderAlgorithms.ProcessRenderInstruction( - instruction, - *mImpl->currentContext, - mImpl->renderBufferIndex, - depthBufferAvailable, - stencilBufferAvailable, - mImpl->boundTextures ); - // Synchronise the FBO/Texture access when there are multiple contexts - if ( mImpl->currentContext->IsSurfacelessContextSupported() ) - { - // Check whether any binded texture is in the dependency list - bool textureFound = false; + mImpl->currentContext->Viewport(viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height); - if ( mImpl->boundTextures.Count() > 0u && mImpl->textureDependencyList.Count() > 0u ) + if( instruction.mIsClearColorSet ) { - for ( auto textureId : mImpl->textureDependencyList ) - { + mImpl->currentContext->ClearColor( clearColor.r, + clearColor.g, + clearColor.b, + clearColor.a ); - textureFound = std::find_if( mImpl->boundTextures.Begin(), mImpl->boundTextures.End(), - [textureId]( GLuint id ) - { - return textureId == id; - } ) != mImpl->boundTextures.End(); + if( !clearFullFrameRect ) + { + mImpl->currentContext->SetScissorTest( true ); + mImpl->currentContext->Scissor( viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height ); + mImpl->currentContext->Clear( clearMask, Context::FORCE_CLEAR ); + mImpl->currentContext->SetScissorTest( false ); + } + else + { + mImpl->currentContext->SetScissorTest( false ); + mImpl->currentContext->Clear( clearMask, Context::FORCE_CLEAR ); } } - if ( textureFound ) + // Clear the list of bound textures + mImpl->boundTextures.Clear(); + + mImpl->renderAlgorithms.ProcessRenderInstruction( + instruction, + *mImpl->currentContext, + mImpl->renderBufferIndex, + depthBufferAvailable, + stencilBufferAvailable, + mImpl->boundTextures ); + + // Synchronise the FBO/Texture access when there are multiple contexts + if ( mImpl->currentContext->IsSurfacelessContextSupported() ) { + // Check whether any binded texture is in the dependency list + bool textureFound = false; - if ( !instruction.mFrameBuffer || !instruction.mFrameBuffer->IsSurfaceBacked() ) + if ( mImpl->boundTextures.Count() > 0u && mImpl->textureDependencyList.Count() > 0u ) { - // For off-screen buffer - - // Wait until all rendering calls for the currently context are executed - mImpl->glContextHelperAbstraction.WaitClient(); + for ( auto textureId : mImpl->textureDependencyList ) + { - // Clear the dependency list - mImpl->textureDependencyList.Clear(); + textureFound = std::find_if( mImpl->boundTextures.Begin(), mImpl->boundTextures.End(), + [textureId]( GLuint id ) + { + return textureId == id; + } ) != mImpl->boundTextures.End(); + } } - else + + if ( textureFound ) { - // For surface-backed frame buffer + if ( instruction.mFrameBuffer ) + { + // For off-screen buffer + + // Wait until all rendering calls for the currently context are executed + mImpl->glContextHelperAbstraction.WaitClient(); - // Worker thread lambda function - auto& glContextHelperAbstraction = mImpl->glContextHelperAbstraction; - auto workerFunction = [&glContextHelperAbstraction]( int workerThread ) + // Clear the dependency list + mImpl->textureDependencyList.Clear(); + } + else { - // Switch to the shared context in the worker thread - glContextHelperAbstraction.MakeSurfacelessContextCurrent(); + // Worker thread lambda function + auto& glContextHelperAbstraction = mImpl->glContextHelperAbstraction; + auto workerFunction = [&glContextHelperAbstraction]( int workerThread ) + { + // Switch to the shared context in the worker thread + glContextHelperAbstraction.MakeSurfacelessContextCurrent(); - // Wait until all rendering calls for the shared context are executed - glContextHelperAbstraction.WaitClient(); + // Wait until all rendering calls for the shared context are executed + glContextHelperAbstraction.WaitClient(); - // Must clear the context in the worker thread - // Otherwise the shared context cannot be switched to from the render thread - glContextHelperAbstraction.MakeContextNull(); - }; + // Must clear the context in the worker thread + // Otherwise the shared context cannot be switched to from the render thread + glContextHelperAbstraction.MakeContextNull(); + }; - auto future = mImpl->threadPool->SubmitTask( 0u, workerFunction ); - if ( future ) - { - mImpl->threadPool->Wait(); + auto future = mImpl->threadPool->SubmitTask( 0u, workerFunction ); + if ( future ) + { + mImpl->threadPool->Wait(); - // Clear the dependency list - mImpl->textureDependencyList.Clear(); + // Clear the dependency list + mImpl->textureDependencyList.Clear(); + } } } } + + if( instruction.mRenderTracker && instruction.mFrameBuffer ) + { + // This will create a sync object every frame this render tracker + // is alive (though it should be now be created only for + // render-once render tasks) + instruction.mRenderTracker->CreateSyncObject( mImpl->glSyncAbstraction ); + instruction.mRenderTracker = nullptr; // Only create once. + } + + if ( renderToFbo ) + { + mImpl->currentContext->Flush(); + } } - if( instruction.mRenderTracker && ( instruction.mFrameBuffer != 0 ) ) + GLenum attachments[] = { GL_DEPTH, GL_STENCIL }; + mImpl->currentContext->InvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments); +} + +void RenderManager::PostRender( bool uploadOnly ) +{ + if ( !uploadOnly ) { - // This will create a sync object every frame this render tracker - // is alive (though it should be now be created only for - // render-once render tasks) - instruction.mRenderTracker->CreateSyncObject( mImpl->glSyncAbstraction ); - instruction.mRenderTracker = NULL; // Only create once. + if ( mImpl->currentContext->IsSurfacelessContextSupported() ) + { + mImpl->glContextHelperAbstraction.MakeSurfacelessContextCurrent(); + } + + GLenum attachments[] = { GL_DEPTH, GL_STENCIL }; + mImpl->context.InvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments); } - if ( surfaceFrameBuffer ) + //Notify RenderGeometries that rendering has finished + for ( auto&& iter : mImpl->geometryContainer ) { - surfaceFrameBuffer->PostRender(); + iter->OnRenderFinished(); } - else + + mImpl->UpdateTrackers(); + + + uint32_t count = 0u; + for( uint32_t i = 0; i < mImpl->sceneContainer.size(); ++i ) { - mImpl->currentContext->Flush(); + count += mImpl->sceneContainer[i]->GetRenderInstructions().Count( mImpl->renderBufferIndex ); } + + const bool haveInstructions = count > 0u; + + // If this frame was rendered due to instructions existing, we mark this so we know to clear the next frame. + mImpl->lastFrameWasRendered = haveInstructions; + + /** + * The rendering has finished; swap to the next buffer. + * Ideally the update has just finished using this buffer; otherwise the render thread + * should block until the update has finished. + */ + mImpl->renderBufferIndex = (0 != mImpl->renderBufferIndex) ? 0 : 1; + + DALI_PRINT_RENDER_END(); } } // namespace SceneGraph diff --git a/dali/internal/render/common/render-manager.h b/dali/internal/render/common/render-manager.h index 5aa90d8..9b89959 100644 --- a/dali/internal/render/common/render-manager.h +++ b/dali/internal/render/common/render-manager.h @@ -2,7 +2,7 @@ #define DALI_INTERNAL_SCENE_GRAPH_RENDER_MANAGER_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. @@ -35,6 +35,7 @@ class GlAbstraction; class GlSyncAbstraction; class GlContextHelperAbstraction; class RenderStatus; +class Scene; } struct Vector4; @@ -62,6 +63,7 @@ class RenderInstruction; class RenderInstructionContainer; class Shader; class PropertyBufferDataProvider; +class Scene; /** * RenderManager is responsible for rendering the result of the previous "update", which @@ -114,12 +116,6 @@ public: */ void SetShaderSaver( ShaderSaver& upstream ); - /** - * Retrieve the render instructions; these should be set during each "update" traversal. - * @return The render instruction container. - */ - RenderInstructionContainer& GetRenderInstructionContainer(); - // The following methods should be called via RenderQueue messages /* @@ -297,6 +293,24 @@ public: void AttachColorTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::Texture* texture, uint32_t mipmapLevel, uint32_t layer ); /** + * Initializes a Scene to the render manager + * @param[in] scene The Scene to initialize + */ + void InitializeScene( SceneGraph::Scene* scene ); + + /** + * Uninitializes a Scene to the render manager + * @param[in] scene The Scene to uninitialize + */ + void UninitializeScene( SceneGraph::Scene* scene ); + + /** + * This is called when the surface of the scene has been replaced. + * @param[in] scene The scene. + */ + void SurfaceReplaced( SceneGraph::Scene* scene ); + + /** * Adds a render tracker to the RenderManager. RenderManager takes ownership of the * tracker. The lifetime of the tracker is related to the lifetime of the tracked * object, usually an offscreen render task. @@ -316,23 +330,45 @@ public: */ ProgramCache* GetProgramCache(); - // This method should be called from Core::Render() + // This method should be called from Core::PreRender() /** - * Renders the results of the previous "update" traversal. - * @param[out] status contains the rendering flags. - * @param[in] forceClear Force the Clear on the framebuffer even if nothing is rendered. - * @param[in] uploadOnly Upload the resource only without rendering. + * This is called before rendering any scene in the next frame. This method should be preceded + * by a call up Update. + * Multi-threading note: this method should be called from a dedicated rendering thread. + * @pre The GL context must have been created, and made current. + * @param[out] status showing whether update is required to run. + * @param[in] forceClear force the Clear on the framebuffer even if nothing is rendered. + * @param[in] uploadOnly uploadOnly Upload the resource only without rendering. */ - void Render( Integration::RenderStatus& status, bool forceClear, bool uploadOnly ); + void PreRender( Integration::RenderStatus& status, bool forceClear, bool uploadOnly ); -private: + // This method should be called from Core::RenderScene() + + /** + * Render a scene in the next frame. This method should be preceded by a call up PreRender. + * This method should be called twice. The first pass to render off-screen frame buffers if any, + * and the second pass to render the surface. + * Multi-threading note: this method should be called from a dedicated rendering thread. + * @pre The GL context must have been created, and made current. + * @param[in] scene The scene to be rendered. + * @param[in] renderToFbo True to render off-screen frame buffers only if any, and False to render the surface only. + */ + void RenderScene( Integration::Scene& scene, bool renderToFbo ); + + // This method should be called from Core::PostRender() /** - * Helper to process a single RenderInstruction. - * @param[in] instruction A description of the rendering operation. + * This is called after rendering all the scenes in the next frame. This method should be + * followed by a call up RenderScene. + * Multi-threading note: this method should be called from a dedicated rendering thread. + * @pre The GL context must have been created, and made current. + * @param[in] uploadOnly uploadOnly Upload the resource only without rendering. */ - void DoRender( RenderInstruction& instruction ); + void PostRender( bool uploadOnly ); + + +private: private: diff --git a/dali/internal/render/gl-resources/context.cpp b/dali/internal/render/gl-resources/context.cpp index b37c267..ead1be3 100644 --- a/dali/internal/render/gl-resources/context.cpp +++ b/dali/internal/render/gl-resources/context.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. @@ -69,7 +69,7 @@ Context::Context( Integration::GlAbstraction& glAbstraction ) { } -Context::Context( Integration::GlAbstraction& glAbstraction, OwnerContainer< Context* >* contexts ) +Context::Context( Integration::GlAbstraction& glAbstraction, std::vector< Context* >* contexts ) : mGlAbstraction(glAbstraction), mGlContextCreated(false), mColorMask(true), @@ -107,7 +107,7 @@ Context::Context( Integration::GlAbstraction& glAbstraction, OwnerContainer< Con mClearColor(Color::WHITE), // initial color, never used until it's been set by the user mCullFaceMode( FaceCullingMode::NONE ), mViewPort( 0, 0, 0, 0 ), - mSurfaceContexts( contexts ) + mSceneContexts( contexts ) { } diff --git a/dali/internal/render/gl-resources/context.h b/dali/internal/render/gl-resources/context.h index 06f6ba4..be2db89 100644 --- a/dali/internal/render/gl-resources/context.h +++ b/dali/internal/render/gl-resources/context.h @@ -2,7 +2,7 @@ #define DALI_INTERNAL_CONTEXT_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. @@ -79,9 +79,9 @@ public: * @pre Context has not been created. * @exception Context already created. * @param glAbstraction the gl abstraction. - * @param contexts The list of surface contexts (for surface rendering) + * @param contexts The list of scene contexts (for surface rendering) */ - Context( Integration::GlAbstraction& glAbstraction, OwnerContainer< Context* >* contexts ); + Context( Integration::GlAbstraction& glAbstraction, std::vector< Context* >* contexts ); /** * Destructor @@ -647,9 +647,9 @@ public: // Need to reset the buffer cache in the surface contexts // This will only be executed by the surfaceless context when there are contexts for surface rendering - if ( mSurfaceContexts ) + if ( mSceneContexts ) { - for ( auto&& context : *mSurfaceContexts ) + for ( auto&& context : *mSceneContexts ) { if ( context ) { @@ -698,11 +698,11 @@ public: ResetTextureCache(); - // Need to reset the texture cache in the surface contexts + // Need to reset the texture cache in the scene contexts // This will only be executed by the surfaceless context when there are contexts for surface rendering - if ( mSurfaceContexts ) + if ( mSceneContexts ) { - for ( auto&& context : *mSurfaceContexts ) + for ( auto&& context : *mSceneContexts ) { if ( context ) { @@ -1829,7 +1829,7 @@ private: // Data FrameBufferStateCache mFrameBufferStateCache; ///< frame buffer state cache - OwnerContainer< Context* >* mSurfaceContexts; ///< The pointer of the container of contexts for surface rendering + std::vector< Context* >* mSceneContexts; ///< The pointer of the container of contexts for surface rendering }; } // namespace Internal diff --git a/dali/internal/render/renderers/render-texture-frame-buffer.cpp b/dali/internal/render/renderers/render-frame-buffer.cpp similarity index 81% rename from dali/internal/render/renderers/render-texture-frame-buffer.cpp rename to dali/internal/render/renderers/render-frame-buffer.cpp index 24a17f4..44c00b0 100644 --- a/dali/internal/render/renderers/render-texture-frame-buffer.cpp +++ b/dali/internal/render/renderers/render-frame-buffer.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. @@ -15,7 +15,7 @@ */ // CLASS HEADER -#include +#include // INTERNAL INCLUDES #include @@ -41,9 +41,8 @@ const GLenum COLOR_ATTACHMENTS[] = }; } -TextureFrameBuffer::TextureFrameBuffer( uint32_t width, uint32_t height, Mask attachments ) -: FrameBuffer(), - mId( 0u ), +FrameBuffer::FrameBuffer( uint32_t width, uint32_t height, Mask attachments ) +: mId( 0u ), mTextureId{ 0u }, mDepthBuffer( attachments & Dali::FrameBuffer::Attachment::DEPTH ), mStencilBuffer( attachments & Dali::FrameBuffer::Attachment::STENCIL ), @@ -53,10 +52,11 @@ TextureFrameBuffer::TextureFrameBuffer( uint32_t width, uint32_t height, Mask at { } -TextureFrameBuffer::~TextureFrameBuffer() -{} +FrameBuffer::~FrameBuffer() +{ +} -void TextureFrameBuffer::Destroy( Context& context ) +void FrameBuffer::Destroy( Context& context ) { if( mId ) { @@ -64,12 +64,12 @@ void TextureFrameBuffer::Destroy( Context& context ) } } -void TextureFrameBuffer::GlContextDestroyed() +void FrameBuffer::GlContextDestroyed() { mId = 0u; } -void TextureFrameBuffer::Initialize(Context& context) +void FrameBuffer::Initialize(Context& context) { context.GenFramebuffers( 1, &mId ); context.BindFramebuffer( GL_FRAMEBUFFER, mId ); @@ -95,7 +95,7 @@ void TextureFrameBuffer::Initialize(Context& context) context.BindFramebuffer( GL_FRAMEBUFFER, 0 ); } -void TextureFrameBuffer::AttachColorTexture( Context& context, Render::Texture* texture, uint32_t mipmapLevel, uint32_t layer ) +void FrameBuffer::AttachColorTexture( Context& context, Render::Texture* texture, uint32_t mipmapLevel, uint32_t layer ) { context.BindFramebuffer( GL_FRAMEBUFFER, mId ); @@ -120,17 +120,17 @@ void TextureFrameBuffer::AttachColorTexture( Context& context, Render::Texture* context.BindFramebuffer( GL_FRAMEBUFFER, 0 ); } -void TextureFrameBuffer::Bind( Context& context ) +void FrameBuffer::Bind( Context& context ) { context.BindFramebuffer( GL_FRAMEBUFFER, mId ); } -uint32_t TextureFrameBuffer::GetWidth() const +uint32_t FrameBuffer::GetWidth() const { return mWidth; } -uint32_t TextureFrameBuffer::GetHeight() const +uint32_t FrameBuffer::GetHeight() const { return mHeight; } diff --git a/dali/internal/render/renderers/render-frame-buffer.h b/dali/internal/render/renderers/render-frame-buffer.h index 16d2a73..bbd2bf0 100644 --- a/dali/internal/render/renderers/render-frame-buffer.h +++ b/dali/internal/render/renderers/render-frame-buffer.h @@ -2,7 +2,7 @@ #define DALI_INTERNAL_RENDER_FRAME_BUFFER_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. @@ -19,16 +19,20 @@ // INTERNAL INCLUDES #include +#include #include #include #include namespace Dali { +using Mask = Dali::FrameBuffer::Attachment::Mask; + namespace Internal { namespace Render { +class Texture; class FrameBuffer { @@ -37,53 +41,69 @@ public: /** * Constructor */ - FrameBuffer() {}; + FrameBuffer( uint32_t width, uint32_t height, Mask attachments ); /** * Destructor */ - virtual ~FrameBuffer() {}; + virtual ~FrameBuffer(); /** * Creates a FrameBuffer object in the GPU. * @param[in] context The GL context */ - virtual void Initialize( Context& context ) = 0; + virtual void Initialize( Context& context ); /** * Deletes the framebuffer object from the GPU * @param[in] context The GL context */ - virtual void Destroy( Context& context ) = 0; + virtual void Destroy( Context& context ); /** * Called by RenderManager to inform the framebuffer that the context has been destroyed */ - virtual void GlContextDestroyed() = 0; + virtual void GlContextDestroyed(); /** * @brief Bind the framebuffer * @param[in] context The GL context */ - virtual void Bind( Context& context ) = 0; + virtual void Bind( Context& context ); /** * @brief Get the width of the FrameBuffer * @return The width of the framebuffer */ - virtual uint32_t GetWidth() const = 0; + virtual uint32_t GetWidth() const; /** * @brief Get the height of the FrameBuffer * @return The height of the framebuffer */ - virtual uint32_t GetHeight() const = 0; + virtual uint32_t GetHeight() const; + + /** + * @brief Attach a texture for color rendering. Valid only for Framebuffers with COLOR attachments. + * @param[in] context The GL context + * @param[in] texture The texture that will be used as output when rendering + * @param[in] mipmapLevel The mipmap of the texture to be attached + * @param[in] layer Indicates which layer of a cube map or array texture to attach. Unused for 2D textures + * @note A maximum of Dali::FrameBuffer::MAX_COLOR_ATTACHMENTS are supported. + */ + void AttachColorTexture( Context& context, Render::Texture* texture, uint32_t mipmapLevel, uint32_t layer ); /** - * @brief Check whether the FrameBuffer is backed by a render surface - * @return True if the FrameBuffer is backed by a render surface + * @brief Get the number of textures bound to this frame buffer as color attachments. + * @return The number of color attachments. */ - virtual bool IsSurfaceBacked() = 0; + uint8_t GetColorAttachmentCount() const { return mColorAttachmentCount; } + + /** + * @brief Get the id (OpenGL handle) of the texture bound to this frame buffer as color attachment @a index. + * @return The texture id. + */ + GLuint GetTextureId(uint8_t index) { return mTextureId[index]; }; private: @@ -97,6 +117,15 @@ private: */ FrameBuffer& operator=( const FrameBuffer& rhs ) = delete; +private: + + GLuint mId; + GLuint mTextureId[ Dali::DevelFrameBuffer::MAX_COLOR_ATTACHMENTS ]; + GLuint mDepthBuffer; + GLuint mStencilBuffer; + uint32_t mWidth; + uint32_t mHeight; + uint8_t mColorAttachmentCount; }; } // namespace Render diff --git a/dali/internal/render/renderers/render-surface-frame-buffer.cpp b/dali/internal/render/renderers/render-surface-frame-buffer.cpp deleted file mode 100644 index 396af00..0000000 --- a/dali/internal/render/renderers/render-surface-frame-buffer.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (c) 2019 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 -{ -namespace Internal -{ -namespace Render -{ - -SurfaceFrameBuffer::SurfaceFrameBuffer( Integration::RenderSurface* surface ) -: FrameBuffer(), - mSurface( surface ), - mContext( nullptr ), - mWidth( mSurface->GetPositionSize().width ), - mHeight( mSurface->GetPositionSize().height ), - mSizeChanged( false ), - mIsSurfaceInvalid( false ) -{ -} - -SurfaceFrameBuffer::~SurfaceFrameBuffer() -{} - -void SurfaceFrameBuffer::Destroy( Context& context ) -{ - if ( IsSurfaceValid() ) - { - mSurface->DestroySurface(); - mSurface = nullptr; - } -} - -void SurfaceFrameBuffer::GlContextDestroyed() -{ - if ( mContext ) - { - mContext->GlContextDestroyed(); - } - - if ( IsSurfaceValid() ) - { - mSurface->DestroySurface(); - mSurface = nullptr; - } -} - -void SurfaceFrameBuffer::Initialize(Context& context) -{ - mContext = &context; - mContext->GlContextCreated(); - - if ( IsSurfaceValid() ) - { - mSurface->InitializeGraphics(); - } -} - -void SurfaceFrameBuffer::Bind( Context& context ) -{ - if ( IsSurfaceValid() ) - { - mSurface->PreRender( mSizeChanged ); - - context.BindFramebuffer( GL_FRAMEBUFFER, 0u ); - } -} - -uint32_t SurfaceFrameBuffer::GetWidth() const -{ - return mWidth; -} - -uint32_t SurfaceFrameBuffer::GetHeight() const -{ - return mHeight; -} - -void SurfaceFrameBuffer::PostRender() -{ - if ( IsSurfaceValid() ) - { - mSurface->PostRender( false, false, mSizeChanged ); - } - - mSizeChanged = false; -} - -Context* SurfaceFrameBuffer::GetContext() -{ - return mContext; -} - -void SurfaceFrameBuffer::MakeContextCurrent() -{ - if ( IsSurfaceValid() ) - { - mSurface->MakeContextCurrent(); - } -} - -void SurfaceFrameBuffer::SetSize( uint32_t width, uint32_t height ) -{ - mWidth = width; - mHeight = height; - mSizeChanged = true; -} - -bool SurfaceFrameBuffer::IsSurfaceValid() const -{ - return mSurface && !mIsSurfaceInvalid; -} - -} //Render - -} //Internal - -} //Dali diff --git a/dali/internal/render/renderers/render-surface-frame-buffer.h b/dali/internal/render/renderers/render-surface-frame-buffer.h deleted file mode 100644 index e08666c..0000000 --- a/dali/internal/render/renderers/render-surface-frame-buffer.h +++ /dev/null @@ -1,156 +0,0 @@ -#ifndef DALI_INTERNAL_RENDER_SURFACE_FRAME_BUFFER_H -#define DALI_INTERNAL_RENDER_SURFACE_FRAME_BUFFER_H - -/* - * Copyright (c) 2019 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 - -// INTERNAL INCLUDES -#include -#include -#include - -namespace Dali -{ - -namespace Internal -{ - -class Context; - -namespace Render -{ - -class SurfaceFrameBuffer : public FrameBuffer -{ -public: - - /** - * Constructor - * @param[in] surface The render surface - */ - SurfaceFrameBuffer( Integration::RenderSurface* surface ); - - /** - * Destructor - */ - virtual ~SurfaceFrameBuffer(); - - /** - * @copydoc Dali::Internal::Renderer::FrameBuffer::Initialize() - */ - void Initialize( Context& context ) override; - - /** - * @copydoc Dali::Internal::Renderer::FrameBuffer::Destroy() - */ - void Destroy( Context& context ) override; - - /** - * @copydoc Dali::Internal::Renderer::FrameBuffer::GlContextDestroyed() - */ - void GlContextDestroyed() override; - - /** - * @copydoc Dali::Internal::Renderer::FrameBuffer::Bind() - */ - void Bind( Context& context ) override; - - /** - * @copydoc Dali::Internal::Renderer::FrameBuffer::GetWidth() - */ - uint32_t GetWidth() const override; - - /** - * @copydoc Dali::Internal::Renderer::FrameBuffer::GetHeight() - */ - uint32_t GetHeight() const override; - - /** - * @copydoc Dali::Internal::Renderer::FrameBuffer::IsSurfaceBacked() - */ - bool IsSurfaceBacked() override { return true; }; - - /** - * @brief Sets the frame buffer size. - * @param[in] width The width size - * @param[in] height The height size - */ - void SetSize( uint32_t width, uint32_t height ); - - /** - * @copydoc Dali::Internal::FrameBuffer::MarkSurfaceAsInvalid() - */ - void MarkSurfaceAsInvalid() { mIsSurfaceInvalid = true; }; - - /** - * @brief Gets whether the render surface in this frame buffer is valid or not - * @note The render surface becomes invalid when it is deleted in the event thread - * @return Whether the render surface is valid or not - */ - bool IsSurfaceValid() const; - -public: - - /** - * Called after this frame buffer is rendered in the render manager - */ - void PostRender(); - - /** - * Gets the context holding the GL state of rendering for the surface - * @return the context - */ - Context* GetContext(); - - /** - * @brief Makes the graphics context current - */ - void MakeContextCurrent(); - -private: - - Integration::RenderSurface* mSurface; ///< The render surface - Context* mContext; ///< The context holding the GL state of rendering for the surface backed frame buffer - - uint32_t mWidth; - uint32_t mHeight; - bool mSizeChanged; - std::atomic mIsSurfaceInvalid; ///< This is set only from the event thread and read only from the render thread -}; - -// Messages for FrameBuffer -inline void SetFrameBufferSizeMessage( SceneGraph::UpdateManager& updateManager, SurfaceFrameBuffer* surfaceFrameBuffer, uint32_t width, uint32_t height ) -{ - typedef MessageValue2< SurfaceFrameBuffer, uint32_t, uint32_t > LocalType; - - // Reserve some memory inside the message queue - uint32_t* slot = updateManager.ReserveMessageSlot( sizeof( LocalType ) ); - - // Construct message in the message queue memory; note that delete should not be called on the return value - new (slot) LocalType( surfaceFrameBuffer, &SurfaceFrameBuffer::SetSize, width, height ); -} - -} // namespace Render - -} // namespace Internal - -} // namespace Dali - - -#endif // DALI_INTERNAL_RENDER_SURFACE_FRAME_BUFFER_H diff --git a/dali/internal/render/renderers/render-texture-frame-buffer.h b/dali/internal/render/renderers/render-texture-frame-buffer.h deleted file mode 100644 index 5c297d9..0000000 --- a/dali/internal/render/renderers/render-texture-frame-buffer.h +++ /dev/null @@ -1,127 +0,0 @@ -#ifndef DALI_INTERNAL_RENDER_TEXTURE_FRAME_BUFFER_H -#define DALI_INTERNAL_RENDER_TEXTURE_FRAME_BUFFER_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 -{ -using Mask = Dali::FrameBuffer::Attachment::Mask; - -namespace Internal -{ -namespace Render -{ -class Texture; - -class TextureFrameBuffer : public FrameBuffer -{ -public: - - /** - * Constructor - * @param[in] width The width of the FrameBuffer - * @param[in] height The height of the FrameBuffer - * @param[in] attachments The attachments comprising the format of the FrameBuffer (bit-mask) - */ - TextureFrameBuffer( uint32_t width, uint32_t height, Mask attachments ); - - /** - * Destructor - */ - virtual ~TextureFrameBuffer(); - - /** - * @copydoc Dali::Internal::Renderer::FrameBuffer::Initialize() - */ - void Initialize( Context& context ) override; - - /** - * @copydoc Dali::Internal::Renderer::FrameBuffer::Destroy() - */ - void Destroy( Context& context ) override; - - /** - * @copydoc Dali::Internal::Renderer::FrameBuffer::GlContextDestroyed() - */ - void GlContextDestroyed() override; - - /** - * @copydoc Dali::Internal::Renderer::FrameBuffer::Bind() - */ - void Bind( Context& context ) override; - - /** - * @copydoc Dali::Internal::Renderer::FrameBuffer::GetWidth() - */ - uint32_t GetWidth() const override; - - /** - * @copydoc Dali::Internal::Renderer::FrameBuffer::GetHeight() - */ - uint32_t GetHeight() const override; - - /** - * @copydoc Dali::Internal::Renderer::FrameBuffer::IsSurfaceBacked() - */ - bool IsSurfaceBacked() override { return false; }; - - /** - * @brief Attach a texture for color rendering. Valid only for Framebuffers with COLOR attachments. - * @param[in] context The GL context - * @param[in] texture The texture that will be used as output when rendering - * @param[in] mipmapLevel The mipmap of the texture to be attached - * @param[in] layer Indicates which layer of a cube map or array texture to attach. Unused for 2D textures - * @note A maximum of Dali::FrameBuffer::MAX_COLOR_ATTACHMENTS are supported. - */ - void AttachColorTexture( Context& context, Render::Texture* texture, uint32_t mipmapLevel, uint32_t layer ); - - /** - * @brief Get the number of textures bound to this frame buffer as color attachments. - * @return The number of color attachments. - */ - uint8_t GetColorAttachmentCount() const { return mColorAttachmentCount; } - - /** - * @brief Get the id (OpenGL handle) of the texture bound to this frame buffer as color attachment @a index. - * @return The texture id. - */ - GLuint GetTextureId(uint8_t index) { return mTextureId[index]; }; - -private: - - GLuint mId; - GLuint mTextureId[ Dali::DevelFrameBuffer::MAX_COLOR_ATTACHMENTS ]; - GLuint mDepthBuffer; - GLuint mStencilBuffer; - uint32_t mWidth; - uint32_t mHeight; - uint8_t mColorAttachmentCount; -}; - - -} // namespace Render - -} // namespace Internal - -} // namespace Dali - - -#endif // DALI_INTERNAL_RENDER_TEXTURE_FRAME_BUFFER_H diff --git a/dali/internal/update/common/scene-graph-scene.cpp b/dali/internal/update/common/scene-graph-scene.cpp new file mode 100644 index 0000000..0540516 --- /dev/null +++ b/dali/internal/update/common/scene-graph-scene.cpp @@ -0,0 +1,82 @@ +/* + * 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 + +#include + +namespace Dali +{ +namespace Internal +{ +namespace SceneGraph +{ + +Scene::Scene() +: mContext( nullptr ) +{ +} + +Scene::~Scene() +{ + if ( mContext ) + { + mContext->GlContextDestroyed(); + + delete mContext; + mContext = nullptr; + } +} + +void Scene::GlContextDestroyed() +{ + if ( mContext ) + { + mContext->GlContextDestroyed(); + } +} + +void Scene::Initialize( Context& context ) +{ + if ( mContext != &context ) + { + if ( mContext ) + { + mContext->GlContextDestroyed(); + delete mContext; + } + + mContext = &context; + mContext->GlContextCreated(); + } +} + +Context* Scene::GetContext() +{ + return mContext; +} + +RenderInstructionContainer& Scene::GetRenderInstructions() +{ + return mInstructions; +} + +} //SceneGraph + +} //Internal + +} //Dali diff --git a/dali/internal/update/common/scene-graph-scene.h b/dali/internal/update/common/scene-graph-scene.h new file mode 100644 index 0000000..221c42e --- /dev/null +++ b/dali/internal/update/common/scene-graph-scene.h @@ -0,0 +1,94 @@ +#ifndef DALI_INTERNAL_SCENE_GRAPH_SCENE_H +#define DALI_INTERNAL_SCENE_GRAPH_SCENE_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 +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +class Context; + +namespace SceneGraph +{ +class RenderInstructionContainer; + +class Scene +{ +public: + + /** + * Constructor + * @param[in] surface The render surface + */ + Scene(); + + /** + * Destructor + */ + virtual ~Scene(); + + /** + * Creates a scene object in the GPU. + * @param[in] context The GL context + */ + void Initialize( Context& context ); + + /** + * Called by RenderManager to inform the scene that the context has been destroyed + */ + void GlContextDestroyed(); + + /** + * Gets the context holding the GL state of rendering for the scene + * @return the context + */ + Context* GetContext(); + + /** + * Gets the render instructions for the scene + * @return the render instructions + */ + RenderInstructionContainer& GetRenderInstructions(); + +private: + + Context* mContext; ///< The context holding the GL state of rendering for the scene + + // Render instructions describe what should be rendered during RenderManager::RenderScene() + // Update manager updates instructions for the next frame while we render the current one + + RenderInstructionContainer mInstructions; ///< Render instructions for the scene +}; + + +} // namespace SceneGraph + +} // namespace Internal + +} // namespace Dali + + +#endif // DALI_INTERNAL_SCENE_GRAPH_SCENE_H diff --git a/dali/internal/update/manager/render-instruction-processor.cpp b/dali/internal/update/manager/render-instruction-processor.cpp index 204a472..1e41c12 100644 --- a/dali/internal/update/manager/render-instruction-processor.cpp +++ b/dali/internal/update/manager/render-instruction-processor.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. @@ -397,6 +397,7 @@ inline void RenderInstructionProcessor::SortRenderItems( BufferIndex bufferIndex void RenderInstructionProcessor::Prepare( BufferIndex updateBufferIndex, SortedLayerPointers& sortedLayers, + Context& context, RenderTask& renderTask, bool cull, bool hasClippingNodes, @@ -404,8 +405,7 @@ void RenderInstructionProcessor::Prepare( BufferIndex updateBufferIndex, { // Retrieve the RenderInstruction buffer from the RenderInstructionContainer // then populate with instructions. - RenderInstruction& instruction = instructions.GetNextInstruction( updateBufferIndex ); - renderTask.PrepareRenderInstruction( instruction, updateBufferIndex ); + RenderInstruction& instruction = renderTask.PrepareRenderInstruction( updateBufferIndex ); bool viewMatrixHasNotChanged = !renderTask.ViewMatrixUpdated(); bool isRenderListAdded = false; bool isRootLayerDirty = false; @@ -475,9 +475,10 @@ void RenderInstructionProcessor::Prepare( BufferIndex updateBufferIndex, // Inform the render instruction that all renderers have been added and this frame is complete. instruction.UpdateCompleted(); - if( !isRenderListAdded && !instruction.mIsClearColorSet && !isRootLayerDirty ) + if( isRenderListAdded || instruction.mIsClearColorSet || isRootLayerDirty ) { - instructions.DiscardCurrentInstruction( updateBufferIndex ); + instruction.mContext = &context; + instructions.PushBack( updateBufferIndex, &instruction ); } } diff --git a/dali/internal/update/manager/render-instruction-processor.h b/dali/internal/update/manager/render-instruction-processor.h index 95cc818..9cc7b54 100644 --- a/dali/internal/update/manager/render-instruction-processor.h +++ b/dali/internal/update/manager/render-instruction-processor.h @@ -2,7 +2,7 @@ #define DALI_INTERNAL_SCENE_GRAPH_RENDER_INSTRUCTION_PROCESSOR_H /* - * Copyright (c) 2017 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. @@ -29,6 +29,8 @@ namespace Dali namespace Internal { +class Context; + namespace Render { class Geometry; @@ -97,6 +99,7 @@ public: * * @param[in] updateBufferIndex The current update buffer index. * @param[in] sortedLayers The layers containing lists of opaque/transparent renderables. + * @param[in] context The context holding the GL state of rendering for the rendering instructions. * @param[in] renderTask The rendering task information. * @param[in] cull Whether frustum culling is enabled or not * @param[in] hasClippingNodes Whether any clipping nodes exist within this layer, to optimize sorting if not @@ -104,6 +107,7 @@ public: */ void Prepare( BufferIndex updateBufferIndex, SortedLayerPointers& sortedLayers, + Context& context, RenderTask& renderTask, bool cull, bool hasClippingNodes, diff --git a/dali/internal/update/manager/render-task-processor.cpp b/dali/internal/update/manager/render-task-processor.cpp index 6c30d58..0fdc554 100644 --- a/dali/internal/update/manager/render-task-processor.cpp +++ b/dali/internal/update/manager/render-task-processor.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. @@ -207,6 +207,7 @@ bool AddRenderablesForTask( BufferIndex updateBufferIndex, * @param[in] taskContainer The container of render-tasks. * @param[in] rootNode The root node of the scene-graph. * @param[in] sortedLayers The layers containing lists of opaque / transparent renderables. + * @param[in] context The context holding the GL state of rendering for the rendering instructions. * @param[out] instructions The instructions for rendering the next frame. * @param[in] renderInstructionProcessor An instance of the RenderInstructionProcessor used to sort and handle the renderers for each layer. * @param[in] renderToFboEnabled Whether rendering into the Frame Buffer Object is enabled (used to measure FPS above 60) @@ -218,6 +219,7 @@ bool ProcessTasks( BufferIndex updateBufferIndex, RenderTaskList::RenderTaskContainer& taskContainer, Layer& rootNode, SortedLayerPointers& sortedLayers, + Context& context, RenderInstructionContainer& instructions, RenderInstructionProcessor& renderInstructionProcessor, bool renderToFboEnabled, @@ -237,9 +239,8 @@ bool ProcessTasks( BufferIndex updateBufferIndex, const bool isDefaultRenderTask = isFirstRenderTask; isFirstRenderTask = false; - const bool isSurfaceBacked = hasFrameBuffer && renderTask.GetFrameBuffer()->IsSurfaceBacked(); - if( ( !renderToFboEnabled && ( ( !processOffscreen && hasFrameBuffer && !isSurfaceBacked ) || - ( processOffscreen && ( !hasFrameBuffer || isSurfaceBacked ) ) ) ) || + if( ( !renderToFboEnabled && ( ( !processOffscreen && hasFrameBuffer ) || + ( processOffscreen && !hasFrameBuffer ) ) ) || ( renderToFboEnabled && ( ( processOffscreen && !hasFrameBuffer ) || ( isDefaultRenderTask && processOffscreen ) || ( !isDefaultRenderTask && !processOffscreen && hasFrameBuffer ) ) ) || @@ -286,6 +287,7 @@ bool ProcessTasks( BufferIndex updateBufferIndex, renderInstructionProcessor.Prepare( updateBufferIndex, sortedLayers, + context, renderTask, renderTask.GetCullMode(), hasClippingNodes, @@ -321,6 +323,7 @@ bool RenderTaskProcessor::Process( BufferIndex updateBufferIndex, RenderTaskList& renderTasks, Layer& rootNode, SortedLayerPointers& sortedLayers, + Context& context, RenderInstructionContainer& instructions, bool renderToFboEnabled, bool isRenderingToFbo ) @@ -348,6 +351,7 @@ bool RenderTaskProcessor::Process( BufferIndex updateBufferIndex, taskContainer, rootNode, sortedLayers, + context, instructions, mRenderInstructionProcessor, renderToFboEnabled, @@ -363,6 +367,7 @@ bool RenderTaskProcessor::Process( BufferIndex updateBufferIndex, taskContainer, rootNode, sortedLayers, + context, instructions, mRenderInstructionProcessor, renderToFboEnabled, diff --git a/dali/internal/update/manager/render-task-processor.h b/dali/internal/update/manager/render-task-processor.h index 7d7774f..4f39220 100644 --- a/dali/internal/update/manager/render-task-processor.h +++ b/dali/internal/update/manager/render-task-processor.h @@ -2,7 +2,7 @@ #define DALI_INTERNAL_SCENE_GRAPH_RENDER_TASK_PROCESSOR_H /* - * Copyright (c) 2017 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. @@ -58,6 +58,7 @@ public: * @param[in] renderTasks The list of render-tasks. * @param[in] rootNode The root node of the scene-graph. * @param[in] sortedLayers The layers containing lists of opaque / transparent renderables. + * @param[in] context The context holding the GL state of rendering for the rendering instructions. * @param[out] instructions The instructions for rendering the next frame. * @param[in] renderToFboEnabled Whether rendering into the Frame Buffer Object is enabled (used to measure FPS above 60) * @param[in] isRenderingToFbo Whether this frame is being rendered into the Frame Buffer Object (used to measure FPS above 60) @@ -67,6 +68,7 @@ public: RenderTaskList& renderTasks, Layer& rootNode, SortedLayerPointers& sortedLayers, + Context& context, RenderInstructionContainer& instructions, bool renderToFboEnabled, bool isRenderingToFbo ); diff --git a/dali/internal/update/manager/update-manager.cpp b/dali/internal/update/manager/update-manager.cpp index 9b1eae0..ce42bd7 100644 --- a/dali/internal/update/manager/update-manager.cpp +++ b/dali/internal/update/manager/update-manager.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. @@ -173,6 +173,7 @@ struct UpdateManager::Impl Layer* root{ nullptr }; ///< Root node (root is a layer). The layer is not stored in the node memory pool. OwnerPointer< RenderTaskList > taskList; ///< Scene graph render task list SortedLayerPointers sortedLayerList; ///< List of Layer pointers sorted by depth (one list of sorted layers per root) + OwnerPointer< Scene > scene; ///< Scene graph object of the scene }; Impl( NotificationManager& notificationManager, @@ -195,7 +196,6 @@ struct UpdateManager::Impl sceneController( NULL ), renderManager( renderManager ), renderQueue( renderQueue ), - renderInstructions( renderManager.GetRenderInstructionContainer() ), renderTaskProcessor( renderTaskProcessor ), backgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ), renderers(), @@ -283,7 +283,6 @@ struct UpdateManager::Impl SceneControllerImpl* sceneController; ///< scene controller RenderManager& renderManager; ///< This is responsible for rendering the results of each "update" RenderQueue& renderQueue; ///< Used to queue messages for the next render - RenderInstructionContainer& renderInstructions; ///< Used to prepare the render instructions RenderTaskProcessor& renderTaskProcessor; ///< Handles RenderTasks and RenderInstrucitons Vector4 backgroundColor; ///< The glClear color used at the beginning of each frame. @@ -515,6 +514,42 @@ void UpdateManager::RemoveRenderTaskList( RenderTaskList* taskList ) } } +void UpdateManager::AddScene( OwnerPointer< Scene >& scene ) +{ + mImpl->scenes.back()->scene = scene.Release(); + + // Initialize the context from render manager + typedef MessageValue1< RenderManager, SceneGraph::Scene* > DerivedType; + + // Reserve some memory inside the render queue + uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) ); + + // Construct message in the render queue memory; note that delete should not be called on the return value + SceneGraph::Scene& sceneObject = *mImpl->scenes.back()->scene; + new (slot) DerivedType( &mImpl->renderManager, &RenderManager::InitializeScene, &sceneObject ); +} + +void UpdateManager::RemoveScene( Scene* scene ) +{ + // Initialize the context from render manager + typedef MessageValue1< RenderManager, SceneGraph::Scene* > DerivedType; + + // Reserve some memory inside the render queue + uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) ); + + // Construct message in the render queue memory; note that delete should not be called on the return value + new (slot) DerivedType( &mImpl->renderManager, &RenderManager::UninitializeScene, scene ); + + for ( auto&& sceneInfo : mImpl->scenes ) + { + if ( sceneInfo && sceneInfo->scene && sceneInfo->scene.Get() == scene ) + { + sceneInfo->scene.Reset(); + break; + } + } +} + void UpdateManager::AddAnimation( OwnerPointer< SceneGraph::Animation >& animation ) { mImpl->animations.PushBack( animation.Release() ); @@ -970,26 +1005,31 @@ uint32_t UpdateManager::Update( float elapsedSeconds, } } - mImpl->renderInstructions.ResetAndReserve( bufferIndex, - static_cast( numberOfRenderTasks ) ); + std::size_t numberOfRenderInstructions = 0; for ( auto&& scene : mImpl->scenes ) { - if ( scene && scene->root && scene->taskList ) + if ( scene && scene->root && scene->taskList && scene->scene ) { + scene->scene->GetRenderInstructions().ResetAndReserve( bufferIndex, + static_cast( scene->taskList->GetTasks().Count() ) ); + keepRendererRendering |= mImpl->renderTaskProcessor.Process( bufferIndex, *scene->taskList, *scene->root, scene->sortedLayerList, - mImpl->renderInstructions, + *scene->scene->GetContext(), + scene->scene->GetRenderInstructions(), renderToFboEnabled, isRenderingToFbo ); + + numberOfRenderInstructions += scene->scene->GetRenderInstructions().Count( bufferIndex ); } } DALI_LOG_INFO( gLogFilter, Debug::General, "Update: numberOfRenderTasks(%d), Render Instructions(%d)\n", - numberOfRenderTasks, mImpl->renderInstructions.Count( bufferIndex ) ); + numberOfRenderTasks, numberOfRenderInstructions ); } } @@ -1102,6 +1142,17 @@ void UpdateManager::SetDefaultSurfaceRect( const Rect& rect ) new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceRect, rect ); } +void UpdateManager::SurfaceReplaced( Scene* scene ) +{ + typedef MessageValue1< RenderManager, Scene* > DerivedType; + + // Reserve some memory inside the render queue + uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) ); + + // Construct message in the render queue memory; note that delete should not be called on the return value + new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SurfaceReplaced, scene ); +} + void UpdateManager::KeepRendering( float durationSeconds ) { mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds ); diff --git a/dali/internal/update/manager/update-manager.h b/dali/internal/update/manager/update-manager.h index a11fc40..ae691e3 100644 --- a/dali/internal/update/manager/update-manager.h +++ b/dali/internal/update/manager/update-manager.h @@ -2,7 +2,7 @@ #define DALI_INTERNAL_SCENE_GRAPH_UPDATE_MANAGER_H /* - * Copyright (c) 2018 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. @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include // for OwnerPointer< FrameCallback > @@ -238,6 +239,19 @@ public: */ void RemoveRenderTaskList( RenderTaskList* taskList ); + /** + * Add a newly created scene. + * @param[in] scene The scene to add. + * @post The scene is owned by UpdateManager. + */ + void AddScene( OwnerPointer& scene ); + + /** + * Remove a scene. + * @param[in] scene The scene to remove. + */ + void RemoveScene( Scene* scene ); + // Animations /** @@ -576,6 +590,12 @@ public: */ void AttachColorTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::Texture* texture, uint32_t mipmapLevel, uint32_t face ); + /** + * This is called when the surface of the scene has been replaced. + * @param[in] scene The scene. + */ + void SurfaceReplaced( Scene* scene ); + public: /** @@ -922,6 +942,31 @@ inline void RemoveRenderTaskListMessage( UpdateManager& manager, const RenderTas new (slot) LocalType( &manager, &UpdateManager::RemoveRenderTaskList, &taskList ); } +inline void AddSceneMessage( UpdateManager& manager, OwnerPointer< SceneGraph::Scene >& scene ) +{ + typedef MessageValue1< UpdateManager, OwnerPointer< SceneGraph::Scene > > LocalType; + + // Reserve some memory inside the message queue + uint32_t* slot = manager.ReserveMessageSlot( sizeof( LocalType ) ); + + // Construct message in the message queue memory; note that delete should not be called on the return value + new (slot) LocalType( &manager, &UpdateManager::AddScene, scene ); +} + +inline void RemoveSceneMessage( UpdateManager& manager, const SceneGraph::Scene& constScene ) +{ + // The scene-graph thread owns this object so it can safely edit it. + Scene& scene = const_cast< Scene& >( constScene ); + + typedef MessageValue1< UpdateManager, Scene* > LocalType; + + // Reserve some memory inside the message queue + uint32_t* slot = manager.ReserveMessageSlot( sizeof( LocalType ) ); + + // Construct message in the message queue memory; note that delete should not be called on the return value + new (slot) LocalType( &manager, &UpdateManager::RemoveScene, &scene ); +} + inline void AddPropertyNotificationMessage( UpdateManager& manager, OwnerPointer< PropertyNotification >& propertyNotification ) { // Message has ownership of PropertyNotification while in transit from event -> update @@ -1013,6 +1058,20 @@ inline void SetDefaultSurfaceRectMessage( UpdateManager& manager, const Rect( constScene ); + + typedef MessageValue1< UpdateManager, Scene* > LocalType; + + // Reserve some memory inside the message queue + uint32_t* slot = manager.ReserveMessageSlot( sizeof( LocalType ) ); + + // Construct message in the message queue memory; note that delete should not be called on the return value + new (slot) LocalType( &manager, &UpdateManager::SurfaceReplaced, &scene ); +} + inline void KeepRenderingMessage( UpdateManager& manager, float durationSeconds ) { typedef MessageValue1< UpdateManager, float > LocalType; diff --git a/dali/internal/update/render-tasks/scene-graph-render-task.cpp b/dali/internal/update/render-tasks/scene-graph-render-task.cpp index b175fd5..641e4e2 100644 --- a/dali/internal/update/render-tasks/scene-graph-render-task.cpp +++ b/dali/internal/update/render-tasks/scene-graph-render-task.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 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. @@ -361,7 +361,7 @@ const Matrix& RenderTask::GetProjectionMatrix( BufferIndex bufferIndex ) const return mCamera->GetProjectionMatrix( bufferIndex ); } -void RenderTask::PrepareRenderInstruction( RenderInstruction& instruction, BufferIndex updateBufferIndex ) +RenderInstruction& RenderTask::PrepareRenderInstruction( BufferIndex updateBufferIndex ) { DALI_ASSERT_DEBUG( nullptr != mCamera ); @@ -370,10 +370,10 @@ void RenderTask::PrepareRenderInstruction( RenderInstruction& instruction, Buffe Viewport viewport; bool viewportSet = QueryViewport( updateBufferIndex, viewport ); - instruction.Reset( mCamera, - GetFrameBuffer(), - viewportSet ? &viewport : nullptr, - mClearEnabled ? &GetClearColor( updateBufferIndex ) : nullptr ); + mRenderInstruction[updateBufferIndex].Reset( mCamera, + GetFrameBuffer(), + viewportSet ? &viewport : nullptr, + mClearEnabled ? &GetClearColor( updateBufferIndex ) : nullptr ); if( mRequiresSync && mRefreshRate == Dali::RenderTask::REFRESH_ONCE ) @@ -384,13 +384,15 @@ void RenderTask::PrepareRenderInstruction( RenderInstruction& instruction, Buffe mRenderSyncTracker = new Render::RenderTracker(); mRenderMessageDispatcher->AddRenderTracker( *mRenderSyncTracker ); } - instruction.mRenderTracker = mRenderSyncTracker; + mRenderInstruction[updateBufferIndex].mRenderTracker = mRenderSyncTracker; } else { // no sync needed, texture FBOs are "ready" the same frame they are rendered to - instruction.mRenderTracker = nullptr; + mRenderInstruction[updateBufferIndex].mRenderTracker = nullptr; } + + return mRenderInstruction[updateBufferIndex]; } bool RenderTask::ViewMatrixUpdated() diff --git a/dali/internal/update/render-tasks/scene-graph-render-task.h b/dali/internal/update/render-tasks/scene-graph-render-task.h index 724681b..15c0e4f 100644 --- a/dali/internal/update/render-tasks/scene-graph-render-task.h +++ b/dali/internal/update/render-tasks/scene-graph-render-task.h @@ -2,7 +2,7 @@ #define DALI_INTERNAL_SCENE_GRAPH_RENDER_TASK_H /* - * Copyright (c) 2018 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,6 +27,7 @@ #include #include #include +#include namespace Dali { @@ -310,10 +311,10 @@ public: * then this method will ensure that a GL sync object is created to track * when the rendering has finished. * - * @param[out] instruction to prepare * @param[in] updateBufferIndex The current update buffer index. + * @return instruction to prepare */ - void PrepareRenderInstruction( RenderInstruction& instruction, BufferIndex updateBufferIndex ); + RenderInstruction& PrepareRenderInstruction( BufferIndex updateBufferIndex ); /** * @return true if the view matrix has been updated during this or last frame @@ -326,6 +327,16 @@ public: */ void SetSyncRequired( bool requiresSync ); + /** + * Retrieve the render instruction. + * @param[in] updateBufferIndex The current update buffer index. + * @return The render instruction + */ + RenderInstruction& GetRenderInstruction( BufferIndex updateBufferIndex ) + { + return mRenderInstruction[updateBufferIndex]; + } + private: // from PropertyOwner::Observer /** @@ -369,6 +380,8 @@ private: SceneGraph::Camera* mCamera; Render::FrameBuffer* mFrameBuffer; + RenderInstruction mRenderInstruction[2]; ///< Owned double buffered render instruction. (Double buffered because this owns render commands for the currently drawn frame) + uint32_t mRefreshRate; ///< REFRESH_ONCE, REFRESH_ALWAYS or render every N frames uint32_t mFrameCounter; ///< counter for rendering every N frames uint32_t mRenderedOnceCounter;///< Incremented whenever state changes to RENDERED_ONCE_AND_NOTIFIED -- 2.7.4