Merge "Remove std::vector dependency for dali-signal.h" into devel/master
[platform/core/uifw/dali-core.git] / dali / internal / update / manager / render-instruction-processor.cpp
index ce5d270..74b76c1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -137,29 +137,35 @@ bool CompareItems3DWithClipping(const RenderInstructionProcessor::SortAttributes
 }
 
 /**
- * Set the update size of the node
+ * Set the update area of the node
  * @param[in] node The node of the renderer
  * @param[in] isLayer3d Whether we are processing a 3D layer or not
  * @param[in,out] nodeWorldMatrix The world matrix of the node
  * @param[in,out] nodeSize The size of the node
- * @param[in,out] nodeUpdateSize The update size of the node
+ * @param[in,out] nodeUpdateArea The update area of the node
+ *
+ * @return True if node use it's own UpdateAreaHint, or z transform occured. False if we use nodeUpdateArea equal with Vector4(0, 0, nodeSize.width, nodeSize.height).
  */
-inline void SetNodeUpdateSize(Node* node, bool isLayer3d, Matrix& nodeWorldMatrix, Vector3& nodeSize, Vector3& nodeUpdateSize)
+inline bool SetNodeUpdateArea(Node* node, bool isLayer3d, Matrix& nodeWorldMatrix, Vector3& nodeSize, Vector4& nodeUpdateArea)
 {
   node->GetWorldMatrixAndSize(nodeWorldMatrix, nodeSize);
 
-  if(node->GetUpdateSizeHint() == Vector3::ZERO)
+  if(node->GetUpdateAreaHint() == Vector4::ZERO)
   {
     // RenderItem::CalculateViewportSpaceAABB cannot cope with z transform
     // I don't use item.mModelMatrix.GetTransformComponents() for z transform, would be too slow
     if(!isLayer3d && nodeWorldMatrix.GetZAxis() == Vector3(0.0f, 0.0f, 1.0f))
     {
-      nodeUpdateSize = nodeSize;
+      nodeUpdateArea = Vector4(0.0f, 0.0f, nodeSize.width, nodeSize.height);
+      return false;
     }
+    // Keep nodeUpdateArea as Vector4::ZERO, and return true.
+    return true;
   }
   else
   {
-    nodeUpdateSize = node->GetUpdateSizeHint();
+    nodeUpdateArea = node->GetUpdateAreaHint();
+    return true;
   }
 }
 
