Skip duplicated vertex binding
[platform/core/uifw/dali-core.git] / dali / internal / render / common / render-algorithms.cpp
index 9727826..13dfcc4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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 <dali/internal/render/common/render-list.h>
 #include <dali/internal/render/renderers/render-renderer.h>
 #include <dali/internal/update/nodes/scene-graph-layer.h>
+#include <dali/public-api/math/uint-16-pair.h>
 
 using Dali::Internal::SceneGraph::RenderInstruction;
 using Dali::Internal::SceneGraph::RenderItem;
@@ -143,15 +144,30 @@ struct GraphicsStencilOp
   Graphics::StencilOp op{Graphics::StencilOp::KEEP};
 };
 
-inline Graphics::Viewport ViewportFromClippingBox(ClippingBox clippingBox, int orientation)
+inline Graphics::Viewport ViewportFromClippingBox(const Uint16Pair& sceneSize, ClippingBox clippingBox, int orientation)
 {
   Graphics::Viewport viewport{static_cast<float>(clippingBox.x), static_cast<float>(clippingBox.y), static_cast<float>(clippingBox.width), static_cast<float>(clippingBox.height), 0.0f, 0.0f};
 
   if(orientation == 90 || orientation == 270)
   {
+    if(orientation == 90)
+    {
+      viewport.x = sceneSize.GetY() - (clippingBox.y + clippingBox.height);
+      viewport.y = clippingBox.x;
+    }
+    else // orientation == 270
+    {
+      viewport.x = clippingBox.y;
+      viewport.y = sceneSize.GetX() - (clippingBox.x + clippingBox.width);
+    }
     viewport.width  = static_cast<float>(clippingBox.height);
     viewport.height = static_cast<float>(clippingBox.width);
   }
+  else if(orientation == 180)
+  {
+    viewport.x = sceneSize.GetX() - (clippingBox.x + clippingBox.width);
+    viewport.y = sceneSize.GetY() - (clippingBox.y + clippingBox.height);
+  }
   return viewport;
 }
 
@@ -383,11 +399,13 @@ inline void SetupDepthBuffer(const RenderItem& item, Graphics::CommandBuffer& co
  * @param[in]     item                     The current RenderItem about to be rendered
  * @param[in,out] commandBuffer            The command buffer to write into
  * @param[in]     instruction              The render-instruction to process.
+ * @param[in]     orientation              The Scene's surface orientation.
  */
 inline void RenderAlgorithms::SetupScissorClipping(
   const RenderItem&        item,
   Graphics::CommandBuffer& commandBuffer,
-  const RenderInstruction& instruction)
+  const RenderInstruction& instruction,
+  int                      orientation)
 {
   // Get the number of child scissors in the stack (do not include layer or root box).
   size_t         childStackDepth = mScissorStack.size() - 1u;
@@ -427,7 +445,7 @@ inline void RenderAlgorithms::SetupScissorClipping(
       // 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(item.mSize, mViewportRectangle.width, mViewportRectangle.height));
+      const ClippingBox scissorBox(RenderItem::CalculateViewportSpaceAABB(item.mModelViewMatrix, Vector3::ZERO, item.mSize, mViewportRectangle.width, mViewportRectangle.height));
 
       // Get the AABB for the parent item that we must intersect with.
       const ClippingBox& parentBox(mScissorStack.back());
@@ -456,8 +474,20 @@ inline void RenderAlgorithms::SetupScissorClipping(
       {
         useScissorBox.y = (instruction.mFrameBuffer->GetHeight() - useScissorBox.height) - useScissorBox.y;
       }
-      Graphics::Rect2D scissorBox = {useScissorBox.x, useScissorBox.y, uint32_t(useScissorBox.width), uint32_t(useScissorBox.height)};
-      commandBuffer.SetScissor(scissorBox);
+
+      Graphics::Viewport graphicsViewport = ViewportFromClippingBox(Uint16Pair{0, 0}, mViewportRectangle, 0);
+      commandBuffer.SetScissor(Rect2DFromClippingBox(useScissorBox, orientation, graphicsViewport));
+    }
+  }
+  else
+  {
+    // If there is render callback on the Renderer we need to calculate the scissor box and provide it to the
+    // callback so it may be clipped
+    if(item.mRenderer->GetRenderCallback())
+    {
+      // store clipping box inside the render callback input structure
+      auto& input       = item.mRenderer->GetRenderCallbackInput();
+      input.clippingBox = ClippingBox(RenderItem::CalculateViewportSpaceAABB(item.mModelViewMatrix, Vector3::ZERO, item.mSize, mViewportRectangle.width, mViewportRectangle.height));
     }
   }
 }
