Added VisualRenderer (for visual default properties) 83/271183/6
authorDavid Steele <david.steele@samsung.com>
Tue, 15 Feb 2022 10:01:35 +0000 (10:01 +0000)
committerDavid Steele <david.steele@samsung.com>
Wed, 9 Mar 2022 14:22:20 +0000 (14:22 +0000)
Rather than have registered properties for each visual,
embedded them in a specific type of VisualRenderer.

Added UniformMappings to ensure that they can be used as
uniforms. (Properties don't have to have the same name
as the uniform, but it's probably advisable. However, we
have some very specific hardcoded mapping for actor "size"
-> uniform "uSize" in render-renderer...), so it's less
confusing having property "transformSize"->uniform "size".

Changed types to ensure they match the actual uniform types
in the shaders.

Reduces creation time for each visual, as much more is done
at compilation time.

Change-Id: I386504fabf82f8e57f1138e3814897604b094061
Signed-off-by: David Steele <david.steele@samsung.com>
20 files changed:
automated-tests/src/dali/CMakeLists.txt
automated-tests/src/dali/dali-test-suite-utils/test-gl-abstraction.cpp
automated-tests/src/dali/dali-test-suite-utils/test-graphics-buffer.cpp
automated-tests/src/dali/dali-test-suite-utils/test-graphics-controller.cpp
automated-tests/src/dali/dali-test-suite-utils/test-graphics-reflection.cpp
automated-tests/src/dali/dali-test-suite-utils/test-trace-call-stack.cpp
automated-tests/src/dali/dali-test-suite-utils/test-trace-call-stack.h
automated-tests/src/dali/utc-Dali-VisualRenderer.cpp [new file with mode: 0644]
dali/internal/event/rendering/renderer-impl.cpp
dali/internal/event/rendering/renderer-impl.h
dali/internal/event/rendering/visual-renderer-impl.cpp [new file with mode: 0644]
dali/internal/event/rendering/visual-renderer-impl.h [new file with mode: 0644]
dali/internal/file.list
dali/internal/update/rendering/scene-graph-renderer.h
dali/public-api/dali-core.h
dali/public-api/file.list
dali/public-api/object/property-index-ranges.h
dali/public-api/rendering/renderer.h
dali/public-api/rendering/visual-renderer.cpp [new file with mode: 0644]
dali/public-api/rendering/visual-renderer.h [new file with mode: 0644]

index a352f26..cba77af 100644 (file)
@@ -68,6 +68,7 @@ SET(TC_SOURCES
         utc-Dali-Random.cpp
         utc-Dali-Rect.cpp
         utc-Dali-Renderer.cpp
+        utc-Dali-VisualRenderer.cpp
         utc-Dali-RenderTask.cpp
         utc-Dali-RenderTaskList.cpp
         utc-Dali-RotationGestureDetector.cpp
index e99de5c..e6416e3 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.
@@ -140,6 +140,8 @@ void TestGlAbstraction::Initialize()
     {"uViewMatrix", GL_FLOAT_MAT4, 1},
     {"uLightCameraProjectionMatrix", GL_FLOAT_MAT4, 1},
     {"uLightCameraViewMatrix", GL_FLOAT_MAT4, 1}};
+
+  // WARNING: IF YOU CHANGE THIS LIST, ALSO CHANGE UNIFORMS IN test-graphics-reflection.cpp
 }
 
 void TestGlAbstraction::PreRender()
index 83b7899..8f9b9fc 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.
@@ -28,7 +28,7 @@ TestGraphicsBuffer::TestGraphicsBuffer(TraceCallStack& callStack, TestGlAbstract
   mUsage(usage)
 {
   memory.resize(size);
-  mGl.GetBufferTrace().EnableLogging(true);
+  mGl.GetBufferTrace().EnableLogging(false);
 }
 
 void TestGraphicsBuffer::Bind()
index 3ed6b56..bedce18 100644 (file)
@@ -584,15 +584,15 @@ public:
 };
 
 TestGraphicsController::TestGraphicsController()
-: mCallStack(true, "TestGraphicsController."),
-  mCommandBufferCallStack(true, "TestCommandBuffer."),
-  mFrameBufferCallStack(true, "TestFrameBuffer.")
+: mCallStack(false, "TestGraphicsController."),
+  mCommandBufferCallStack(false, "TestCommandBuffer."),
+  mFrameBufferCallStack(false, "TestFrameBuffer.")
 {
   mCallStack.Enable(true);
   mCommandBufferCallStack.Enable(true);
   auto& trace = mGl.GetTextureTrace();
   trace.Enable(true);
-  trace.EnableLogging(true);
+  trace.EnableLogging(false);
 }
 
 void TestGraphicsController::SubmitCommandBuffers(const Graphics::SubmitInfo& submitInfo)
index 25c09b5..6971b71 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.
@@ -50,6 +50,8 @@ static const std::vector<UniformData> UNIFORMS =
     UniformData("uViewMatrix", Property::Type::MATRIX),
     UniformData("uLightCameraProjectionMatrix", Property::Type::MATRIX),
     UniformData("uLightCameraViewMatrix", Property::Type::MATRIX),
+
+    // WARNING: IF YOU CHANGE THIS LIST, ALSO CHANGE mActiveUniforms IN test-gl-abstraction, Initialize
 };
 }
 
index 7f2de63..2316036 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.
@@ -146,7 +146,26 @@ bool TraceCallStack::FindMethodAndGetParameters(std::string method, std::string&
   }
   if(!found)
   {
-    fprintf(stderr, "Search for %s(%s) failed\n", method.c_str(), params.c_str());
+    fprintf(stderr, "Search for %s() failed\n", method.c_str());
+  }
+  return found;
+}
+
+bool TraceCallStack::FindMethodAndGetParameters(std::string method, NamedParams& params) const
+{
+  bool found = false;
+  for(size_t i = 0; i < mCallStack.size(); i++)
+  {
+    if(0 == mCallStack[i].method.compare(method))
+    {
+      found  = true;
+      params = mCallStack[i].namedParams;
+      break;
+    }
+  }
+  if(!found)
+  {
+    fprintf(stderr, "Search for %s() failed\n", method.c_str());
   }
   return found;
 }
