[Tizen] (Partial Update) Ensure to renderer dirty if Geometry changed 23/319523/1
authorEunki, Hong <eunkiki.hong@samsung.com>
Wed, 12 Feb 2025 03:24:09 +0000 (12:24 +0900)
committerEunki, Hong <eunkiki.hong@samsung.com>
Wed, 12 Feb 2025 09:07:54 +0000 (18:07 +0900)
Let we also make item.mRenderer is Updated() if Render::Geometry information
changed.

For example, Toolkit::TextEditor change the vertex buffer data and indicise
when some texts, or highlighted area are changed.
But if the size of each actors are not be changed, the infomation of
geometry changed not be applied to the PreRender() dirtyrect calculation.

To fix this issue, let we make ensure that geometry is updated at Upload time,
and notify it to Render::Renderer's Update() time.

Change-Id: I67ff3c9e7a155703fba6b3be8b80d5aede8ce02d
Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
automated-tests/src/dali/utc-Dali-Geometry.cpp
dali/internal/render/renderers/render-geometry.cpp
dali/internal/render/renderers/render-geometry.h
dali/internal/render/renderers/render-renderer.cpp
dali/internal/render/renderers/render-vertex-buffer.h

index 437ea1b78adaf0342b949fca690389c8b4d19975..af398d3fd840ea9de9265164a5b76e5f4d3ae1fe 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 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.
@@ -814,3 +814,207 @@ int UtcDaliGeometryDestructWorkerThreadN(void)
 
   END_TEST;
 }
+
+int utcDaliGeometryPartialUpdateChangeIndicies(void)
+{
+  TestApplication application(
+    TestApplication::DEFAULT_SURFACE_WIDTH,
+    TestApplication::DEFAULT_SURFACE_HEIGHT,
+    TestApplication::DEFAULT_HORIZONTAL_DPI,
+    TestApplication::DEFAULT_VERTICAL_DPI,
+    true,
+    true);
+
+  tet_infoline("Check the damaged rect with changing uniform");
+
+  const TestGlAbstraction::ScissorParams& glScissorParams(application.GetGlAbstraction().GetScissorParams());
+
+  std::vector<Rect<int>> damagedRects;
+  Rect<int>              clippingRect;
+  application.SendNotification();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+
+  // First render pass, nothing to render, adaptor would just do swap buffer.
+  DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  Shader shader = Shader::New("VertexSource", "FragmentSource");
+
+  VertexBuffer vertexData   = CreateVertexBuffer();
+  const float  halfQuadSize = .5f;
+  struct TexturedQuadVertex
+  {
+    Vector2 position;
+    Vector2 textureCoordinates;
+  };
+  TexturedQuadVertex texturedQuadVertexData[5] = {
+    {Vector2(-halfQuadSize, -halfQuadSize), Vector2(0.f, 0.f)},
+    {Vector2(halfQuadSize, -halfQuadSize), Vector2(1.f, 0.f)},
+    {Vector2(-halfQuadSize, halfQuadSize), Vector2(0.f, 1.f)},
+    {Vector2(halfQuadSize, halfQuadSize), Vector2(1.f, 1.f)},
+    {Vector2(0.0f, 0.0f), Vector2(0.5f, 0.5f)}};
+  vertexData.SetData(texturedQuadVertexData, 4);
+
+  unsigned short indexData[6] = {0, 3, 1, 0, 2, 3};
+
+  Geometry geometry = Geometry::New();
+  geometry.AddVertexBuffer(vertexData);
+  geometry.SetIndexBuffer(indexData, sizeof(indexData) / sizeof(indexData[0]));
+
+  Renderer renderer = Renderer::New(geometry, shader);
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+  actor.SetProperty(Actor::Property::POSITION, Vector3(16.0f, 16.0f, 0.0f));
+  actor.SetProperty(Actor::Property::SIZE, Vector3(16.0f, 16.0f, 0.0f));
+  actor.SetResizePolicy(ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS);
+  application.GetScene().Add(actor);
+
+  application.SendNotification();
+
+  // 1. Actor added, damaged rect is added size of actor
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+
+  // Aligned by 16
+  clippingRect = Rect<int>(16, 768, 32, 32); // in screen coordinates
+  DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+  DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION);
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  // Ensure the damaged rect is empty
+  DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION);
+
+  // 2. Change the index buffer
+  geometry.SetIndexBuffer(indexData, sizeof(indexData) / sizeof(indexData[0]) - 1u);
+  application.SendNotification();
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+
+  // Aligned by 16
+  clippingRect = Rect<int>(16, 768, 32, 32); // in screen coordinates
+  DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+  DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION);
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  // Ensure the damaged rect is empty
+  DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION);
+
+  // 3. Change vertex buffer data
+  vertexData.SetData(texturedQuadVertexData, 5);
+  application.SendNotification();
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+
+  // Aligned by 16
+  clippingRect = Rect<int>(16, 768, 32, 32); // in screen coordinates
+  DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+  DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION);
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  // Ensure the damaged rect is empty
+  DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION);
+
+  // 4. Change geometry type
+  geometry.SetType(Geometry::LINES);
+  application.SendNotification();
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+
+  // Aligned by 16
+  clippingRect = Rect<int>(16, 768, 32, 32); // in screen coordinates
+  DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+  DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION);
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  // Ensure the damaged rect is empty
+  DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION);
+
+  // 5. Add vertex data
+  VertexBuffer vertexData2 = CreateVertexBuffer();
+  vertexData2.SetData(texturedQuadVertexData, 4);
+  geometry.AddVertexBuffer(vertexData2);
+  application.SendNotification();
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+
+  // Aligned by 16
+  clippingRect = Rect<int>(16, 768, 32, 32); // in screen coordinates
+  DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+  DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION);
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  // Ensure the damaged rect is empty
+  DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION);
+
+  // 5. Remove vertex data
+  geometry.RemoveVertexBuffer(0);
+  application.SendNotification();
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+
+  // Aligned by 16
+  clippingRect = Rect<int>(16, 768, 32, 32); // in screen coordinates
+  DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+  DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION);
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  // Ensure the damaged rect is empty
+  DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION);
+
+  END_TEST;
+}
index 2b4c367d52bfdd3f6f05e0ce48375208d00ae28b..a8b711552028c58c96a23ff2406fdfbb23070ed8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 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.
@@ -56,8 +56,8 @@ Geometry::Geometry()
   mIndexType(Dali::Graphics::Format::R16_UINT),
   mGeometryType(Dali::Geometry::TRIANGLES),
   mIndicesChanged(false),
