From: Richard Huang Date: Thu, 11 Jul 2019 13:50:53 +0000 (+0100) Subject: FBO/Texture access synchronization for multiple contexts X-Git-Tag: dali_1.4.29~2 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-core.git;a=commitdiff_plain;h=refs%2Fchanges%2F91%2F210091%2F7 FBO/Texture access synchronization for multiple contexts Change-Id: I62e2671eb14537d4267485ebaefa237b4743737f --- 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 d457916..6e41c42 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 @@ -58,6 +58,7 @@ void TestApplication::CreateCore() mPlatformAbstraction, mGlAbstraction, mGlSyncAbstraction, + mGlContextHelperAbstraction, mDataRetentionPolicy, Integration::RenderToFrameBuffer::FALSE, Integration::DepthBufferAvailable::TRUE, @@ -156,6 +157,11 @@ TestGlSyncAbstraction& TestApplication::GetGlSyncAbstraction() return mGlSyncAbstraction; } +TestGlContextHelperAbstraction& TestApplication::GetGlContextHelperAbstraction() +{ + return mGlContextHelperAbstraction; +} + void TestApplication::ProcessEvent(const Integration::Event& event) { mCore->QueueEvent(event); 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 32447d6..cc694df 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 @@ -22,6 +22,7 @@ #include #include "test-gl-sync-abstraction.h" #include "test-gl-abstraction.h" +#include "test-gl-context-helper-abstraction.h" #include "test-render-controller.h" #include "test-render-surface.h" #include @@ -66,6 +67,7 @@ public: TestRenderController& GetRenderController(); TestGlAbstraction& GetGlAbstraction(); TestGlSyncAbstraction& GetGlSyncAbstraction(); + TestGlContextHelperAbstraction& GetGlContextHelperAbstraction(); void ProcessEvent(const Integration::Event& event); void SendNotification(); bool Render( uint32_t intervalMilliseconds = DEFAULT_RENDER_INTERVAL, const char* location=NULL ); @@ -93,6 +95,7 @@ protected: TestRenderController mRenderController; TestGlAbstraction mGlAbstraction; TestGlSyncAbstraction mGlSyncAbstraction; + TestGlContextHelperAbstraction mGlContextHelperAbstraction; TestRenderSurface* mRenderSurface; Integration::UpdateStatus mStatus; 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 new file mode 100644 index 0000000..0442f0d --- /dev/null +++ b/automated-tests/src/dali/dali-test-suite-utils/test-gl-context-helper-abstraction.h @@ -0,0 +1,71 @@ +#ifndef TEST_GL_CONTEXT_HELPER_ABSTRACTION_H +#define TEST_GL_CONTEXT_HELPER_ABSTRACTION_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 + +namespace Dali +{ + +/** + * Class to emulate the GL context helper + */ +class DALI_CORE_API TestGlContextHelperAbstraction: public Integration::GlContextHelperAbstraction +{ +public: + /** + * Constructor + */ + TestGlContextHelperAbstraction() {}; + + /** + * Destructor + */ + ~TestGlContextHelperAbstraction() {}; + + /** + * @brief Switch to the surfaceless GL context + */ + 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() {}; + + /** + * @brief Wait until all GL rendering calls for the current GL context are executed + */ + virtual void WaitClient() {}; +private: + + TestGlContextHelperAbstraction( const TestGlContextHelperAbstraction& ); ///< Undefined + TestGlContextHelperAbstraction& operator=( const TestGlContextHelperAbstraction& ); ///< Undefined +}; + +} // Dali + +#endif // TEST_GL_CONTEXT_HELPER_ABSTRACTION_H diff --git a/dali/integration-api/CMakeLists.txt b/dali/integration-api/CMakeLists.txt index c205870..e02a8cf 100644 --- a/dali/integration-api/CMakeLists.txt +++ b/dali/integration-api/CMakeLists.txt @@ -34,6 +34,7 @@ SET(INTEGRATION_API_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/gl-abstraction.h ${CMAKE_CURRENT_SOURCE_DIR}/gl-defines.h ${CMAKE_CURRENT_SOURCE_DIR}/gl-sync-abstraction.h + ${CMAKE_CURRENT_SOURCE_DIR}/gl-context-helper-abstraction.h ${CMAKE_CURRENT_SOURCE_DIR}/render-controller.h ${CMAKE_CURRENT_SOURCE_DIR}/platform-abstraction.h ${CMAKE_CURRENT_SOURCE_DIR}/processor-interface.h diff --git a/dali/integration-api/core.cpp b/dali/integration-api/core.cpp index 596ef9a..c2c0fcf 100644 --- a/dali/integration-api/core.cpp +++ b/dali/integration-api/core.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -38,6 +39,7 @@ Core* Core::New( RenderController& renderController, PlatformAbstraction& platformAbstraction, GlAbstraction& glAbstraction, GlSyncAbstraction& glSyncAbstraction, + GlContextHelperAbstraction& glContextHelperAbstraction, ResourcePolicy::DataRetention policy, RenderToFrameBuffer renderToFboEnabled, DepthBufferAvailable depthBufferAvailable, @@ -48,6 +50,7 @@ Core* Core::New( RenderController& renderController, platformAbstraction, glAbstraction, glSyncAbstraction, + glContextHelperAbstraction, policy, renderToFboEnabled, depthBufferAvailable, diff --git a/dali/integration-api/core.h b/dali/integration-api/core.h index ff62bcb..8da5583 100644 --- a/dali/integration-api/core.h +++ b/dali/integration-api/core.h @@ -43,6 +43,7 @@ namespace Integration class Core; class GlAbstraction; class GlSyncAbstraction; +class GlContextHelperAbstraction; class PlatformAbstraction; class Processor; class RenderController; @@ -224,6 +225,7 @@ public: * @param[in] platformAbstraction The interface providing platform specific services. * @param[in] glAbstraction The interface providing OpenGL services. * @param[in] glSyncAbstraction The interface providing OpenGL sync objects. + * @param[in] glContextHelperAbstraction The interface providing OpenGL context helper objects. * @param[in] policy The data retention policy. This depends on application setting * and platform support. Dali should honour this policy when deciding to discard * intermediate resource data. @@ -236,6 +238,7 @@ public: PlatformAbstraction& platformAbstraction, GlAbstraction& glAbstraction, GlSyncAbstraction& glSyncAbstraction, + GlContextHelperAbstraction& glContextHelperAbstraction, ResourcePolicy::DataRetention policy, RenderToFrameBuffer renderToFboEnabled, DepthBufferAvailable depthBufferAvailable, diff --git a/dali/integration-api/file.list b/dali/integration-api/file.list index 9ec9155..c4174fa 100644 --- a/dali/integration-api/file.list +++ b/dali/integration-api/file.list @@ -33,6 +33,7 @@ platform_abstraction_header_files = \ $(platform_abstraction_src_dir)/gl-abstraction.h \ $(platform_abstraction_src_dir)/gl-defines.h \ $(platform_abstraction_src_dir)/gl-sync-abstraction.h \ + $(platform_abstraction_src_dir)/gl-context-helper-abstraction.h \ $(platform_abstraction_src_dir)/render-controller.h \ $(platform_abstraction_src_dir)/platform-abstraction.h \ $(platform_abstraction_src_dir)/processor-interface.h \ diff --git a/dali/integration-api/gl-context-helper-abstraction.h b/dali/integration-api/gl-context-helper-abstraction.h new file mode 100644 index 0000000..7e425f9 --- /dev/null +++ b/dali/integration-api/gl-context-helper-abstraction.h @@ -0,0 +1,68 @@ +#ifndef DALI_INTEGRATION_GL_CONTEXT_HELPER_ABSTRACTION_H +#define DALI_INTEGRATION_GL_CONTEXT_HELPER_ABSTRACTION_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 +{ +namespace Integration +{ + +/** + * This abstraction defines the interface for accessing GL context. + */ +class GlContextHelperAbstraction +{ +protected: + /** + * Virtual protected destructor, no deletion through this interface + */ + virtual ~GlContextHelperAbstraction() = default; + +public: + + /** + * @brief Switch to the surfaceless GL context + */ + 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; + + /** + * @brief Wait until all GL rendering calls for the current GL context are executed + */ + virtual void WaitClient() = 0; +}; + +} // namespace Integration +} // namespace Dali + +#endif // DALI_INTEGRATION_GL_CONTEXT_HELPER_ABSTRACTION_H diff --git a/dali/internal/common/core-impl.cpp b/dali/internal/common/core-impl.cpp index b906d8f..fb5eb11 100644 --- a/dali/internal/common/core-impl.cpp +++ b/dali/internal/common/core-impl.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -75,6 +76,7 @@ using Integration::RenderController; using Integration::PlatformAbstraction; using Integration::GlSyncAbstraction; using Integration::GlAbstraction; +using Integration::GlContextHelperAbstraction; using Integration::Event; using Integration::UpdateStatus; using Integration::RenderStatus; @@ -83,6 +85,7 @@ Core::Core( RenderController& renderController, PlatformAbstraction& platform, GlAbstraction& glAbstraction, GlSyncAbstraction& glSyncAbstraction, + GlContextHelperAbstraction& glContextHelperAbstraction, ResourcePolicy::DataRetention dataRetentionPolicy, Integration::RenderToFrameBuffer renderToFboEnabled, Integration::DepthBufferAvailable depthBufferAvailable, @@ -106,7 +109,7 @@ Core::Core( RenderController& renderController, mRenderTaskProcessor = new SceneGraph::RenderTaskProcessor(); - mRenderManager = RenderManager::New( glAbstraction, glSyncAbstraction, depthBufferAvailable, stencilBufferAvailable ); + mRenderManager = RenderManager::New( glAbstraction, glSyncAbstraction, glContextHelperAbstraction, depthBufferAvailable, stencilBufferAvailable ); RenderQueue& renderQueue = mRenderManager->GetRenderQueue(); diff --git a/dali/internal/common/core-impl.h b/dali/internal/common/core-impl.h index 21e0a74..e419745 100644 --- a/dali/internal/common/core-impl.h +++ b/dali/internal/common/core-impl.h @@ -41,6 +41,7 @@ class RenderController; class PlatformAbstraction; class GlAbstraction; class GlSyncAbstraction; +class GlContextHelperAbstraction; class UpdateStatus; class RenderStatus; class RenderSurface; @@ -83,6 +84,7 @@ public: Integration::PlatformAbstraction& platform, Integration::GlAbstraction& glAbstraction, Integration::GlSyncAbstraction& glSyncAbstraction, + Integration::GlContextHelperAbstraction& glContextHelperAbstraction, ResourcePolicy::DataRetention dataRetentionPolicy, Integration::RenderToFrameBuffer renderToFboEnabled, Integration::DepthBufferAvailable depthBufferAvailable, diff --git a/dali/internal/render/common/render-algorithms.cpp b/dali/internal/render/common/render-algorithms.cpp index 1d80991..0061b87 100644 --- a/dali/internal/render/common/render-algorithms.cpp +++ b/dali/internal/render/common/render-algorithms.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * 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. @@ -389,7 +389,8 @@ inline void RenderAlgorithms::ProcessRenderList( const RenderList& renderList, const Matrix& viewMatrix, const Matrix& projectionMatrix, Integration::DepthBufferAvailable depthBufferAvailable, - Integration::StencilBufferAvailable stencilBufferAvailable ) + Integration::StencilBufferAvailable stencilBufferAvailable, + Vector& boundTextures ) { DALI_PRINT_RENDER_LIST( renderList ); @@ -447,7 +448,7 @@ inline void RenderAlgorithms::ProcessRenderList( const RenderList& renderList, // Render the item. item.mRenderer->Render( context, bufferIndex, *item.mNode, item.mModelMatrix, item.mModelViewMatrix, - viewMatrix, projectionMatrix, item.mSize, !item.mIsOpaque ); + viewMatrix, projectionMatrix, item.mSize, !item.mIsOpaque, boundTextures ); } } } @@ -462,7 +463,8 @@ void RenderAlgorithms::ProcessRenderInstruction( const RenderInstruction& instru Context& context, BufferIndex bufferIndex, Integration::DepthBufferAvailable depthBufferAvailable, - Integration::StencilBufferAvailable stencilBufferAvailable ) + Integration::StencilBufferAvailable stencilBufferAvailable, + Vector& boundTextures ) { DALI_PRINT_RENDER_INSTRUCTION( instruction, bufferIndex ); @@ -490,7 +492,8 @@ void RenderAlgorithms::ProcessRenderInstruction( const RenderInstruction& instru *viewMatrix, *projectionMatrix, depthBufferAvailable, - stencilBufferAvailable ); + stencilBufferAvailable, + boundTextures ); } } } diff --git a/dali/internal/render/common/render-algorithms.h b/dali/internal/render/common/render-algorithms.h index 523cc14..30c8041 100644 --- a/dali/internal/render/common/render-algorithms.h +++ b/dali/internal/render/common/render-algorithms.h @@ -2,7 +2,7 @@ #define DALI_INTERNAL_RENDER_ALGORITHMS_H /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * 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. @@ -58,12 +58,14 @@ class RenderAlgorithms * @param[in] bufferIndex The current render buffer index (previous update buffer) * @param[in] depthBufferAvailable Whether the depth buffer is available * @param[in] stencilBufferAvailable Whether the stencil buffer is available + * @param[in] boundTextures The textures bound for rendering */ void ProcessRenderInstruction( const SceneGraph::RenderInstruction& instruction, Context& context, BufferIndex bufferIndex, Integration::DepthBufferAvailable depthBufferAvailable, - Integration::StencilBufferAvailable stencilBufferAvailable ); + Integration::StencilBufferAvailable stencilBufferAvailable, + Vector& boundTextures ); private: @@ -113,6 +115,7 @@ class RenderAlgorithms * @param[in] projectionMatrix The projection matrix from the appropriate camera. * @param[in] depthBufferAvailable Whether the depth buffer is available * @param[in] stencilBufferAvailable Whether the stencil buffer is available + * @param[in] boundTextures The textures bound for rendering */ inline void ProcessRenderList( const Dali::Internal::SceneGraph::RenderList& renderList, Context& context, @@ -120,7 +123,8 @@ class RenderAlgorithms const Matrix& viewMatrix, const Matrix& projectionMatrix, Integration::DepthBufferAvailable depthBufferAvailable, - Integration::StencilBufferAvailable stencilBufferAvailable ); + Integration::StencilBufferAvailable stencilBufferAvailable, + Vector& boundTextures ); // Prevent copying: RenderAlgorithms( RenderAlgorithms& rhs ); diff --git a/dali/internal/render/common/render-manager.cpp b/dali/internal/render/common/render-manager.cpp index 2d550b5..2eec97a 100644 --- a/dali/internal/render/common/render-manager.cpp +++ b/dali/internal/render/common/render-manager.cpp @@ -18,13 +18,18 @@ // CLASS HEADER #include +// EXTERNAL INCLUDES +#include + // INTERNAL INCLUDES #include #include #include #include +#include #include #include +#include #include #include #include @@ -64,12 +69,14 @@ struct RenderManager::Impl { Impl( Integration::GlAbstraction& glAbstraction, Integration::GlSyncAbstraction& glSyncAbstraction, + Integration::GlContextHelperAbstraction& glContextHelperAbstraction, Integration::DepthBufferAvailable depthBufferAvailableParam, Integration::StencilBufferAvailable stencilBufferAvailableParam ) : context( glAbstraction ), currentContext( &context ), glAbstraction( glAbstraction ), glSyncAbstraction( glSyncAbstraction ), + glContextHelperAbstraction( glContextHelperAbstraction ), renderQueue(), instructions(), renderAlgorithms(), @@ -86,10 +93,14 @@ struct RenderManager::Impl depthBufferAvailable( depthBufferAvailableParam ), stencilBufferAvailable( stencilBufferAvailableParam ) { + // Create thread pool with just one thread ( there may be a need to create more threads in the future ). + threadPool = std::unique_ptr( new Dali::ThreadPool() ); + threadPool->Initialize( 1u ); } ~Impl() { + threadPool.reset( nullptr ); // reset now to maintain correct destruction order } void AddRenderTracker( Render::RenderTracker* renderTracker ) @@ -129,6 +140,7 @@ struct RenderManager::Impl OwnerContainer< Context* > surfaceContextContainer; ///< List of owned contexts holding the GL state per surface 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() @@ -159,16 +171,21 @@ struct RenderManager::Impl Integration::DepthBufferAvailable depthBufferAvailable; ///< Whether the depth buffer is available Integration::StencilBufferAvailable stencilBufferAvailable; ///< Whether the stencil buffer is available + std::unique_ptr threadPool; ///< The thread pool + Vector boundTextures; ///< The textures bound for rendering + Vector textureDependencyList; ///< The dependency list of binded textures }; RenderManager* RenderManager::New( Integration::GlAbstraction& glAbstraction, Integration::GlSyncAbstraction& glSyncAbstraction, + Integration::GlContextHelperAbstraction& glContextHelperAbstraction, Integration::DepthBufferAvailable depthBufferAvailable, Integration::StencilBufferAvailable stencilBufferAvailable ) { RenderManager* manager = new RenderManager; manager->mImpl = new Impl( glAbstraction, glSyncAbstraction, + glContextHelperAbstraction, depthBufferAvailable, stencilBufferAvailable ); return manager; @@ -476,11 +493,16 @@ void RenderManager::Render( Integration::RenderStatus& status, bool forceClear ) if ( mImpl->currentContext != &mImpl->context ) { mImpl->currentContext = &mImpl->context; + + if ( mImpl->currentContext->IsSurfacelessContextSupported() ) + { + mImpl->glContextHelperAbstraction.MakeSurfacelessContextCurrent(); + } + // Clear the current cached program when the context is switched mImpl->programController.ClearCurrentProgram(); } - // Upload the geometries for( uint32_t i = 0; i < count; ++i ) { @@ -524,6 +546,11 @@ void RenderManager::Render( Integration::RenderStatus& status, bool forceClear ) DoRender( instruction ); } + if ( mImpl->currentContext->IsSurfacelessContextSupported() ) + { + mImpl->glContextHelperAbstraction.MakeSurfacelessContextCurrent(); + } + GLenum attachments[] = { GL_DEPTH, GL_STENCIL }; mImpl->context.InvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments); for ( auto&& context : mImpl->surfaceContextContainer ) @@ -590,6 +617,8 @@ void RenderManager::DoRender( RenderInstruction& instruction ) { // Switch the correct context if rendering to a surface mImpl->currentContext = surfaceContext; + surfaceFrameBuffer->MakeContextCurrent(); + // Clear the current cached program when the context is switched mImpl->programController.ClearCurrentProgram(); } @@ -602,6 +631,11 @@ void RenderManager::DoRender( RenderInstruction& instruction ) { // Switch to shared context for off-screen buffer mImpl->currentContext = &mImpl->context; + + if ( mImpl->currentContext->IsSurfacelessContextSupported() ) + { + mImpl->glContextHelperAbstraction.MakeSurfacelessContextCurrent(); + } } } @@ -614,6 +648,13 @@ void RenderManager::DoRender( RenderInstruction& instruction ) if( instruction.mFrameBuffer ) { instruction.mFrameBuffer->Bind( *mImpl->currentContext ); + + if ( !instruction.mFrameBuffer->IsSurfaceBacked() ) + { + // 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 ); + mImpl->textureDependencyList.PushBack( textureFrameBuffer->GetTextureId() ); + } } else { @@ -728,12 +769,79 @@ void RenderManager::DoRender( RenderInstruction& instruction ) mImpl->currentContext->SetScissorTest( false ); } + // Clear the list of bound textures + mImpl->boundTextures.Clear(); + mImpl->renderAlgorithms.ProcessRenderInstruction( instruction, *mImpl->currentContext, mImpl->renderBufferIndex, depthBufferAvailable, - stencilBufferAvailable ); + 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 ( mImpl->boundTextures.Count() > 0u && mImpl->textureDependencyList.Count() > 0u ) + { + for ( auto textureId : mImpl->textureDependencyList ) + { + + textureFound = std::find_if( mImpl->boundTextures.Begin(), mImpl->boundTextures.End(), + [textureId]( GLuint id ) + { + return textureId == id; + } ) != mImpl->boundTextures.End(); + } + } + + if ( textureFound ) + { + + if ( !instruction.mFrameBuffer || !instruction.mFrameBuffer->IsSurfaceBacked() ) + { + // For off-screen buffer + + // Wait until all rendering calls for the currently context are executed + mImpl->glContextHelperAbstraction.WaitClient(); + + // Clear the dependency list + mImpl->textureDependencyList.Clear(); + } + else + { + // For surface-backed frame buffer + + // 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(); + + // 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(); + + // Clear the dependency list + mImpl->textureDependencyList.Clear(); + } + } + } + } if( instruction.mRenderTracker && ( instruction.mFrameBuffer != 0 ) ) { @@ -748,6 +856,10 @@ void RenderManager::DoRender( RenderInstruction& instruction ) { surfaceFrameBuffer->PostRender(); } + else + { + mImpl->currentContext->Flush(); + } } } // namespace SceneGraph diff --git a/dali/internal/render/common/render-manager.h b/dali/internal/render/common/render-manager.h index aceece5..fd3e35c 100644 --- a/dali/internal/render/common/render-manager.h +++ b/dali/internal/render/common/render-manager.h @@ -33,6 +33,7 @@ namespace Integration { class GlAbstraction; class GlSyncAbstraction; +class GlContextHelperAbstraction; class RenderStatus; } @@ -72,13 +73,15 @@ public: /** * Construct a new RenderManager. - * @param[in] glAbstraction The GL abstraction used for rendering. - * @param[in] glSyncAbstraction The GL sync abstraction used fence sync creation/deletion. - * @param[in] depthBufferAvailable Whether the depth buffer is available - * @param[in] stencilBufferAvailable Whether the stencil buffer is available + * @param[in] glAbstraction The GL abstraction used for rendering. + * @param[in] glSyncAbstraction The GL sync abstraction used fence sync creation/deletion. + * @param[in] glContextHelperAbstraction The GL context helper abstraction for accessing GL context. + * @param[in] depthBufferAvailable Whether the depth buffer is available + * @param[in] stencilBufferAvailable Whether the stencil buffer is available */ static RenderManager* New( Integration::GlAbstraction& glAbstraction, Integration::GlSyncAbstraction& glSyncAbstraction, + Integration::GlContextHelperAbstraction& glContextHelperAbstraction, Integration::DepthBufferAvailable depthBufferAvailable, Integration::StencilBufferAvailable stencilBufferAvailable ); diff --git a/dali/internal/render/renderers/render-renderer.cpp b/dali/internal/render/renderers/render-renderer.cpp index 2222abd..74c4959 100644 --- a/dali/internal/render/renderers/render-renderer.cpp +++ b/dali/internal/render/renderers/render-renderer.cpp @@ -342,7 +342,7 @@ void Renderer::SetUniformFromProperty( BufferIndex bufferIndex, Program& program } } -bool Renderer::BindTextures( Context& context, Program& program ) +bool Renderer::BindTextures( Context& context, Program& program, Vector& boundTextures ) { uint32_t textureUnit = 0; bool result = true; @@ -355,6 +355,7 @@ bool Renderer::BindTextures( Context& context, Program& program ) if( textures[i] ) { result = textures[i]->Bind(context, textureUnit, samplers[i] ); + boundTextures.PushBack( textures[i]->GetId() ); if( result && program.GetSamplerUniformLocation( i, uniformLocation ) ) { program.SetUniform1i( uniformLocation, textureUnit ); @@ -519,7 +520,8 @@ void Renderer::Render( Context& context, const Matrix& viewMatrix, const Matrix& projectionMatrix, const Vector3& size, - bool blend ) + bool blend, + Vector& boundTextures ) { // Get the program to use: Program* program = mRenderDataProvider->GetShader().GetProgram(); @@ -538,7 +540,7 @@ void Renderer::Render( Context& context, // Take the program into use so we can send uniforms to it program->Use(); - if( DALI_LIKELY( BindTextures( context, *program ) ) ) + if( DALI_LIKELY( BindTextures( context, *program, boundTextures ) ) ) { // Only set up and draw if we have textures and they are all valid diff --git a/dali/internal/render/renderers/render-renderer.h b/dali/internal/render/renderers/render-renderer.h index 66e33aa..9157d72 100755 --- a/dali/internal/render/renderers/render-renderer.h +++ b/dali/internal/render/renderers/render-renderer.h @@ -350,6 +350,7 @@ public: * @param[in] projectionMatrix The projection matrix. * @param[in] size Size of the render item * @param[in] blend If true, blending is enabled + * @param[in] boundTextures The textures bound for rendering */ void Render( Context& context, BufferIndex bufferIndex, @@ -359,7 +360,8 @@ public: const Matrix& viewMatrix, const Matrix& projectionMatrix, const Vector3& size, - bool blend ); + bool blend, + Vector& boundTextures ); /** * Write the renderer's sort attributes to the passed in reference @@ -407,9 +409,10 @@ private: * Bind the textures and setup the samplers * @param[in] context The GL context * @param[in] program The shader program + * @param[in] boundTextures The textures bound for rendering * @return False if create or bind failed, true if success. */ - bool BindTextures( Context& context, Program& program ); + bool BindTextures( Context& context, Program& program, Vector& boundTextures ); private: diff --git a/dali/internal/render/renderers/render-surface-frame-buffer.cpp b/dali/internal/render/renderers/render-surface-frame-buffer.cpp index 2049620..7f1866d 100644 --- a/dali/internal/render/renderers/render-surface-frame-buffer.cpp +++ b/dali/internal/render/renderers/render-surface-frame-buffer.cpp @@ -111,6 +111,14 @@ Context* SurfaceFrameBuffer::GetContext() return mContext; } +void SurfaceFrameBuffer::MakeContextCurrent() +{ + if ( mSurface && !mIsSurfaceInvalid ) + { + mSurface->MakeContextCurrent(); + } +} + Integration::DepthBufferAvailable SurfaceFrameBuffer::GetDepthBufferRequired() { return mSurface && !mIsSurfaceInvalid ? Integration::DepthBufferAvailable::FALSE : mSurface->GetDepthBufferRequired(); diff --git a/dali/internal/render/renderers/render-surface-frame-buffer.h b/dali/internal/render/renderers/render-surface-frame-buffer.h index 7225769..704a360 100644 --- a/dali/internal/render/renderers/render-surface-frame-buffer.h +++ b/dali/internal/render/renderers/render-surface-frame-buffer.h @@ -118,6 +118,11 @@ public: Context* GetContext(); /** + * @brief Makes the graphics context current + */ + void MakeContextCurrent(); + + /** * @brief Gets whether the depth buffer is required * @return TRUE if the depth buffer is required */ diff --git a/dali/internal/render/renderers/render-texture-frame-buffer.cpp b/dali/internal/render/renderers/render-texture-frame-buffer.cpp index 9e3120e..4e5cd51 100644 --- a/dali/internal/render/renderers/render-texture-frame-buffer.cpp +++ b/dali/internal/render/renderers/render-texture-frame-buffer.cpp @@ -30,6 +30,7 @@ namespace Render TextureFrameBuffer::TextureFrameBuffer( uint32_t width, uint32_t height, Mask attachments ) : FrameBuffer(), mId( 0u ), + mTextureId( 0u ), mDepthBuffer( attachments & Dali::FrameBuffer::Attachment::DEPTH ), mStencilBuffer( attachments & Dali::FrameBuffer::Attachment::STENCIL ), mWidth( width ), @@ -83,22 +84,24 @@ void TextureFrameBuffer::AttachColorTexture( Context& context, Render::Texture* { context.BindFramebuffer( GL_FRAMEBUFFER, mId ); + mTextureId = texture->GetId(); + // Create a color attachment. if( texture->GetType() == TextureType::TEXTURE_2D ) { if( !texture->IsNativeImage() ) { - context.FramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture->GetId(), mipmapLevel ); + context.FramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextureId, mipmapLevel ); } else { // If it's a native image we need to use GL_TEXTURE_EXTERNAL_OES as the texture target parameter - context.FramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_EXTERNAL_OES, texture->GetId(), mipmapLevel ); + context.FramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_EXTERNAL_OES, mTextureId, mipmapLevel ); } } else { - context.FramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer, texture->GetId(), mipmapLevel ); + context.FramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer, mTextureId, mipmapLevel ); } context.BindFramebuffer( GL_FRAMEBUFFER, 0 ); diff --git a/dali/internal/render/renderers/render-texture-frame-buffer.h b/dali/internal/render/renderers/render-texture-frame-buffer.h index 021890f..7eecced 100644 --- a/dali/internal/render/renderers/render-texture-frame-buffer.h +++ b/dali/internal/render/renderers/render-texture-frame-buffer.h @@ -91,9 +91,16 @@ public: */ void AttachColorTexture( Context& context, Render::Texture* texture, uint32_t mipmapLevel, uint32_t layer ); + /** + * @brief Get the id of the texture binded to this frame buffer + * @return The texture id + */ + GLuint GetTextureId() { return mTextureId; }; + private: GLuint mId; + GLuint mTextureId; GLuint mDepthBuffer; GLuint mStencilBuffer; uint32_t mWidth;