@@ -189,12 +195,16 @@ inline void AddRendererToRenderList(BufferIndex         updateBufferIndex,
   Node*   node = renderable.mNode;
   Matrix  nodeWorldMatrix(false);
   Vector3 nodeSize;
-  Vector3 nodeUpdateSize;
-  bool    nodeUpdateSizeSet(false);
+  Vector4 nodeUpdateArea;
+  bool    nodeUpdateAreaSet(false);
+  bool    nodeUpdateAreaUseHint(false);
   Matrix  nodeModelViewMatrix(false);
   bool    nodeModelViewMatrixSet(false);
 
-  if(cull && renderable.mRenderer && !renderable.mRenderer->GetShader().HintEnabled(Dali::Shader::Hint::MODIFIES_GEOMETRY) && node->GetClippingMode() == ClippingMode::DISABLED)
+  // Don't cull items which have render callback
+  bool hasRenderCallback = (renderable.mRenderer && renderable.mRenderer->GetRenderCallback());
+
+  if(cull && renderable.mRenderer && (hasRenderCallback || (!renderable.mRenderer->GetShader().HintEnabled(Dali::Shader::Hint::MODIFIES_GEOMETRY) && node->GetClippingMode() == ClippingMode::DISABLED)))
   {
     const Vector4& boundingSphere = node->GetBoundingSphere();
     inside                        = (boundingSphere.w > Math::MACHINE_EPSILON_1000) &&
@@ -202,30 +212,44 @@ inline void AddRendererToRenderList(BufferIndex         updateBufferIndex,
 
     if(inside && !isLayer3d && viewportSet)
     {
-      SetNodeUpdateSize(node, isLayer3d, nodeWorldMatrix, nodeSize, nodeUpdateSize);
-      nodeUpdateSizeSet = true;
+      nodeUpdateAreaUseHint = SetNodeUpdateArea(node, isLayer3d, nodeWorldMatrix, nodeSize, nodeUpdateArea);
+      nodeUpdateAreaSet     = true;
 
-      const Vector3& scale    = node->GetWorldScale(updateBufferIndex);
-      const Vector3& halfSize = nodeUpdateSize * scale * 0.5f;
-      float          radius(halfSize.Length());
+      const Vector3& scale = node->GetWorldScale(updateBufferIndex);
+      const Vector3& size  = Vector3(nodeUpdateArea.z, nodeUpdateArea.w, 1.0f) * scale;
 
-      if(radius > Math::MACHINE_EPSILON_1000)
+      if(size.LengthSquared() > Math::MACHINE_EPSILON_1000)
       {
         Matrix::Multiply(nodeModelViewMatrix, nodeWorldMatrix, viewMatrix);
         nodeModelViewMatrixSet = true;
 
-        ClippingBox clippingBox = RenderItem::CalculateViewportSpaceAABB(nodeModelViewMatrix, nodeUpdateSize, viewport.width, viewport.height);
-        inside                  = clippingBox.Intersects(viewport);
+        // Assume actors are at z=0, compute AABB in view space & test rect intersection
+        // against z=0 plane boundaries for frustum. (NOT viewport). This should take into account
+        // magnification due to FOV etc.
+        ClippingBox boundingBox = RenderItem::CalculateTransformSpaceAABB(nodeModelViewMatrix, Vector3(nodeUpdateArea.x, nodeUpdateArea.y, 0.0f), Vector3(nodeUpdateArea.z, nodeUpdateArea.w, 0.0f));
+        ClippingBox clippingBox(camera.mLeftClippingPlane, camera.mBottomClippingPlane, camera.mRightClippingPlane - camera.mLeftClippingPlane, fabsf(camera.mBottomClippingPlane - camera.mTopClippingPlane));
+        inside = clippingBox.Intersects(boundingBox);
       }
     }
+    /*
+     * Note, the API Camera::CheckAABBInFrustum() can be used to test if a bounding box is (partially/fully) inside the view frustum.
+     */
   }
 
   if(inside)
   {
-    Renderer::OpacityType opacityType = renderable.mRenderer ? renderable.mRenderer->GetOpacityType(updateBufferIndex, *node) : Renderer::OPAQUE;
+    bool skipRender(false);
+    bool isOpaque = true;
+    if(!hasRenderCallback)
+    {
+      Renderer::OpacityType opacityType = renderable.mRenderer ? renderable.mRenderer->GetOpacityType(updateBufferIndex, *node) : Renderer::OPAQUE;
+
+      // We can skip render when node is not clipping and transparent
+      skipRender = (opacityType == Renderer::TRANSPARENT && node->GetClippingMode() == ClippingMode::DISABLED);
+
+      isOpaque = (opacityType == Renderer::OPAQUE);
+    }
 
-    // We can skip render when node is not clipping and transparent
-    const bool skipRender(opacityType == Renderer::TRANSPARENT && node->GetClippingMode() == ClippingMode::DISABLED);
     if(!skipRender)
     {
       // Get the next free RenderItem.
@@ -237,18 +261,19 @@ inline void AddRendererToRenderList(BufferIndex         updateBufferIndex,
       auto& partialRenderingCacheInfo = node->GetPartialRenderingData().GetCurrentCacheInfo();
 
       partialRenderingCacheInfo.node       = node;
-      partialRenderingCacheInfo.isOpaque   = (opacityType == Renderer::OPAQUE);
+      partialRenderingCacheInfo.isOpaque   = isOpaque;
       partialRenderingCacheInfo.renderer   = renderable.mRenderer;
-      partialRenderingCacheInfo.color      = node->GetColor(updateBufferIndex);
+      partialRenderingCacheInfo.color      = node->GetWorldColor(updateBufferIndex);
       partialRenderingCacheInfo.depthIndex = node->GetDepthIndex();
 
       if(DALI_LIKELY(renderable.mRenderer))
       {
+        partialRenderingCacheInfo.color.a *= renderable.mRenderer->GetOpacity(updateBufferIndex);
         partialRenderingCacheInfo.textureSet = renderable.mRenderer->GetTextureSet();
       }
 
       item.mNode     = node;
-      item.mIsOpaque = (opacityType == Renderer::OPAQUE);
+      item.mIsOpaque = isOpaque;
       item.mColor    = node->GetColor(updateBufferIndex);
 
       item.mDepthIndex = 0;
@@ -262,6 +287,9 @@ inline void AddRendererToRenderList(BufferIndex         updateBufferIndex,
         item.mRenderer   = &renderable.mRenderer->GetRenderer();
         item.mTextureSet = renderable.mRenderer->GetTextureSet();
         item.mDepthIndex += renderable.mRenderer->GetDepthIndex();
+
+        // Get whether collected map is up to date
+        item.mIsUpdated |= renderable.mRenderer->UniformMapUpdated();
       }
       else
       {
@@ -270,32 +298,54 @@ inline void AddRendererToRenderList(BufferIndex         updateBufferIndex,
 
       item.mIsUpdated |= isLayer3d;
 
-      if(!nodeUpdateSizeSet)
+      if(!nodeUpdateAreaSet)
       {
-        SetNodeUpdateSize(node, isLayer3d, nodeWorldMatrix, nodeSize, nodeUpdateSize);
+        nodeUpdateAreaUseHint = SetNodeUpdateArea(node, isLayer3d, nodeWorldMatrix, nodeSize, nodeUpdateArea);
       }
 
       item.mSize        = nodeSize;
-      item.mUpdateSize  = nodeUpdateSize;
+      item.mUpdateArea  = nodeUpdateArea;
       item.mModelMatrix = nodeWorldMatrix;
 
+      // Apply transform informations if node doesn't have update size hint and use VisualRenderer.
+      if(!nodeUpdateAreaUseHint && renderable.mRenderer && renderable.mRenderer->GetVisualProperties())
+      {
+        Vector3 updateSize = renderable.mRenderer->CalculateVisualTransformedUpdateSize(updateBufferIndex, Vector3(item.mUpdateArea.z, item.mUpdateArea.w, 0.0f));
+        item.mUpdateArea.z = updateSize.x;
+        item.mUpdateArea.w = updateSize.y;
+      }
+
       if(!nodeModelViewMatrixSet)
       {
         Matrix::Multiply(nodeModelViewMatrix, nodeWorldMatrix, viewMatrix);
       }
       item.mModelViewMatrix = nodeModelViewMatrix;
 
-      partialRenderingCacheInfo.matrix      = item.mModelViewMatrix;
-      partialRenderingCacheInfo.size        = item.mSize;
-      partialRenderingCacheInfo.updatedSize = item.mUpdateSize;
+      partialRenderingCacheInfo.matrix              = item.mModelViewMatrix;
+      partialRenderingCacheInfo.size                = item.mSize;
+      partialRenderingCacheInfo.updatedPositionSize = item.mUpdateArea;
 
       item.mIsUpdated = partialRenderingData.IsUpdated() || item.mIsUpdated;
+
+      partialRenderingData.mRendered = true;
+
       partialRenderingData.SwapBuffers();
     }
+    else
+    {
+      // Mark as not rendered
+      auto& partialRenderingData     = node->GetPartialRenderingData();
+      partialRenderingData.mRendered = false;
+    }
+
     node->SetCulled(updateBufferIndex, false);
   }
   else
   {
+    // Mark as not rendered
+    auto& partialRenderingData     = node->GetPartialRenderingData();
+    partialRenderingData.mRendered = false;
+
     node->SetCulled(updateBufferIndex, true);
   }
 }