index 6f720c5..c2d0a49 100644 (file)
@@ -207,6 +207,14 @@ public:
   bool FindMethodAndGetParameters(std::string method, std::string& params) const;
 
   /**
+   * Search for a method in the stack and return its parameters if found
+   * @param[in] method The name of the method
+   * @param[out] params of the method
+   * @return true if the method was in the stack
+   */
+  bool FindMethodAndGetParameters(std::string method, NamedParams& params) const;
+
+  /**
    * Count how many times a method was called
    * @param[in] method The name of the method
    * @return The number of times it was called
diff --git a/automated-tests/src/dali/utc-Dali-VisualRenderer.cpp b/automated-tests/src/dali/utc-Dali-VisualRenderer.cpp
new file mode 100644 (file)
index 0000000..2b589e9
--- /dev/null
@@ -0,0 +1,673 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/actors/actor-devel.h>
+#include <dali/devel-api/common/capabilities.h>
+#include <dali/devel-api/common/stage.h>
+#include <dali/devel-api/rendering/renderer-devel.h>
+#include <dali/integration-api/render-task-list-integ.h>
+#include <dali/public-api/dali-core.h>
+#include <cstdio>
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali-test-suite-utils.h>
+#include <mesh-builder.h>
+#include <test-trace-call-stack.h>
+#include "test-graphics-command-buffer.h"
+
+using namespace Dali;
+
+void visual_renderer_test_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void visual_renderer_test_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+int UtcDaliVisualRendererNew01(void)
+{
+  TestApplication application;
+
+  Geometry       geometry = CreateQuadGeometry();
+  Shader         shader   = CreateShader();
+  VisualRenderer renderer = VisualRenderer::New(geometry, shader);
+
+  DALI_TEST_EQUALS((bool)renderer, true, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVisualRendererNew02(void)
+{
+  TestApplication application;
+  VisualRenderer  renderer;
+  DALI_TEST_EQUALS((bool)renderer, false, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVisualRendererCopyConstructor(void)
+{
+  TestApplication application;
+
+  Geometry       geometry = CreateQuadGeometry();
+  Shader         shader   = CreateShader();
+  VisualRenderer renderer = VisualRenderer::New(geometry, shader);
+
+  VisualRenderer rendererCopy(renderer);
+  DALI_TEST_EQUALS((bool)rendererCopy, true, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliVisualRendererAssignmentOperator(void)
+{
+  TestApplication application;
+
+  Geometry       geometry = CreateQuadGeometry();
+  Shader         shader   = CreateShader();
+  VisualRenderer renderer = VisualRenderer::New(geometry, shader);
+
+  VisualRenderer renderer2;
+  DALI_TEST_EQUALS((bool)renderer2, false, TEST_LOCATION);
+
+  renderer2 = renderer;
+  DALI_TEST_EQUALS((bool)renderer2, true, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVisualRendererMoveConstructor(void)
+{
+  TestApplication application;
+
+  Geometry       geometry = CreateQuadGeometry();
+  Shader         shader   = Shader::New("vertexSrc", "fragmentSrc");
+  VisualRenderer renderer = VisualRenderer::New(geometry, shader);
+  DALI_TEST_CHECK(renderer);
+  DALI_TEST_EQUALS(1, renderer.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+  DALI_TEST_EQUALS(renderer.GetProperty<Vector3>(VisualRenderer::Property::VISUAL_MIX_COLOR), Vector3::ONE, TEST_LOCATION);
+
+  auto testColor = Vector3(1.0f, 0.0f, 1.0f);
+  renderer.SetProperty(VisualRenderer::Property::VISUAL_MIX_COLOR, testColor);
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS(renderer.GetProperty<Vector3>(VisualRenderer::Property::VISUAL_MIX_COLOR), testColor, TEST_LOCATION);
+
+  VisualRenderer move = std::move(renderer);
+  DALI_TEST_CHECK(move);
+  DALI_TEST_EQUALS(1, move.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+  DALI_TEST_EQUALS(move.GetProperty<Vector3>(VisualRenderer::Property::VISUAL_MIX_COLOR), testColor, TEST_LOCATION);
+  DALI_TEST_CHECK(!renderer);
+
+  END_TEST;
+}
+
+int UtcDaliVisualRendererMoveAssignment(void)
+{
+  TestApplication application;
+
+  Geometry       geometry = CreateQuadGeometry();
+  Shader         shader   = Shader::New("vertexSrc", "fragmentSrc");
+  VisualRenderer renderer = VisualRenderer::New(geometry, shader);
+  DALI_TEST_CHECK(renderer);
+  DALI_TEST_EQUALS(1, renderer.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+  DALI_TEST_EQUALS(renderer.GetProperty<Vector3>(VisualRenderer::Property::VISUAL_MIX_COLOR), Vector3::ONE, TEST_LOCATION);
+
+  renderer.SetProperty(VisualRenderer::Property::VISUAL_MIX_COLOR, Vector3(1.0f, 0.0f, 1.0f));
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS(renderer.GetProperty<Vector3>(VisualRenderer::Property::VISUAL_MIX_COLOR), Vector3(1.0f, 0.0f, 1.0f), TEST_LOCATION);
+
+  VisualRenderer move;
+  move = std::move(renderer);
+  DALI_TEST_CHECK(move);
+  DALI_TEST_EQUALS(1, move.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+  DALI_TEST_EQUALS(move.GetProperty<Vector3>(VisualRenderer::Property::VISUAL_MIX_COLOR), Vector3(1.0f, 0.0f, 1.0f), TEST_LOCATION);
+  DALI_TEST_CHECK(!renderer);
+
+  END_TEST;
+}
+
+int UtcDaliVisualRendererDownCast01(void)
+{
+  TestApplication application;
+
+  Geometry       geometry = CreateQuadGeometry();
+  Shader         shader   = CreateShader();
+  VisualRenderer renderer = VisualRenderer::New(geometry, shader);
+
+  BaseHandle     handle(renderer);
+  VisualRenderer renderer2 = VisualRenderer::DownCast(handle);
+  DALI_TEST_EQUALS((bool)renderer2, true, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVisualRendererDownCast02(void)
+{
+  TestApplication application;
+
+  Handle         handle   = Handle::New(); // Create a custom object
+  VisualRenderer renderer = VisualRenderer::DownCast(handle);
+  DALI_TEST_EQUALS((bool)renderer, false, TEST_LOCATION);
+  END_TEST;
+}
+
+// using a template to auto deduce the parameter types
+template<typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
+void TEST_RENDERER_PROPERTY(P1 renderer, P2 stringName, P3 type, P4 isWriteable, P5 isAnimateable, P6 isConstraintInput, P7 enumName, P8 LOCATION)
+{
+  DALI_TEST_EQUALS(renderer.GetPropertyName(enumName), stringName, LOCATION);
+  DALI_TEST_EQUALS(renderer.GetPropertyIndex(stringName), static_cast<Property::Index>(enumName), LOCATION);
+  DALI_TEST_EQUALS(renderer.GetPropertyType(enumName), type, LOCATION);
+  DALI_TEST_EQUALS(renderer.IsPropertyWritable(enumName), isWriteable, LOCATION);
+  DALI_TEST_EQUALS(renderer.IsPropertyAnimatable(enumName), isAnimateable, LOCATION);
+  DALI_TEST_EQUALS(renderer.IsPropertyAConstraintInput(enumName), isConstraintInput, LOCATION);
+}
+
+int UtcDaliVisualRendererDefaultProperties(void)
+{
+  TestApplication application;
+  Geometry        geometry     = CreateQuadGeometry();
+  Shader          shader       = CreateShader();
+  VisualRenderer  renderer     = VisualRenderer::New(geometry, shader);
+  Renderer        baseRenderer = Renderer::New(geometry, shader);
+
+  DALI_TEST_EQUALS(baseRenderer.GetPropertyCount(), 27, TEST_LOCATION);
+  DALI_TEST_EQUALS(renderer.GetPropertyCount(), 27 + 8, TEST_LOCATION);
+
+  TEST_RENDERER_PROPERTY(renderer, "transformOffset", Property::VECTOR2, true, true, true, VisualRenderer::Property::TRANSFORM_OFFSET, TEST_LOCATION);
+  TEST_RENDERER_PROPERTY(renderer, "transformSize", Property::VECTOR2, true, true, true, VisualRenderer::Property::TRANSFORM_SIZE, TEST_LOCATION);
+  TEST_RENDERER_PROPERTY(renderer, "transformOrigin", Property::VECTOR2, true, false, false, VisualRenderer::Property::TRANSFORM_ORIGIN, TEST_LOCATION);
+  TEST_RENDERER_PROPERTY(renderer, "transformAnchorPoint", Property::VECTOR2, true, false, false, VisualRenderer::Property::TRANSFORM_ANCHOR_POINT, TEST_LOCATION);
+  TEST_RENDERER_PROPERTY(renderer, "transformOffsetSizeMode", Property::VECTOR4, true, false, false, VisualRenderer::Property::TRANSFORM_OFFSET_SIZE_MODE, TEST_LOCATION);
+  TEST_RENDERER_PROPERTY(renderer, "extraSize", Property::VECTOR2, true, true, true, VisualRenderer::Property::EXTRA_SIZE, TEST_LOCATION);
+
+  TEST_RENDERER_PROPERTY(renderer, "visualMixColor", Property::VECTOR3, true, true, true, VisualRenderer::Property::VISUAL_MIX_COLOR, TEST_LOCATION);
+  TEST_RENDERER_PROPERTY(renderer, "preMultipliedAlpha", Property::FLOAT, true, false, false, VisualRenderer::Property::VISUAL_PRE_MULTIPLIED_ALPHA, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliVisualRendererAnimatedProperty01(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that a visual renderer property can be animated");
+
+  Shader         shader   = Shader::New("VertexSource", "FragmentSource");
+  Geometry       geometry = CreateQuadGeometry();
+  VisualRenderer renderer = VisualRenderer::New(geometry, shader);
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetProperty(Actor::Property::SIZE, Vector2(400.0f, 400.0f));
+  application.GetScene().Add(actor);
+
+  Property::Index colorIndex = VisualRenderer::Property::VISUAL_MIX_COLOR;
+  renderer.SetProperty(colorIndex, Vector3(1.0f, 1.0f, 1.0f));
+
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS(renderer.GetProperty<Vector3>(colorIndex), Vector3(1.0f, 1.0f, 1.0f), 0.001f, TEST_LOCATION);
+
+  Animation animation = Animation::New(1.0f);
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, Vector3(1.0f, 0.0f, 1.0f));
+  keyFrames.Add(1.0f, Vector3(0.0f, 0.0f, 0.0f));
+  animation.AnimateBetween(Property(renderer, colorIndex), keyFrames);
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(500);
+
+  DALI_TEST_EQUALS(renderer.GetCurrentProperty<Vector3>(colorIndex), Vector3(0.5f, 0.f, 0.5f), TEST_LOCATION);
+
+  application.Render(400);
+  DALI_TEST_EQUALS(renderer.GetCurrentProperty<Vector3>(colorIndex), Vector3(0.1f, 0.f, 0.1f), TEST_LOCATION);
+
+  application.Render(100);
+  DALI_TEST_EQUALS(renderer.GetCurrentProperty<Vector3>(colorIndex), Vector3(0.f, 0.f, 0.f), TEST_LOCATION);
+  DALI_TEST_EQUALS(renderer.GetProperty<Vector3>(colorIndex), Vector3(0.f, 0.f, 0.f), TEST_LOCATION);
+
+  // Can we test to see if the actor has stopped being drawn?
+  END_TEST;
+}
+
+int UtcDaliVisualRendererAnimatedProperty02(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that a visual renderer property can be animated");
+
+  Shader         shader   = Shader::New("VertexSource", "FragmentSource");
+  Geometry       geometry = CreateQuadGeometry();
+  VisualRenderer renderer = VisualRenderer::New(geometry, shader);
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetProperty(Actor::Property::SIZE, Vector2(400.0f, 400.0f));
+  application.GetScene().Add(actor);
+
+  Property::Index index = VisualRenderer::Property::TRANSFORM_OFFSET;
+  renderer.SetProperty(index, Vector2(1.0f, 0.0f));
+
+  application.SendNotification();
+  application.Render(0);
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS(renderer.GetProperty<Vector2>(index), Vector2(1.0f, 0.0f), 0.001f, TEST_LOCATION);
+
+  Animation animation = Animation::New(1.0f);
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, Vector2(1.0f, 0.0f));
+  keyFrames.Add(1.0f, Vector2(0.0f, 1.0f));
+  animation.AnimateBetween(Property(renderer, index), keyFrames);
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(500);
+
+  DALI_TEST_EQUALS(renderer.GetCurrentProperty<Vector2>(index), Vector2(0.5f, 0.5f), TEST_LOCATION);
+
+  application.Render(400);
+  DALI_TEST_EQUALS(renderer.GetCurrentProperty<Vector2>(index), Vector2(0.1f, 0.9f), TEST_LOCATION);
+
+  application.Render(100);
+  DALI_TEST_EQUALS(renderer.GetCurrentProperty<Vector2>(index), Vector2(0.f, 1.0f), TEST_LOCATION);
+  DALI_TEST_EQUALS(renderer.GetProperty<Vector2>(index), Vector2(0.f, 1.f), TEST_LOCATION);
+
+  END_TEST;
+}
+
+struct VisualProperties
+{
+  VisualProperties() = default;
+
+  VisualProperties(Vector2 offset, Vector2 size, Vector2 origin, Vector2 pivot, Vector4 modes, Vector2 extraSize, Vector3 mixColor)
+  : mTransformOffset(offset),
+    mTransformSize(size),
+    mTransformOrigin(origin),
+    mTransformAnchorPoint(pivot),
+    mTransformOffsetSizeMode(modes),
+    mExtraSize(extraSize),
+    mMixColor(mixColor)
+  {
+  }
+
+  Vector2 mTransformOffset{Vector2::ZERO};
+  Vector2 mTransformSize{Vector2::ZERO};
+  Vector2 mTransformOrigin{Vector2::ZERO};
+  Vector2 mTransformAnchorPoint{Vector2::ZERO};
+  Vector4 mTransformOffsetSizeMode{Vector2::ZERO};
+  Vector2 mExtraSize{Vector2::ZERO};
+  Vector3 mMixColor{Vector3::ONE};
+
+  static VisualProperties GetPropsAt(float alpha, const VisualProperties& start, const VisualProperties& end)
+  {
+    VisualProperties progress;
+    progress.mTransformOffset         = start.mTransformOffset + (end.mTransformOffset - start.mTransformOffset) * alpha;
+    progress.mTransformSize           = start.mTransformSize + (end.mTransformSize - start.mTransformSize) * alpha;
+    progress.mExtraSize               = start.mExtraSize + (end.mExtraSize - start.mExtraSize) * alpha;
+    progress.mMixColor                = start.mMixColor + (end.mMixColor - start.mMixColor) * alpha;
+    progress.mTransformOffsetSizeMode = end.mTransformOffsetSizeMode;
+    progress.mTransformOrigin         = end.mTransformOrigin;
+    progress.mTransformAnchorPoint    = end.mTransformAnchorPoint;
+    return progress;
+  }
+};
+
+void PrintVisualProperties(const VisualProperties& props, const std::string& prefix)
+{
+  tet_printf(
+    "%s: offset:(%5.3f, %5.3f)\n"
+    "%*c size:(%5.3f, %5.3f)\n"
+    "%*c origin:(%5.3f, %5.3f)\n"
+    "%*c anchorPoint:(%5.3f, %5.3f)\n"
+    "%*c offsetSizeMode:(%5.3f, %5.3f, %5.3f, %5.3f)\n"
+    "%*c extraSize:(%5.3f, %5.3f)\n"
+    "%*c mixColor:(%5.3f, %5.3f, %5.3f, %5.3f)\n",
+    prefix.c_str(),
+    props.mTransformOffset.x,
+    props.mTransformOffset.y,
+    prefix.length(),
+    ' ',
+    props.mTransformSize.x,
+    props.mTransformSize.y,
+    prefix.length(),
+    ' ',
+    props.mTransformOrigin.x,
+    props.mTransformOrigin.y,
+    prefix.length(),
+    ' ',
+    props.mTransformAnchorPoint.x,
+    props.mTransformAnchorPoint.y,
+    prefix.length(),
+    ' ',
+    props.mTransformOffsetSizeMode.x,
+    props.mTransformOffsetSizeMode.y,
+    props.mTransformOffsetSizeMode.z,
+    props.mTransformOffsetSizeMode.w,
+    prefix.length(),
+    ' ',
+    props.mExtraSize.x,
+    props.mExtraSize.y,
+    prefix.length(),
+    ' ',
+    props.mMixColor.x,
+    props.mMixColor.y,
+    props.mMixColor.z);
+}
+
+void SetVisualProperties(VisualRenderer renderer, VisualProperties props)
+{
+  renderer.SetProperty(VisualRenderer::Property::TRANSFORM_OFFSET, props.mTransformOffset);
+  renderer.SetProperty(VisualRenderer::Property::TRANSFORM_SIZE, props.mTransformSize);
+  renderer.SetProperty(VisualRenderer::Property::TRANSFORM_ORIGIN, props.mTransformOrigin);
+  renderer.SetProperty(VisualRenderer::Property::TRANSFORM_ANCHOR_POINT, props.mTransformAnchorPoint);
+  renderer.SetProperty(VisualRenderer::Property::TRANSFORM_OFFSET_SIZE_MODE, props.mTransformOffsetSizeMode);
+  renderer.SetProperty(VisualRenderer::Property::EXTRA_SIZE, props.mExtraSize);
+  renderer.SetProperty(VisualRenderer::Property::VISUAL_MIX_COLOR, props.mMixColor);
+}
+
+void CheckEventVisualProperties(VisualRenderer renderer, VisualProperties expectedProps)
+{
+  tet_infoline("CheckEventVisualProperties\n");
+
+  VisualProperties actualProps;
+  actualProps.mTransformOffset         = renderer.GetProperty<Vector2>(VisualRenderer::Property::TRANSFORM_OFFSET);
+  actualProps.mTransformSize           = renderer.GetProperty<Vector2>(VisualRenderer::Property::TRANSFORM_SIZE);
+  actualProps.mTransformOrigin         = renderer.GetProperty<Vector2>(VisualRenderer::Property::TRANSFORM_ORIGIN);
+  actualProps.mTransformAnchorPoint    = renderer.GetProperty<Vector2>(VisualRenderer::Property::TRANSFORM_ANCHOR_POINT);
+  actualProps.mTransformOffsetSizeMode = renderer.GetProperty<Vector4>(VisualRenderer::Property::TRANSFORM_OFFSET_SIZE_MODE);
+  actualProps.mExtraSize               = renderer.GetProperty<Vector2>(VisualRenderer::Property::EXTRA_SIZE);
+  actualProps.mMixColor                = renderer.GetProperty<Vector3>(VisualRenderer::Property::VISUAL_MIX_COLOR);
+
+  PrintVisualProperties(actualProps, "Actual event props");
+
+  DALI_TEST_EQUALS(actualProps.mTransformOffset, expectedProps.mTransformOffset, TEST_LOCATION);
+  DALI_TEST_EQUALS(actualProps.mTransformSize, expectedProps.mTransformSize, TEST_LOCATION);
+  DALI_TEST_EQUALS(actualProps.mTransformOrigin, expectedProps.mTransformOrigin, TEST_LOCATION);
+  DALI_TEST_EQUALS(actualProps.mTransformAnchorPoint, expectedProps.mTransformAnchorPoint, TEST_LOCATION);
+  DALI_TEST_EQUALS(actualProps.mTransformOffsetSizeMode, expectedProps.mTransformOffsetSizeMode, TEST_LOCATION);
+  DALI_TEST_EQUALS(actualProps.mExtraSize, expectedProps.mExtraSize, TEST_LOCATION);
+  DALI_TEST_EQUALS(actualProps.mMixColor, expectedProps.mMixColor, TEST_LOCATION);
+}
+
+void CheckSceneGraphVisualProperties(VisualRenderer renderer, VisualProperties expectedProps)
+{
+  tet_infoline("CheckSceneGraphVisualProperties\n");
+
+  VisualProperties actualProps;
+
+  actualProps.mTransformOffset         = renderer.GetCurrentProperty<Vector2>(VisualRenderer::Property::TRANSFORM_OFFSET);
+  actualProps.mTransformSize           = renderer.GetCurrentProperty<Vector2>(VisualRenderer::Property::TRANSFORM_SIZE);
+  actualProps.mTransformOrigin         = renderer.GetCurrentProperty<Vector2>(VisualRenderer::Property::TRANSFORM_ORIGIN);
+  actualProps.mTransformAnchorPoint    = renderer.GetCurrentProperty<Vector2>(VisualRenderer::Property::TRANSFORM_ANCHOR_POINT);
+  actualProps.mTransformOffsetSizeMode = renderer.GetCurrentProperty<Vector4>(VisualRenderer::Property::TRANSFORM_OFFSET_SIZE_MODE);
+  actualProps.mExtraSize               = renderer.GetCurrentProperty<Vector2>(VisualRenderer::Property::EXTRA_SIZE);
+  actualProps.mMixColor                = renderer.GetCurrentProperty<Vector3>(VisualRenderer::Property::VISUAL_MIX_COLOR);
+
+  PrintVisualProperties(actualProps, "Actual update props");
+
+  DALI_TEST_EQUALS(actualProps.mTransformOffset, expectedProps.mTransformOffset, TEST_LOCATION);
+  DALI_TEST_EQUALS(actualProps.mTransformSize, expectedProps.mTransformSize, TEST_LOCATION);
+  DALI_TEST_EQUALS(actualProps.mTransformOrigin, expectedProps.mTransformOrigin, TEST_LOCATION);
+  DALI_TEST_EQUALS(actualProps.mTransformAnchorPoint, expectedProps.mTransformAnchorPoint, TEST_LOCATION);
+  DALI_TEST_EQUALS(actualProps.mTransformOffsetSizeMode, expectedProps.mTransformOffsetSizeMode, TEST_LOCATION);
+  DALI_TEST_EQUALS(actualProps.mExtraSize, expectedProps.mExtraSize, TEST_LOCATION);
+  DALI_TEST_EQUALS(actualProps.mMixColor, expectedProps.mMixColor, TEST_LOCATION);
+}
+
+void CheckUniforms(VisualRenderer renderer, VisualProperties props, std::vector<UniformData>& uniforms, TraceCallStack& callStack, TestGlAbstraction& gl)
+{
+  tet_infoline("CheckUniforms\n");
+
+  TraceCallStack::NamedParams params;
+
+  tet_printf("Callback trace: \n%s\n", callStack.GetTraceString().c_str());
+
+  DALI_TEST_CHECK(callStack.FindMethodAndGetParameters(uniforms[0].name, params));
+  DALI_TEST_CHECK(gl.GetUniformValue<Vector2>(uniforms[0].name.c_str(), props.mTransformOffset));
+
+  DALI_TEST_CHECK(callStack.FindMethodAndGetParameters(uniforms[1].name, params));
+  DALI_TEST_CHECK(gl.GetUniformValue<Vector2>(uniforms[1].name.c_str(), props.mTransformSize));
+
+  DALI_TEST_CHECK(callStack.FindMethodAndGetParameters(uniforms[2].name, params));
+  DALI_TEST_CHECK(gl.GetUniformValue<Vector2>(uniforms[2].name.c_str(), props.mTransformOrigin));
+
+  DALI_TEST_CHECK(callStack.FindMethodAndGetParameters(uniforms[3].name, params));
+  DALI_TEST_CHECK(gl.GetUniformValue<Vector2>(uniforms[3].name.c_str(), props.mTransformAnchorPoint));
+
+  DALI_TEST_CHECK(callStack.FindMethodAndGetParameters(uniforms[4].name, params));
+  DALI_TEST_CHECK(gl.GetUniformValue<Vector4>(uniforms[4].name.c_str(), props.mTransformOffsetSizeMode));
+
+  DALI_TEST_CHECK(callStack.FindMethodAndGetParameters(uniforms[5].name, params));
+  DALI_TEST_CHECK(gl.GetUniformValue<Vector2>(uniforms[5].name.c_str(), props.mExtraSize));
+
+  DALI_TEST_CHECK(callStack.FindMethodAndGetParameters(uniforms[6].name, params));
+  DALI_TEST_CHECK(gl.GetUniformValue<Vector3>(uniforms[6].name.c_str(), props.mMixColor));
+}
+
+int UtcDaliVisualRendererAnimatedProperty03(void)
+{
+  TestApplication    application;
+  TestGlAbstraction& gl        = application.GetGlAbstraction();
+  TraceCallStack&    callStack = gl.GetSetUniformTrace();
+  gl.EnableSetUniformCallTrace(true);
+
+  tet_infoline("Test that a visual renderer property can be animated and that the uniforms are set");
+
+  std::vector<UniformData> customUniforms{{"offset", Property::VECTOR2},
+                                          {"size", Property::VECTOR2},
+                                          {"origin", Property::VECTOR2},
+                                          {"anchorPoint", Property::VECTOR2},
+                                          {"offsetSizeMode", Property::VECTOR4},
+                                          {"extraSize", Property::VECTOR2},
+                                          {"mixColor", Property::VECTOR3}};
+
+  application.GetGraphicsController().AddCustomUniforms(customUniforms);
+
+  Shader         shader   = Shader::New("VertexSource", "FragmentSource");
+  Geometry       geometry = CreateQuadGeometry();
+  VisualRenderer renderer = VisualRenderer::New(geometry, shader);
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetProperty(Actor::Property::SIZE, Vector2(400.0f, 400.0f));
+  application.GetScene().Add(actor);
+
+  VisualProperties props{Vector2(10.f, 10.f), Vector2(200.f, 100.f), Vector2(0.5f, 0.5f), Vector2(0.5f, 0.5f), Vector4::ZERO, Vector2(0.0f, 0.0f), Vector3(Color::SEA_GREEN)};
+  VisualProperties targetProps{Vector2(40.f, 40.f), Vector2(100.f, 200.f), Vector2(0.5f, 0.5f), Vector2(0.5f, 0.5f), Vector4::ZERO, Vector2(25.0f, 25.0f), Vector3(Color::MEDIUM_PURPLE)};
+
+  SetVisualProperties(renderer, props);
+  CheckEventVisualProperties(renderer, props);
+  application.SendNotification();
+  application.Render(0);
+  CheckSceneGraphVisualProperties(renderer, props);
+  CheckUniforms(renderer, props, customUniforms, callStack, gl);
+
+  // Set up a 1 second anim.
+  Animation animation = Animation::New(1.0f);
+
+  animation.AnimateTo(Property(renderer, VisualRenderer::Property::TRANSFORM_OFFSET), targetProps.mTransformOffset);
+  animation.AnimateTo(Property(renderer, VisualRenderer::Property::TRANSFORM_SIZE), targetProps.mTransformSize);
+  animation.AnimateTo(Property(renderer, VisualRenderer::Property::EXTRA_SIZE), targetProps.mExtraSize);
+  animation.AnimateTo(Property(renderer, VisualRenderer::Property::VISUAL_MIX_COLOR), targetProps.mMixColor);
+  animation.Play();
+
+  CheckEventVisualProperties(renderer, targetProps);
+
+  for(int i = 0; i <= 10; ++i)
+  {
+    tet_printf("\n###########  Animation progress: %d%%\n\n", i * 10);
+    VisualProperties propsProgress = VisualProperties::GetPropsAt(0.1f * i, props, targetProps);
+    PrintVisualProperties(propsProgress, "Expected values");
+
+    callStack.Reset();
+    application.SendNotification();
+    application.Render((i == 0 ? 0 : 100));
+
+    CheckEventVisualProperties(renderer, targetProps);
+
+    CheckSceneGraphVisualProperties(renderer, propsProgress);
+    CheckUniforms(renderer, propsProgress, customUniforms, callStack, gl);
+  }
+
+  // Ensure animation finishes
+  application.SendNotification();
+  application.Render(100);
+  CheckSceneGraphVisualProperties(renderer, targetProps);
+  CheckUniforms(renderer, targetProps, customUniforms, callStack, gl);
+
+  END_TEST;
+}
+
+int UtcDaliVisualRendererAnimatedProperty04(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that a visual renderer property can't be animated");
+
+  Shader         shader   = Shader::New("VertexSource", "FragmentSource");
+  Geometry       geometry = CreateQuadGeometry();
+  VisualRenderer renderer = VisualRenderer::New(geometry, shader);
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetProperty(Actor::Property::SIZE, Vector2(400.0f, 400.0f));
+  application.GetScene().Add(actor);
+
+  Property::Index index = VisualRenderer::Property::TRANSFORM_ANCHOR_POINT;
+  renderer.SetProperty(index, Vector2(AnchorPoint::TOP_RIGHT));
+
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS(renderer.GetProperty<Vector2>(index), Vector2(AnchorPoint::TOP_RIGHT), 0.001f, TEST_LOCATION);
+
+  Animation animation = Animation::New(1.0f);
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, Vector2::ZERO);
+  keyFrames.Add(1.0f, Vector2(10.0f, 10.0f));
+  try
+  {
+    animation.AnimateBetween(Property(renderer, index), keyFrames);
+    tet_result(TET_FAIL);
+  }
+  catch(DaliException& e)
+  {
+    DALI_TEST_ASSERT(e, "baseProperty && \"Property is not animatable\"", TEST_LOCATION);
+  }
+
+  END_TEST;
+}
+
+int UtcDaliVisualRendererAnimatedProperty05(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that a visual renderer property can't be animated");
+
+  Shader         shader   = Shader::New("VertexSource", "FragmentSource");
+  Geometry       geometry = CreateQuadGeometry();
+  VisualRenderer renderer = VisualRenderer::New(geometry, shader);
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetProperty(Actor::Property::SIZE, Vector2(400.0f, 400.0f));
+  application.GetScene().Add(actor);
+
+  Property::Index index = VisualRenderer::Property::VISUAL_PRE_MULTIPLIED_ALPHA;
+  renderer.SetProperty(index, 1.0f);
+
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS(renderer.GetProperty<float>(index), 1.0f, 0.001f, TEST_LOCATION);
+
+  Animation animation = Animation::New(1.0f);
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, 0.5f);
+  keyFrames.Add(1.0f, 1.0f);
+  try
+  {
+    animation.AnimateBetween(Property(renderer, index), keyFrames);
+    tet_result(TET_FAIL);
+  }
+  catch(DaliException& e)
+  {
+    DALI_TEST_ASSERT(e, "baseProperty && \"Property is not animatable\"", TEST_LOCATION);
+  }
+
+  DALI_TEST_EQUALS(renderer.GetProperty<float>(index), 1.0f, 0.0001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(renderer.GetCurrentProperty<float>(index), 1.0f, 0.0001f, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliVisualRendererAnimatedProperty06(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that a parent renderer property can still be animated");
+
+  Shader         shader   = Shader::New("VertexSource", "FragmentSource");
+  Geometry       geometry = CreateQuadGeometry();
+  VisualRenderer renderer = VisualRenderer::New(geometry, shader);
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetProperty(Actor::Property::SIZE, Vector2(400.0f, 400.0f));
+  application.GetScene().Add(actor);
+
+  Property::Index index = DevelRenderer::Property::OPACITY;
+  renderer.SetProperty(index, 1.0f);
+
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS(renderer.GetProperty<float>(index), 1.0f, 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(renderer.GetCurrentProperty<float>(DevelRenderer::Property::OPACITY), 1.0f, 0.0001f, TEST_LOCATION);
+
+  Animation animation = Animation::New(1.0f);
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, float(0.5f));
+  keyFrames.Add(1.0f, float(0.0f));
+  animation.AnimateBetween(Property(renderer, index), keyFrames);
+  animation.Play();
+
+  application.SendNotification();
+
+  // Test that the event side properties are set to target value of 0
+  DALI_TEST_EQUALS(renderer.GetProperty<float>(DevelRenderer::Property::OPACITY), 0.0f, 0.0001f, TEST_LOCATION);
+
+  application.Render(500);
+
+  DALI_TEST_EQUALS(renderer.GetCurrentProperty<float>(index), 0.25f, 0.0001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(renderer.GetCurrentProperty<float>(DevelRenderer::Property::OPACITY), 0.25f, 0.0001f, TEST_LOCATION);
+
+  // Test that the event side properties are set to target value 0f 0
+  DALI_TEST_EQUALS(renderer.GetProperty<float>(DevelRenderer::Property::OPACITY), 0.0f, 0.0001f, TEST_LOCATION);
+
+  // Complete the animation
+  application.Render(500);
+
+  DALI_TEST_EQUALS(renderer.GetCurrentProperty<float>(index), 0.0f, 0.0001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(renderer.GetCurrentProperty<float>(DevelRenderer::Property::OPACITY), 0.0f, 0.0001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(renderer.GetProperty<float>(DevelRenderer::Property::OPACITY), 0.0f, 0.0001f, TEST_LOCATION);
+  END_TEST;
+}
index 4342d90..fc9b85a 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.
@@ -763,6 +763,23 @@ const PropertyInputImpl* Renderer::GetSceneObjectInputProperty(Property::Index i
   return GetSceneObjectAnimatableProperty(index);
 }
 
+void Renderer::AddDrawCommand(const Dali::DevelRenderer::DrawCommand& command)
+{
+  if(!mDrawCommands.capacity())
+  {
+    mDrawCommands.reserve(8);
+  }
+
+  mDrawCommands.emplace_back(command);
+
+  Dali::Internal::SceneGraph::SetDrawCommandsMessage(GetEventThreadServices(),
+                                                     GetRendererSceneObject(),
+                                                     mDrawCommands.data(),
+                                                     uint32_t(mDrawCommands.size())
+
+  );
+}
+
 Renderer::Renderer(const SceneGraph::Renderer* sceneObject)
 : Object(sceneObject),
   mDepthIndex(0),
@@ -781,22 +798,6 @@ Renderer::Renderer(const SceneGraph::Renderer* sceneObject)
 {
 }
 
-void Renderer::SetBlendColor(const Vector4& blendColor)
-{
-  mBlendingOptions.SetBlendColor(blendColor);
-  SetBlendColorMessage(GetEventThreadServices(), GetRendererSceneObject(), GetBlendColor());
-}
-
-const Vector4& Renderer::GetBlendColor() const
-{
-  const Vector4* blendColor = mBlendingOptions.GetBlendColor();
-  if(blendColor)
-  {
-    return *blendColor;
-  }
-  return Color::TRANSPARENT; // GL default
-}
-
 Renderer::~Renderer()
 {
   if(EventThreadServices::IsCoreRunning())
@@ -1163,21 +1164,20 @@ bool Renderer::GetCurrentPropertyValue(Property::Index index, Property::Value& v
   return valueSet;
 }
 
-void Renderer::AddDrawCommand(const Dali::DevelRenderer::DrawCommand& command)
+void Renderer::SetBlendColor(const Vector4& blendColor)
 {
-  if(!mDrawCommands.capacity())
+  mBlendingOptions.SetBlendColor(blendColor);
+  SetBlendColorMessage(GetEventThreadServices(), GetRendererSceneObject(), GetBlendColor());
+}
+
+const Vector4& Renderer::GetBlendColor() const
+{
+  const Vector4* blendColor = mBlendingOptions.GetBlendColor();
+  if(blendColor)
   {
-    mDrawCommands.reserve(8);
+    return *blendColor;
   }
-
-  mDrawCommands.emplace_back(command);
-
-  Dali::Internal::SceneGraph::SetDrawCommandsMessage(GetEventThreadServices(),
-                                                     GetRendererSceneObject(),
-                                                     mDrawCommands.data(),
-                                                     uint32_t(mDrawCommands.size())
-
-  );
+  return Color::TRANSPARENT; // GL default
 }
 
 } // namespace Internal
index ad5ff55..17818ab 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_RENDERER_H
 
 /*
- * 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.
@@ -211,7 +211,7 @@ public: // Default property extensions from Object
    */
   void AddDrawCommand(const Dali::DevelRenderer::DrawCommand& command);
 