-  mHasBeenUpdated(false),
-  mAttributesChanged(true)
+  mHasBeenUploaded(false),
+  mUpdated(true)
 {
 }
 
@@ -66,7 +66,7 @@ Geometry::~Geometry() = default;
 void Geometry::AddVertexBuffer(Render::VertexBuffer* vertexBuffer)
 {
   mVertexBuffers.PushBack(vertexBuffer);
-  mAttributesChanged = true;
+  mUpdated = true;
 }
 
 const Vector<Render::VertexBuffer*>& Geometry::GetVertexBuffers() const
@@ -78,6 +78,7 @@ void Geometry::SetIndexBuffer(Uint16ContainerType& indices)
 {
   mIndices.Swap(indices);
   mIndicesChanged = true;
+  mUpdated        = true;
   mIndexType      = Graphics::Format::R16_UINT;
 }
 
@@ -87,6 +88,7 @@ void Geometry::SetIndexBuffer(Uint32ContainerType& indices)
   mIndices.ResizeUninitialized(indices.Count() * 2);
   memcpy(mIndices.Begin(), indices.Begin(), indices.Count() * sizeof(uint32_t));
   mIndicesChanged = true;
+  mUpdated        = true;
   mIndexType      = Graphics::Format::R32_UINT;
 }
 
@@ -100,7 +102,7 @@ void Geometry::RemoveVertexBuffer(const Render::VertexBuffer* vertexBuffer)
     {
       //This will delete the gpu buffer associated to the RenderVertexBuffer if there is one
       mVertexBuffers.Remove(iter);
-      mAttributesChanged = true;
+      mUpdated = true;
       break;
     }
   }