@@ -468,10 +498,11 @@ inline void RenderAlgorithms::SetupClipping(const RenderItem&
                                             uint32_t&                           lastClippingDepth,
                                             uint32_t&                           lastClippingId,
                                             Integration::StencilBufferAvailable stencilBufferAvailable,
-                                            const RenderInstruction&            instruction)
+                                            const RenderInstruction&            instruction,
+                                            int                                 orientation)
 {
   RenderMode::Type renderMode = RenderMode::AUTO;
-  const Renderer*  renderer   = item.mRenderer;
+  RendererKey      renderer   = item.mRenderer;
   if(renderer)
   {
     renderMode = renderer->GetRenderMode();
@@ -490,7 +521,7 @@ inline void RenderAlgorithms::SetupClipping(const RenderItem&
       // 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, commandBuffer, instruction);
+      SetupScissorClipping(item, commandBuffer, instruction, orientation);
 
       if(stencilBufferAvailable == Integration::StencilBufferAvailable::TRUE)
       {
@@ -559,7 +590,8 @@ inline void RenderAlgorithms::ProcessRenderList(const RenderList&
                                                 const RenderInstruction&            instruction,
                                                 const Rect<int32_t>&                viewport,
                                                 const Rect<int>&                    rootClippingRect,
-                                                int                                 orientation)
+                                                int                                 orientation,
+                                                const Uint16Pair&                   sceneSize)
 {
   DALI_PRINT_RENDER_LIST(renderList);
 
@@ -579,8 +611,7 @@ inline void RenderAlgorithms::ProcessRenderList(const RenderList&
   auto* mutableRenderList      = const_cast<RenderList*>(&renderList);
   auto& secondaryCommandBuffer = mutableRenderList->GetCommandBuffer(mGraphicsController);
   secondaryCommandBuffer.Reset();
-
-  secondaryCommandBuffer.SetViewport(ViewportFromClippingBox(mViewportRectangle, orientation));
+  secondaryCommandBuffer.SetViewport(ViewportFromClippingBox(sceneSize, mViewportRectangle, orientation));
   mHasLayerScissor = false;
 
   // Setup Scissor testing (for both viewport and per-node scissor)
@@ -590,7 +621,7 @@ inline void RenderAlgorithms::ProcessRenderList(const RenderList&
   // on the bottom of the stack
   if(!rootClippingRect.IsEmpty())
   {
-    Graphics::Viewport graphicsViewport = ViewportFromClippingBox(mViewportRectangle, 0);
+    Graphics::Viewport graphicsViewport = ViewportFromClippingBox(sceneSize, mViewportRectangle, 0);
     secondaryCommandBuffer.SetScissorTestEnable(true);
     secondaryCommandBuffer.SetScissor(Rect2DFromRect(rootClippingRect, orientation, graphicsViewport));
     mScissorStack.push_back(rootClippingRect);
@@ -604,7 +635,7 @@ inline void RenderAlgorithms::ProcessRenderList(const RenderList&
 
   if(renderList.IsClipping())
   {
-    Graphics::Viewport graphicsViewport = ViewportFromClippingBox(mViewportRectangle, 0);
+    Graphics::Viewport graphicsViewport = ViewportFromClippingBox(sceneSize, mViewportRectangle, 0);
     secondaryCommandBuffer.SetScissorTestEnable(true);
     const ClippingBox& layerScissorBox = renderList.GetClippingBox();
     secondaryCommandBuffer.SetScissor(Rect2DFromClippingBox(layerScissorBox, orientation, graphicsViewport));
@@ -612,6 +643,9 @@ inline void RenderAlgorithms::ProcessRenderList(const RenderList&
     mHasLayerScissor = true;
   }
 
+  // Prepare Render::Renderer Render for this secondary command buffer.
+  Renderer::PrepareCommandBuffer();
+
   // Loop through all RenderItems in the RenderList, set up any prerequisites to render them, then perform the render.
   for(uint32_t index = 0u; index < count; ++index)
   {
@@ -621,7 +655,8 @@ inline void RenderAlgorithms::ProcessRenderList(const RenderList&
     bool skip = true;
     if(!rootClippingRect.IsEmpty())
     {
-      auto rect = item.CalculateViewportSpaceAABB(item.mUpdateSize, mViewportRectangle.width, mViewportRectangle.height);
+      Vector4 updateArea = item.mRenderer ? item.mRenderer->GetVisualTransformedUpdateArea(bufferIndex, item.mUpdateArea) : item.mUpdateArea;
+      auto    rect       = RenderItem::CalculateViewportSpaceAABB(item.mModelViewMatrix, Vector3(updateArea.x, updateArea.y, 0.0f), Vector3(updateArea.z, updateArea.w, 0.0f), mViewportRectangle.width, mViewportRectangle.height);
 
       if(rect.Intersect(rootClippingRect))
       {
@@ -637,7 +672,7 @@ inline void RenderAlgorithms::ProcessRenderList(const RenderList&
 
     // 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, secondaryCommandBuffer, usedStencilBuffer, lastClippingDepth, lastClippingId, stencilBufferAvailable, instruction);
+    SetupClipping(item, secondaryCommandBuffer, usedStencilBuffer, lastClippingDepth, lastClippingId, stencilBufferAvailable, instruction, orientation);
 
     if(DALI_LIKELY(item.mRenderer))
     {
@@ -708,7 +743,8 @@ void RenderAlgorithms::ProcessRenderInstruction(const RenderInstruction&
                                                 Vector<Graphics::Texture*>&         boundTextures,
                                                 const Rect<int32_t>&                viewport,
                                                 const Rect<int>&                    rootClippingRect,
-                                                int                                 orientation)
+                                                int                                 orientation,
+                                                const Uint16Pair&                   sceneSize)
 {
   DALI_PRINT_RENDER_INSTRUCTION(instruction, bufferIndex);
 
@@ -741,7 +777,8 @@ void RenderAlgorithms::ProcessRenderInstruction(const RenderInstruction&
                           instruction, //added for reflection effect
                           viewport,
                           rootClippingRect,
-                          orientation);
+                          orientation,
+                          sceneSize);
 
         // Execute command buffer
         auto* commandBuffer = renderList->GetCommandBuffer();