X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Frender%2Fcommon%2Frender-algorithms.cpp;h=941035834f0b7496d9aa1ab026c106c6533c926f;hb=refs%2Fchanges%2F60%2F86960%2F1;hp=bb5183147ce17e56c050508a3f45c58792bff69a;hpb=3b20d8e3e6922ee57cfbd78a86db9ee744cbe32a;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 bb51831..9410358 100644 --- a/dali/internal/render/common/render-algorithms.cpp +++ b/dali/internal/render/common/render-algorithms.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * Copyright (c) 2016 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 using Dali::Internal::SceneGraph::RenderItem; using Dali::Internal::SceneGraph::RenderList; @@ -39,6 +40,23 @@ namespace Internal 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 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 + /** * Sets up the scissor test if required. * @param[in] renderList The render list from which to get the clipping flag @@ -61,53 +79,131 @@ inline void SetScissorTest( const RenderList& renderList, Context& context ) } /** - * Sets the render flags for depth testing and stencil buffer - * + * Sets the render flags for the stencil buffer and clears all required buffers (depth and stencil if required). * @param[in] renderList The render list from which to get the render flags * @param[in] context The 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 ) +inline void SetRenderFlags( const RenderList& renderList, Context& context, bool depthTestEnabled ) { const unsigned int renderFlags = renderList.GetFlags(); + GLbitfield clearMask = 0u; - if( ( renderFlags & RenderList::DEPTH_BUFFER_ENABLED ) != 0u ) + // Stencil enabled, writing, and clearing... + const bool enableStencilBuffer( renderFlags & RenderList::STENCIL_BUFFER_ENABLED ); + const bool enableStencilWrite( renderFlags & RenderList::STENCIL_WRITE ); + context.EnableStencilBuffer( enableStencilBuffer ); + if( enableStencilBuffer ) { - //Enable depth testing + 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; + } + + // Enable and Clear the depth buffer if required. + if( depthTestEnabled ) + { + 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. context.EnableDepthBuffer( true ); } else { - //Disable depth test and depth write context.EnableDepthBuffer( false ); - context.DepthMask( false ); } - GLbitfield clearMask = ( renderFlags & RenderList::DEPTH_CLEAR ) ? GL_DEPTH_BUFFER_BIT : 0u; + // Clear Depth and/or stencil buffers as required. + // Note: The buffers will only be cleared if written to since a previous clear. + context.Clear( clearMask, Context::CHECK_CACHED_VALUES ); +} - // Stencil enabled, writing, and clearing... - const bool enableStencilBuffer( renderFlags & RenderList::STENCIL_BUFFER_ENABLED ); - const bool enableStencilWrite( renderFlags & RenderList::STENCIL_WRITE ); - context.EnableStencilBuffer( enableStencilBuffer ); - if( enableStencilBuffer ) +/** + * @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 ) { - context.StencilFunc( (enableStencilWrite ? GL_ALWAYS : GL_EQUAL), 1, 0xFF ); - context.StencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE); + return; + } + + // Setup the color buffer based on the renderers properties. + Renderer *renderer = item.mRenderer; + context.ColorMask( renderer->GetWriteToColorBuffer() ); - clearMask |= (renderFlags & RenderList::STENCIL_CLEAR) ? GL_STENCIL_BUFFER_BIT : 0u; + // If the stencil buffer is disabled for this renderer, exit now to save unnecessary value setting. + if( renderer->GetStencilMode() != StencilMode::ON ) + { + // No per-renderer stencil setup, exit. + context.EnableStencilBuffer( false ); + return; } - // Write to stencil buffer or color buffer, but not both - context.StencilMask( enableStencilWrite ? 0xFF : 0x00 ); - context.ColorMask( !enableStencilWrite ); + // At this point, the stencil buffer is enabled. + context.EnableStencilBuffer( true ); - // Clear depth and/or stencil buffer. - if( clearMask ) + // If this is the first use of the stencil buffer within this RenderList, clear it now. + // This avoids unnecessary clears. + if( !usedStencilBuffer ) { - // only clear if the depth and/or stencil buffer have been written to after a previous clear - context.Clear( clearMask, Context::CHECK_CACHED_VALUES ); + 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 depthTestEnabled True if depth testing has been enabled. + */ +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 ) && 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 ) && depthTestEnabled ) || + ( depthTestMode == DepthTestMode::ON ); + // Look-up the GL depth function from the Dali::DepthFunction enum, and set it. + context.DepthFunc( DaliDepthToGLDepthTable[ item.mRenderer->GetDepthFunction() ] ); + + // The depth buffer must be enabled if either reading or writing. + context.EnableDepthBuffer( enableDepthWrite || enableDepthTest ); +} /** * Process a render-list. @@ -129,50 +225,29 @@ inline void ProcessRenderList( { DALI_PRINT_RENDER_LIST( renderList ); - SetScissorTest( renderList, context ); - SetRenderFlags( renderList, context ); - - if( renderList.HasColorRenderItems() ) - { - bool depthBufferEnabled = ( ( renderList.GetFlags() & RenderList::DEPTH_BUFFER_ENABLED ) != 0u ); - size_t count = renderList.Count(); - - if( depthBufferEnabled ) - { - for ( size_t index = 0; index < count; ++index ) - { - const RenderItem& item = renderList.GetItem( index ); - DALI_PRINT_RENDER_ITEM( item ); + bool autoDepthTestMode = !( renderList.GetSourceLayer()->IsDepthTestDisabled() ) && renderList.HasColorRenderItems(); + bool usedStencilBuffer = false; + bool stencilManagedByDrawMode = renderList.GetFlags() & RenderList::STENCIL_BUFFER_ENABLED; - Renderer& renderer = item.GetRenderer(); - Dali::Renderer::DepthWriteMode depthWriteMode = renderer.GetDepthWriteMode(); - context.DepthMask( ( depthWriteMode == Dali::Renderer::DEPTH_WRITE_AUTO && item.IsOpaque() ) || - ( depthWriteMode == Dali::Renderer::DEPTH_WRITE_ON ) ); + SetScissorTest( renderList, context ); + SetRenderFlags( renderList, context, autoDepthTestMode ); - renderer.Render( context, textureCache, bufferIndex, item.GetNode(), defaultShader, item.GetModelViewMatrix(), viewMatrix, projectionMatrix, item.GetSize(), !item.IsOpaque() ); - } - } - else - { - for ( size_t index = 0; index < count; ++index ) - { - const RenderItem& item = renderList.GetItem( index ); - DALI_PRINT_RENDER_ITEM( item ); - item.GetRenderer().Render( context, textureCache, bufferIndex, item.GetNode(), defaultShader, item.GetModelViewMatrix(), viewMatrix, projectionMatrix, item.GetSize(), !item.IsOpaque() ); - } - } - } - else + 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.GetRenderer().Render( context, textureCache, bufferIndex, item.GetNode(), defaultShader, item.GetModelViewMatrix(), viewMatrix, projectionMatrix, item.GetSize(), !item.IsOpaque() ); - } - + 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 ); } }