[3.0] Set up the depth buffer based on per-renderer flags.
[platform/core/uifw/dali-core.git] / dali / internal / render / common / render-algorithms.cpp
index faa4b4e..9410358 100644 (file)
@@ -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.
@@ -23,7 +23,8 @@
 #include <dali/internal/render/common/render-list.h>
 #include <dali/internal/render/common/render-instruction.h>
 #include <dali/internal/render/gl-resources/context.h>
-#include <dali/internal/render/renderers/scene-graph-renderer.h>
+#include <dali/internal/render/renderers/render-renderer.h>
+#include <dali/internal/update/nodes/scene-graph-layer.h>
 
 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,164 +79,183 @@ 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();
-
-  bool enableDepthBuffer = ( ( renderFlags & RenderList::DEPTH_BUFFER_ENABLED ) != 0u );
-
-  GLbitfield clearMask   = ( renderFlags & RenderList::DEPTH_CLEAR ) ? GL_DEPTH_BUFFER_BIT : 0u;
-
-  context.EnableDepthBuffer( enableDepthBuffer );
+  GLbitfield clearMask = 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 )
   {
-    context.StencilFunc( (enableStencilWrite ? GL_ALWAYS : GL_EQUAL), 1, 0xFF );
-    context.StencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
+    context.StencilFunc( ( enableStencilWrite ? GL_ALWAYS : GL_EQUAL ), 1, 0xFF );
+    context.StencilOp( GL_KEEP, GL_REPLACE, GL_REPLACE );
 
-    clearMask |= (renderFlags & RenderList::STENCIL_CLEAR) ? GL_STENCIL_BUFFER_BIT : 0u;
+    // 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.
+  if( depthTestEnabled )
+  {
+    clearMask |= GL_DEPTH_BUFFER_BIT;
 
-  // Clear depth and/or stencil buffer.
-  if( clearMask )
+    // 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
   {
-    // 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.EnableDepthBuffer( false );
   }
-}
 
+  // 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 );
+}
 
 /**
- * Process a render-list.
- * @param[in] renderList The render-list to process.
- * @param[in] context The GL context.
- * @param[in] defaultShader The default shader to use.
- * @param[in] buffer The current render buffer index (previous update buffer)
- * @param[in] frameTime The elapsed time between the last two updates.
- * @param[in] viewMatrix The view matrix from the appropriate camera.
- * @param[in] projectionMatrix The projection matrix from the appropriate camera.
- * @param[in] cullMode True if the renderers should be subjected to clipspace culling
+ * @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 ProcessRenderList(
-  const RenderList& renderList,
-  Context& context,
-  SceneGraph::TextureCache& textureCache,
-  SceneGraph::Shader& defaultShader,
-  BufferIndex bufferIndex,
-  float frameTime,
-  const Matrix& viewMatrix,
-  const Matrix& projectionMatrix,
-  bool cullMode )
+inline void SetupPerRendererFlags( const RenderItem& item, Context& context, bool& usedStencilBuffer, bool stencilManagedByDrawMode )
 {
-  DALI_PRINT_RENDER_LIST( renderList );
+  // 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;
+  }
 
-  SetScissorTest( renderList, context );
-  SetRenderFlags( renderList, context );
+  // Setup the color buffer based on the renderers properties.
+  Renderer *renderer = item.mRenderer;
+  context.ColorMask( renderer->GetWriteToColorBuffer() );
 
-  if( renderList.HasColorRenderItems() )
+  // If the stencil buffer is disabled for this renderer, exit now to save unnecessary value setting.
+  if( renderer->GetStencilMode() != StencilMode::ON )
   {
-    bool depthBufferEnabled = ( ( renderList.GetFlags() & RenderList::DEPTH_BUFFER_ENABLED ) != 0u );
-    size_t count = renderList.Count();
-    for ( size_t index = 0; index < count; ++index )
-    {
-      const RenderItem& item = renderList.GetItem( index );
-      DALI_PRINT_RENDER_ITEM( item );
+    // No per-renderer stencil setup, exit.
+    context.EnableStencilBuffer( false );
+    return;
+  }
 
-      //Enable depth writes if depth buffer is enabled and item is opaque
-      context.DepthMask( depthBufferEnabled && item.IsOpaque() );
+  // At this point, the stencil buffer is enabled.
+  context.EnableStencilBuffer( true );
 
-      SceneGraph::Renderer* renderer = const_cast< SceneGraph::Renderer* >( item.GetRenderer() );
-      renderer->Render( context, textureCache, bufferIndex, defaultShader, item.GetModelViewMatrix(), viewMatrix, projectionMatrix, frameTime, cullMode );
-    }
-  }
-  else
+  // If this is the first use of the stencil buffer within this RenderList, clear it now.
+  // This avoids unnecessary clears.
+  if( !usedStencilBuffer )
   {
-    size_t count = renderList.Count();
-    for ( size_t index = 0; index < count; ++index )
-    {
-      const RenderItem& item = renderList.GetItem( index );
-      DALI_PRINT_RENDER_ITEM( item );
+    context.Clear( GL_STENCIL_BUFFER_BIT, Context::CHECK_CACHED_VALUES );
+    usedStencilBuffer = true;
+  }
 
-      SceneGraph::Renderer* renderer = const_cast< SceneGraph::Renderer* >( item.GetRenderer() );
-      renderer->Render( context, textureCache, bufferIndex, defaultShader, item.GetModelViewMatrix(), viewMatrix, projectionMatrix, frameTime, cullMode );
-    }
+  // 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 );
 }
 
 /**
- * Render items from the currentIndex until the depth index changes.
- * Leaves currentIndex pointing at the
- *
+ * Process a render-list.
  * @param[in] renderList The render-list to process.
  * @param[in] context The GL context.
  * @param[in] defaultShader The default shader to use.
  * @param[in] buffer The current render buffer index (previous update buffer)
- * @param[in] frameTime The elapsed time between the last two updates.
  * @param[in] viewMatrix The view matrix from the appropriate camera.
  * @param[in] projectionMatrix The projection matrix from the appropriate camera.
- * @param[in] cullMode True if the renderers should be subjected to clipspace culling
- * @param[in] depthIndex The current depth index
- * @param[inout] currentIndex On entry, the index in the render list of the first item at the given depth index. On exit, the index of the first item at the next depth index.
  */
