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 a352f262904bec1e51e77d3e1c9de517dcbe80aa..cba77afcbaa89137e8dd0747cc478a236870cf25 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 e99de5cc2722967c30c86de25860796b62370ba4..e6416e3f4fe37244448c561a553ae123d9ea73fb 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 83b7899b35095a2a4c54d93dd1e3264585717934..8f9b9fc1426fe8dbbe0146e4a73ba5c61513998e 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 3ed6b56843da60041dd5d34c66b91d626992e103..bedce1837a2873ac3bf95fd7241f437598150cad 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 25c09b55227772b691100473f7c500578eb2931a..6971b712c2880aa9365dc1211d76c16792afe169 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 7f2de6361bdd3a5e81215c62e8aee5a2ca49b6ce..231603681c956027101022c63dcb16143b10ecaa 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 6f720c5d19bf070fe1665bda301cb27f4e8d813f..c2d0a49bd5358ecb6d38a6d169e9a12efc445100 100644 (file)
@@ -206,6 +206,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
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 4342d90b8d4c7a89d592c24323e9c74eebfb4d4f..fc9b85a0e5b2517dd1259356995bb2d975d93cc1 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 ad5ff554e32e9c2c00ba781e4bcfa7ac00dab593..17818ab90fba7c4e1b44f381697c7e0d3830eed6 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 bd014f7853802773b5606eb9ea1f73130bc4578c..73911cc1b24d42c4a475edd9837c58d569434880 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 7fc994f719c983d37a6901bfaa636cdb4bb22d25..d818dcddb83f81602eaf0e9581cd5537c798e221 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 a70879b4c55a003d4d0af94eb2883128396741b1..03c1f1fe0b60e82a2cdc6d345b50f1d8f755c1e7 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 43b14781a264baac21eee29ce4c09ef4d57e0e03..70d86849ddf4242e27006f8eca5d9a89b33d9d64 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 bb43b424db745ceac1af8a496cfd8e50a4d73564..1cb254418df7f236383075f947b8940676e5a9fd 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 d384918bf3129aa4b02e2bcf6c7be5ce03485700..d434f72634a909d4f533813fedceae71dfd8d7cb 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