-private: // implementation
+protected: // implementation
   /**
    * @brief Constructor.
    *
@@ -220,16 +220,13 @@ private: // implementation
   Renderer(const SceneGraph::Renderer* sceneObject);
 
   /**
-   * @brief Sets the blend color.
-   * @param[in] blendColor The blend color to set.
+   * A reference counted object may only be deleted by calling Unreference()
    */
-  void SetBlendColor(const Vector4& blendColor);
+  ~Renderer() override;
 
-  /**
-   * @brief Retrieves the blend-color.
-   * @return A const reference to the blend-color
-   */
-  const Vector4& GetBlendColor() const;
+private:
+  Renderer(const Renderer&) = delete;            ///< Deleted copy constructor
+  Renderer& operator=(const Renderer&) = delete; ///< Deleted assignment operator
 
   /**
    * @brief Retrieves the cached event side value of a default property.
@@ -247,17 +244,19 @@ private: // implementation
    */
   bool GetCurrentPropertyValue(Property::Index index, Property::Value& value) const;
 
-protected:
   /**
-   * A reference counted object may only be deleted by calling Unreference()
+   * @brief Sets the blend color.
+   * @param[in] blendColor The blend color to set.
    */
-  ~Renderer() override;
+  void SetBlendColor(const Vector4& blendColor);
 
