X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Frender%2Fcommon%2Frender-manager.cpp;h=7c56dfba823a5edab56431098a7046ea2e5f980b;hb=0654f01e2e9611e1127d946abb0e92715f8df6d6;hp=a69d02f8c488c4131c9dd1ba9ce07e1fe7400e2d;hpb=403f5989d41f4e5c5a657e24020fe32c77fc1414;p=platform%2Fcore%2Fuifw%2Fdali-core.git diff --git a/dali/internal/render/common/render-manager.cpp b/dali/internal/render/common/render-manager.cpp index a69d02f..7c56dfb 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 @@ -50,6 +55,13 @@ namespace Internal namespace SceneGraph { +#if defined(DEBUG_ENABLED) +namespace +{ +Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RENDER_MANAGER" ); +} // unnamed namespace +#endif + /** * Structure to contain internal data */ @@ -57,12 +69,14 @@ struct RenderManager::Impl { Impl( Integration::GlAbstraction& glAbstraction, Integration::GlSyncAbstraction& glSyncAbstraction, + Integration::GlContextHelperAbstraction& glContextHelperAbstraction, Integration::DepthBufferAvailable depthBufferAvailableParam, Integration::StencilBufferAvailable stencilBufferAvailableParam ) - : context( glAbstraction ), + : context( glAbstraction, &surfaceContextContainer ), currentContext( &context ), glAbstraction( glAbstraction ), glSyncAbstraction( glSyncAbstraction ), + glContextHelperAbstraction( glContextHelperAbstraction ), renderQueue(), instructions(), renderAlgorithms(), @@ -79,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 ) @@ -122,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() @@ -152,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; @@ -303,16 +327,17 @@ void RenderManager::SetWrapMode( Render::Sampler* sampler, uint32_t rWrapMode, u sampler->mTWrapMode = static_cast(tWrapMode); } -void RenderManager::AddFrameBuffer( Render::FrameBuffer* frameBuffer ) +void RenderManager::AddFrameBuffer( OwnerPointer< Render::FrameBuffer >& frameBuffer ) { - mImpl->frameBufferContainer.PushBack( frameBuffer ); - if ( frameBuffer->IsSurfaceBacked() ) + Render::FrameBuffer* frameBufferPtr = frameBuffer.Release(); + mImpl->frameBufferContainer.PushBack( frameBufferPtr ); + if ( frameBufferPtr->IsSurfaceBacked() ) { - frameBuffer->Initialize( *mImpl->CreateSurfaceContext() ); + frameBufferPtr->Initialize( *mImpl->CreateSurfaceContext() ); } else { - frameBuffer->Initialize( mImpl->context ); + frameBufferPtr->Initialize( mImpl->context ); } } @@ -450,9 +475,17 @@ void RenderManager::Render( Integration::RenderStatus& status, bool forceClear ) const uint32_t count = mImpl->instructions.Count( mImpl->renderBufferIndex ); const bool haveInstructions = count > 0u; + DALI_LOG_INFO( gLogFilter, Debug::General, + "Render: haveInstructions(%s) || mImpl->lastFrameWasRendered(%s) || forceClear(%s)\n", + haveInstructions ? "true" : "false", + mImpl->lastFrameWasRendered ? "true" : "false", + forceClear ? "true" : "false" ); + // Only render if we have instructions to render, or the last frame was rendered (and therefore a clear is required). if( haveInstructions || mImpl->lastFrameWasRendered || forceClear ) { + DALI_LOG_INFO( gLogFilter, Debug::General, "Render: Processing\n" ); + // Mark that we will require a post-render step to be performed (includes swap-buffers). status.SetNeedsPostRender( true ); @@ -460,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 ) { @@ -508,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 ) @@ -521,6 +564,10 @@ void RenderManager::Render( Integration::RenderStatus& status, bool forceClear ) iter->OnRenderFinished(); } } + else + { + DALI_LOG_RELEASE_INFO( "RenderManager::Render: Skip rendering [%d, %d, %d]\n", haveInstructions, mImpl->lastFrameWasRendered, forceClear ); + } mImpl->UpdateTrackers(); @@ -557,23 +604,45 @@ void RenderManager::DoRender( RenderInstruction& instruction ) Integration::StencilBufferAvailable stencilBufferAvailable = mImpl->stencilBufferAvailable; Render::SurfaceFrameBuffer* surfaceFrameBuffer = nullptr; - if ( ( instruction.mFrameBuffer != 0 ) && instruction.mFrameBuffer->IsSurfaceBacked() ) + if ( instruction.mFrameBuffer != 0 ) { - surfaceFrameBuffer = static_cast( instruction.mFrameBuffer ); - -#if DALI_GLES_VERSION >= 30 - Context* surfaceContext = surfaceFrameBuffer->GetContext(); - if ( mImpl->currentContext != surfaceContext ) + if ( instruction.mFrameBuffer->IsSurfaceBacked() ) { - // Switch the correct context if rendering to a surface - mImpl->currentContext = surfaceContext; - // Clear the current cached program when the context is switched - mImpl->programController.ClearCurrentProgram(); + surfaceFrameBuffer = static_cast( instruction.mFrameBuffer ); + + if ( !surfaceFrameBuffer->IsSurfaceValid() ) + { + // Skip rendering the frame buffer if the render surface becomes invalid + return; + } + + if ( mImpl->currentContext->IsSurfacelessContextSupported() ) + { + Context* surfaceContext = surfaceFrameBuffer->GetContext(); + if ( mImpl->currentContext != surfaceContext ) + { + // 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(); + } + } + + surfaceRect = Rect( 0, 0, static_cast( surfaceFrameBuffer->GetWidth() ), static_cast( surfaceFrameBuffer->GetHeight() ) ); + backgroundColor = surfaceFrameBuffer->GetBackgroundColor(); } -#endif + else + { + // Switch to shared context for off-screen buffer + mImpl->currentContext = &mImpl->context; - surfaceRect = Rect( 0, 0, static_cast( surfaceFrameBuffer->GetWidth() ), static_cast( surfaceFrameBuffer->GetHeight() ) ); - backgroundColor = surfaceFrameBuffer->GetBackgroundColor(); + if ( mImpl->currentContext->IsSurfacelessContextSupported() ) + { + mImpl->glContextHelperAbstraction.MakeSurfacelessContextCurrent(); + } + } } DALI_ASSERT_DEBUG( mImpl->currentContext->IsGlContextCreated() ); @@ -585,17 +654,31 @@ void RenderManager::DoRender( RenderInstruction& instruction ) if( instruction.mFrameBuffer ) { instruction.mFrameBuffer->Bind( *mImpl->currentContext ); - } - mImpl->currentContext->Viewport( surfaceRect.x, - surfaceRect.y, - surfaceRect.width, - surfaceRect.height ); + 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 + { + mImpl->currentContext->BindFramebuffer( GL_FRAMEBUFFER, 0u ); + } - mImpl->currentContext->ClearColor( backgroundColor.r, - backgroundColor.g, - backgroundColor.b, - backgroundColor.a ); + if ( surfaceFrameBuffer ) + { + mImpl->currentContext->Viewport( surfaceRect.x, + surfaceRect.y, + surfaceRect.width, + surfaceRect.height ); + + mImpl->currentContext->ClearColor( backgroundColor.r, + backgroundColor.g, + backgroundColor.b, + backgroundColor.a ); + } // 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 @@ -692,12 +775,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 ) ) { @@ -712,6 +862,10 @@ void RenderManager::DoRender( RenderInstruction& instruction ) { surfaceFrameBuffer->PostRender(); } + else + { + mImpl->currentContext->Flush(); + } } } // namespace SceneGraph