+ // The automatic clipping feature will manage the scissor and stencil functions.
+ // As both scissor and stencil clips can be nested, we may be simultaneously traversing up the scissor tree, requiring a scissor to be un-done. Whilst simultaneously adding a new stencil clip.
+ // We process both based on our current and old clipping depths for each mode.
+ // Both methods with return rapidly if there is nothing to be done for that type of clipping.
+ SetupScissorClipping( item, context );
+ SetupStencilClipping( item, context, lastClippingDepth, lastClippingId );
+ break;
+ }
+
+ case RenderMode::NONE:
+ case RenderMode::COLOR:
+ {
+ // No clipping is performed for these modes.
+ // Note: We do not turn off scissor clipping as it may be used for the whole layer.
+ // The stencil buffer will not be used at all.
+ context.EnableStencilBuffer( false );
+
+ // Setup the color buffer based on the RenderMode.
+ context.ColorMask( renderMode == RenderMode::COLOR );
+ break;
+ }
+
+ case RenderMode::STENCIL:
+ case RenderMode::COLOR_STENCIL:
+ {
+ // We are using the low-level Renderer Stencil API.
+ // The stencil buffer must be enabled for every renderer with stencil mode on, as renderers in between can disable it.
+ // Note: As the command state is cached, it is only sent when needed.
+ context.EnableStencilBuffer( true );
+
+ // Setup the color buffer based on the RenderMode.
+ context.ColorMask( renderMode == RenderMode::COLOR_STENCIL );
+
+ // If this is the first use of the stencil buffer within this RenderList, clear it (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() );
+ break;
+ }
+ }
+}
+
+inline void RenderAlgorithms::ProcessRenderList( const RenderList& renderList,
+ Context& context,
+ BufferIndex bufferIndex,
+ const Matrix& viewMatrix,
+ const Matrix& projectionMatrix )
+{
+ DALI_PRINT_RENDER_LIST( renderList );
+
+ // Note: The depth buffer is enabled or disabled on a per-renderer basis.
+ // Here we pre-calculate the value to use if these modes are set to AUTO.
+ const bool autoDepthTestMode( !( renderList.GetSourceLayer()->IsDepthTestDisabled() ) && renderList.HasColorRenderItems() );
+ const std::size_t count = renderList.Count();
+ uint32_t lastClippingDepth( 0u );
+ uint32_t lastClippingId( 0u );
+ bool usedStencilBuffer( false );
+ bool firstDepthBufferUse( true );
+ mViewportRectangle = context.GetViewport();
+ mHasLayerScissor = false;
+
+ // Setup Scissor testing (for both viewport and per-node scissor)
+ mScissorStack.clear();
+ if( renderList.IsClipping() )
+ {
+ context.SetScissorTest( true );
+ const ClippingBox& layerScissorBox = renderList.GetClippingBox();
+ context.Scissor( layerScissorBox.x, layerScissorBox.y, layerScissorBox.width, layerScissorBox.height );
+ mScissorStack.push_back( layerScissorBox );
+ mHasLayerScissor = true;
+ }
+ else
+ {
+ // We are not performing a layer clip. Add the viewport as the root scissor rectangle.
+ context.SetScissorTest( false );
+ mScissorStack.push_back( mViewportRectangle );
+ }
+
+ // Loop through all RenderList in the RenderList, set up any prerequisites to render them, then perform the render.
+ for( size_t index( 0u ); index < count; ++index )
+ {
+ const RenderItem& item = renderList.GetItem( index );