[Tizen] Implement partial update
[platform/core/uifw/dali-core.git] / dali / internal / render / common / render-algorithms.cpp
old mode 100644 (file)
new mode 100755 (executable)
index 7c5063f..610496d
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2019 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.
@@ -194,9 +194,6 @@ inline void SetupDepthBuffer( const RenderItem& item, Context& context, bool dep
     // The depth buffer must be enabled if either reading or writing.
     context.EnableDepthBuffer( true );
 
-    // Set up the depth mask based on our depth write setting.
-    context.DepthMask( enableDepthWrite );
-
     // Look-up the GL depth function from the Dali::DepthFunction enum, and set it.
     context.DepthFunc( DaliDepthToGLDepthTable[ item.mRenderer->GetDepthFunction() ] );
 
@@ -210,8 +207,12 @@ inline void SetupDepthBuffer( const RenderItem& item, Context& context, bool dep
       firstDepthBufferUse = false;
 
       // Note: The buffer will only be cleared if written to since a previous clear.
+      context.DepthMask( true );
       context.Clear( GL_DEPTH_BUFFER_BIT, Context::CHECK_CACHED_VALUES );
     }
+
+    // Set up the depth mask based on our depth write setting.
+    context.DepthMask( enableDepthWrite );
   }
   else
   {
@@ -230,7 +231,7 @@ inline void SetupDepthBuffer( const RenderItem& item, Context& context, bool dep
  * @param[in]     item                     The current RenderItem about to be rendered
  * @param[in]     context                  The context
  */
-inline void RenderAlgorithms::SetupScissorClipping( const RenderItem& item, Context& context )
+inline void RenderAlgorithms::SetupScissorClipping( const RenderItem& item, Context& context, int orientation )
 {
   // Get the number of child scissors in the stack (do not include layer or root box).
   size_t childStackDepth = mScissorStack.size() - 1u;
@@ -255,7 +256,7 @@ inline void RenderAlgorithms::SetupScissorClipping( const RenderItem& item, Cont
     // We traversed up the tree, we need to apply a new scissor rectangle (unless we are at the root).
     traversedUpTree = true;
   }
-  else if( clippingNode && childStackDepth > 0u && childStackDepth == scissorDepth ) // case of sibling clip area
+  if( clippingNode && childStackDepth > 0u && childStackDepth == scissorDepth ) // case of sibling clip area
   {
     mScissorStack.pop_back();
     --childStackDepth;
@@ -291,12 +292,41 @@ inline void RenderAlgorithms::SetupScissorClipping( const RenderItem& item, Cont
     if( scissorEnabled )
     {
       ClippingBox useScissorBox( mScissorStack.back() );
-      context.Scissor( useScissorBox.x, useScissorBox.y, useScissorBox.width, useScissorBox.height );
+      GLint x = useScissorBox.x;
+      GLint y = useScissorBox.y;
+      if( orientation == 90 )
+      {
+        x = mViewportRectangle.height - (useScissorBox.y + useScissorBox.height);
+        y = useScissorBox.x;
+        context.Scissor( x, y, useScissorBox.height, useScissorBox.width );
+      }
+      else if( orientation == 180 )
+      {
+        x = mViewportRectangle.width - (useScissorBox.x + useScissorBox.width);
+        y = mViewportRectangle.height - (useScissorBox.y + useScissorBox.height);
+        context.Scissor( x, y, useScissorBox.width, useScissorBox.height );
+      }
+      else if( orientation == 270 )
+      {
+        x = useScissorBox.y;
+        y = mViewportRectangle.width - (useScissorBox.x + useScissorBox.width);
+        context.Scissor( x, y, useScissorBox.height, useScissorBox.width );
+      }
+      else
+      {
+        context.Scissor( x, y, useScissorBox.width, useScissorBox.height );
+      }
     }
   }
 }
 
-inline void RenderAlgorithms::SetupClipping( const RenderItem& item, Context& context, bool& usedStencilBuffer, uint32_t& lastClippingDepth, uint32_t& lastClippingId )
+inline void RenderAlgorithms::SetupClipping( const RenderItem& item,
+                                             Context& context,
+                                             bool& usedStencilBuffer,
+                                             uint32_t& lastClippingDepth,
+                                             uint32_t& lastClippingId,
+                                             Integration::StencilBufferAvailable stencilBufferAvailable,
+                                             int orientation )
 {
   RenderMode::Type renderMode = RenderMode::AUTO;
   const Renderer *renderer = item.mRenderer;
@@ -314,12 +344,16 @@ inline void RenderAlgorithms::SetupClipping( const RenderItem& item, Context& co
       // Turn the color buffer on as we always want to render this renderer, regardless of clipping hierarchy.
       context.ColorMask( true );
 
-      // The automatic clipping feature will manage the scissor and stencil functions.
+      // The automatic clipping feature will manage the scissor and stencil functions, only if stencil buffer is available for the latter.
       // 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 );
+      SetupScissorClipping( item, context, orientation );
+
+      if( stencilBufferAvailable == Integration::StencilBufferAvailable::TRUE )
+      {
+        SetupStencilClipping( item, context, lastClippingDepth, lastClippingId );
+      }
       break;
     }
 
@@ -328,8 +362,11 @@ inline void RenderAlgorithms::SetupClipping( const RenderItem& item, Context& co
     {
       // 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 );
+      // The stencil buffer will not be used at all, but we only need to disable it if it's available.
+      if( stencilBufferAvailable == Integration::StencilBufferAvailable::TRUE )
+      {
+        context.EnableStencilBuffer( false );
+      }
 
       // Setup the color buffer based on the RenderMode.
       context.ColorMask( renderMode == RenderMode::COLOR );
@@ -339,29 +376,32 @@ inline void RenderAlgorithms::SetupClipping( const RenderItem& item, Context& co
     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 )
+      if( stencilBufferAvailable == Integration::StencilBufferAvailable::TRUE )
       {
-        context.Clear( GL_STENCIL_BUFFER_BIT, Context::CHECK_CACHED_VALUES );
-        usedStencilBuffer = true;
+        // 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() );
       }
-
-      // 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;
     }
   }
@@ -371,13 +411,20 @@ inline void RenderAlgorithms::ProcessRenderList( const RenderList& renderList,
                                                  Context& context,
                                                  BufferIndex bufferIndex,
                                                  const Matrix& viewMatrix,
-                                                 const Matrix& projectionMatrix )
+                                                 const Matrix& projectionMatrix,
+                                                 Integration::DepthBufferAvailable depthBufferAvailable,
+                                                 Integration::StencilBufferAvailable stencilBufferAvailable,
+                                                 Vector<GLuint>& boundTextures,
+                                                 int orientation,
+                                                 Dali::ClippingBox& scissorBox )
 {
   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 bool autoDepthTestMode(  ( depthBufferAvailable == Integration::DepthBufferAvailable::TRUE ) &&
+                                !( renderList.GetSourceLayer()->IsDepthTestDisabled() ) &&
+                                 renderList.HasColorRenderItems() );
   const std::size_t count = renderList.Count();
   uint32_t lastClippingDepth( 0u );
   uint32_t lastClippingId( 0u );
@@ -386,16 +433,54 @@ inline void RenderAlgorithms::ProcessRenderList( const RenderList& renderList,
   mViewportRectangle = context.GetViewport();
   mHasLayerScissor = false;
 
+  if( orientation == 90 || orientation == 270 )
+  {
+    int temp = mViewportRectangle.width;
+    mViewportRectangle.width = mViewportRectangle.height;
+    mViewportRectangle.height = temp;
+  }
+
   // 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 );
+    GLint x = layerScissorBox.x;
+    GLint y = layerScissorBox.y;
+
+    if( orientation == 90 )
+    {
+      x = mViewportRectangle.height - (layerScissorBox.y + layerScissorBox.height);
+      y = layerScissorBox.x;
+      context.Scissor( x, y, layerScissorBox.height, layerScissorBox.width );
+    }
+    else if( orientation == 180 )
+    {
+      x = mViewportRectangle.width - (layerScissorBox.x + layerScissorBox.width);
+      y = mViewportRectangle.height - (layerScissorBox.y + layerScissorBox.height);
+      context.Scissor( x, y, layerScissorBox.width, layerScissorBox.height );
+    }
+    else if( orientation == 270 )
+    {
+      x = layerScissorBox.y;
+      y = mViewportRectangle.width - (layerScissorBox.x + layerScissorBox.width);
+      context.Scissor( x, y, layerScissorBox.height, layerScissorBox.width );
+    }
+    else
+    {
+      context.Scissor( x, y, layerScissorBox.width, layerScissorBox.height );
+    }
+
     mScissorStack.push_back( layerScissorBox );
     mHasLayerScissor = true;
   }
+  else if ( !scissorBox.IsEmpty() )
+  {
+    context.SetScissorTest( true );
+    context.Scissor( scissorBox.x, scissorBox.y, scissorBox.width, scissorBox.height );
+    mScissorStack.push_back( scissorBox );
+  }
   else
   {
     // We are not performing a layer clip. Add the viewport as the root scissor rectangle.
@@ -404,27 +489,30 @@ inline void RenderAlgorithms::ProcessRenderList( const RenderList& renderList,
   }
 
   // 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 )
+  for( uint32_t index = 0u; index < count; ++index )
   {
     const RenderItem& item = renderList.GetItem( index );
     DALI_PRINT_RENDER_ITEM( item );
 
     // Set up clipping based on both the Renderer and Actor APIs.
     // The Renderer API will be used if specified. If AUTO, the Actors automatic clipping feature will be used.
-    SetupClipping( item, context, usedStencilBuffer, lastClippingDepth, lastClippingId );
+    SetupClipping( item, context, usedStencilBuffer, lastClippingDepth, lastClippingId, stencilBufferAvailable, orientation );
 
     if( DALI_LIKELY( item.mRenderer ) )
     {
-      // Set up the depth buffer based on per-renderer flags.
+      // Set up the depth buffer based on per-renderer flags if depth buffer is available
       // 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 behavior 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, firstDepthBufferUse );
+      if( depthBufferAvailable == Integration::DepthBufferAvailable::TRUE )
+      {
+        SetupDepthBuffer( item, context, autoDepthTestMode, firstDepthBufferUse );
+      }
 
       // Render the item.
       item.mRenderer->Render( context, bufferIndex, *item.mNode, item.mModelMatrix, item.mModelViewMatrix,
-                              viewMatrix, projectionMatrix, item.mSize, !item.mIsOpaque );
+                              viewMatrix, projectionMatrix, item.mSize, !item.mIsOpaque, boundTextures );
     }
   }
 }
@@ -435,7 +523,14 @@ RenderAlgorithms::RenderAlgorithms()
 {
 }
 
-void RenderAlgorithms::ProcessRenderInstruction( const RenderInstruction& instruction, Context& context, BufferIndex bufferIndex )
+void RenderAlgorithms::ProcessRenderInstruction( const RenderInstruction& instruction,
+                                                 Context& context,
+                                                 BufferIndex bufferIndex,
+                                                 Integration::DepthBufferAvailable depthBufferAvailable,
+                                                 Integration::StencilBufferAvailable stencilBufferAvailable,
+                                                 Vector<GLuint>& boundTextures,
+                                                 int orientation,
+                                                 Dali::ClippingBox& scissorBox )
 {
   DALI_PRINT_RENDER_INSTRUCTION( instruction, bufferIndex );
 
@@ -457,7 +552,16 @@ void RenderAlgorithms::ProcessRenderInstruction( const RenderInstruction& instru
 
       if( renderList && !renderList->IsEmpty() )
       {
-        ProcessRenderList( *renderList, context, bufferIndex, *viewMatrix, *projectionMatrix );
+        ProcessRenderList( *renderList,
+                            context,
+                            bufferIndex,
+                           *viewMatrix,
+                           *projectionMatrix,
+                            depthBufferAvailable,
+                            stencilBufferAvailable,
+                            boundTextures,
+                            orientation,
+                            scissorBox );
       }
     }
   }