[Tizen] Add screen and client rotation itself function
[platform/core/uifw/dali-core.git] / dali / internal / render / common / render-algorithms.cpp
old mode 100644 (file)
new mode 100755 (executable)
index 01bba05..406f216
@@ -231,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;
@@ -271,7 +271,7 @@ inline void RenderAlgorithms::SetupScissorClipping( const RenderItem& item, Cont
       // This is a clipping node. We generate the AABB for this node and intersect it with the previous intersection further up the tree.
 
       // Get the AABB bounding box for the current render item.
-      const ClippingBox scissorBox( item.CalculateViewportSpaceAABB( mViewportRectangle.width, mViewportRectangle.height ) );
+      const ClippingBox scissorBox( item.CalculateViewportSpaceAABB( item.mSize, mViewportRectangle.width, mViewportRectangle.height ) );
 
       // Get the AABB for the parent item that we must intersect with.
       const ClippingBox& parentBox( mScissorStack.back() );
@@ -292,7 +292,30 @@ 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 );
+      }
     }
   }
 }
@@ -302,7 +325,8 @@ inline void RenderAlgorithms::SetupClipping( const RenderItem& item,
                                              bool& usedStencilBuffer,
                                              uint32_t& lastClippingDepth,
                                              uint32_t& lastClippingId,
-                                             Integration::StencilBufferAvailable stencilBufferAvailable )
+                                             Integration::StencilBufferAvailable stencilBufferAvailable,
+                                             int orientation )
 {
   RenderMode::Type renderMode = RenderMode::AUTO;
   const Renderer *renderer = item.mRenderer;
@@ -324,7 +348,7 @@ inline void RenderAlgorithms::SetupClipping( const RenderItem& item,
       // 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 );
+      SetupScissorClipping( item, context, orientation );
 
       if( stencilBufferAvailable == Integration::StencilBufferAvailable::TRUE )
       {
@@ -391,8 +415,9 @@ inline void RenderAlgorithms::ProcessRenderList( const RenderList& renderList,
                                                  Integration::DepthBufferAvailable depthBufferAvailable,
                                                  Integration::StencilBufferAvailable stencilBufferAvailable,
                                                  Vector<GLuint>& boundTextures,
-                                                 const RenderInstruction& instruction
-                                                 )
+                                                 const RenderInstruction& instruction,
+                                                 const Rect<int>& rootClippingRect,
+                                                 int orientation )
 {
   DALI_PRINT_RENDER_LIST( renderList );
 
@@ -409,32 +434,91 @@ 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() )
+
+  // Add root clipping rect (set manually for Render function ny partial update for example)
+  // on the bottom of the stack
+  if (!rootClippingRect.IsEmpty())
   {
     context.SetScissorTest( true );
-    const ClippingBox& layerScissorBox = renderList.GetClippingBox();
-    context.Scissor( layerScissorBox.x, layerScissorBox.y, layerScissorBox.width, layerScissorBox.height );
-    mScissorStack.push_back( layerScissorBox );
-    mHasLayerScissor = true;
+    context.Scissor( rootClippingRect.x, rootClippingRect.y, rootClippingRect.width, rootClippingRect.height );
+    mScissorStack.push_back( rootClippingRect );
   }
-  else
+  // We are not performing a layer clip and no clipping rect set. Add the viewport as the root scissor rectangle.
+  else if (!renderList.IsClipping())
   {
-    // We are not performing a layer clip. Add the viewport as the root scissor rectangle.
     context.SetScissorTest( false );
     mScissorStack.push_back( mViewportRectangle );
   }
 
+  if( renderList.IsClipping() )
+  {
+    context.SetScissorTest( true );
+    const ClippingBox& layerScissorBox = renderList.GetClippingBox();
+    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;
+  }
+
   // Loop through all RenderList in the RenderList, set up any prerequisites to render them, then perform the render.
   for( uint32_t index = 0u; index < count; ++index )
   {
     const RenderItem& item = renderList.GetItem( index );
+
+    // Discard renderers outside the root clipping rect
+    bool skip = true;
+    if( !rootClippingRect.IsEmpty() )
+    {
+      auto rect = item.CalculateViewportSpaceAABB( item.mUpdateSize, mViewportRectangle.width, mViewportRectangle.height );
+
+      if(rect.Intersect( rootClippingRect ))
+      {
+        skip = false;
+      }
+    }
+    else
+    {
+      skip = false;
+    }
+
     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, stencilBufferAvailable );
+    SetupClipping( item, context, usedStencilBuffer, lastClippingDepth, lastClippingId, stencilBufferAvailable, orientation );
 
     if( DALI_LIKELY( item.mRenderer ) )
     {
@@ -443,14 +527,26 @@ inline void RenderAlgorithms::ProcessRenderList( const RenderList& renderList,
       // 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.
-      if( depthBufferAvailable == Integration::DepthBufferAvailable::TRUE )
+      if (depthBufferAvailable == Integration::DepthBufferAvailable::TRUE)
       {
-        SetupDepthBuffer( item, context, autoDepthTestMode, firstDepthBufferUse );
+        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, boundTextures, instruction ); // Added instruction for reflection effect
+      // Depending on whether the renderer has draw commands attached or not the rendering process will
+      // iterate through all the render queues. If there are no draw commands attached, only one
+      // iteration must be done and the default behaviour of the renderer will be executed.
+      // The queues allow to iterate over the same renderer multiple times changing the state of the renderer.
+      // It is similar to the multi-pass rendering.
+      if( !skip )
+      {
+        auto const MAX_QUEUE = item.mRenderer->GetDrawCommands().empty() ? 1 : DevelRenderer::RENDER_QUEUE_MAX;
+        for (auto queue = 0u; queue < MAX_QUEUE; ++queue)
+        {
+          // Render the item.
+          item.mRenderer->Render(context, bufferIndex, *item.mNode, item.mModelMatrix, item.mModelViewMatrix,
+                                 viewMatrix, projectionMatrix, item.mSize, !item.mIsOpaque, boundTextures, instruction, queue);
+        }
+      }
     }
   }
 }
@@ -466,7 +562,9 @@ void RenderAlgorithms::ProcessRenderInstruction( const RenderInstruction& instru
                                                  BufferIndex bufferIndex,
                                                  Integration::DepthBufferAvailable depthBufferAvailable,
                                                  Integration::StencilBufferAvailable stencilBufferAvailable,
-                                                 Vector<GLuint>& boundTextures )
+                                                 Vector<GLuint>& boundTextures,
+                                                 const Rect<int>& rootClippingRect,
+                                                 int orientation )
 {
   DALI_PRINT_RENDER_INSTRUCTION( instruction, bufferIndex );
 
@@ -496,8 +594,9 @@ void RenderAlgorithms::ProcessRenderInstruction( const RenderInstruction& instru
                             depthBufferAvailable,
                             stencilBufferAvailable,
                             boundTextures,
-                            instruction //added for reflection effect
-                            );
+                            instruction, //added for reflection effect
+                            rootClippingRect,
+                            orientation );
       }
     }
   }