-inline void RenderItemsAtDepthIndex(
-  const RenderList&         renderList,
-  Context&                  context,
+inline void ProcessRenderList(
+  const RenderList& renderList,
+  Context& context,
   SceneGraph::TextureCache& textureCache,
-  SceneGraph::Shader&       defaultShader,
-  BufferIndex               bufferIndex,
-  float                     frameTime,
-  const Matrix&             viewMatrix,
-  const Matrix&             projectionMatrix,
-  bool                      cullMode,
-  int                       depthIndex,
-  size_t&                   currentIndex ) // Out parameter
+  SceneGraph::Shader& defaultShader,
+  BufferIndex bufferIndex,
+  const Matrix& viewMatrix,
+  const Matrix& projectionMatrix )
 {
-  const size_t count = renderList.Count();
+  DALI_PRINT_RENDER_LIST( renderList );
 
-  // Don't initialise currentIndex. Ever.
-  for( ; currentIndex < count ; currentIndex++ )
-  {
-    const RenderItem& renderItem = renderList.GetItem( currentIndex );
-    DALI_PRINT_RENDER_ITEM( renderItem );
+  bool autoDepthTestMode = !( renderList.GetSourceLayer()->IsDepthTestDisabled() ) && renderList.HasColorRenderItems();
+  bool usedStencilBuffer = false;
+  bool stencilManagedByDrawMode = renderList.GetFlags() & RenderList::STENCIL_BUFFER_ENABLED;
 
-    if( renderItem.GetDepthIndex() == depthIndex )
-    {
-      SceneGraph::Renderer* renderer = const_cast< SceneGraph::Renderer* >( renderItem.GetRenderer() );
-      const Matrix& modelViewMatrix = renderItem.GetModelViewMatrix();
-      renderer->Render( context, textureCache, bufferIndex, defaultShader, modelViewMatrix, viewMatrix, projectionMatrix, frameTime, cullMode );
+  SetScissorTest( renderList, context );
+  SetRenderFlags( renderList, context, autoDepthTestMode );
 
-    }
-    else
-    {
-      break; // Stop iterating when we reach a new depth index
-    }
+  const 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.
+    // 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 );
   }
 }
 
-
-
 void ProcessRenderInstruction( const RenderInstruction& instruction,
                                Context& context,
                                SceneGraph::TextureCache& textureCache,
                                SceneGraph::Shader& defaultShader,
-                               BufferIndex bufferIndex,
-                               float frameTime )
+                               BufferIndex bufferIndex )
 {
   DALI_PRINT_RENDER_INSTRUCTION( instruction, bufferIndex );
 
@@ -242,7 +279,7 @@ void ProcessRenderInstruction( const RenderInstruction& instruction,
       if(  renderList &&
           !renderList->IsEmpty() )
       {
-          ProcessRenderList( *renderList, context, textureCache, defaultShader, bufferIndex, frameTime, *viewMatrix, *projectionMatrix, instruction.mCullMode );
+        ProcessRenderList( *renderList, context, textureCache, defaultShader, bufferIndex, *viewMatrix, *projectionMatrix );
       }
     }
   }