Merge branch 'devel/master' into tizen accepted/tizen/unified/20220311.112104 submit/tizen/20220311.015202
authordongsug.song <dongsug.song@samsung.com>
Fri, 11 Mar 2022 00:26:53 +0000 (09:26 +0900)
committerdongsug.song <dongsug.song@samsung.com>
Fri, 11 Mar 2022 00:26:53 +0000 (09:26 +0900)
Change-Id: I8acdcd16aaf3caa04bd9aff85e883bd694620ccd

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