-private: // unimplemented methods
-  Renderer(const Renderer&);
-  Renderer& operator=(const Renderer&);
+  /**
+   * @brief Retrieves the blend-color.
+   * @return A const reference to the blend-color
+   */
+  const Vector4& GetBlendColor() const;
 
-private:                     // data
+protected:
   GeometryPtr   mGeometry;   ///< Intrusive pointer to the geometry used by this renderer
   TextureSetPtr mTextureSet; ///< Intrusive pointer to the texture set used by this renderer
   ShaderPtr     mShader;     ///< Intrusive pointer to the shader used by this renderer
@@ -279,6 +278,7 @@ private:                     // data
   DevelRenderer::Rendering::Type mRenderingBehavior : 2;        ///< The rendering behavior
   bool                           mPremultipledAlphaEnabled : 1; ///< Flag indicating whether the Pre-multiplied Alpha Blending is required
 
+private:
   std::vector<Dali::DevelRenderer::DrawCommand> mDrawCommands; ///< list of draw commands
 };
 
diff --git a/dali/internal/event/rendering/visual-renderer-impl.cpp b/dali/internal/event/rendering/visual-renderer-impl.cpp
new file mode 100644 (file)
index 0000000..c90448c
--- /dev/null
@@ -0,0 +1,574 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/rendering/visual-renderer-impl.h>
+
+// INTERNAL INCLUDES
+#include <dali/devel-api/rendering/renderer-devel.h>
+#include <dali/devel-api/scripting/scripting.h>
+#include <dali/internal/event/common/property-helper.h> // DALI_PROPERTY_TABLE_BEGIN, DALI_PROPERTY, DALI_PROPERTY_TABLE_END
+#include <dali/internal/event/common/property-input-impl.h>
+#include <dali/internal/update/manager/update-manager.h>
+#include <dali/internal/update/rendering/scene-graph-renderer.h>
+#include <dali/public-api/object/type-registry.h>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace
+{
+/**
+ * Properties: |name                              |type     |writable|animatable|constraint-input|enum for index-checking|
+ */
+DALI_PROPERTY_TABLE_BEGIN
+DALI_PROPERTY("transformOffset", VECTOR2, true, true, true, Dali::VisualRenderer::Property::TRANSFORM_OFFSET)
+DALI_PROPERTY("transformSize", VECTOR2, true, true, true, Dali::VisualRenderer::Property::TRANSFORM_SIZE)
+DALI_PROPERTY("transformOrigin", VECTOR2, true, false, false, Dali::VisualRenderer::Property::TRANSFORM_ORIGIN)
+DALI_PROPERTY("transformAnchorPoint", VECTOR2, true, false, false, Dali::VisualRenderer::Property::TRANSFORM_ANCHOR_POINT)
+DALI_PROPERTY("transformOffsetSizeMode", VECTOR4, true, false, false, Dali::VisualRenderer::Property::TRANSFORM_OFFSET_SIZE_MODE)
+DALI_PROPERTY("extraSize", VECTOR2, true, true, true, Dali::VisualRenderer::Property::EXTRA_SIZE)
+DALI_PROPERTY("visualMixColor", VECTOR3, true, true, true, Dali::VisualRenderer::Property::VISUAL_MIX_COLOR)
+DALI_PROPERTY("preMultipliedAlpha", FLOAT, true, false, false, Dali::VisualRenderer::Property::VISUAL_PRE_MULTIPLIED_ALPHA)
+DALI_PROPERTY_TABLE_END(Dali::VisualRenderer::Property::DEFAULT_VISUAL_RENDERER_PROPERTY_START_INDEX, VisualRendererDefaultProperties)
+
+// Property string to enumeration tables:
+
+DALI_ENUM_TO_STRING_TABLE_BEGIN(TRANSFORM_POLICY)
+  DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::VisualRenderer::TransformPolicy::Type, RELATIVE)
+  DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::VisualRenderer::TransformPolicy::Type, ABSOLUTE)
+DALI_ENUM_TO_STRING_TABLE_END(TRANSFORM_POLICY)
+
+BaseHandle Create()
+{
+  return Dali::BaseHandle();
+}
+
+TypeRegistration mType(typeid(Dali::VisualRenderer), typeid(Dali::Renderer), Create, VisualRendererDefaultProperties);
+
+} // unnamed namespace
+
+VisualRendererPtr VisualRenderer::New()
+{
+  // create scene object first so it's guaranteed to exist for the event side
+  auto sceneObject = SceneGraph::Renderer::New();
+
+  sceneObject->SetVisualProperties(new AnimatableVisualProperties());
+
+  OwnerPointer<SceneGraph::Renderer> transferOwnership(sceneObject);
+  // pass the pointer to base for message passing
+  VisualRendererPtr rendererPtr(new VisualRenderer(sceneObject));
+
+  rendererPtr->AddUniformMappings(); // Ensure properties are mapped to uniforms
+
+  // transfer scene object ownership to update manager
+  EventThreadServices&       eventThreadServices = rendererPtr->GetEventThreadServices();
+  SceneGraph::UpdateManager& updateManager       = eventThreadServices.GetUpdateManager();
+  AddRendererMessage(updateManager, transferOwnership);
+
+  eventThreadServices.RegisterObject(rendererPtr.Get());
+  return rendererPtr;
+}
+
+VisualRenderer::VisualRenderer(const SceneGraph::Renderer* sceneObject)
+: Renderer(sceneObject)
+{
+}
+
+VisualRenderer::~VisualRenderer()
+{
+  if(EventThreadServices::IsCoreRunning())
+  {
+    EventThreadServices&       eventThreadServices = GetEventThreadServices();
+    SceneGraph::UpdateManager& updateManager       = eventThreadServices.GetUpdateManager();
+    RemoveRendererMessage(updateManager, GetVisualRendererSceneObject());
+
+    eventThreadServices.UnregisterObject(this);
+  }
+}
+
+const SceneGraph::Renderer& VisualRenderer::GetVisualRendererSceneObject() const
+{
+  return static_cast<const SceneGraph::Renderer&>(GetSceneObject());
+}
+
+void VisualRenderer::SetDefaultProperty(Property::Index        index,
+                                        const Property::Value& propertyValue)
+{
+  if(index < Dali::VisualRenderer::Property::DEFAULT_VISUAL_RENDERER_PROPERTY_START_INDEX)
+  {
+    Renderer::SetDefaultProperty(index, propertyValue);
+  }
+  else
+  {
+    switch(index)
+    {
+      case Dali::VisualRenderer::Property::TRANSFORM_OFFSET:
+      {
+        if(propertyValue.Get(mPropertyCache.mTransformOffset))
+        {
+          const SceneGraph::Renderer& sceneObject      = GetVisualRendererSceneObject();
+          auto                        visualProperties = sceneObject.GetVisualProperties();
+
+          if(visualProperties)
+          {
+            BakeMessage<Vector2>(GetEventThreadServices(), visualProperties->mTransformOffset, mPropertyCache.mTransformOffset);
+          }
+        }
+        break;
+      }
+
+      case Dali::VisualRenderer::Property::TRANSFORM_SIZE:
+      {
+        if(propertyValue.Get(mPropertyCache.mTransformSize))
+        {
+          const SceneGraph::Renderer& sceneObject      = GetVisualRendererSceneObject();
+          auto                        visualProperties = sceneObject.GetVisualProperties();
+          if(visualProperties)
+          {
+            BakeMessage<Vector2>(GetEventThreadServices(), visualProperties->mTransformSize, mPropertyCache.mTransformSize);
+          }
+        }
+        break;
+      }
+      case Dali::VisualRenderer::Property::TRANSFORM_ORIGIN:
+      {
+        if(propertyValue.Get(mPropertyCache.mTransformOrigin))
+        {
+          const SceneGraph::Renderer& sceneObject      = GetVisualRendererSceneObject();
+          auto                        visualProperties = sceneObject.GetVisualProperties();
+          if(visualProperties)
+          {
+            BakeMessage<Vector2>(GetEventThreadServices(), visualProperties->mTransformOrigin, mPropertyCache.mTransformOrigin);
+          }
+        }
+        break;
+      }
+      case Dali::VisualRenderer::Property::TRANSFORM_ANCHOR_POINT:
+      {
+        if(propertyValue.Get(mPropertyCache.mTransformAnchorPoint))
+        {
+          const SceneGraph::Renderer& sceneObject      = GetVisualRendererSceneObject();
+          auto                        visualProperties = sceneObject.GetVisualProperties();
+          if(visualProperties)
+          {
+            BakeMessage<Vector2>(GetEventThreadServices(), visualProperties->mTransformAnchorPoint, mPropertyCache.mTransformAnchorPoint);
+          }
+        }
+        break;
+      }
+      case Dali::VisualRenderer::Property::TRANSFORM_OFFSET_SIZE_MODE:
+      {
+        if(propertyValue.Get(mPropertyCache.mTransformOffsetSizeMode))
+        {
+          const SceneGraph::Renderer& sceneObject      = GetVisualRendererSceneObject();
+          auto                        visualProperties = sceneObject.GetVisualProperties();
+          if(visualProperties)
+          {
+            BakeMessage<Vector4>(GetEventThreadServices(), visualProperties->mTransformOffsetSizeMode, mPropertyCache.mTransformOffsetSizeMode);
+          }
+        }
+        break;
+      }
+      case Dali::VisualRenderer::Property::EXTRA_SIZE:
+      {
+        if(propertyValue.Get(mPropertyCache.mExtraSize))
+        {
+          const SceneGraph::Renderer& sceneObject      = GetVisualRendererSceneObject();
+          auto                        visualProperties = sceneObject.GetVisualProperties();
+          if(visualProperties)
+          {
+            BakeMessage<Vector2>(GetEventThreadServices(), visualProperties->mExtraSize, mPropertyCache.mExtraSize);
+          }
+        }
+        break;
+      }
+      case Dali::VisualRenderer::Property::VISUAL_MIX_COLOR:
+      {
+        if(propertyValue.Get(mPropertyCache.mMixColor))
+        {
+          const SceneGraph::Renderer& sceneObject      = GetVisualRendererSceneObject();
+          auto                        visualProperties = sceneObject.GetVisualProperties();
+          if(visualProperties)
+          {
+            BakeMessage<Vector3>(GetEventThreadServices(), visualProperties->mMixColor, mPropertyCache.mMixColor);
+          }
+        }
+        break;
+      }
+      case Dali::VisualRenderer::Property::VISUAL_PRE_MULTIPLIED_ALPHA:
+      {
+        float preMultipliedAlpha;
+        if(propertyValue.Get(preMultipliedAlpha))
+        {
+          if(!Equals(mPropertyCache.mPreMultipliedAlpha, preMultipliedAlpha))
+          {
+            const SceneGraph::Renderer& sceneObject      = GetVisualRendererSceneObject();
+            auto                        visualProperties = sceneObject.GetVisualProperties();
+            if(visualProperties)
+            {
+              mPropertyCache.mPreMultipliedAlpha = preMultipliedAlpha;
+              BakeMessage<float>(GetEventThreadServices(), visualProperties->mPreMultipliedAlpha, preMultipliedAlpha);
+            }
+          }
+        }
+        break;
+      }
+    }
+  }
+}
+
+Property::Value VisualRenderer::GetDefaultProperty(Property::Index index) const
+{
+  Property::Value value;
+
+  if(index < Dali::VisualRenderer::Property::DEFAULT_VISUAL_RENDERER_PROPERTY_START_INDEX)
+  {
+    value = Renderer::GetDefaultProperty(index);
+  }
+  else
+  {
+    switch(index)
+    {
+      case Dali::VisualRenderer::Property::TRANSFORM_OFFSET:
+      {
+        value = mPropertyCache.mTransformOffset;
+        break;
+      }
+      case Dali::VisualRenderer::Property::TRANSFORM_SIZE:
+      {
+        value = mPropertyCache.mTransformSize;
+        break;
+      }
+      case Dali::VisualRenderer::Property::TRANSFORM_ORIGIN:
+      {
+        value = mPropertyCache.mTransformOrigin;
+        break;
+      }
+      case Dali::VisualRenderer::Property::TRANSFORM_ANCHOR_POINT:
+      {
+        value = mPropertyCache.mTransformAnchorPoint;
+        break;
+      }
+      case Dali::VisualRenderer::Property::TRANSFORM_OFFSET_SIZE_MODE:
+      {
+        value = mPropertyCache.mTransformOffsetSizeMode;
+        break;
+      }
+      case Dali::VisualRenderer::Property::EXTRA_SIZE:
+      {
+        value = mPropertyCache.mExtraSize;
+        break;
+      }
+      case Dali::VisualRenderer::Property::VISUAL_MIX_COLOR:
+      {
+        value = mPropertyCache.mMixColor;
+        break;
+      }
+      case Dali::VisualRenderer::Property::VISUAL_PRE_MULTIPLIED_ALPHA:
+      {
+        value = mPropertyCache.mPreMultipliedAlpha;
+        break;
+      }
+      default:
+      {
+        break;
+      }
+    }
+  }
+
+  return value;
+}
+
+Property::Value VisualRenderer::GetDefaultPropertyCurrentValue(Property::Index index) const
+{
+  Property::Value value;
+
+  if(index < Dali::VisualRenderer::Property::DEFAULT_VISUAL_RENDERER_PROPERTY_START_INDEX)
+  {
+    value = Renderer::GetDefaultPropertyCurrentValue(index);
+  }
+  else
+  {
+    const SceneGraph::Renderer& sceneObject = GetVisualRendererSceneObject();
+
+    switch(index)
+    {
+      case Dali::VisualRenderer::Property::TRANSFORM_OFFSET:
+      {
+        auto visualProperties = sceneObject.GetVisualProperties();
+        if(visualProperties)
+        {
+          value = visualProperties->mTransformOffset[GetEventThreadServices().GetEventBufferIndex()];
+        }
+        break;
+      }
+      case Dali::VisualRenderer::Property::TRANSFORM_SIZE:
+      {
+        auto visualProperties = sceneObject.GetVisualProperties();
+        if(visualProperties)
+        {
+          value = visualProperties->mTransformSize[GetEventThreadServices().GetEventBufferIndex()];
+        }
+        break;
+      }
+      case Dali::VisualRenderer::Property::TRANSFORM_ORIGIN:
+      {
+        auto visualProperties = sceneObject.GetVisualProperties();
+        if(visualProperties)
+        {
+          value = visualProperties->mTransformOrigin[GetEventThreadServices().GetEventBufferIndex()];
+        }
+        break;
+      }
+      case Dali::VisualRenderer::Property::TRANSFORM_ANCHOR_POINT:
+      {
+        auto visualProperties = sceneObject.GetVisualProperties();
+        if(visualProperties)
+        {
+          value = visualProperties->mTransformAnchorPoint[GetEventThreadServices().GetEventBufferIndex()];
+        }
+        break;
+      }
+      case Dali::VisualRenderer::Property::TRANSFORM_OFFSET_SIZE_MODE:
+      {
+        auto visualProperties = sceneObject.GetVisualProperties();
+        if(visualProperties)
+        {
+          value = visualProperties->mTransformOffsetSizeMode[GetEventThreadServices().GetEventBufferIndex()];
+        }
+        break;
+      }
+      case Dali::VisualRenderer::Property::EXTRA_SIZE:
+      {
+        auto visualProperties = sceneObject.GetVisualProperties();
+        if(visualProperties)
+        {
+          value = visualProperties->mExtraSize[GetEventThreadServices().GetEventBufferIndex()];
+        }
+        break;
+      }
+      case Dali::VisualRenderer::Property::VISUAL_MIX_COLOR:
+      {
+        auto visualProperties = sceneObject.GetVisualProperties();
+        if(visualProperties)
+        {
+          value = visualProperties->mMixColor[GetEventThreadServices().GetEventBufferIndex()];
+        }
+        break;
+      }
+      case Dali::VisualRenderer::Property::VISUAL_PRE_MULTIPLIED_ALPHA:
+      {
+        auto visualProperties = sceneObject.GetVisualProperties();
+        if(visualProperties)
+        {
+          value = visualProperties->mPreMultipliedAlpha[GetEventThreadServices().GetEventBufferIndex()];
+        }
+        break;
+      }
+    }
+  }
+  return value;
+}
+
+void VisualRenderer::OnNotifyDefaultPropertyAnimation(Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType)
+{
+  if(index < Dali::VisualRenderer::Property::DEFAULT_VISUAL_RENDERER_PROPERTY_START_INDEX)
+  {
+    Renderer::OnNotifyDefaultPropertyAnimation(animation, index, value, animationType);
+  }
+  else
+  {
+    switch(animationType)
+    {
+      case Animation::TO:
+      case Animation::BETWEEN:
+      {
+        switch(index)
+        {
+          case Dali::VisualRenderer::Property::TRANSFORM_OFFSET:
+          {
+            value.Get(mPropertyCache.mTransformOffset);
+            break;
+          }
+          case Dali::VisualRenderer::Property::TRANSFORM_SIZE:
+          {
+            value.Get(mPropertyCache.mTransformSize);
+            break;
+          }
+          case Dali::VisualRenderer::Property::EXTRA_SIZE:
+          {
+            value.Get(mPropertyCache.mExtraSize);
+            break;
+          }
+          case Dali::VisualRenderer::Property::VISUAL_MIX_COLOR:
+          {
+            value.Get(mPropertyCache.mMixColor);
+            break;
+          }
+        }
+        break;
+      }
+
+      case Animation::BY:
+      {
+        switch(index)
+        {
+          case Dali::VisualRenderer::Property::TRANSFORM_OFFSET:
+          {
+            AdjustValue<Vector2>(mPropertyCache.mTransformOffset, value);
+            break;
+          }
+          case Dali::VisualRenderer::Property::TRANSFORM_SIZE:
+          {
+            AdjustValue<Vector2>(mPropertyCache.mTransformSize, value);
+            break;
+          }
+          case Dali::VisualRenderer::Property::EXTRA_SIZE:
+          {
+            AdjustValue<Vector2>(mPropertyCache.mExtraSize, value);
+            break;
+          }
+          case Dali::VisualRenderer::Property::VISUAL_MIX_COLOR:
+          {
+            AdjustValue<Vector3>(mPropertyCache.mMixColor, value);
+            break;
+          }
+        }
+        break;
+      }
+    }
+  }
+}
+
+const SceneGraph::PropertyBase* VisualRenderer::GetSceneObjectAnimatableProperty(Property::Index index) const
+{
+  const SceneGraph::PropertyBase* property = nullptr;
+
+  switch(index)
+  {
+    case Dali::VisualRenderer::Property::TRANSFORM_OFFSET:
+    {
+      auto visualProperties = GetVisualRendererSceneObject().GetVisualProperties();
+      if(visualProperties)
+      {
+        property = &visualProperties->mTransformOffset;
+      }
+      break;
+    }
+    case Dali::VisualRenderer::Property::TRANSFORM_SIZE:
+    {
+      auto visualProperties = GetVisualRendererSceneObject().GetVisualProperties();
+      if(visualProperties)
+      {
+        property = &visualProperties->mTransformSize;
+      }
+      break;
+    }
+    case Dali::VisualRenderer::Property::EXTRA_SIZE:
+    {
+      auto visualProperties = GetVisualRendererSceneObject().GetVisualProperties();
+      if(visualProperties)
+      {
+        property = &visualProperties->mExtraSize;
+      }
+      break;
+    }
+    case Dali::VisualRenderer::Property::VISUAL_MIX_COLOR:
+    {
+      auto visualProperties = GetVisualRendererSceneObject().GetVisualProperties();
+      if(visualProperties)
+      {
+        property = &visualProperties->mMixColor;
+      }
+      break;
+    }
+  }
+
+  if(!property)
+  {
+    // not our property, ask base
+    property = Renderer::GetSceneObjectAnimatableProperty(index);
+  }
+
+  return property;
+}
+
+const PropertyInputImpl* VisualRenderer::GetSceneObjectInputProperty(Property::Index index) const
+{
+  switch(index)
+  {
+    case Dali::VisualRenderer::Property::TRANSFORM_ORIGIN:
+    {
+      auto visualProperties = GetVisualRendererSceneObject().GetVisualProperties();
+      if(visualProperties)
+      {
+        return &visualProperties->mTransformOrigin;
+      }
+      break;
+    }
+    case Dali::VisualRenderer::Property::TRANSFORM_ANCHOR_POINT:
+    {
+      auto visualProperties = GetVisualRendererSceneObject().GetVisualProperties();
+      if(visualProperties)
+      {
+        return &visualProperties->mTransformAnchorPoint;
+      }
+      break;
+    }
+    case Dali::VisualRenderer::Property::TRANSFORM_OFFSET_SIZE_MODE:
+    {
+      auto visualProperties = GetVisualRendererSceneObject().GetVisualProperties();
+      if(visualProperties)
+      {
+        return &visualProperties->mTransformOffsetSizeMode;
+      }
+      break;
+    }
+    case Dali::VisualRenderer::Property::VISUAL_PRE_MULTIPLIED_ALPHA:
+    {
+      auto visualProperties = GetVisualRendererSceneObject().GetVisualProperties();
+      if(visualProperties)
+      {
+        return &visualProperties->mPreMultipliedAlpha;
+      }
+      break;
+    }
+    default:
+    {
+      return GetSceneObjectAnimatableProperty(index);
+    }
+  }
+  return nullptr;
+}
+
+void VisualRenderer::AddUniformMappings()
+{
+  AddUniformMapping(Dali::VisualRenderer::Property::TRANSFORM_OFFSET, ConstString("offset"));
+  AddUniformMapping(Dali::VisualRenderer::Property::TRANSFORM_SIZE, ConstString("size"));
+  AddUniformMapping(Dali::VisualRenderer::Property::TRANSFORM_OFFSET_SIZE_MODE, ConstString("offsetSizeMode"));
+  AddUniformMapping(Dali::VisualRenderer::Property::TRANSFORM_ORIGIN, ConstString("origin"));
+  AddUniformMapping(Dali::VisualRenderer::Property::TRANSFORM_ANCHOR_POINT, ConstString("anchorPoint"));
+  AddUniformMapping(Dali::VisualRenderer::Property::EXTRA_SIZE, ConstString("extraSize"));
+  AddUniformMapping(Dali::VisualRenderer::Property::VISUAL_MIX_COLOR, ConstString("mixColor"));
+  AddUniformMapping(Dali::VisualRenderer::Property::VISUAL_PRE_MULTIPLIED_ALPHA, ConstString("preMultipliedAlpha"));
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/rendering/visual-renderer-impl.h b/dali/internal/event/rendering/visual-renderer-impl.h
new file mode 100644 (file)
index 0000000..996ce11
--- /dev/null
@@ -0,0 +1,183 @@
+#ifndef DALI_INTERNAL_VISUAL_RENDERER_H
+#define DALI_INTERNAL_VISUAL_RENDERER_H
+
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/rendering/renderer-impl.h> // Dali::Internal::Renderer
+#include <dali/internal/update/common/animatable-property.h>
+#include <dali/public-api/rendering/visual-renderer.h> // Dali::VisualRenderer
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+class Renderer;
+}
+
+class VisualRenderer;
+using VisualRendererPtr = IntrusivePtr<VisualRenderer>;
+
+/**
+ * VisualRenderer is a Renderer that has additional default properties for toolkit
+ */
+class VisualRenderer : public Renderer
+{
+public:
+  /**
+   * Create a new VisualRenderer.
+   * @return A smart-pointer to the newly allocated VisualRenderer.
+   */
+  static VisualRendererPtr New();
+
+  /**
+   * @brief Get the scene graph object
+   *
+   * @return the scene object
+   */
+  const SceneGraph::Renderer& GetVisualRendererSceneObject() const;
+
+public: // Default property extensions from Object
+  /**
+   * @copydoc Dali::Internal::Object::SetDefaultProperty()
+   */
+  void SetDefaultProperty(Property::Index index, const Property::Value& propertyValue) override;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultProperty()
+   */
+  Property::Value GetDefaultProperty(Property::Index index) const override;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyCurrentValue()
+   */
+  Property::Value GetDefaultPropertyCurrentValue(Property::Index index) const override;
+
+  /**
+    * @copydoc Dali::Internal::Object::OnNotifyDefaultPropertyAnimation()
+    */
+  void OnNotifyDefaultPropertyAnimation(Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType) override;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObjectAnimatableProperty()
+   */
+  const SceneGraph::PropertyBase* GetSceneObjectAnimatableProperty(Property::Index index) const override;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObjectInputProperty()
+   */
+  const PropertyInputImpl* GetSceneObjectInputProperty(Property::Index index) const override;
+
+private: // implementation
+  /**
+   * @brief Constructor.
+   *
+   * @param sceneObject the scene graph renderer
+   */
+  VisualRenderer(const SceneGraph::Renderer* sceneObject);
+
+  /**
+   * @brief Retrieves the current value of a default property from the scene-graph.
+   * @param[in]  index  The index of the property
+   * @param[out] value  Is set with the current scene-graph value of the property
+   * @return True if value set, false otherwise.
+   */
+  bool GetCurrentPropertyValue(Property::Index index, Property::Value& value) const;
+
+protected:
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  ~VisualRenderer() override;
+
+private:
+  VisualRenderer(const VisualRenderer&) = delete;
+  VisualRenderer& operator=(const VisualRenderer&) = delete;
+
+  /**
+   * @brief Ensure that properties are mapped to uniforms
+   */
+  void AddUniformMappings();
+
+public:
+  struct VisualPropertyCache
+  {
+    Vector2 mTransformOffset{Vector2::ZERO};
+    Vector2 mTransformSize{Vector2::ZERO};
+    Vector2 mTransformOrigin{Vector2::ZERO};
+    Vector2 mTransformAnchorPoint{Vector2::ZERO};
+    Vector4 mTransformOffsetSizeMode{Vector2::ZERO};
+    Vector2 mExtraSize{Vector2::ZERO};
+    Vector3 mMixColor{Vector3::ONE};
+    float   mPreMultipliedAlpha{0.0f};
+  };
+
+  struct AnimatableVisualProperties
+  {
+    AnimatableVisualProperties()
+    : mTransformOffset(Vector2::ZERO),
+      mTransformSize(Vector2::ZERO),
+      mTransformOrigin(Vector2::ZERO),
+      mTransformAnchorPoint(Vector2::ZERO),
+      mTransformOffsetSizeMode(Vector4::ZERO),
+      mExtraSize(Vector2::ZERO),
+      mMixColor(Vector3::ONE),
+      mPreMultipliedAlpha(0.0f)
+    {
+    }
+    SceneGraph::AnimatableProperty<Vector2> mTransformOffset;
+    SceneGraph::AnimatableProperty<Vector2> mTransformSize;
+    SceneGraph::AnimatableProperty<Vector2> mTransformOrigin;
+    SceneGraph::AnimatableProperty<Vector2> mTransformAnchorPoint;
+    SceneGraph::AnimatableProperty<Vector4> mTransformOffsetSizeMode;
+    SceneGraph::AnimatableProperty<Vector2> mExtraSize;
+    SceneGraph::AnimatableProperty<Vector3> mMixColor;
+    SceneGraph::AnimatableProperty<float>   mPreMultipliedAlpha;
+    void*                                   mExtendedProperties{nullptr}; // Enable derived class to extend properties further
+  };
+
+private:
+  VisualPropertyCache mPropertyCache;
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+inline Internal::VisualRenderer& GetImplementation(Dali::VisualRenderer& handle)
+{
+  DALI_ASSERT_ALWAYS(handle && "VisualRenderer handle is empty");
+
+  BaseObject& object = handle.GetBaseObject();
+
+  return static_cast<Internal::VisualRenderer&>(object);
+}
+
+inline const Internal::VisualRenderer& GetImplementation(const Dali::VisualRenderer& handle)
+{
+  DALI_ASSERT_ALWAYS(handle && "VisualRenderer handle is empty");
+
+  const BaseObject& object = handle.GetBaseObject();
+
+  return static_cast<const Internal::VisualRenderer&>(object);
+}
+
+} // namespace Dali
+
+#endif // DALI_INTERNAL_RENDERER_H
index bd014f7..73911cc 100644 (file)
@@ -95,6 +95,7 @@ SET( internal_src_files
   ${internal_src_dir}/event/rendering/texture-impl.cpp
   ${internal_src_dir}/event/rendering/texture-set-impl.cpp
   ${internal_src_dir}/event/rendering/renderer-impl.cpp
+  ${internal_src_dir}/event/rendering/visual-renderer-impl.cpp
   ${internal_src_dir}/event/rendering/sampler-impl.cpp
   ${internal_src_dir}/event/rendering/shader-impl.cpp
   ${internal_src_dir}/event/rendering/vertex-buffer-impl.cpp
index 7fc994f..d818dcd 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_SCENE_GRAPH_RENDERER_H
 
 /*
- * 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.
@@ -21,6 +21,7 @@
 #include <dali/internal/common/blending-options.h>
 #include <dali/internal/common/type-abstraction-enums.h>
 #include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/event/rendering/visual-renderer-impl.h>
 #include <dali/internal/render/data-providers/render-data-provider.h>
 #include <dali/internal/render/renderers/render-renderer.h>
 #include <dali/internal/update/common/animatable-property.h>
@@ -435,6 +436,23 @@ public: // From UniformMapDataProvider
 
   void SetDrawCommands(Dali::DevelRenderer::DrawCommand* pDrawCommands, uint32_t size);
 
+public: // For VisualProperties
+  /**
+   * To be used only for 1st stage initialization in event thread.
+   */
+  void SetVisualProperties(Internal::VisualRenderer::AnimatableVisualProperties* visualProperties)
+  {
+    mVisualProperties = visualProperties;
+  }
+
+  /**
+   * May be accessed from event thread
+   */
+  const Internal::VisualRenderer::AnimatableVisualProperties* GetVisualProperties() const
+  {
+    return mVisualProperties;
+  }
+
 private:
   /**
    * Protected constructor; See also Renderer::New()
@@ -444,12 +462,13 @@ private:
 private:
   CollectedUniformMap mCollectedUniformMap[2]; ///< Uniform maps collected by the renderer
 
-  SceneController*      mSceneController; ///< Used for initializing renderers
-  Render::Renderer*     mRenderer;        ///< Raw pointer to the renderer (that's owned by RenderManager)
-  TextureSet*           mTextureSet;      ///< The texture set this renderer uses. (Not owned)
-  Render::Geometry*     mGeometry;        ///< The geometry this renderer uses. (Not owned)
-  Shader*               mShader;          ///< The shader this renderer uses. (Not owned)
-  OwnerPointer<Vector4> mBlendColor;      ///< The blend color for blending operation
+  SceneController*                            mSceneController;           ///< Used for initializing renderers
+  Render::Renderer*                           mRenderer;                  ///< Raw pointer to the renderer (that's owned by RenderManager)
+  TextureSet*                                 mTextureSet;                ///< The texture set this renderer uses. (Not owned)
+  Render::Geometry*                           mGeometry;                  ///< The geometry this renderer uses. (Not owned)
+  Shader*                                     mShader;                    ///< The shader this renderer uses. (Not owned)
+  VisualRenderer::AnimatableVisualProperties* mVisualProperties{nullptr}; ///< VisualProperties (optional/owned)
+  OwnerPointer<Vector4>                       mBlendColor;                ///< The blend color for blending operation
 
   Dali::Internal::Render::Renderer::StencilParameters mStencilParameters; ///< Struct containing all stencil related options
 
index a70879b..03c1f1f 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_CORE_H
 
 /*
- * Copyright (c) 2020 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.
 #include <dali/public-api/rendering/texture-set.h>
 #include <dali/public-api/rendering/texture.h>
 #include <dali/public-api/rendering/vertex-buffer.h>
+#include <dali/public-api/rendering/visual-renderer.h>
 
 #include <dali/public-api/signals/base-signal.h>
 #include <dali/public-api/signals/callback.h>
index 43b1478..70d8684 100644 (file)
@@ -70,6 +70,7 @@ SET( public_api_src_files
   ${public_api_src_dir}/rendering/texture.cpp
   ${public_api_src_dir}/rendering/texture-set.cpp
   ${public_api_src_dir}/rendering/renderer.cpp
+  ${public_api_src_dir}/rendering/visual-renderer.cpp
   ${public_api_src_dir}/rendering/sampler.cpp
   ${public_api_src_dir}/rendering/shader.cpp
   ${public_api_src_dir}/signals/callback.cpp
@@ -219,6 +220,7 @@ SET( public_api_core_rendering_header_files
   ${public_api_src_dir}/rendering/texture.h
   ${public_api_src_dir}/rendering/texture-set.h
   ${public_api_src_dir}/rendering/renderer.h
+  ${public_api_src_dir}/rendering/visual-renderer.h
   ${public_api_src_dir}/rendering/sampler.h
   ${public_api_src_dir}/rendering/shader.h
 )
index bb43b42..1cb2544 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_PROPERTY_INDEX_RANGES_H
 
 /*
- * Copyright (c) 2020 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.
@@ -48,7 +48,7 @@ enum PropertyRanges
   DEFAULT_GESTURE_DETECTOR_PROPERTY_START_INDEX = DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX,                            ///< Used by PanGestureDetector. @SINCE_1_0.0
 
   DEFAULT_RENDERER_PROPERTY_START_INDEX         = 9000000,                                                               ///< Start index for Renderer. @SINCE_1_1.44
-  DEFAULT_RENDERER_PROPERTY_MAX_INDEX           = DEFAULT_RENDERER_PROPERTY_START_INDEX + 100000,                        ///< Renderer range: 9000000 to 9100000 @SINCE_1_1.44
+  DEFAULT_RENDERER_PROPERTY_MAX_INDEX           = DEFAULT_RENDERER_PROPERTY_START_INDEX + DEFAULT_PROPERTY_MAX_COUNT_PER_DERIVATION-1,///< Renderer range: 9,000,000 to 9,009,999 @SINCE_2_1.13
 
   PROPERTY_REGISTRATION_START_INDEX             = 10000000,                                                              ///< The index when registering a property should start from this number. @SINCE_1_0.0
   DEFAULT_PROPERTY_MAX_COUNT                    = PROPERTY_REGISTRATION_START_INDEX,                                     ///< Default Property Range: 0 to 9999999 @SINCE_1_0.0
index d384918..d434f72 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_RENDERER_H
 
 /*
- * Copyright (c) 2020 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.
@@ -545,6 +545,7 @@ public:
   Shader GetShader() const;
 
 public:
+  /// @cond internal
   /**
    * @brief The constructor.
    * @note  Not intended for application developers.
@@ -552,6 +553,7 @@ public:
    * @param[in] pointer A pointer to a newly allocated Renderer
    */
   explicit DALI_INTERNAL Renderer(Internal::Renderer* pointer);
+  /// @endcond
 };
 
 /**
diff --git a/dali/public-api/rendering/visual-renderer.cpp b/dali/public-api/rendering/visual-renderer.cpp
new file mode 100644 (file)
index 0000000..224efd0
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/rendering/visual-renderer.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/rendering/visual-renderer-impl.h>
+
+namespace Dali
+{
+VisualRenderer VisualRenderer::New(Geometry& geometry, Shader& shader)
+{
+  Internal::VisualRendererPtr renderer = Internal::VisualRenderer::New();
+  renderer->SetGeometry(GetImplementation(geometry));
+  renderer->SetShader(GetImplementation(shader));
+  return VisualRenderer(renderer.Get());
+}
+
+VisualRenderer::VisualRenderer() = default;
+
+VisualRenderer::~VisualRenderer() = default;
+
+VisualRenderer::VisualRenderer(const VisualRenderer& handle) = default;
+
+VisualRenderer VisualRenderer::DownCast(BaseHandle handle)
+{
+  return VisualRenderer(dynamic_cast<Dali::Internal::VisualRenderer*>(handle.GetObjectPtr()));
+}
+
+VisualRenderer& VisualRenderer::operator=(const VisualRenderer& handle) = default;
+
+VisualRenderer::VisualRenderer(VisualRenderer&& rhs) = default;
+
+VisualRenderer& VisualRenderer::operator=(VisualRenderer&& rhs) = default;
+
+VisualRenderer::VisualRenderer(Internal::VisualRenderer* pointer)
+: Dali::Renderer(pointer)
+{
+}
+
+} //namespace Dali
diff --git a/dali/public-api/rendering/visual-renderer.h b/dali/public-api/rendering/visual-renderer.h
new file mode 100644 (file)
index 0000000..844d480
--- /dev/null
@@ -0,0 +1,235 @@
+#ifndef DALI_VISUAL_RENDERER_H
+#define DALI_VISUAL_RENDERER_H
+
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/rendering/renderer.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_rendering_effects
+ * @{
+ */
+
+namespace Internal DALI_INTERNAL
+{
+class VisualRenderer;
+}
+
+/**
+ * @brief VisualRenderer is a handle to a Renderer with extra properties for Toolkit::Visuals
+ *
+ * @SINCE_2_1.13
+ */
+class DALI_CORE_API VisualRenderer : public Renderer
+{
+public:
+  /**
+   * @brief Policies used by the transform for the offset or size.
+   * @SINCE_2_1.13
+   */
+  struct TransformPolicy
+  {
+    /**
+     * @brief Enumeration for the type of Transform Policy.
+     * @SINCE_2_1.13
+     */
+    enum Type
+    {
+      RELATIVE = 0, ///< Relative to the control (percentage [0.0f to 1.0f] of the control). @SINCE_2_1.13
+      ABSOLUTE = 1  ///< Absolute value in world units. @SINCE_2_1.13
+    };
+  };
+
+  /**
+   * @brief Enumeration for instances of properties belonging to the VisualRenderer class.
+   * @SINCE_2_1.13
+   */
+  struct Property
+  {
+    static constexpr Dali::Property::Index DEFAULT_VISUAL_RENDERER_PROPERTY_START_INDEX = DEFAULT_RENDERER_PROPERTY_START_INDEX + DEFAULT_PROPERTY_MAX_COUNT_PER_DERIVATION;
+
+    /**
+     * @brief Enumeration for instances of properties belonging to the VisualRenderer class.
+     * @SINCE_2_1.13
+     */
+    enum
+    {
+      /**
+       * @brief Name "transformOffset", type Property::Vector2, animatable.
+       * @SINCE_2_1.13
+       * @note The default value is (0,0).
+       */
+      TRANSFORM_OFFSET = DEFAULT_VISUAL_RENDERER_PROPERTY_START_INDEX,
+
+      /**
+       * @brief Size of the visual, which can be either relative (percentage [0.0f to 1.0f] of the parent) or absolute (in world units).
+       * @details Name "transformSize", type Property::VECTOR2, animatable.
+       * @SINCE_2_1.13
+       * @see TRANSFORM_SIZE_POLICY
+       */
+      TRANSFORM_SIZE,
+
+      /**
+       * @brief The origin of the visual renderer within its control area.
+       * @details Name "transformOrigin", type Property::VECTOR2
+       * @note This is relative to the size of the actor, where the origin is the center of the actor,
+       * and the range is -0.5 to +0.5 vertically and horizontally
+       * @note Toolkit may impose additional layout directions
+       * @SINCE_2_1.13
+       * @note The default is top left
+       */
+      TRANSFORM_ORIGIN,
+
+      /**
+       * @brief The anchor-point of the visual renderer
+       * @details Name "transformAnchorPoint", type Property::VECTOR2
+       * @note This is relative to the size of the actor; where the origin is the center of the actor,
+       * and the range is -0.5 to +0.5 vertically and horizontally
+       * @note Toolkit may impose additional layout directions
+       * @SINCE_2_1.13
+       * @note The default is top left.
+       */
+      TRANSFORM_ANCHOR_POINT,
+
+      /**
+       * @brief Whether the x or y OFFSET/SIZE values are relative (percentage [0.0f to 1.0f] of the control) or absolute (in world units).
+       * @details Name "transformOffsetSizeMode", type Property::VECTOR4
+       *
+       * @code
+       * visualRenderer.SetProperty( VisualRenderer::Property::TRANSFORM_OFFSET_SIZE_MODE,
+       *                             Vector4( Policy::ABSOLUTE, Policy::RELATIVE, Policy::ABSOLUTE, Policy::RELATIVE ));
+       * @endcode
+       * @see Policy::Type
+       * @SINCE_2_1.13
+       * @note By default, both the x and the y offset/size is RELATIVE.
+       */
+      TRANSFORM_OFFSET_SIZE_MODE,
+
+      /**
+       * @brief Any extra size the shader needs for drawing into.
+       * @details Name "extraSize", type Property::VECTOR2, animatable
+       * @SINCE_2_1.13
+       * @note the default is (0, 0)
+       */
+      EXTRA_SIZE,
+
+      /**
+       * @brief Mix color is a generic color for any visual.
+       * @details Name "visualMixColor", type Property::VECTOR3, animatable
+       * @SINCE_2_1.13
+       */
+      VISUAL_MIX_COLOR,
+
+      /**
+       * @brief PremultipliedAlpha is a float representing a bool, and is either 0.0f, or 1.0f
+       * @details Name "preMultipliedAlpha", type Property::FLOAT
+       * @SINCE_2_1.13
+       */
+      VISUAL_PRE_MULTIPLIED_ALPHA,
+    };
+  };
+
+  /**
+   * @brief Creates a new Renderer object.
+   *
+   * @SINCE_2_1.13
+   * @param[in] geometry Geometry to be used by this renderer
+   * @param[in] shader Shader to be used by this renderer
+   * @return A handle to the Renderer
+   */
+  static VisualRenderer New(Geometry& geometry, Shader& shader);
+
+  /**
+   * @brief Default constructor, creates an empty handle
+   *
+   * @SINCE_2_1.13
+   */
+  VisualRenderer();
+
+  /**
+   * @brief Destructor.
+   *
+   * @SINCE_2_1.13
+   */
+  ~VisualRenderer();
+
+  /**
+   * @brief Copy constructor, creates a new handle to the same object.
+   *
+   * @SINCE_2_1.13
+   * @param[in] handle Handle to an object
+   */
+  VisualRenderer(const VisualRenderer& handle);
+
+  /**
+   * @brief Downcasts to a visual renderer handle.
+   * If not, a renderer the returned visual renderer handle is left uninitialized.
+   *
+   * @SINCE_2_1.13
+   * @param[in] handle Handle to an object
+   * @return Renderer handle or an uninitialized handle
+   */
+  static VisualRenderer DownCast(BaseHandle handle);
+
+  /**
+   * @brief Assignment operator, changes this handle to point at the same object.
+   *
+   * @SINCE_2_1.13
+   * @param[in] handle Handle to an object
+   * @return Reference to the assigned object
+   */
+  VisualRenderer& operator=(const VisualRenderer& handle);
+
+  /**
+   * @brief Move constructor.
+   *
+   * @SINCE_2_1.13
+   * @param[in] rhs A reference to the moved handle
+   */
+  VisualRenderer(VisualRenderer&& rhs);
+
+  /**
+   * @brief Move assignment operator.
+   *
+   * @SINCE_2_1.13
+   * @param[in] rhs A reference to the moved handle
+   * @return A reference to this handle
+   */
+  VisualRenderer& operator=(VisualRenderer&& rhs);
+
+public:
+  /// @cond internal
+  /**
+   * @brief The constructor.
+   * @note  Not intended for application developers.
+   * @SINCE_2_1.13
+   * @param[in] pointer A pointer to a newly allocated VisualRenderer
+   */
+  explicit DALI_INTERNAL VisualRenderer(Internal::VisualRenderer* pointer);
+  /// @endcond
+};
+
+/**
+ * @}
+ */
+} //namespace Dali
+
+#endif // DALI_VISUAL_RENDERER_H