@@ -108,13 +110,13 @@ void Geometry::RemoveVertexBuffer(const Render::VertexBuffer* vertexBuffer)
 
 void Geometry::OnRenderFinished()
 {
-  mHasBeenUpdated    = false;
-  mAttributesChanged = false;
+  mHasBeenUploaded = false;
+  mUpdated         = false;
 }
 
 void Geometry::Upload(Graphics::Controller& graphicsController)
 {
-  if(!mHasBeenUpdated)
+  if(!mHasBeenUploaded)
   {
     // Update buffers
     if(mIndicesChanged)
@@ -140,6 +142,7 @@ void Geometry::Upload(Graphics::Controller& graphicsController)
 
     for(auto&& buffer : mVertexBuffers)
     {
+      mUpdated = mUpdated || buffer->IsDataChanged();
       if(!buffer->Update(graphicsController))
       {
         //Vertex buffer is not ready ( Size, data or format has not been specified yet )
@@ -147,7 +150,7 @@ void Geometry::Upload(Graphics::Controller& graphicsController)
       }
     }
 
-    mHasBeenUpdated = true;
+    mHasBeenUploaded = true;
   }
 }
 
index f2f27b259622c8eedaac55c25cb56f8bf5e7754f..1443d59f5f2b6627e00dae81d8a6a6708c4c0b41 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_RENDER_GEOMETRY_H
 
 /*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 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.
@@ -97,9 +97,9 @@ public:
    * Check if the attributes for the geometry have changed
    * @return True if vertex buffers have been added or removed since last frame, false otherwise
    */
-  [[maybe_unused]] [[nodiscard]] bool AttributesChanged() const
+  [[maybe_unused]] [[nodiscard]] bool Updated() const
   {
-    return mAttributesChanged;
+    return mUpdated;
   }
 
   /**
@@ -109,6 +109,8 @@ public:
   void SetType(Type type)
   {
     mGeometryType = type;
+
+    mUpdated = true;
   }
 
   /**
@@ -156,8 +158,8 @@ private:
 
   // Booleans
   bool mIndicesChanged : 1;
-  bool mHasBeenUpdated : 1;
-  bool mAttributesChanged : 1;
+  bool mHasBeenUploaded : 1;
+  bool mUpdated : 1; ///< Flag to know if data has changed in a frame. Value fixed after Upload() call, and reset as false after OnRenderFinished
 };
 
 } // namespace Render
index a24911722f5220784872adfb69c704e14b951268..c0dfababcc3a721b9965b3071ab892b1ba37a3ef 100644 (file)
@@ -963,7 +963,7 @@ void Renderer::SetShaderChanged(bool value)
 
 bool Renderer::Updated()
 {
-  if(mRenderCallback || mShaderChanged || mGeometry->AttributesChanged() || mRenderDataProvider->IsUpdated())
+  if(mRenderCallback || mShaderChanged || mGeometry->Updated() || mRenderDataProvider->IsUpdated())
   {
     return true;
   }
index 63825372ac3fb655a0b63fdc8de2661d29764426..80d708f3a7df5912c0f788fe46a1e94fff0de260 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_RENDER_VERTEX_BUFFER_H
 
 /*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 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.
@@ -122,6 +122,7 @@ public:
   /**
    * Perform the upload of the buffer only when required
    * @param[in] graphicsController The controller
+   * @return True if all data are valid so update success. False if some data are invalid.
    */
   bool Update(Graphics::Controller& graphicsController);
 
@@ -206,6 +207,11 @@ public:
     return mGpuBuffer.Get();
   }
 
+  [[nodiscard]] inline bool IsDataChanged() const
+  {
+    return mDataChanged;
+  }
+
 private:
   OwnerPointer<VertexBuffer::Format>   mFormat;    ///< Format of the buffer
   OwnerPointer<Dali::Vector<uint8_t> > mData;      ///< Data
@@ -232,7 +238,7 @@ private:
 
   StateLock<VertexBufferSyncState> mVertexBufferStateLock{VertexBufferSyncState::UNLOCKED};
 
-  bool mDataChanged; ///< Flag to know if data has changed in a frame
+  bool mDataChanged : 1; ///< Flag to know if data has changed in a frame. Reset as false after Update successed.
 };
 
 } // namespace Render