X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Frender%2Fcommon%2Frender-algorithms.cpp;h=ce56324b50a524183cf6446a4c6c496c17135ad2;hb=be285a5aa0ba77ea635e8d8c2692d585ca30630e;hp=695a57440f51a5b0a875bceef7e3f10e4805732b;hpb=1504ffe03f767eec8035864db2753494fe7a063c;p=platform%2Fcore%2Fuifw%2Fdali-core.git diff --git a/dali/internal/render/common/render-algorithms.cpp b/dali/internal/render/common/render-algorithms.cpp index 695a574..ce56324 100644 --- a/dali/internal/render/common/render-algorithms.cpp +++ b/dali/internal/render/common/render-algorithms.cpp @@ -42,9 +42,19 @@ namespace Render namespace { + // Table for fast look-up of Dali::DepthFunction enum to a GL depth function. // Note: These MUST be in the same order as Dali::DepthFunction enum. -const short DaliDepthToGLDepthTable[] = { GL_NEVER, GL_ALWAYS, GL_LESS, GL_GREATER, GL_EQUAL, GL_NOTEQUAL, GL_LEQUAL, GL_GEQUAL }; +const int DaliDepthToGLDepthTable[] = { GL_NEVER, GL_ALWAYS, GL_LESS, GL_GREATER, GL_EQUAL, GL_NOTEQUAL, GL_LEQUAL, GL_GEQUAL }; + +// Table for fast look-up of Dali::StencilFunction enum to a GL stencil function. +// Note: These MUST be in the same order as Dali::StencilFunction enum. +const int DaliStencilFunctionToGL[] = { GL_NEVER, GL_LESS, GL_EQUAL, GL_LEQUAL, GL_GREATER, GL_NOTEQUAL, GL_GEQUAL, GL_ALWAYS }; + +// Table for fast look-up of Dali::StencilOperation enum to a GL stencil operation. +// Note: These MUST be in the same order as Dali::StencilOperation enum. +const int DaliStencilOperationToGL[] = { GL_ZERO, GL_KEEP, GL_REPLACE, GL_INCR, GL_DECR, GL_INVERT, GL_INCR_WRAP, GL_DECR_WRAP }; + } // Unnamed namespace /** @@ -75,7 +85,7 @@ inline void SetScissorTest( const RenderList& renderList, Context& context ) * @param[in] depthTestEnabled True if depth test is enabled for the layer * @param[in] isLayer3D True if the layer is a 3D layer */ -inline void SetRenderFlags( const RenderList& renderList, Context& context, bool depthTestEnabled, bool isLayer3D ) +inline void SetRenderFlags( const RenderList& renderList, Context& context, bool depthTestEnabled ) { const unsigned int renderFlags = renderList.GetFlags(); GLbitfield clearMask = 0u; @@ -89,28 +99,27 @@ inline void SetRenderFlags( const RenderList& renderList, Context& context, bool context.StencilFunc( ( enableStencilWrite ? GL_ALWAYS : GL_EQUAL ), 1, 0xFF ); context.StencilOp( GL_KEEP, GL_REPLACE, GL_REPLACE ); + // Write to stencil buffer or color buffer, but not both. + // These should only be set if the Actor::DrawMode is managing the stencil (and color) buffer. + context.StencilMask( enableStencilWrite ? 0xFF : 0x00 ); + context.ColorMask( !enableStencilWrite ); + clearMask |= ( renderFlags & RenderList::STENCIL_CLEAR ) ? GL_STENCIL_BUFFER_BIT : 0u; } - // Write to stencil buffer or color buffer, but not both - context.StencilMask( enableStencilWrite ? 0xFF : 0x00 ); - context.ColorMask( !enableStencilWrite ); - // Enable and Clear the depth buffer if required. - // DepthTest must be enabled for the layer, else testing is turned off. - if( !depthTestEnabled ) + if( depthTestEnabled ) { - context.EnableDepthBuffer( false ); - } - else if( renderList.HasColorRenderItems() || isLayer3D ) // Also, within the context of this if(), depth test is enabled. - { - clearMask |= GL_DEPTH_BUFFER_BIT; + // We need to enable the depth buffer to clear it. // Subsequently it is enabled and disabled on a per-RenderItem basis. - // If we do not have color renderers, this is only done for 3D layers. context.EnableDepthBuffer( true ); } + else + { + context.EnableDepthBuffer( false ); + } // Clear Depth and/or stencil buffers as required. // Note: The buffers will only be cleared if written to since a previous clear. @@ -118,27 +127,78 @@ inline void SetRenderFlags( const RenderList& renderList, Context& context, bool } /** + * @brief This method sets up the stencil and color buffer based on the current Renderers flags. + * @param[in] item The current RenderItem about to be rendered + * @param[in] context The context + * @param[in/out] usedStencilBuffer True if the stencil buffer has been used so far within this RenderList + * @param[in] stencilManagedByDrawMode True if the stencil and color buffer is being managed by DrawMode::STENCIL + */ +inline void SetupPerRendererFlags( const RenderItem& item, Context& context, bool& usedStencilBuffer, bool stencilManagedByDrawMode ) +{ + // DrawMode::STENCIL is deprecated, however to support it we must not set + // flags based on the renderer properties if it is in use. + if( stencilManagedByDrawMode ) + { + return; + } + + // Setup the color buffer based on the renderers properties. + Renderer *renderer = item.mRenderer; + RenderMode::Type renderMode = renderer->GetRenderMode(); + const bool writeToColorBuffer = ( renderMode == RenderMode::AUTO ) || ( renderMode == RenderMode::COLOR ) || ( renderMode == RenderMode::COLOR_STENCIL ); + context.ColorMask( writeToColorBuffer ); + + // If the stencil buffer is disabled for this renderer, exit now to save unnecessary value setting. + if( ( renderMode != RenderMode::STENCIL ) && ( renderMode != RenderMode::COLOR_STENCIL ) ) + { + // No per-renderer stencil setup, exit. + context.EnableStencilBuffer( false ); + return; + } + + // At this point, the stencil buffer is enabled. + context.EnableStencilBuffer( true ); + + // If this is the first use of the stencil buffer within this RenderList, clear it now. + // This avoids unnecessary clears. + if( !usedStencilBuffer ) + { + context.Clear( GL_STENCIL_BUFFER_BIT, Context::CHECK_CACHED_VALUES ); + usedStencilBuffer = true; + } + + // Setup the stencil buffer based on the renderers properties. + context.StencilFunc( DaliStencilFunctionToGL[ renderer->GetStencilFunction() ], + renderer->GetStencilFunctionReference(), + renderer->GetStencilFunctionMask() ); + context.StencilOp( DaliStencilOperationToGL[ renderer->GetStencilOperationOnFail() ], + DaliStencilOperationToGL[ renderer->GetStencilOperationOnZFail() ], + DaliStencilOperationToGL[ renderer->GetStencilOperationOnZPass() ] ); + context.StencilMask( renderer->GetStencilMask() ); +} + +/** * Sets up the depth buffer for reading and writing based on the current render item. * The items read and write mode are used if specified. * If AUTO is selected for reading, the decision will be based on the Layer Behavior. * If AUTO is selected for writing, the decision will be based on the items opacity. * @param item The RenderItem to set up the depth buffer for * @param context The context used to execute GL commands. - * @param isLayer3D True if the layer behavior is set to LAYER_3D + * @param depthTestEnabled True if depth testing has been enabled. */ -inline void SetupDepthBuffer( const RenderItem& item, Context& context, bool isLayer3D ) +inline void SetupDepthBuffer( const RenderItem& item, Context& context, bool depthTestEnabled ) { // Set up whether or not to write to the depth buffer. const DepthWriteMode::Type depthWriteMode = item.mRenderer->GetDepthWriteMode(); // Most common mode (AUTO) is tested first. - bool enableDepthWrite = ( ( depthWriteMode == DepthWriteMode::AUTO ) && item.mIsOpaque ) || + bool enableDepthWrite = ( ( depthWriteMode == DepthWriteMode::AUTO ) && depthTestEnabled && item.mIsOpaque ) || ( depthWriteMode == DepthWriteMode::ON ); context.DepthMask( enableDepthWrite ); // Set up whether or not to read from (test) the depth buffer. const DepthTestMode::Type depthTestMode = item.mRenderer->GetDepthTestMode(); // Most common mode (AUTO) is tested first. - bool enableDepthTest = ( ( depthTestMode == DepthTestMode::AUTO ) && isLayer3D ) || + bool enableDepthTest = ( ( depthTestMode == DepthTestMode::AUTO ) && depthTestEnabled ) || ( depthTestMode == DepthTestMode::ON ); // Look-up the GL depth function from the Dali::DepthFunction enum, and set it. context.DepthFunc( DaliDepthToGLDepthTable[ item.mRenderer->GetDepthFunction() ] ); @@ -167,41 +227,29 @@ inline void ProcessRenderList( { DALI_PRINT_RENDER_LIST( renderList ); - bool depthTestEnabled = !( renderList.GetSourceLayer()->IsDepthTestDisabled() ); - bool isLayer3D = renderList.GetSourceLayer()->GetBehavior() == Dali::Layer::LAYER_3D; + bool autoDepthTestMode = !( renderList.GetSourceLayer()->IsDepthTestDisabled() ) && renderList.HasColorRenderItems(); + bool usedStencilBuffer = false; + bool stencilManagedByDrawMode = renderList.GetFlags() & RenderList::STENCIL_BUFFER_ENABLED; SetScissorTest( renderList, context ); - SetRenderFlags( renderList, context, depthTestEnabled, isLayer3D ); + SetRenderFlags( renderList, context, autoDepthTestMode ); - // The Layers depth enabled flag overrides the per-renderer depth flags. - // So if depth test is disabled at the layer level, we ignore per-render flags. - // Note: Overlay renderers will not read or write from the depth buffer. - if( DALI_LIKELY( !renderList.HasColorRenderItems() || !depthTestEnabled ) ) + const size_t count = renderList.Count(); + for ( size_t index = 0; index < count; ++index ) { - size_t count = renderList.Count(); - for ( size_t index = 0; index < count; ++index ) - { - const RenderItem& item = renderList.GetItem( index ); - DALI_PRINT_RENDER_ITEM( item ); - - item.mRenderer->Render( context, textureCache, bufferIndex, *item.mNode, defaultShader, - item.mModelMatrix, item.mModelViewMatrix, viewMatrix, projectionMatrix, item.mSize, !item.mIsOpaque ); - } - } - else - { - size_t count = renderList.Count(); - for ( size_t index = 0; index < count; ++index ) - { - const RenderItem& item = renderList.GetItem( index ); - DALI_PRINT_RENDER_ITEM( item ); - - // Set up the depth buffer based on per-renderer flags. - SetupDepthBuffer( item, context, isLayer3D ); - - item.mRenderer->Render( context, textureCache, bufferIndex, *item.mNode, defaultShader, - item.mModelMatrix, item.mModelViewMatrix, viewMatrix, projectionMatrix, item.mSize, !item.mIsOpaque ); - } + const RenderItem& item = renderList.GetItem( index ); + DALI_PRINT_RENDER_ITEM( item ); + + // Set up the depth buffer based on per-renderer flags. + // If the per renderer flags are set to "ON" or "OFF", they will always override any Layer depth mode or + // draw-mode state, such as Overlays. + // If the flags are set to "AUTO", the behaviour then depends on the type of renderer. Overlay Renderers will always + // disable depth testing and writing. Color Renderers will enable them if the Layer does. + SetupDepthBuffer( item, context, autoDepthTestMode ); + SetupPerRendererFlags( item, context, usedStencilBuffer, stencilManagedByDrawMode ); + + item.mRenderer->Render( context, textureCache, bufferIndex, *item.mNode, defaultShader, + item.mModelMatrix, item.mModelViewMatrix, viewMatrix, projectionMatrix, item.mSize, !item.mIsOpaque ); } }