X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Frender%2Fcommon%2Frender-manager.cpp;h=630f870e3da30da25835a337176ba43431992b64;hb=55827866fcb8c7ee47581ac4335a3390472090e8;hp=2d550b5ff2bb231b32b10d28d828a33a6222546a;hpb=9aa1524146da93e1696e96bfc7f3792bd2748a39;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 old mode 100644 new mode 100755 index 2d550b5..630f870 --- 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 @@ -57,6 +62,9 @@ Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_REN } // unnamed namespace #endif +const int partialUpdateMargin = 4u; +const float partialUpdateRatio = 0.8f; // If the partial update area exceeds 80%, change to full update. + /** * Structure to contain internal data */ @@ -64,12 +72,15 @@ struct RenderManager::Impl { Impl( Integration::GlAbstraction& glAbstraction, Integration::GlSyncAbstraction& glSyncAbstraction, + Integration::GlContextHelperAbstraction& glContextHelperAbstraction, Integration::DepthBufferAvailable depthBufferAvailableParam, - Integration::StencilBufferAvailable stencilBufferAvailableParam ) - : context( glAbstraction ), + Integration::StencilBufferAvailable stencilBufferAvailableParam, + Integration::PartialUpdateAvailable partialUpdateAvailableParam ) + : context( glAbstraction, &surfaceContextContainer ), currentContext( &context ), glAbstraction( glAbstraction ), glSyncAbstraction( glSyncAbstraction ), + glContextHelperAbstraction( glContextHelperAbstraction ), renderQueue(), instructions(), renderAlgorithms(), @@ -84,12 +95,18 @@ struct RenderManager::Impl lastFrameWasRendered( false ), programController( glAbstraction ), depthBufferAvailable( depthBufferAvailableParam ), - stencilBufferAvailable( stencilBufferAvailableParam ) + stencilBufferAvailable( stencilBufferAvailableParam ), + partialUpdateAvailable( partialUpdateAvailableParam ), + defaultSurfaceOrientation( 0 ) { + // 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 +146,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() @@ -158,19 +176,29 @@ struct RenderManager::Impl Integration::DepthBufferAvailable depthBufferAvailable; ///< Whether the depth buffer is available Integration::StencilBufferAvailable stencilBufferAvailable; ///< Whether the stencil buffer is available + Integration::PartialUpdateAvailable partialUpdateAvailable; ///< Whether the partial update is available + + std::unique_ptr threadPool; ///< The thread pool + Vector boundTextures; ///< The textures bound for rendering + Vector textureDependencyList; ///< The dependency list of binded textures + int defaultSurfaceOrientation; ///< defaultSurfaceOrientation for the default surface we are rendering to }; RenderManager* RenderManager::New( Integration::GlAbstraction& glAbstraction, Integration::GlSyncAbstraction& glSyncAbstraction, + Integration::GlContextHelperAbstraction& glContextHelperAbstraction, Integration::DepthBufferAvailable depthBufferAvailable, - Integration::StencilBufferAvailable stencilBufferAvailable ) + Integration::StencilBufferAvailable stencilBufferAvailable, + Integration::PartialUpdateAvailable partialUpdateAvailable ) { RenderManager* manager = new RenderManager; manager->mImpl = new Impl( glAbstraction, glSyncAbstraction, + glContextHelperAbstraction, depthBufferAvailable, - stencilBufferAvailable ); + stencilBufferAvailable, + partialUpdateAvailable ); return manager; } @@ -242,6 +270,11 @@ void RenderManager::SetDefaultSurfaceRect(const Rect& rect) mImpl->defaultSurfaceRect = rect; } +void RenderManager::SetDefaultSurfaceOrientation( int orientation ) +{ + mImpl->defaultSurfaceOrientation = orientation; +} + void RenderManager::AddRenderer( OwnerPointer< Render::Renderer >& renderer ) { // Initialize the renderer as we are now in render thread @@ -476,11 +509,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 +562,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 ) @@ -557,10 +600,69 @@ void RenderManager::Render( Integration::RenderStatus& status, bool forceClear ) DALI_PRINT_RENDER_END(); } +bool GetDamagedRect( Rect &viewportRect, RenderInstruction& instruction, Rect &damagedRect ) +{ + // merge bounding + int dx1 = viewportRect.width, dx2 = 0, dy1 = viewportRect.height, dy2 = 0; + int checkWidth = static_cast( static_cast( viewportRect.width ) * partialUpdateRatio ); + int checkHeight = static_cast( static_cast( viewportRect.height ) * partialUpdateRatio ); + Rect screenRect; + + bool isPartialUpdate = false; + + const RenderListContainer::SizeType renderListCount = instruction.RenderListCount(); + // Iterate through each render list. + + for( RenderListContainer::SizeType index = 0; index < renderListCount; ++index ) + { + const RenderList* renderList = instruction.GetRenderList( index ); + + if( renderList && !renderList->IsEmpty() && renderList->IsPartialUpdateEnabled() ) + { + const std::size_t itemCount = renderList->Count(); + for( uint32_t itemIndex = 0u; itemIndex < itemCount; ++itemIndex ) + { + const RenderItem& item = renderList->GetItem( itemIndex ); + + if( item.mPartialUpdateEnabled ) + { + isPartialUpdate = true; + + screenRect = item.CalculateViewportSpaceAABB( viewportRect.width, viewportRect.height, true ); + + dx1 = std::min( screenRect.x, dx1 ); + dx2 = std::max( screenRect.x + screenRect.width, dx2); + dy1 = std::min( screenRect.y, dy1 ); + dy2 = std::max( screenRect.y + screenRect.height, dy2 ); + + if( ( dx2 - dx1 ) > checkWidth && ( dy2 - dy1 ) > checkHeight ) + { + return false; + } + } + } + } + } + + if( isPartialUpdate ) + { + damagedRect.x = dx1 - partialUpdateMargin; + damagedRect.y = dy1 - partialUpdateMargin; + damagedRect.width = dx2 - dx1 + ( 2 * partialUpdateMargin ); + damagedRect.height = dy2 - dy1 + ( 2 * partialUpdateMargin ); + } + + return isPartialUpdate; +} + void RenderManager::DoRender( RenderInstruction& instruction ) { Rect viewportRect; Vector4 clearColor; + bool isPartialUpdate = false; + Rect damagedRect; + Rect mergedRect; + Dali::ClippingBox scissorBox; if ( instruction.mIsClearColorSet ) { @@ -572,9 +674,11 @@ void RenderManager::DoRender( RenderInstruction& instruction ) } Rect surfaceRect = mImpl->defaultSurfaceRect; + int surfaceOrientation = mImpl->defaultSurfaceOrientation; Vector4 backgroundColor = mImpl->backgroundColor; Integration::DepthBufferAvailable depthBufferAvailable = mImpl->depthBufferAvailable; Integration::StencilBufferAvailable stencilBufferAvailable = mImpl->stencilBufferAvailable; + Integration::PartialUpdateAvailable partialUpdateAvailable = mImpl->partialUpdateAvailable; Render::SurfaceFrameBuffer* surfaceFrameBuffer = nullptr; if ( instruction.mFrameBuffer != 0 ) @@ -583,6 +687,12 @@ void RenderManager::DoRender( RenderInstruction& instruction ) { 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(); @@ -590,6 +700,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 +714,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,32 +731,76 @@ 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 { mImpl->currentContext->BindFramebuffer( GL_FRAMEBUFFER, 0u ); } + + if( surfaceFrameBuffer && + partialUpdateAvailable == Integration::PartialUpdateAvailable::TRUE ) + { + const RenderListContainer::SizeType renderListCount = instruction.RenderListCount(); + // Iterate through each render list. + if( surfaceFrameBuffer->IsPartialUpdateEnabled() ) + { + isPartialUpdate = GetDamagedRect( surfaceRect, instruction, damagedRect ) ; + } + + if( !isPartialUpdate ) + { + damagedRect = surfaceRect; + } + + mergedRect = surfaceFrameBuffer->SetDamagedRect( damagedRect ); + + if( mergedRect.IsEmpty() ) + { + isPartialUpdate = false; + } + else + { + scissorBox.x = mergedRect.x; + scissorBox.y = mergedRect.y; + scissorBox.width = mergedRect.width; + scissorBox.height = mergedRect.height; + } + } + if ( surfaceFrameBuffer ) { - mImpl->currentContext->Viewport( surfaceRect.x, - surfaceRect.y, - surfaceRect.width, - surfaceRect.height ); + mImpl->currentContext->Viewport( surfaceRect.x, + surfaceRect.y, + surfaceRect.width, + surfaceRect.height ); + - mImpl->currentContext->ClearColor( backgroundColor.r, - backgroundColor.g, - backgroundColor.b, - backgroundColor.a ); + 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 // 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. - mImpl->currentContext->SetScissorTest( false ); + if( isPartialUpdate ) + { + mImpl->currentContext->SetScissorTest( true ); + mImpl->currentContext->Scissor( scissorBox.x, scissorBox.y, scissorBox.width, scissorBox.height ); + } + GLbitfield clearMask = GL_COLOR_BUFFER_BIT; mImpl->currentContext->ColorMask( true ); @@ -659,6 +820,12 @@ void RenderManager::DoRender( RenderInstruction& instruction ) mImpl->currentContext->Clear( clearMask, Context::FORCE_CLEAR ); + if( isPartialUpdate ) + { + mImpl->currentContext->SetScissorTest( false ); + } + + if( !instruction.mIgnoreRenderToFbo && ( instruction.mFrameBuffer != 0 ) ) { if ( instruction.mFrameBuffer->IsSurfaceBacked() ) // Surface rendering @@ -668,7 +835,7 @@ void RenderManager::DoRender( RenderInstruction& instruction ) // 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 ); + viewportRect.Set( instruction.mViewport.x, y, instruction.mViewport.width, instruction.mViewport.height ); } else { @@ -687,6 +854,7 @@ void RenderManager::DoRender( RenderInstruction& instruction ) { viewportRect.Set( 0, 0, instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight() ); } + surfaceOrientation = 0; } } else // No Offscreen frame buffer rendering @@ -698,7 +866,7 @@ void RenderManager::DoRender( RenderInstruction& instruction ) { // For glViewport the lower-left corner is (0,0) const int32_t y = ( instruction.mFrameBuffer->GetHeight() - instruction.mViewport.height ) - instruction.mViewport.y; - viewportRect.Set( instruction.mViewport.x, y, instruction.mViewport.width, instruction.mViewport.height ); + viewportRect.Set( instruction.mViewport.x, y, instruction.mViewport.width, instruction.mViewport.height ); } else { @@ -711,6 +879,13 @@ void RenderManager::DoRender( RenderInstruction& instruction ) } } + if ( surfaceOrientation == 90 || surfaceOrientation == 270 ) + { + int temp = viewportRect.width; + viewportRect.width = viewportRect.height; + viewportRect.height = temp; + } + mImpl->currentContext->Viewport(viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height); if ( instruction.mIsClearColorSet ) @@ -722,18 +897,94 @@ void RenderManager::DoRender( RenderInstruction& instruction ) // Clear the viewport area only mImpl->currentContext->SetScissorTest( true ); - mImpl->currentContext->Scissor( viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height ); + if( isPartialUpdate ) + { + mImpl->currentContext->Scissor( scissorBox.x, scissorBox.y, scissorBox.width, scissorBox.height ); + } + else + { + mImpl->currentContext->Scissor( viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height ); + } mImpl->currentContext->ColorMask( true ); mImpl->currentContext->Clear( GL_COLOR_BUFFER_BIT , Context::CHECK_CACHED_VALUES ); 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, + surfaceOrientation, + scissorBox ); + + // 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 +999,10 @@ void RenderManager::DoRender( RenderInstruction& instruction ) { surfaceFrameBuffer->PostRender(); } + else + { + mImpl->currentContext->Flush(); + } } } // namespace SceneGraph