utc-Dali-ConstraintSource.cpp
utc-Dali-Core.cpp
utc-Dali-CustomActor.cpp
+ utc-Dali-DecoratedVisualRenderer.cpp
utc-Dali-Degree.cpp
utc-Dali-DistanceField.cpp
utc-Dali-DrawableActor.cpp
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
utc-Dali-Vector3.cpp
utc-Dali-Vector4.cpp
utc-Dali-VertexBuffer.cpp
+ utc-Dali-VisualRenderer.cpp
utc-Dali-WeakHandle.cpp
utc-Dali-WheelEvent.cpp
)
/*
- * 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.
*
*/
+#define ENABLE_VECTOR_ASSERTS
+
#include <dali-test-suite-utils.h>
#include <dali/devel-api/common/circular-queue.h>
#include <dali/public-api/dali-core.h>
--- /dev/null
+/*
+ * 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 decorated_visual_renderer_test_startup(void)
+{
+ test_return_value = TET_UNDEF;
+}
+
+void decorated_visual_renderer_test_cleanup(void)
+{
+ test_return_value = TET_PASS;
+}
+
+int UtcDaliDecoratedVisualRendererNew01(void)
+{
+ TestApplication application;
+
+ Geometry geometry = CreateQuadGeometry();
+ Shader shader = CreateShader();
+ DecoratedVisualRenderer renderer = DecoratedVisualRenderer::New(geometry, shader);
+
+ DALI_TEST_EQUALS((bool)renderer, true, TEST_LOCATION);
+ END_TEST;
+}
+
+int UtcDaliDecoratedVisualRendererNew02(void)
+{
+ TestApplication application;
+ DecoratedVisualRenderer renderer;
+ DALI_TEST_EQUALS((bool)renderer, false, TEST_LOCATION);
+ END_TEST;
+}
+
+int UtcDaliDecoratedVisualRendererCopyConstructor(void)
+{
+ TestApplication application;
+
+ Geometry geometry = CreateQuadGeometry();
+ Shader shader = CreateShader();
+ DecoratedVisualRenderer renderer = DecoratedVisualRenderer::New(geometry, shader);
+
+ DecoratedVisualRenderer rendererCopy(renderer);
+ DALI_TEST_EQUALS((bool)rendererCopy, true, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliDecoratedVisualRendererAssignmentOperator(void)
+{
+ TestApplication application;
+
+ Geometry geometry = CreateQuadGeometry();
+ Shader shader = CreateShader();
+ DecoratedVisualRenderer renderer = DecoratedVisualRenderer::New(geometry, shader);
+
+ DecoratedVisualRenderer renderer2;
+ DALI_TEST_EQUALS((bool)renderer2, false, TEST_LOCATION);
+
+ renderer2 = renderer;
+ DALI_TEST_EQUALS((bool)renderer2, true, TEST_LOCATION);
+ END_TEST;
+}
+
+int UtcDaliDecoratedVisualRendererMoveConstructor(void)
+{
+ TestApplication application;
+
+ Geometry geometry = CreateQuadGeometry();
+ Shader shader = Shader::New("vertexSrc", "fragmentSrc");
+ DecoratedVisualRenderer renderer = DecoratedVisualRenderer::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);
+ DALI_TEST_EQUALS(renderer.GetProperty<Vector4>(DecoratedVisualRenderer::Property::BORDERLINE_COLOR), Color::BLACK, TEST_LOCATION);
+
+ auto testColor = Vector3(1.0f, 0.0f, 1.0f);
+ auto testBorderlineColor = Vector4(1.0f, 0.0f, 1.0f, 0.5f);
+ renderer.SetProperty(VisualRenderer::Property::VISUAL_MIX_COLOR, testColor);
+ renderer.SetProperty(DecoratedVisualRenderer::Property::BORDERLINE_COLOR, testBorderlineColor);
+ application.SendNotification();
+ application.Render();
+ DALI_TEST_EQUALS(renderer.GetProperty<Vector3>(VisualRenderer::Property::VISUAL_MIX_COLOR), testColor, TEST_LOCATION);
+ DALI_TEST_EQUALS(renderer.GetProperty<Vector4>(DecoratedVisualRenderer::Property::BORDERLINE_COLOR), testBorderlineColor, TEST_LOCATION);
+
+ DecoratedVisualRenderer 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_EQUALS(move.GetProperty<Vector4>(DecoratedVisualRenderer::Property::BORDERLINE_COLOR), testBorderlineColor, TEST_LOCATION);
+
+ DALI_TEST_CHECK(!renderer);
+
+ END_TEST;
+}
+
+int UtcDaliDecoratedVisualRendererMoveAssignment(void)
+{
+ TestApplication application;
+
+ Geometry geometry = CreateQuadGeometry();
+ Shader shader = Shader::New("vertexSrc", "fragmentSrc");
+ DecoratedVisualRenderer renderer = DecoratedVisualRenderer::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);
+ DALI_TEST_EQUALS(renderer.GetProperty<Vector4>(DecoratedVisualRenderer::Property::BORDERLINE_COLOR), Color::BLACK, TEST_LOCATION);
+
+ auto testColor = Vector3(1.0f, 0.0f, 1.0f);
+ auto testBorderlineColor = Vector4(1.0f, 0.0f, 1.0f, 0.5f);
+ renderer.SetProperty(VisualRenderer::Property::VISUAL_MIX_COLOR, testColor);
+ renderer.SetProperty(DecoratedVisualRenderer::Property::BORDERLINE_COLOR, testBorderlineColor);
+ application.SendNotification();
+ application.Render();
+ DALI_TEST_EQUALS(renderer.GetProperty<Vector3>(VisualRenderer::Property::VISUAL_MIX_COLOR), testColor, TEST_LOCATION);
+ DALI_TEST_EQUALS(renderer.GetProperty<Vector4>(DecoratedVisualRenderer::Property::BORDERLINE_COLOR), testBorderlineColor, TEST_LOCATION);
+
+ DecoratedVisualRenderer 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), testColor, TEST_LOCATION);
+ DALI_TEST_EQUALS(move.GetProperty<Vector4>(DecoratedVisualRenderer::Property::BORDERLINE_COLOR), testBorderlineColor, TEST_LOCATION);
+ DALI_TEST_CHECK(!renderer);
+
+ END_TEST;
+}
+
+int UtcDaliDecoratedVisualRendererDownCast01(void)
+{
+ TestApplication application;
+
+ Geometry geometry = CreateQuadGeometry();
+ Shader shader = CreateShader();
+ DecoratedVisualRenderer renderer = DecoratedVisualRenderer::New(geometry, shader);
+
+ BaseHandle handle(renderer);
+ DecoratedVisualRenderer renderer2 = DecoratedVisualRenderer::DownCast(handle);
+ DALI_TEST_EQUALS((bool)renderer2, true, TEST_LOCATION);
+ END_TEST;
+}
+
+int UtcDaliDecoratedVisualRendererDownCast02(void)
+{
+ TestApplication application;
+
+ Handle handle = Handle::New(); // Create a custom object
+ DecoratedVisualRenderer renderer = DecoratedVisualRenderer::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 UtcDaliDecoratedVisualRendererDefaultProperties(void)
+{
+ TestApplication application;
+ Geometry geometry = CreateQuadGeometry();
+ Shader shader = CreateShader();
+ DecoratedVisualRenderer renderer = DecoratedVisualRenderer::New(geometry, shader);
+ VisualRenderer baseVisualRenderer = VisualRenderer::New(geometry, shader);
+ Renderer baseRenderer = Renderer::New(geometry, shader);
+
+ DALI_TEST_EQUALS(baseRenderer.GetPropertyCount(), 27, TEST_LOCATION);
+ DALI_TEST_EQUALS(baseVisualRenderer.GetPropertyCount(), 27 + 8, TEST_LOCATION);
+ DALI_TEST_EQUALS(renderer.GetPropertyCount(), 27 + 8 + 6, TEST_LOCATION);
+
+ TEST_RENDERER_PROPERTY(renderer, "cornerRadius", Property::VECTOR4, true, true, true, DecoratedVisualRenderer::Property::CORNER_RADIUS, TEST_LOCATION);
+ TEST_RENDERER_PROPERTY(renderer, "cornerRadiusPolicy", Property::FLOAT, true, false, true, DecoratedVisualRenderer::Property::CORNER_RADIUS_POLICY, TEST_LOCATION);
+ TEST_RENDERER_PROPERTY(renderer, "borderlineWidth", Property::FLOAT, true, true, true, DecoratedVisualRenderer::Property::BORDERLINE_WIDTH, TEST_LOCATION);
+ TEST_RENDERER_PROPERTY(renderer, "borderlineColor", Property::VECTOR4, true, true, true, DecoratedVisualRenderer::Property::BORDERLINE_COLOR, TEST_LOCATION);
+ TEST_RENDERER_PROPERTY(renderer, "borderlineOffset", Property::FLOAT, true, true, true, DecoratedVisualRenderer::Property::BORDERLINE_OFFSET, TEST_LOCATION);
+ TEST_RENDERER_PROPERTY(renderer, "blurRadius", Property::FLOAT, true, true, true, DecoratedVisualRenderer::Property::BLUR_RADIUS, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliDecoratedVisualRendererAnimatedProperty01(void)
+{
+ TestApplication application;
+
+ tet_infoline("Test that a decorated visual renderer property can be animated");
+
+ Shader shader = Shader::New("VertexSource", "FragmentSource");
+ Geometry geometry = CreateQuadGeometry();
+ DecoratedVisualRenderer renderer = DecoratedVisualRenderer::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 cornerRadiusIndex = DecoratedVisualRenderer::Property::CORNER_RADIUS;
+ renderer.SetProperty(cornerRadiusIndex, Vector4(1.0f, 10.0f, 5.0f, 0.0f));
+
+ application.SendNotification();
+ application.Render(0);
+ DALI_TEST_EQUALS(renderer.GetProperty<Vector4>(cornerRadiusIndex), Vector4(1.0f, 10.0f, 5.0f, 0.0f), 0.001f, TEST_LOCATION);
+
+ Animation animation = Animation::New(1.0f);
+ KeyFrames keyFrames = KeyFrames::New();
+ keyFrames.Add(0.0f, Vector4(1.0f, 0.0f, 1.0f, 0.0f));
+ keyFrames.Add(1.0f, Vector4(0.0f, 1.0f, 0.0f, 1.0f));
+ animation.AnimateBetween(Property(renderer, cornerRadiusIndex), keyFrames);
+ animation.Play();
+
+ application.SendNotification();
+ application.Render(500);
+
+ DALI_TEST_EQUALS(renderer.GetCurrentProperty<Vector4>(cornerRadiusIndex), Vector4(0.5f, 0.5f, 0.5f, 0.5f), TEST_LOCATION);
+
+ application.Render(400);
+ DALI_TEST_EQUALS(renderer.GetCurrentProperty<Vector4>(cornerRadiusIndex), Vector4(0.1f, 0.9f, 0.1f, 0.9f), TEST_LOCATION);
+
+ application.Render(100);
+ DALI_TEST_EQUALS(renderer.GetCurrentProperty<Vector4>(cornerRadiusIndex), Vector4(0.f, 1.f, 0.f, 1.f), TEST_LOCATION);
+ DALI_TEST_EQUALS(renderer.GetProperty<Vector4>(cornerRadiusIndex), Vector4(0.f, 1.f, 0.f, 1.f), TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliDecoratedVisualRendererAnimatedProperty02(void)
+{
+ TestApplication application;
+
+ tet_infoline("Test that a decorated visual renderer property can be animated");
+
+ Shader shader = Shader::New("VertexSource", "FragmentSource");
+ Geometry geometry = CreateQuadGeometry();
+ DecoratedVisualRenderer renderer = DecoratedVisualRenderer::New(geometry, shader);
+
+ Actor actor = Actor::New();
+ actor.AddRenderer(renderer);
+ actor.SetProperty(Actor::Property::SIZE, Vector2(400.0f, 400.0f));
+ application.GetScene().Add(actor);
+
+ renderer.SetProperty(DecoratedVisualRenderer::Property::CORNER_RADIUS, Vector4(1.0f, 1.0f, 0.0f, 0.0f));
+ renderer.SetProperty(DecoratedVisualRenderer::Property::BORDERLINE_WIDTH, 1.0f);
+ renderer.SetProperty(DecoratedVisualRenderer::Property::BORDERLINE_COLOR, Vector4(1.0f, 0.0f, 0.0f, 1.0f));
+ renderer.SetProperty(DecoratedVisualRenderer::Property::BORDERLINE_OFFSET, -1.0f);
+ renderer.SetProperty(DecoratedVisualRenderer::Property::BLUR_RADIUS, 0.0f);
+
+ application.SendNotification();
+ application.Render(0);
+ application.SendNotification();
+ application.Render(0);
+ DALI_TEST_EQUALS(renderer.GetProperty<Vector4>(DecoratedVisualRenderer::Property::CORNER_RADIUS), Vector4(1.0f, 1.0f, 0.0f, 0.0f), 0.001f, TEST_LOCATION);
+ DALI_TEST_EQUALS(renderer.GetProperty<float>(DecoratedVisualRenderer::Property::BORDERLINE_WIDTH), 1.0f, 0.001f, TEST_LOCATION);
+ DALI_TEST_EQUALS(renderer.GetProperty<Vector4>(DecoratedVisualRenderer::Property::BORDERLINE_COLOR), Vector4(1.0f, 0.0f, 0.0f, 1.0f), 0.001f, TEST_LOCATION);
+ DALI_TEST_EQUALS(renderer.GetProperty<float>(DecoratedVisualRenderer::Property::BORDERLINE_OFFSET), -1.0f, 0.001f, TEST_LOCATION);
+ DALI_TEST_EQUALS(renderer.GetProperty<float>(DecoratedVisualRenderer::Property::BLUR_RADIUS), 0.0f, 0.001f, TEST_LOCATION);
+
+ Animation animation = Animation::New(1.0f);
+ animation.AnimateBy(Property(renderer, DecoratedVisualRenderer::Property::CORNER_RADIUS), Vector4(10.0f, 100.0f, 100.0f, 10.0f));
+ animation.AnimateBy(Property(renderer, DecoratedVisualRenderer::Property::BORDERLINE_WIDTH), 10.0f);
+ animation.AnimateBy(Property(renderer, DecoratedVisualRenderer::Property::BORDERLINE_COLOR), Vector4(-1.0f, 1.0f, 1.0f, 0.0f));
+ animation.AnimateBy(Property(renderer, DecoratedVisualRenderer::Property::BORDERLINE_OFFSET), 2.0f);
+ animation.AnimateBy(Property(renderer, DecoratedVisualRenderer::Property::BLUR_RADIUS), 20.0f);
+ animation.Play();
+
+ application.SendNotification();
+ application.Render(500);
+
+ DALI_TEST_EQUALS(renderer.GetCurrentProperty<Vector4>(DecoratedVisualRenderer::Property::CORNER_RADIUS), Vector4(6.0f, 51.0f, 50.0f, 5.0f), 0.001f, TEST_LOCATION);
+ DALI_TEST_EQUALS(renderer.GetCurrentProperty<float>(DecoratedVisualRenderer::Property::BORDERLINE_WIDTH), 6.0f, 0.001f, TEST_LOCATION);
+ DALI_TEST_EQUALS(renderer.GetCurrentProperty<Vector4>(DecoratedVisualRenderer::Property::BORDERLINE_COLOR), Vector4(0.5f, 0.5f, 0.5f, 1.0f), 0.001f, TEST_LOCATION);
+ DALI_TEST_EQUALS(renderer.GetCurrentProperty<float>(DecoratedVisualRenderer::Property::BORDERLINE_OFFSET), 0.0f, 0.001f, TEST_LOCATION);
+ DALI_TEST_EQUALS(renderer.GetCurrentProperty<float>(DecoratedVisualRenderer::Property::BLUR_RADIUS), 10.0f, 0.001f, TEST_LOCATION);
+
+ application.Render(400);
+ DALI_TEST_EQUALS(renderer.GetCurrentProperty<Vector4>(DecoratedVisualRenderer::Property::CORNER_RADIUS), Vector4(10.0f, 91.0f, 90.0f, 9.0f), 0.001f, TEST_LOCATION);
+ DALI_TEST_EQUALS(renderer.GetCurrentProperty<float>(DecoratedVisualRenderer::Property::BORDERLINE_WIDTH), 10.0f, 0.001f, TEST_LOCATION);
+ DALI_TEST_EQUALS(renderer.GetCurrentProperty<Vector4>(DecoratedVisualRenderer::Property::BORDERLINE_COLOR), Vector4(0.1f, 0.9f, 0.9f, 1.0f), 0.001f, TEST_LOCATION);
+ DALI_TEST_EQUALS(renderer.GetCurrentProperty<float>(DecoratedVisualRenderer::Property::BORDERLINE_OFFSET), 0.8f, 0.001f, TEST_LOCATION);
+ DALI_TEST_EQUALS(renderer.GetCurrentProperty<float>(DecoratedVisualRenderer::Property::BLUR_RADIUS), 18.0f, 0.001f, TEST_LOCATION);
+
+ application.Render(100);
+ DALI_TEST_EQUALS(renderer.GetCurrentProperty<Vector4>(DecoratedVisualRenderer::Property::CORNER_RADIUS), Vector4(11.0f, 101.0f, 100.0f, 10.0f), 0.001f, TEST_LOCATION);
+ DALI_TEST_EQUALS(renderer.GetCurrentProperty<float>(DecoratedVisualRenderer::Property::BORDERLINE_WIDTH), 11.0f, 0.001f, TEST_LOCATION);
+ DALI_TEST_EQUALS(renderer.GetCurrentProperty<Vector4>(DecoratedVisualRenderer::Property::BORDERLINE_COLOR), Vector4(0.0f, 1.0f, 1.0f, 1.0f), 0.001f, TEST_LOCATION);
+ DALI_TEST_EQUALS(renderer.GetCurrentProperty<float>(DecoratedVisualRenderer::Property::BORDERLINE_OFFSET), 1.0f, 0.001f, TEST_LOCATION);
+ DALI_TEST_EQUALS(renderer.GetCurrentProperty<float>(DecoratedVisualRenderer::Property::BLUR_RADIUS), 20.0f, 0.001f, TEST_LOCATION);
+
+ DALI_TEST_EQUALS(renderer.GetProperty<Vector4>(DecoratedVisualRenderer::Property::CORNER_RADIUS), Vector4(11.0f, 101.0f, 100.0f, 10.0f), 0.001f, TEST_LOCATION);
+ DALI_TEST_EQUALS(renderer.GetProperty<float>(DecoratedVisualRenderer::Property::BORDERLINE_WIDTH), 11.0f, 0.001f, TEST_LOCATION);
+ DALI_TEST_EQUALS(renderer.GetProperty<Vector4>(DecoratedVisualRenderer::Property::BORDERLINE_COLOR), Vector4(0.0f, 1.0f, 1.0f, 1.0f), 0.001f, TEST_LOCATION);
+ DALI_TEST_EQUALS(renderer.GetProperty<float>(DecoratedVisualRenderer::Property::BORDERLINE_OFFSET), 1.0f, 0.001f, TEST_LOCATION);
+ DALI_TEST_EQUALS(renderer.GetProperty<float>(DecoratedVisualRenderer::Property::BLUR_RADIUS), 20.0f, 0.001f, TEST_LOCATION);
+
+ END_TEST;
+}
+
+struct DecoratedVisualProperties
+{
+ DecoratedVisualProperties() = default;
+
+ DecoratedVisualProperties(Vector2 offset, Vector2 size, Vector2 origin, Vector2 pivot, Vector4 modes, Vector2 extraSize, Vector3 mixColor, float preMultipliedAlpha, Vector4 cornerRadius, float cornerRadiusPolicy, float borderlineWidth, Vector4 borderlineColor, float borderlineOffset, float blurRadius)
+ : mTransformOffset(offset),
+ mTransformSize(size),
+ mTransformOrigin(origin),
+ mTransformAnchorPoint(pivot),
+ mTransformOffsetSizeMode(modes),
+ mExtraSize(extraSize),
+ mMixColor(mixColor),
+ mPreMultipliedAlpha(preMultipliedAlpha),
+ mCornerRadius(cornerRadius),
+ mCornerRadiusPolicy(cornerRadiusPolicy),
+ mBorderlineWidth(borderlineWidth),
+ mBorderlineColor(borderlineColor),
+ mBorderlineOffset(borderlineOffset),
+ mBlurRadius(blurRadius)
+ {
+ }
+
+ Vector2 mTransformOffset{Vector2::ZERO};
+ Vector2 mTransformSize{Vector2::ONE};
+ Vector2 mTransformOrigin{Vector2::ZERO};
+ Vector2 mTransformAnchorPoint{Vector2::ZERO};
+ Vector4 mTransformOffsetSizeMode{Vector2::ZERO};
+ Vector2 mExtraSize{Vector2::ZERO};
+ Vector3 mMixColor{Vector3::ONE};
+ float mPreMultipliedAlpha{0.0f};
+
+ Vector4 mCornerRadius{Vector4::ZERO};
+ float mCornerRadiusPolicy{1.0f};
+ float mBorderlineWidth{0.0f};
+ Vector4 mBorderlineColor{Vector4::ZERO};
+ float mBorderlineOffset{0.0f};
+ float mBlurRadius{0.0f};
+
+ static DecoratedVisualProperties GetPropsAt(float alpha, const DecoratedVisualProperties& start, const DecoratedVisualProperties& end)
+ {
+ DecoratedVisualProperties 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.mCornerRadius = start.mCornerRadius + (end.mCornerRadius - start.mCornerRadius) * alpha;
+ progress.mBorderlineWidth = start.mBorderlineWidth + (end.mBorderlineWidth - start.mBorderlineWidth) * alpha;
+ progress.mBorderlineColor = start.mBorderlineColor + (end.mBorderlineColor - start.mBorderlineColor) * alpha;
+ progress.mBorderlineOffset = start.mBorderlineOffset + (end.mBorderlineOffset - start.mBorderlineOffset) * alpha;
+ progress.mBlurRadius = start.mBlurRadius + (end.mBlurRadius - start.mBlurRadius) * alpha;
+
+ progress.mTransformOffsetSizeMode = end.mTransformOffsetSizeMode;
+ progress.mTransformOrigin = end.mTransformOrigin;
+ progress.mTransformAnchorPoint = end.mTransformAnchorPoint;
+ progress.mPreMultipliedAlpha = end.mPreMultipliedAlpha;
+ progress.mCornerRadiusPolicy = end.mCornerRadiusPolicy;
+ return progress;
+ }
+};
+
+void PrintDecoratedVisualProperties(const DecoratedVisualProperties& 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)\n"
+ "%*c preMultipliedAlpha:(%5.3f)\n"
+ "%*c cornerRadius:(%5.3f, %5.3f, %5.3f, %5.3f)\n"
+ "%*c cornerRadiusPolicy:(%5.3f)\n"
+ "%*c borderlineWidth:(%5.3f)\n"
+ "%*c borderlineColor:(%5.3f, %5.3f, %5.3f, %5.3f)\n"
+ "%*c borderlineOffset:(%5.3f)\n"
+ "%*c blurRadius:(%5.3f)\n",
+ prefix.c_str(),
+ props.mTransformOffset.x,
+ props.mTransformOffset.y,
+ prefix.length() + 1,
+ ' ',
+ props.mTransformSize.x,
+ props.mTransformSize.y,
+ prefix.length() + 1,
+ ' ',
+ props.mTransformOrigin.x,
+ props.mTransformOrigin.y,
+ prefix.length() + 1,
+ ' ',
+ props.mTransformAnchorPoint.x,
+ props.mTransformAnchorPoint.y,
+ prefix.length() + 1,
+ ' ',
+ props.mTransformOffsetSizeMode.x,
+ props.mTransformOffsetSizeMode.y,
+ props.mTransformOffsetSizeMode.z,
+ props.mTransformOffsetSizeMode.w,
+ prefix.length() + 1,
+ ' ',
+ props.mExtraSize.x,
+ props.mExtraSize.y,
+ prefix.length() + 1,
+ ' ',
+ props.mMixColor.x,
+ props.mMixColor.y,
+ props.mMixColor.z,
+ prefix.length() + 1,
+ ' ',
+ props.mPreMultipliedAlpha,
+ prefix.length() + 1,
+ ' ',
+ props.mCornerRadius.x,
+ props.mCornerRadius.y,
+ props.mCornerRadius.z,
+ props.mCornerRadius.w,
+ prefix.length() + 1,
+ ' ',
+ props.mCornerRadiusPolicy,
+ prefix.length() + 1,
+ ' ',
+ props.mBorderlineWidth,
+ prefix.length() + 1,
+ ' ',
+ props.mBorderlineColor.x,
+ props.mBorderlineColor.y,
+ props.mBorderlineColor.z,
+ props.mBorderlineColor.w,
+ prefix.length() + 1,
+ ' ',
+ props.mBorderlineOffset,
+ prefix.length() + 1,
+ ' ',
+ props.mBlurRadius);
+}
+
+void SetDecoratedVisualProperties(DecoratedVisualRenderer renderer, DecoratedVisualProperties 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);
+ renderer.SetProperty(VisualRenderer::Property::VISUAL_PRE_MULTIPLIED_ALPHA, props.mPreMultipliedAlpha);
+
+ renderer.SetProperty(DecoratedVisualRenderer::Property::CORNER_RADIUS, props.mCornerRadius);
+ renderer.SetProperty(DecoratedVisualRenderer::Property::CORNER_RADIUS_POLICY, props.mCornerRadiusPolicy);
+ renderer.SetProperty(DecoratedVisualRenderer::Property::BORDERLINE_WIDTH, props.mBorderlineWidth);
+ renderer.SetProperty(DecoratedVisualRenderer::Property::BORDERLINE_COLOR, props.mBorderlineColor);
+ renderer.SetProperty(DecoratedVisualRenderer::Property::BORDERLINE_OFFSET, props.mBorderlineOffset);
+ renderer.SetProperty(DecoratedVisualRenderer::Property::BLUR_RADIUS, props.mBlurRadius);
+}
+
+void CheckEventDecoratedVisualProperties(DecoratedVisualRenderer renderer, DecoratedVisualProperties expectedProps)
+{
+ tet_infoline("CheckEventDecoratedVisualProperties\n");
+
+ DecoratedVisualProperties 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);
+ actualProps.mPreMultipliedAlpha = renderer.GetProperty<float>(VisualRenderer::Property::VISUAL_PRE_MULTIPLIED_ALPHA);
+
+ actualProps.mCornerRadius = renderer.GetProperty<Vector4>(DecoratedVisualRenderer::Property::CORNER_RADIUS);
+ actualProps.mCornerRadiusPolicy = renderer.GetProperty<float>(DecoratedVisualRenderer::Property::CORNER_RADIUS_POLICY);
+ actualProps.mBorderlineWidth = renderer.GetProperty<float>(DecoratedVisualRenderer::Property::BORDERLINE_WIDTH);
+ actualProps.mBorderlineColor = renderer.GetProperty<Vector4>(DecoratedVisualRenderer::Property::BORDERLINE_COLOR);
+ actualProps.mBorderlineOffset = renderer.GetProperty<float>(DecoratedVisualRenderer::Property::BORDERLINE_OFFSET);
+ actualProps.mBlurRadius = renderer.GetProperty<float>(DecoratedVisualRenderer::Property::BLUR_RADIUS);
+
+ PrintDecoratedVisualProperties(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);
+ DALI_TEST_EQUALS(actualProps.mPreMultipliedAlpha, expectedProps.mPreMultipliedAlpha, TEST_LOCATION);
+
+ DALI_TEST_EQUALS(actualProps.mCornerRadius, expectedProps.mCornerRadius, TEST_LOCATION);
+ DALI_TEST_EQUALS(actualProps.mCornerRadiusPolicy, expectedProps.mCornerRadiusPolicy, TEST_LOCATION);
+ DALI_TEST_EQUALS(actualProps.mBorderlineWidth, expectedProps.mBorderlineWidth, TEST_LOCATION);
+ DALI_TEST_EQUALS(actualProps.mBorderlineColor, expectedProps.mBorderlineColor, TEST_LOCATION);
+ DALI_TEST_EQUALS(actualProps.mBorderlineOffset, expectedProps.mBorderlineOffset, TEST_LOCATION);
+ DALI_TEST_EQUALS(actualProps.mBlurRadius, expectedProps.mBlurRadius, TEST_LOCATION);
+}
+
+void CheckSceneGraphDecoratedVisualProperties(DecoratedVisualRenderer renderer, DecoratedVisualProperties expectedProps)
+{
+ tet_infoline("CheckSceneGraphVisualProperties\n");
+
+ DecoratedVisualProperties 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);
+
+ actualProps.mCornerRadius = renderer.GetCurrentProperty<Vector4>(DecoratedVisualRenderer::Property::CORNER_RADIUS);
+ actualProps.mCornerRadiusPolicy = renderer.GetCurrentProperty<float>(DecoratedVisualRenderer::Property::CORNER_RADIUS_POLICY);
+ actualProps.mBorderlineWidth = renderer.GetCurrentProperty<float>(DecoratedVisualRenderer::Property::BORDERLINE_WIDTH);
+ actualProps.mBorderlineColor = renderer.GetCurrentProperty<Vector4>(DecoratedVisualRenderer::Property::BORDERLINE_COLOR);
+ actualProps.mBorderlineOffset = renderer.GetCurrentProperty<float>(DecoratedVisualRenderer::Property::BORDERLINE_OFFSET);
+ actualProps.mBlurRadius = renderer.GetCurrentProperty<float>(DecoratedVisualRenderer::Property::BLUR_RADIUS);
+
+ PrintDecoratedVisualProperties(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);
+ DALI_TEST_EQUALS(actualProps.mPreMultipliedAlpha, expectedProps.mPreMultipliedAlpha, TEST_LOCATION);
+
+ DALI_TEST_EQUALS(actualProps.mCornerRadius, expectedProps.mCornerRadius, TEST_LOCATION);
+ DALI_TEST_EQUALS(actualProps.mCornerRadiusPolicy, expectedProps.mCornerRadiusPolicy, TEST_LOCATION);
+ DALI_TEST_EQUALS(actualProps.mBorderlineWidth, expectedProps.mBorderlineWidth, TEST_LOCATION);
+ DALI_TEST_EQUALS(actualProps.mBorderlineColor, expectedProps.mBorderlineColor, TEST_LOCATION);
+ DALI_TEST_EQUALS(actualProps.mBorderlineOffset, expectedProps.mBorderlineOffset, TEST_LOCATION);
+ DALI_TEST_EQUALS(actualProps.mBlurRadius, expectedProps.mBlurRadius, TEST_LOCATION);
+}
+
+void CheckUniforms(DecoratedVisualRenderer renderer, DecoratedVisualProperties 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));
+
+ DALI_TEST_CHECK(callStack.FindMethodAndGetParameters(uniforms[7].name, params));
+ DALI_TEST_CHECK(gl.GetUniformValue<float>(uniforms[7].name.c_str(), props.mPreMultipliedAlpha));
+
+ DALI_TEST_CHECK(callStack.FindMethodAndGetParameters(uniforms[8].name, params));
+ DALI_TEST_CHECK(gl.GetUniformValue<Vector4>(uniforms[8].name.c_str(), props.mCornerRadius));
+
+ DALI_TEST_CHECK(callStack.FindMethodAndGetParameters(uniforms[9].name, params));
+ DALI_TEST_CHECK(gl.GetUniformValue<float>(uniforms[9].name.c_str(), props.mCornerRadiusPolicy));
+
+ DALI_TEST_CHECK(callStack.FindMethodAndGetParameters(uniforms[10].name, params));
+ DALI_TEST_CHECK(gl.GetUniformValue<float>(uniforms[10].name.c_str(), props.mBorderlineWidth));
+
+ DALI_TEST_CHECK(callStack.FindMethodAndGetParameters(uniforms[11].name, params));
+ DALI_TEST_CHECK(gl.GetUniformValue<Vector4>(uniforms[11].name.c_str(), props.mBorderlineColor));
+
+ DALI_TEST_CHECK(callStack.FindMethodAndGetParameters(uniforms[12].name, params));
+ DALI_TEST_CHECK(gl.GetUniformValue<float>(uniforms[12].name.c_str(), props.mBorderlineOffset));
+
+ DALI_TEST_CHECK(callStack.FindMethodAndGetParameters(uniforms[13].name, params));
+ DALI_TEST_CHECK(gl.GetUniformValue<float>(uniforms[13].name.c_str(), props.mBlurRadius));
+}
+
+int UtcDaliDecoratedVisualRendererAnimatedProperty03(void)
+{
+ TestApplication application;
+ TestGlAbstraction& gl = application.GetGlAbstraction();
+ TraceCallStack& callStack = gl.GetSetUniformTrace();
+ gl.EnableSetUniformCallTrace(true);
+
+ tet_infoline("Test that a decorated 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},
+ {"preMultipliedAlpha", Property::FLOAT},
+ {"cornerRadius", Property::VECTOR4},
+ {"cornerRadiusPolicy", Property::FLOAT},
+ {"borderlineWidth", Property::FLOAT},
+ {"borderlineColor", Property::VECTOR4},
+ {"borderlineOffset", Property::FLOAT},
+ {"blurRadius", Property::FLOAT}};
+
+ application.GetGraphicsController().AddCustomUniforms(customUniforms);
+
+ Shader shader = Shader::New("VertexSource", "FragmentSource");
+ Geometry geometry = CreateQuadGeometry();
+ DecoratedVisualRenderer renderer = DecoratedVisualRenderer::New(geometry, shader);
+
+ // Add all uniform mappings
+ renderer.RegisterCornerRadiusUniform();
+ renderer.RegisterBorderlineUniform();
+ renderer.RegisterBlurRadiusUniform();
+
+ Actor actor = Actor::New();
+ actor.AddRenderer(renderer);
+ actor.SetProperty(Actor::Property::SIZE, Vector2(400.0f, 400.0f));
+ application.GetScene().Add(actor);
+
+ DecoratedVisualProperties 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), 0.0f, Vector4(100.0f, 10.0f, 1.0f, 0.1f), 1.0f, 20.0f, Vector4(1.0f, 0.0f, 1.0f, 0.5f), 1.0f, 10.0f};
+ DecoratedVisualProperties 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), 0.0f, Vector4(0.2f, 2.0f, 20.0f, 200.0f), 1.0f, 40.0f, Vector4(0.0f, 0.2f, 0.0f, 1.0f), -1.0f, 2.0f};
+
+ SetDecoratedVisualProperties(renderer, props);
+ CheckEventDecoratedVisualProperties(renderer, props);
+ application.SendNotification();
+ application.Render(0);
+ CheckSceneGraphDecoratedVisualProperties(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.AnimateTo(Property(renderer, DecoratedVisualRenderer::Property::CORNER_RADIUS), targetProps.mCornerRadius);
+ animation.AnimateTo(Property(renderer, DecoratedVisualRenderer::Property::BORDERLINE_WIDTH), targetProps.mBorderlineWidth);
+ animation.AnimateTo(Property(renderer, DecoratedVisualRenderer::Property::BORDERLINE_COLOR), targetProps.mBorderlineColor);
+ animation.AnimateTo(Property(renderer, DecoratedVisualRenderer::Property::BORDERLINE_OFFSET), targetProps.mBorderlineOffset);
+ animation.AnimateTo(Property(renderer, DecoratedVisualRenderer::Property::BLUR_RADIUS), targetProps.mBlurRadius);
+ animation.Play();
+
+ CheckEventDecoratedVisualProperties(renderer, targetProps);
+
+ for(int i = 0; i <= 10; ++i)
+ {
+ tet_printf("\n########### Animation progress: %d%%\n\n", i * 10);
+ DecoratedVisualProperties propsProgress = DecoratedVisualProperties::GetPropsAt(0.1f * i, props, targetProps);
+ PrintDecoratedVisualProperties(propsProgress, "Expected values");
+
+ callStack.Reset();
+ application.SendNotification();
+ application.Render((i == 0 ? 0 : 100));
+
+ CheckEventDecoratedVisualProperties(renderer, targetProps);
+
+ CheckSceneGraphDecoratedVisualProperties(renderer, propsProgress);
+ CheckUniforms(renderer, propsProgress, customUniforms, callStack, gl);
+ }
+
+ // Ensure animation finishes
+ application.SendNotification();
+ application.Render(100);
+ CheckSceneGraphDecoratedVisualProperties(renderer, targetProps);
+ CheckUniforms(renderer, targetProps, customUniforms, callStack, gl);
+
+ END_TEST;
+}
+
+int UtcDaliDecoratedVisualRendererAnimatedProperty04(void)
+{
+ TestApplication application;
+
+ tet_infoline("Test that a decorated visual renderer property can't be animated");
+
+ Shader shader = Shader::New("VertexSource", "FragmentSource");
+ Geometry geometry = CreateQuadGeometry();
+ DecoratedVisualRenderer renderer = DecoratedVisualRenderer::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 = DecoratedVisualRenderer::Property::CORNER_RADIUS_POLICY;
+ renderer.SetProperty(index, 0.0f);
+
+ application.SendNotification();
+ application.Render(0);
+ DALI_TEST_EQUALS(renderer.GetProperty<float>(index), 0.0f, 0.001f, TEST_LOCATION);
+
+ Animation animation = Animation::New(1.0f);
+ KeyFrames keyFrames = KeyFrames::New();
+ keyFrames.Add(0.0f, 0.0f);
+ 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);
+ }
+
+ END_TEST;
+}
+
+int UtcDaliDecoratedVisualRendererAnimatedProperty05(void)
+{
+ TestApplication application;
+
+ tet_infoline("Test that a parent visual renderer property can still be animated");
+
+ Shader shader = Shader::New("VertexSource", "FragmentSource");
+ Geometry geometry = CreateQuadGeometry();
+ DecoratedVisualRenderer renderer = DecoratedVisualRenderer::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_SIZE;
+ renderer.SetProperty(index, Vector2(1.0f, 0.5f));
+
+ application.SendNotification();
+ application.Render(0);
+ DALI_TEST_EQUALS(renderer.GetProperty<Vector2>(index), Vector2(1.0f, 0.5f), 0.001f, TEST_LOCATION);
+ DALI_TEST_EQUALS(renderer.GetCurrentProperty<Vector2>(VisualRenderer::Property::TRANSFORM_SIZE), Vector2(1.0f, 0.5f), 0.0001f, 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();
+
+ // Test that the event side properties are set to target value of (0, 1)
+ DALI_TEST_EQUALS(renderer.GetProperty<Vector2>(VisualRenderer::Property::TRANSFORM_SIZE), Vector2(0.0f, 1.0f), 0.0001f, TEST_LOCATION);
+
+ application.Render(500);
+
+ DALI_TEST_EQUALS(renderer.GetCurrentProperty<Vector2>(index), Vector2(0.5f, 0.5f), 0.0001f, TEST_LOCATION);
+ DALI_TEST_EQUALS(renderer.GetCurrentProperty<Vector2>(VisualRenderer::Property::TRANSFORM_SIZE), Vector2(0.5f, 0.5f), 0.0001f, TEST_LOCATION);
+
+ // Test that the event side properties are set to target value 0f (0, 1)
+ DALI_TEST_EQUALS(renderer.GetProperty<Vector2>(VisualRenderer::Property::TRANSFORM_SIZE), Vector2(0.0f, 1.0f), 0.0001f, TEST_LOCATION);
+
+ // Complete the animation
+ application.Render(500);
+
+ DALI_TEST_EQUALS(renderer.GetCurrentProperty<Vector2>(index), Vector2(0.0f, 1.0f), 0.0001f, TEST_LOCATION);
+ DALI_TEST_EQUALS(renderer.GetCurrentProperty<Vector2>(VisualRenderer::Property::TRANSFORM_SIZE), Vector2(0.0f, 1.0f), 0.0001f, TEST_LOCATION);
+ DALI_TEST_EQUALS(renderer.GetProperty<Vector2>(VisualRenderer::Property::TRANSFORM_SIZE), Vector2(0.0f, 1.0f), 0.0001f, TEST_LOCATION);
+ END_TEST;
+}
+
+int UtcDaliDecoratedVisualRendererPartialUpdate(void)
+{
+ TestApplication application(
+ TestApplication::DEFAULT_SURFACE_WIDTH,
+ TestApplication::DEFAULT_SURFACE_HEIGHT,
+ TestApplication::DEFAULT_HORIZONTAL_DPI,
+ TestApplication::DEFAULT_VERTICAL_DPI,
+ true,
+ true);
+
+ tet_infoline("Test that partial update works well when we set visual renderer's animated properties");
+
+ const TestGlAbstraction::ScissorParams& glScissorParams(application.GetGlAbstraction().GetScissorParams());
+
+ Shader shader = Shader::New("VertexSource", "FragmentSource");
+ Geometry geometry = CreateQuadGeometry();
+ DecoratedVisualRenderer renderer = DecoratedVisualRenderer::New(geometry, shader);
+
+ Actor actor = Actor::New();
+ actor.AddRenderer(renderer);
+ actor[Actor::Property::ANCHOR_POINT] = AnchorPoint::TOP_LEFT;
+ actor[Actor::Property::POSITION] = Vector3(64.0f, 64.0f, 0.0f);
+ actor[Actor::Property::SIZE] = Vector3(64.0f, 64.0f, 0.0f);
+ actor.SetResizePolicy(ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS);
+ application.GetScene().Add(actor);
+
+ application.SendNotification();
+
+ std::vector<Rect<int>> damagedRects;
+
+ // Actor added, damaged rect is added size of actor
+ application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+ DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+
+ // Aligned by 16
+ Rect<int> clippingRect = Rect<int>(64, 672, 80, 80); // in screen coordinates, includes 3 last frames updates
+ DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+ DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION);
+ DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION);
+ DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION);
+ DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION);
+
+ damagedRects.clear();
+ application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ damagedRects.clear();
+ application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ // Set clippingRect as full surface now. TODO : Set valid rect if we can.
+ clippingRect = TestApplication::DEFAULT_SURFACE_RECT;
+
+ // Set decoration with borderline as 32 units.
+ renderer.RegisterBorderlineUniform();
+ renderer.SetProperty(DecoratedVisualRenderer::Property::BORDERLINE_WIDTH, 32.0f);
+
+ Property::Index index = DecoratedVisualRenderer::Property::BORDERLINE_OFFSET;
+ renderer.SetProperty(index, 1.0f);
+
+ // Now current actor show as 128x128 rectangle, with center position (96, 96).
+ // So, rectangle's top left position is (32, 32), and bottom right position is (160, 160).
+
+ application.SendNotification();
+ damagedRects.clear();
+ application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+ DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+ // Aligned by 16
+ DALI_TEST_EQUALS<Rect<int>>(Rect<int>(32, 640, 144, 144), damagedRects[0], TEST_LOCATION);
+
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ application.SendNotification();
+ damagedRects.clear();
+ application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ // Update dummy property to damangeRect buffer aging
+ actor.SetProperty(Actor::Property::COLOR, Color::RED);
+
+ application.SendNotification();
+ damagedRects.clear();
+ application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+ DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+
+ // Update dummy property to damangeRect buffer aging
+ actor.SetProperty(Actor::Property::COLOR, Color::BLUE);
+
+ application.SendNotification();
+ damagedRects.clear();
+ application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+ DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+ // Aligned by 16
+ DALI_TEST_EQUALS<Rect<int>>(Rect<int>(32, 640, 144, 144), damagedRects[0], TEST_LOCATION);
+
+ application.SendNotification();
+ damagedRects.clear();
+ application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ application.SendNotification();
+ damagedRects.clear();
+ application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ application.SendNotification();
+ damagedRects.clear();
+ application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ // 3 frame spended after change actor property. Ensure the damaged rect is empty
+ DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION);
+
+ DALI_TEST_EQUALS(renderer.GetProperty<float>(index), 1.0f, 0.001f, TEST_LOCATION);
+
+ // Make flickered animation from 1.0f --> 0.0f --> -1.0f of borderline offset
+ // After finish the animation, actor show as 64x64 rectangle, with center position (96, 96).
+ // So, rectangle's top left position is (64, 64), and bottom right position is (128, 128).
+ Animation animation = Animation::New(1.0f);
+ KeyFrames keyFrames = KeyFrames::New();
+ keyFrames.Add(0.0f, float(1.0f));
+ keyFrames.Add(0.299f, float(1.0f));
+ keyFrames.Add(0.301f, float(0.0f));
+ keyFrames.Add(0.699f, float(0.0f));
+ keyFrames.Add(0.701f, float(-1.0f));
+ keyFrames.Add(1.0f, float(-1.0f));
+ animation.AnimateBetween(Property(renderer, index), keyFrames);
+ animation.Play();
+
+ application.SendNotification();
+ damagedRects.clear();
+ application.PreRenderWithPartialUpdate(200, nullptr, damagedRects); // 200 ms
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ DALI_TEST_EQUALS(renderer.GetCurrentProperty<float>(index), 1.0f, TEST_LOCATION);
+
+ // 302 ~ 600. TransformSize become 0.0f
+ application.SendNotification();
+ damagedRects.clear();
+ application.PreRenderWithPartialUpdate(102, nullptr, damagedRects); // 302 ms
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ DALI_TEST_EQUALS(renderer.GetCurrentProperty<float>(index), 0.0f, TEST_LOCATION);
+
+ // Update dummy property to damangeRect buffer aging
+ actor.SetProperty(Actor::Property::COLOR, Color::RED);
+
+ application.SendNotification();
+ damagedRects.clear();
+ application.PreRenderWithPartialUpdate(16, nullptr, damagedRects); // 318 ms
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ // Update dummy property to damangeRect buffer aging
+ actor.SetProperty(Actor::Property::COLOR, Color::GREEN);
+
+ application.SendNotification();
+ damagedRects.clear();
+ application.PreRenderWithPartialUpdate(16, nullptr, damagedRects); // 334 ms
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ // Update dummy property to damangeRect buffer aging
+ actor.SetProperty(Actor::Property::COLOR, Color::RED);
+
+ application.SendNotification();
+ damagedRects.clear();
+ application.PreRenderWithPartialUpdate(16, nullptr, damagedRects); // 350 ms
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+ // Aligned by 16
+ // Now current actor show as 96x96 rectangle, with center position (96, 96).
+ DALI_TEST_EQUALS<Rect<int>>(Rect<int>(48, 656, 112, 112), damagedRects[0], TEST_LOCATION);
+
+ application.SendNotification();
+ damagedRects.clear();
+ application.PreRenderWithPartialUpdate(250, nullptr, damagedRects); // 600 ms
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ // 702 ~ 1000. TransformSize become -1.0f
+ damagedRects.clear();
+ application.PreRenderWithPartialUpdate(102, nullptr, damagedRects); // 702 ms
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ DALI_TEST_EQUALS(renderer.GetCurrentProperty<float>(index), -1.0f, TEST_LOCATION);
+
+ // Update dummy property to damangeRect buffer aging
+ actor.SetProperty(Actor::Property::COLOR, Color::GREEN);
+
+ application.SendNotification();
+ damagedRects.clear();
+ application.PreRenderWithPartialUpdate(16, nullptr, damagedRects); // 718 ms
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ // Update dummy property to damangeRect buffer aging
+ actor.SetProperty(Actor::Property::COLOR, Color::BLUE);
+
+ application.SendNotification();
+ damagedRects.clear();
+ application.PreRenderWithPartialUpdate(16, nullptr, damagedRects); // 734 ms
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ // Update dummy property to damangeRect buffer aging
+ actor.SetProperty(Actor::Property::COLOR, Color::RED);
+
+ application.SendNotification();
+ damagedRects.clear();
+ application.PreRenderWithPartialUpdate(16, nullptr, damagedRects); // 750 ms
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+ // Aligned by 16
+ // Now current actor show as 64x64 rectangle, with center position (96, 96).
+ DALI_TEST_EQUALS<Rect<int>>(Rect<int>(64, 672, 80, 80), damagedRects[0], TEST_LOCATION);
+
+ application.SendNotification();
+ damagedRects.clear();
+ application.PreRenderWithPartialUpdate(52, nullptr, damagedRects); // 1002 ms. animation finished.
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ // Check finished value bake.
+ DALI_TEST_EQUALS(renderer.GetProperty<float>(index), -1.0f, TEST_LOCATION);
+
+ END_TEST;
+}
\ No newline at end of file
END_TEST;
}
+int UtcDaliRendererRenderAfterAddShader(void)
+{
+ TestApplication application;
+ TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+
+ tet_infoline("Test regenerating uniform map when shader changed");
+
+ Geometry geometry = CreateQuadGeometry();
+ Shader shader1 = Shader::New("vertexSrc1", "fragmentSrc1");
+ Shader shader2 = Shader::New("vertexSrc2", "fragmentSrc2");
+ Renderer renderer = Renderer::New(geometry, shader1);
+
+ // Register each shader1 and shader2 only had
+ shader1.RegisterProperty("uUniform1", Color::CRIMSON);
+ shader2.RegisterProperty("uShader2Only", Color::AQUA_MARINE);
+
+ Actor actor = Actor::New();
+ actor.AddRenderer(renderer);
+ actor.SetProperty(Actor::Property::SIZE, Vector2(400.0f, 400.0f));
+ actor.SetProperty(Actor::Property::COLOR, Vector4(1.0f, 0.0f, 1.0f, 1.0f));
+ application.GetScene().Add(actor);
+
+ Property::Value value = renderer.GetProperty(DevelRenderer::Property::RENDERING_BEHAVIOR);
+ int renderingBehavior;
+ DALI_TEST_CHECK(value.Get(renderingBehavior));
+ DALI_TEST_EQUALS(static_cast<DevelRenderer::Rendering::Type>(renderingBehavior), DevelRenderer::Rendering::IF_REQUIRED, TEST_LOCATION);
+
+ application.SendNotification();
+ application.Render(0);
+
+ // Check uUniform1 rendered and uUniform2 not rendered before
+ Vector4 actualValue(Vector4::ZERO);
+ DALI_TEST_CHECK(glAbstraction.GetUniformValue<Vector4>("uUniform1", actualValue));
+ DALI_TEST_EQUALS(actualValue, Color::CRIMSON, TEST_LOCATION);
+
+ uint32_t updateStatus = application.GetUpdateStatus();
+
+ DALI_TEST_CHECK(!(updateStatus & Integration::KeepUpdating::STAGE_KEEP_RENDERING));
+
+ // Update for several frames
+ application.SendNotification();
+ application.Render();
+ application.SendNotification();
+ application.Render();
+ application.SendNotification();
+ application.Render();
+ application.SendNotification();
+ application.Render();
+ application.SendNotification();
+ application.Render();
+
+ TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
+ drawTrace.Enable(true);
+ drawTrace.Reset();
+
+ std::vector<UniformData> customUniforms{{"uShader2Only", Property::VECTOR4}};
+
+ application.GetGraphicsController().AddCustomUniforms(customUniforms);
+
+ // Change shader.
+ renderer.SetShader(shader2);
+
+ // Render and check the update status
+ application.SendNotification();
+ application.Render(0);
+
+ updateStatus = application.GetUpdateStatus();
+
+ DALI_TEST_CHECK(!(updateStatus & Integration::KeepUpdating::STAGE_KEEP_RENDERING));
+
+ DALI_TEST_EQUALS(drawTrace.CountMethod("DrawElements"), 1, TEST_LOCATION);
+
+ // Check uUniform2 rendered now
+ DALI_TEST_CHECK(glAbstraction.GetUniformValue<Vector4>("uShader2Only", actualValue));
+ DALI_TEST_EQUALS(actualValue, Color::AQUA_MARINE, TEST_LOCATION);
+
+ END_TEST;
+}
+
int UtcDaliRendererAddDrawCommands(void)
{
TestApplication application;
/*
- * 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.
*
*/
+#define ENABLE_VECTOR_ASSERTS
+
#include <dali-test-suite-utils.h>
#include <dali/public-api/dali-core.h>
#include <stdlib.h>
{
VisualProperties() = default;
- VisualProperties(Vector2 offset, Vector2 size, Vector2 origin, Vector2 pivot, Vector4 modes, Vector2 extraSize, Vector3 mixColor)
+ VisualProperties(Vector2 offset, Vector2 size, Vector2 origin, Vector2 pivot, Vector4 modes, Vector2 extraSize, Vector3 mixColor, float preMultipliedAlpha)
: mTransformOffset(offset),
mTransformSize(size),
mTransformOrigin(origin),
mTransformAnchorPoint(pivot),
mTransformOffsetSizeMode(modes),
mExtraSize(extraSize),
- mMixColor(mixColor)
+ mMixColor(mixColor),
+ mPreMultipliedAlpha(preMultipliedAlpha)
{
}
Vector2 mTransformOffset{Vector2::ZERO};
- Vector2 mTransformSize{Vector2::ZERO};
+ Vector2 mTransformSize{Vector2::ONE};
Vector2 mTransformOrigin{Vector2::ZERO};
Vector2 mTransformAnchorPoint{Vector2::ZERO};
Vector4 mTransformOffsetSizeMode{Vector2::ZERO};
Vector2 mExtraSize{Vector2::ZERO};
Vector3 mMixColor{Vector3::ONE};
+ float mPreMultipliedAlpha{0.0f};
static VisualProperties GetPropsAt(float alpha, const VisualProperties& start, const VisualProperties& end)
{
progress.mTransformOffsetSizeMode = end.mTransformOffsetSizeMode;
progress.mTransformOrigin = end.mTransformOrigin;
progress.mTransformAnchorPoint = end.mTransformAnchorPoint;
+ progress.mPreMultipliedAlpha = end.mPreMultipliedAlpha;
return progress;
}
};
"%*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",
+ "%*c mixColor:(%5.3f, %5.3f, %5.3f)\n"
+ "%*c preMultipliedAlpha:(%5.3f)\n",
prefix.c_str(),
props.mTransformOffset.x,
props.mTransformOffset.y,
- prefix.length(),
+ prefix.length() + 1,
' ',
props.mTransformSize.x,
props.mTransformSize.y,
- prefix.length(),
+ prefix.length() + 1,
' ',
props.mTransformOrigin.x,
props.mTransformOrigin.y,
- prefix.length(),
+ prefix.length() + 1,
' ',
props.mTransformAnchorPoint.x,
props.mTransformAnchorPoint.y,
- prefix.length(),
+ prefix.length() + 1,
' ',
props.mTransformOffsetSizeMode.x,
props.mTransformOffsetSizeMode.y,
props.mTransformOffsetSizeMode.z,
props.mTransformOffsetSizeMode.w,
- prefix.length(),
+ prefix.length() + 1,
' ',
props.mExtraSize.x,
props.mExtraSize.y,
- prefix.length(),
+ prefix.length() + 1,
' ',
props.mMixColor.x,
props.mMixColor.y,
- props.mMixColor.z);
+ props.mMixColor.z,
+ prefix.length() + 1,
+ ' ',
+ props.mPreMultipliedAlpha);
}
void SetVisualProperties(VisualRenderer renderer, VisualProperties props)
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);
+ renderer.SetProperty(VisualRenderer::Property::VISUAL_PRE_MULTIPLIED_ALPHA, props.mPreMultipliedAlpha);
}
void CheckEventVisualProperties(VisualRenderer renderer, VisualProperties expectedProps)
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);
+ actualProps.mPreMultipliedAlpha = renderer.GetProperty<float>(VisualRenderer::Property::VISUAL_PRE_MULTIPLIED_ALPHA);
PrintVisualProperties(actualProps, "Actual event props");
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);
+ DALI_TEST_EQUALS(actualProps.mPreMultipliedAlpha, expectedProps.mPreMultipliedAlpha, TEST_LOCATION);
}
void CheckSceneGraphVisualProperties(VisualRenderer renderer, VisualProperties expectedProps)
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);
+ actualProps.mPreMultipliedAlpha = renderer.GetProperty<float>(VisualRenderer::Property::VISUAL_PRE_MULTIPLIED_ALPHA);
PrintVisualProperties(actualProps, "Actual update props");
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);
+ DALI_TEST_EQUALS(actualProps.mPreMultipliedAlpha, expectedProps.mPreMultipliedAlpha, TEST_LOCATION);
}
void CheckUniforms(VisualRenderer renderer, VisualProperties props, std::vector<UniformData>& uniforms, TraceCallStack& callStack, TestGlAbstraction& gl)
DALI_TEST_CHECK(callStack.FindMethodAndGetParameters(uniforms[6].name, params));
DALI_TEST_CHECK(gl.GetUniformValue<Vector3>(uniforms[6].name.c_str(), props.mMixColor));
+
+ DALI_TEST_CHECK(callStack.FindMethodAndGetParameters(uniforms[7].name, params));
+ DALI_TEST_CHECK(gl.GetUniformValue<float>(uniforms[7].name.c_str(), props.mPreMultipliedAlpha));
}
int UtcDaliVisualRendererAnimatedProperty03(void)
{"anchorPoint", Property::VECTOR2},
{"offsetSizeMode", Property::VECTOR4},
{"extraSize", Property::VECTOR2},
- {"mixColor", Property::VECTOR3}};
+ {"mixColor", Property::VECTOR3},
+ {"preMultipliedAlpha", Property::FLOAT}};
application.GetGraphicsController().AddCustomUniforms(customUniforms);
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)};
+ 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), 0.0f};
+ 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), 0.0f};
SetVisualProperties(renderer, props);
CheckEventVisualProperties(renderer, props);
DALI_TEST_EQUALS(renderer.GetProperty<float>(DevelRenderer::Property::OPACITY), 0.0f, 0.0001f, TEST_LOCATION);
END_TEST;
}
+
+int UtcDaliVisualRendererPartialUpdate(void)
+{
+ TestApplication application(
+ TestApplication::DEFAULT_SURFACE_WIDTH,
+ TestApplication::DEFAULT_SURFACE_HEIGHT,
+ TestApplication::DEFAULT_HORIZONTAL_DPI,
+ TestApplication::DEFAULT_VERTICAL_DPI,
+ true,
+ true);
+
+ tet_infoline("Test that partial update works well when we set visual renderer's animated properties");
+
+ const TestGlAbstraction::ScissorParams& glScissorParams(application.GetGlAbstraction().GetScissorParams());
+
+ Shader shader = Shader::New("VertexSource", "FragmentSource");
+ Geometry geometry = CreateQuadGeometry();
+ VisualRenderer renderer = VisualRenderer::New(geometry, shader);
+
+ Actor actor = Actor::New();
+ actor.AddRenderer(renderer);
+ actor[Actor::Property::ANCHOR_POINT] = AnchorPoint::TOP_LEFT;
+ actor[Actor::Property::POSITION] = Vector3(64.0f, 64.0f, 0.0f);
+ actor[Actor::Property::SIZE] = Vector3(64.0f, 64.0f, 0.0f);
+ actor.SetResizePolicy(ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS);
+ application.GetScene().Add(actor);
+
+ application.SendNotification();
+
+ std::vector<Rect<int>> damagedRects;
+
+ // Actor added, damaged rect is added size of actor
+ application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+ DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+
+ // Aligned by 16
+ Rect<int> clippingRect = Rect<int>(64, 672, 80, 80); // in screen coordinates, includes 3 last frames updates
+ DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+ DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION);
+ DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION);
+ DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION);
+ DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION);
+
+ damagedRects.clear();
+ application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ damagedRects.clear();
+ application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ // Set clippingRect as full surface now. TODO : Set valid rect if we can.
+ clippingRect = TestApplication::DEFAULT_SURFACE_RECT;
+
+ Property::Index index = VisualRenderer::Property::TRANSFORM_SIZE;
+ renderer.SetProperty(index, Vector2(2.0f, 0.5f));
+
+ // Now current actor show as 128x32 rectangle, with center position (96, 96).
+ // So, rectangle's top left position is (32, 80), and bottom right position is (160, 112).
+ // NOTE : VisualTransform's anchor point is not relative with actor's anchor point
+
+ application.SendNotification();
+ damagedRects.clear();
+ application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+ DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+ // Aligned by 16
+ // Note, this damagedRect is combine of previous rect and current rect
+ DALI_TEST_EQUALS<Rect<int>>(Rect<int>(32, 672, 144, 80), damagedRects[0], TEST_LOCATION);
+
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ application.SendNotification();
+ damagedRects.clear();
+ application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ // Update dummy property to damangeRect buffer aging
+ actor.SetProperty(Actor::Property::COLOR, Color::RED);
+
+ application.SendNotification();
+ damagedRects.clear();
+ application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+ DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+
+ // Update dummy property to damangeRect buffer aging
+ actor.SetProperty(Actor::Property::COLOR, Color::BLUE);
+
+ application.SendNotification();
+ damagedRects.clear();
+ application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+ DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+
+ // Aligned by 16
+ // Note, this damagedRect don't contain previous rect now.
+ // Current rectangle's top left position is (32, 80), and bottom right position is (160, 112).
+ DALI_TEST_EQUALS<Rect<int>>(Rect<int>(32, 688, 144, 48), damagedRects[0], TEST_LOCATION);
+
+ application.SendNotification();
+ damagedRects.clear();
+ application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ application.SendNotification();
+ damagedRects.clear();
+ application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ application.SendNotification();
+ damagedRects.clear();
+ application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ // 3 frame spended after change actor property. Ensure the damaged rect is empty
+ DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION);
+
+ DALI_TEST_EQUALS(renderer.GetProperty<Vector2>(index), Vector2(2.0f, 0.5f), 0.001f, TEST_LOCATION);
+
+ // Make flickered animation from Vector2(2.0f, 0.5f) --> Vector2(1.0f, 1.0f) --> Vector2(0.5f, 2.0f)
+ // After finish the animation,actor show as 32x128 rectangle, with center position (96, 96).
+ // So, rectangle's top left position is (80, 32), and bottom right position is (112, 160).
+ Animation animation = Animation::New(1.0f);
+ KeyFrames keyFrames = KeyFrames::New();
+ keyFrames.Add(0.0f, Vector2(2.0f, 0.5f));
+ keyFrames.Add(0.299f, Vector2(2.0f, 0.5f));
+ keyFrames.Add(0.301f, Vector2(1.0f, 1.0f));
+ keyFrames.Add(0.699f, Vector2(1.0f, 1.0f));
+ keyFrames.Add(0.701f, Vector2(0.5f, 2.0f));
+ keyFrames.Add(1.0f, Vector2(0.5f, 2.0f));
+ animation.AnimateBetween(Property(renderer, index), keyFrames);
+ animation.Play();
+
+ application.SendNotification();
+ damagedRects.clear();
+ application.PreRenderWithPartialUpdate(200, nullptr, damagedRects); // 200 ms
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ DALI_TEST_EQUALS(renderer.GetCurrentProperty<Vector2>(index), Vector2(2.0f, 0.5f), TEST_LOCATION);
+
+ // 302 ~ 600. TransformSize become Vector2(1.0f, 1.0f)
+ application.SendNotification();
+ damagedRects.clear();
+ application.PreRenderWithPartialUpdate(102, nullptr, damagedRects); // 302 ms
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ DALI_TEST_EQUALS(renderer.GetCurrentProperty<Vector2>(index), Vector2(1.0f, 1.0f), TEST_LOCATION);
+
+ // Update dummy property to damangeRect buffer aging
+ actor.SetProperty(Actor::Property::COLOR, Color::RED);
+
+ application.SendNotification();
+ damagedRects.clear();
+ application.PreRenderWithPartialUpdate(16, nullptr, damagedRects); // 318 ms
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ // Update dummy property to damangeRect buffer aging
+ actor.SetProperty(Actor::Property::COLOR, Color::GREEN);
+
+ application.SendNotification();
+ damagedRects.clear();
+ application.PreRenderWithPartialUpdate(16, nullptr, damagedRects); // 334 ms
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ // Update dummy property to damangeRect buffer aging
+ actor.SetProperty(Actor::Property::COLOR, Color::RED);
+
+ application.SendNotification();
+ damagedRects.clear();
+ application.PreRenderWithPartialUpdate(16, nullptr, damagedRects); // 350 ms
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+ // Aligned by 16
+ DALI_TEST_EQUALS<Rect<int>>(Rect<int>(64, 672, 80, 80), damagedRects[0], TEST_LOCATION);
+
+ application.SendNotification();
+ damagedRects.clear();
+ application.PreRenderWithPartialUpdate(250, nullptr, damagedRects); // 600 ms
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ // 702 ~ 1000. TransformSize become Vector2(0.5f, 2.0f)
+ damagedRects.clear();
+ application.PreRenderWithPartialUpdate(102, nullptr, damagedRects); // 702 ms
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ DALI_TEST_EQUALS(renderer.GetCurrentProperty<Vector2>(index), Vector2(0.5f, 2.0f), TEST_LOCATION);
+
+ // Update dummy property to damangeRect buffer aging
+ actor.SetProperty(Actor::Property::COLOR, Color::GREEN);
+
+ application.SendNotification();
+ damagedRects.clear();
+ application.PreRenderWithPartialUpdate(16, nullptr, damagedRects); // 718 ms
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ // Update dummy property to damangeRect buffer aging
+ actor.SetProperty(Actor::Property::COLOR, Color::BLUE);
+
+ application.SendNotification();
+ damagedRects.clear();
+ application.PreRenderWithPartialUpdate(16, nullptr, damagedRects); // 734 ms
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ // Update dummy property to damangeRect buffer aging
+ actor.SetProperty(Actor::Property::COLOR, Color::RED);
+
+ application.SendNotification();
+ damagedRects.clear();
+ application.PreRenderWithPartialUpdate(16, nullptr, damagedRects); // 750 ms
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+ // Aligned by 16
+ DALI_TEST_EQUALS<Rect<int>>(Rect<int>(80, 640, 48, 144), damagedRects[0], TEST_LOCATION);
+
+ application.SendNotification();
+ damagedRects.clear();
+ application.PreRenderWithPartialUpdate(52, nullptr, damagedRects); // 1002 ms. animation finished.
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ // Check finished value bake.
+ DALI_TEST_EQUALS(renderer.GetProperty<Vector2>(index), Vector2(0.5f, 2.0f), TEST_LOCATION);
+
+ END_TEST;
+}
\ No newline at end of file
#define DALI_INTERNAL_KEY_FRAME_CHANNEL_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.
}
else
{
- auto end = std::find_if(mValues.begin(), mValues.end(), [=](const auto& element) { return element.GetProgress() > progress; });
+ // Find lowest element s.t. progress is greater than progress.
+ // So start->GetProgress() <= progress < end->GetProgress() is satisfied.
+ auto end = std::lower_bound(mValues.begin(), mValues.end(), progress, [](const auto& element, const float& progress) { return element.GetProgress() <= progress; });
auto start = end - 1;
const bool validInterval = (end != mValues.end()) && (start->GetProgress() <= progress);
--- /dev/null
+/*
+ * 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/decorated-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("cornerRadius", VECTOR4, true, true, true, Dali::DecoratedVisualRenderer::Property::CORNER_RADIUS)
+DALI_PROPERTY("cornerRadiusPolicy", FLOAT, true, false, true, Dali::DecoratedVisualRenderer::Property::CORNER_RADIUS_POLICY)
+DALI_PROPERTY("borderlineWidth", FLOAT, true, true, true, Dali::DecoratedVisualRenderer::Property::BORDERLINE_WIDTH)
+DALI_PROPERTY("borderlineColor", VECTOR4, true, true, true, Dali::DecoratedVisualRenderer::Property::BORDERLINE_COLOR)
+DALI_PROPERTY("borderlineOffset", FLOAT, true, true, true, Dali::DecoratedVisualRenderer::Property::BORDERLINE_OFFSET)
+DALI_PROPERTY("blurRadius", FLOAT, true, true, true, Dali::DecoratedVisualRenderer::Property::BLUR_RADIUS)
+DALI_PROPERTY_TABLE_END(Dali::DecoratedVisualRenderer::Property::CORNER_RADIUS, DecoratedVisualRendererDefaultProperties)
+
+BaseHandle Create()
+{
+ return Dali::BaseHandle();
+}
+
+TypeRegistration mType(typeid(Dali::DecoratedVisualRenderer), typeid(Dali::VisualRenderer), Create, DecoratedVisualRendererDefaultProperties);
+
+} // unnamed namespace
+
+DecoratedVisualRendererPtr DecoratedVisualRenderer::New()
+{
+ // create scene object first so it's guaranteed to exist for the event side
+ auto sceneObject = SceneGraph::Renderer::New();
+
+ auto animatableVisualProperties = new AnimatableVisualProperties();
+ auto animatableDecoratedVisualProperties = new AnimatableDecoratedVisualProperties();
+
+ // Append extended properties as AnimatableDecoratedVisualProperties.
+ animatableVisualProperties->mExtendedProperties = animatableDecoratedVisualProperties;
+ animatableVisualProperties->mExtendedPropertiesDeleteFunction = AnimatableDecoratedVisualProperties::DeleteFunction;
+
+ sceneObject->SetVisualProperties(animatableVisualProperties);
+
+ OwnerPointer<SceneGraph::Renderer> transferOwnership(sceneObject);
+ // pass the pointer to base for message passing
+ DecoratedVisualRendererPtr rendererPtr(new DecoratedVisualRenderer(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;
+}
+
+DecoratedVisualRenderer::DecoratedVisualRenderer(const SceneGraph::Renderer* sceneObject)
+: VisualRenderer(sceneObject),
+ mDecoratedPropertyCache(),
+ mAddUniformFlag(0u)
+{
+}
+
+DecoratedVisualRenderer::~DecoratedVisualRenderer()
+{
+ // The scene object will be deleted by ~VisualRenderer
+}
+
+void DecoratedVisualRenderer::SetDefaultProperty(Property::Index index,
+ const Property::Value& propertyValue)
+{
+ if(index < Dali::DecoratedVisualRenderer::Property::DEFAULT_DECORATED_VISUAL_RENDERER_PROPERTY_START_INDEX)
+ {
+ VisualRenderer::SetDefaultProperty(index, propertyValue);
+ }
+ else
+ {
+ switch(index)
+ {
+ case Dali::DecoratedVisualRenderer::Property::CORNER_RADIUS:
+ {
+ if(propertyValue.Get(mDecoratedPropertyCache.mCornerRadius))
+ {
+ const SceneGraph::Renderer& sceneObject = GetVisualRendererSceneObject();
+ auto visualProperties = sceneObject.GetVisualProperties();
+
+ if(visualProperties)
+ {
+ auto decoratedVisualProperties = static_cast<AnimatableDecoratedVisualProperties*>(visualProperties->mExtendedProperties);
+ if(decoratedVisualProperties)
+ {
+ BakeMessage<Vector4>(GetEventThreadServices(), decoratedVisualProperties->mCornerRadius, mDecoratedPropertyCache.mCornerRadius);
+ }
+ }
+ }
+ break;
+ }
+
+ case Dali::DecoratedVisualRenderer::Property::CORNER_RADIUS_POLICY:
+ {
+ if(propertyValue.Get(mDecoratedPropertyCache.mCornerRadiusPolicy))
+ {
+ const SceneGraph::Renderer& sceneObject = GetVisualRendererSceneObject();
+ auto visualProperties = sceneObject.GetVisualProperties();
+
+ if(visualProperties)
+ {
+ auto decoratedVisualProperties = static_cast<AnimatableDecoratedVisualProperties*>(visualProperties->mExtendedProperties);
+ if(decoratedVisualProperties)
+ {
+ BakeMessage<float>(GetEventThreadServices(), decoratedVisualProperties->mCornerRadiusPolicy, mDecoratedPropertyCache.mCornerRadiusPolicy);
+ }
+ }
+ }
+ break;
+ }
+
+ case Dali::DecoratedVisualRenderer::Property::BORDERLINE_WIDTH:
+ {
+ if(propertyValue.Get(mDecoratedPropertyCache.mBorderlineWidth))
+ {
+ const SceneGraph::Renderer& sceneObject = GetVisualRendererSceneObject();
+ auto visualProperties = sceneObject.GetVisualProperties();
+
+ if(visualProperties)
+ {
+ auto decoratedVisualProperties = static_cast<AnimatableDecoratedVisualProperties*>(visualProperties->mExtendedProperties);
+ if(decoratedVisualProperties)
+ {
+ BakeMessage<float>(GetEventThreadServices(), decoratedVisualProperties->mBorderlineWidth, mDecoratedPropertyCache.mBorderlineWidth);
+ }
+ }
+ }
+ break;
+ }
+
+ case Dali::DecoratedVisualRenderer::Property::BORDERLINE_COLOR:
+ {
+ if(propertyValue.Get(mDecoratedPropertyCache.mBorderlineColor))
+ {
+ const SceneGraph::Renderer& sceneObject = GetVisualRendererSceneObject();
+ auto visualProperties = sceneObject.GetVisualProperties();
+
+ if(visualProperties)
+ {
+ auto decoratedVisualProperties = static_cast<AnimatableDecoratedVisualProperties*>(visualProperties->mExtendedProperties);
+ if(decoratedVisualProperties)
+ {
+ BakeMessage<Vector4>(GetEventThreadServices(), decoratedVisualProperties->mBorderlineColor, mDecoratedPropertyCache.mBorderlineColor);
+ }
+ }
+ }
+ break;
+ }
+
+ case Dali::DecoratedVisualRenderer::Property::BORDERLINE_OFFSET:
+ {
+ if(propertyValue.Get(mDecoratedPropertyCache.mBorderlineOffset))
+ {
+ const SceneGraph::Renderer& sceneObject = GetVisualRendererSceneObject();
+ auto visualProperties = sceneObject.GetVisualProperties();
+
+ if(visualProperties)
+ {
+ auto decoratedVisualProperties = static_cast<AnimatableDecoratedVisualProperties*>(visualProperties->mExtendedProperties);
+ if(decoratedVisualProperties)
+ {
+ BakeMessage<float>(GetEventThreadServices(), decoratedVisualProperties->mBorderlineOffset, mDecoratedPropertyCache.mBorderlineOffset);
+ }
+ }
+ }
+ break;
+ }
+
+ case Dali::DecoratedVisualRenderer::Property::BLUR_RADIUS:
+ {
+ if(propertyValue.Get(mDecoratedPropertyCache.mBlurRadius))
+ {
+ const SceneGraph::Renderer& sceneObject = GetVisualRendererSceneObject();
+ auto visualProperties = sceneObject.GetVisualProperties();
+
+ if(visualProperties)
+ {
+ auto decoratedVisualProperties = static_cast<AnimatableDecoratedVisualProperties*>(visualProperties->mExtendedProperties);
+ if(decoratedVisualProperties)
+ {
+ BakeMessage<float>(GetEventThreadServices(), decoratedVisualProperties->mBlurRadius, mDecoratedPropertyCache.mBlurRadius);
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+}
+
+Property::Value DecoratedVisualRenderer::GetDefaultProperty(Property::Index index) const
+{
+ Property::Value value;
+
+ if(index < Dali::DecoratedVisualRenderer::Property::DEFAULT_DECORATED_VISUAL_RENDERER_PROPERTY_START_INDEX)
+ {
+ value = VisualRenderer::GetDefaultProperty(index);
+ }
+ else
+ {
+ switch(index)
+ {
+ case Dali::DecoratedVisualRenderer::Property::CORNER_RADIUS:
+ {
+ value = mDecoratedPropertyCache.mCornerRadius;
+ break;
+ }
+ case Dali::DecoratedVisualRenderer::Property::CORNER_RADIUS_POLICY:
+ {
+ value = mDecoratedPropertyCache.mCornerRadiusPolicy;
+ break;
+ }
+ case Dali::DecoratedVisualRenderer::Property::BORDERLINE_WIDTH:
+ {
+ value = mDecoratedPropertyCache.mBorderlineWidth;
+ break;
+ }
+ case Dali::DecoratedVisualRenderer::Property::BORDERLINE_COLOR:
+ {
+ value = mDecoratedPropertyCache.mBorderlineColor;
+ break;
+ }
+ case Dali::DecoratedVisualRenderer::Property::BORDERLINE_OFFSET:
+ {
+ value = mDecoratedPropertyCache.mBorderlineOffset;
+ break;
+ }
+ case Dali::DecoratedVisualRenderer::Property::BLUR_RADIUS:
+ {
+ value = mDecoratedPropertyCache.mBlurRadius;
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ }
+
+ return value;
+}
+
+Property::Value DecoratedVisualRenderer::GetDefaultPropertyCurrentValue(Property::Index index) const
+{
+ Property::Value value;
+
+ if(index < Dali::DecoratedVisualRenderer::Property::DEFAULT_DECORATED_VISUAL_RENDERER_PROPERTY_START_INDEX)
+ {
+ value = VisualRenderer::GetDefaultPropertyCurrentValue(index);
+ }
+ else
+ {
+ const SceneGraph::Renderer& sceneObject = GetVisualRendererSceneObject();
+
+ switch(index)
+ {
+ case Dali::DecoratedVisualRenderer::Property::CORNER_RADIUS:
+ {
+ auto visualProperties = sceneObject.GetVisualProperties();
+ if(visualProperties)
+ {
+ auto decoratedVisualProperties = static_cast<AnimatableDecoratedVisualProperties*>(visualProperties->mExtendedProperties);
+ if(decoratedVisualProperties)
+ {
+ value = decoratedVisualProperties->mCornerRadius[GetEventThreadServices().GetEventBufferIndex()];
+ }
+ }
+ break;
+ }
+ case Dali::DecoratedVisualRenderer::Property::CORNER_RADIUS_POLICY:
+ {
+ auto visualProperties = sceneObject.GetVisualProperties();
+ if(visualProperties)
+ {
+ auto decoratedVisualProperties = static_cast<AnimatableDecoratedVisualProperties*>(visualProperties->mExtendedProperties);
+ if(decoratedVisualProperties)
+ {
+ value = decoratedVisualProperties->mCornerRadiusPolicy[GetEventThreadServices().GetEventBufferIndex()];
+ }
+ }
+ break;
+ }
+ case Dali::DecoratedVisualRenderer::Property::BORDERLINE_WIDTH:
+ {
+ auto visualProperties = sceneObject.GetVisualProperties();
+ if(visualProperties)
+ {
+ auto decoratedVisualProperties = static_cast<AnimatableDecoratedVisualProperties*>(visualProperties->mExtendedProperties);
+ if(decoratedVisualProperties)
+ {
+ value = decoratedVisualProperties->mBorderlineWidth[GetEventThreadServices().GetEventBufferIndex()];
+ }
+ }
+ break;
+ }
+ case Dali::DecoratedVisualRenderer::Property::BORDERLINE_COLOR:
+ {
+ auto visualProperties = sceneObject.GetVisualProperties();
+ if(visualProperties)
+ {
+ auto decoratedVisualProperties = static_cast<AnimatableDecoratedVisualProperties*>(visualProperties->mExtendedProperties);
+ if(decoratedVisualProperties)
+ {
+ value = decoratedVisualProperties->mBorderlineColor[GetEventThreadServices().GetEventBufferIndex()];
+ }
+ }
+ break;
+ }
+ case Dali::DecoratedVisualRenderer::Property::BORDERLINE_OFFSET:
+ {
+ auto visualProperties = sceneObject.GetVisualProperties();
+ if(visualProperties)
+ {
+ auto decoratedVisualProperties = static_cast<AnimatableDecoratedVisualProperties*>(visualProperties->mExtendedProperties);
+ if(decoratedVisualProperties)
+ {
+ value = decoratedVisualProperties->mBorderlineOffset[GetEventThreadServices().GetEventBufferIndex()];
+ }
+ }
+ break;
+ }
+ case Dali::DecoratedVisualRenderer::Property::BLUR_RADIUS:
+ {
+ auto visualProperties = sceneObject.GetVisualProperties();
+ if(visualProperties)
+ {
+ auto decoratedVisualProperties = static_cast<AnimatableDecoratedVisualProperties*>(visualProperties->mExtendedProperties);
+ if(decoratedVisualProperties)
+ {
+ value = decoratedVisualProperties->mBlurRadius[GetEventThreadServices().GetEventBufferIndex()];
+ }
+ }
+ break;
+ }
+ }
+ }
+ return value;
+}
+
+void DecoratedVisualRenderer::OnNotifyDefaultPropertyAnimation(Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType)
+{
+ if(index < Dali::DecoratedVisualRenderer::Property::DEFAULT_DECORATED_VISUAL_RENDERER_PROPERTY_START_INDEX)
+ {
+ VisualRenderer::OnNotifyDefaultPropertyAnimation(animation, index, value, animationType);
+ }
+ else
+ {
+ switch(animationType)
+ {
+ case Animation::TO:
+ case Animation::BETWEEN:
+ {
+ switch(index)
+ {
+ case Dali::DecoratedVisualRenderer::Property::CORNER_RADIUS:
+ {
+ value.Get(mDecoratedPropertyCache.mCornerRadius);
+ break;
+ }
+ case Dali::DecoratedVisualRenderer::Property::BORDERLINE_WIDTH:
+ {
+ value.Get(mDecoratedPropertyCache.mBorderlineWidth);
+ break;
+ }
+ case Dali::DecoratedVisualRenderer::Property::BORDERLINE_COLOR:
+ {
+ value.Get(mDecoratedPropertyCache.mBorderlineColor);
+ break;
+ }
+ case Dali::DecoratedVisualRenderer::Property::BORDERLINE_OFFSET:
+ {
+ value.Get(mDecoratedPropertyCache.mBorderlineOffset);
+ break;
+ }
+ case Dali::DecoratedVisualRenderer::Property::BLUR_RADIUS:
+ {
+ value.Get(mDecoratedPropertyCache.mBlurRadius);
+ break;
+ }
+ }
+ break;
+ }
+
+ case Animation::BY:
+ {
+ switch(index)
+ {
+ case Dali::DecoratedVisualRenderer::Property::CORNER_RADIUS:
+ {
+ AdjustValue<Vector4>(mDecoratedPropertyCache.mCornerRadius, value);
+ break;
+ }
+ case Dali::DecoratedVisualRenderer::Property::BORDERLINE_WIDTH:
+ {
+ AdjustValue<float>(mDecoratedPropertyCache.mBorderlineWidth, value);
+ break;
+ }
+ case Dali::DecoratedVisualRenderer::Property::BORDERLINE_COLOR:
+ {
+ AdjustValue<Vector4>(mDecoratedPropertyCache.mBorderlineColor, value);
+ break;
+ }
+ case Dali::DecoratedVisualRenderer::Property::BORDERLINE_OFFSET:
+ {
+ AdjustValue<float>(mDecoratedPropertyCache.mBorderlineOffset, value);
+ break;
+ }
+ case Dali::DecoratedVisualRenderer::Property::BLUR_RADIUS:
+ {
+ AdjustValue<float>(mDecoratedPropertyCache.mBlurRadius, value);
+ break;
+ }
+ }
+ break;
+ }
+ }
+ }
+}
+
+const SceneGraph::PropertyBase* DecoratedVisualRenderer::GetSceneObjectAnimatableProperty(Property::Index index) const
+{
+ const SceneGraph::PropertyBase* property = nullptr;
+
+ switch(index)
+ {
+ case Dali::DecoratedVisualRenderer::Property::CORNER_RADIUS:
+ {
+ auto visualProperties = GetVisualRendererSceneObject().GetVisualProperties();
+ if(visualProperties)
+ {
+ auto decoratedVisualProperties = static_cast<AnimatableDecoratedVisualProperties*>(visualProperties->mExtendedProperties);
+ if(decoratedVisualProperties)
+ {
+ property = &decoratedVisualProperties->mCornerRadius;
+ }
+ }
+ break;
+ }
+ case Dali::DecoratedVisualRenderer::Property::BORDERLINE_WIDTH:
+ {
+ auto visualProperties = GetVisualRendererSceneObject().GetVisualProperties();
+ if(visualProperties)
+ {
+ auto decoratedVisualProperties = static_cast<AnimatableDecoratedVisualProperties*>(visualProperties->mExtendedProperties);
+ if(decoratedVisualProperties)
+ {
+ property = &decoratedVisualProperties->mBorderlineWidth;
+ }
+ }
+ break;
+ }
+ case Dali::DecoratedVisualRenderer::Property::BORDERLINE_COLOR:
+ {
+ auto visualProperties = GetVisualRendererSceneObject().GetVisualProperties();
+ if(visualProperties)
+ {
+ auto decoratedVisualProperties = static_cast<AnimatableDecoratedVisualProperties*>(visualProperties->mExtendedProperties);
+ if(decoratedVisualProperties)
+ {
+ property = &decoratedVisualProperties->mBorderlineColor;
+ }
+ }
+ break;
+ }
+ case Dali::DecoratedVisualRenderer::Property::BORDERLINE_OFFSET:
+ {
+ auto visualProperties = GetVisualRendererSceneObject().GetVisualProperties();
+ if(visualProperties)
+ {
+ auto decoratedVisualProperties = static_cast<AnimatableDecoratedVisualProperties*>(visualProperties->mExtendedProperties);
+ if(decoratedVisualProperties)
+ {
+ property = &decoratedVisualProperties->mBorderlineOffset;
+ }
+ }
+ break;
+ }
+ case Dali::DecoratedVisualRenderer::Property::BLUR_RADIUS:
+ {
+ auto visualProperties = GetVisualRendererSceneObject().GetVisualProperties();
+ if(visualProperties)
+ {
+ auto decoratedVisualProperties = static_cast<AnimatableDecoratedVisualProperties*>(visualProperties->mExtendedProperties);
+ if(decoratedVisualProperties)
+ {
+ property = &decoratedVisualProperties->mBlurRadius;
+ }
+ }
+ break;
+ }
+ }
+
+ if(!property)
+ {
+ // not our property, ask base
+ property = VisualRenderer::GetSceneObjectAnimatableProperty(index);
+ }
+
+ return property;
+}
+
+const PropertyInputImpl* DecoratedVisualRenderer::GetSceneObjectInputProperty(Property::Index index) const
+{
+ if(index < Dali::DecoratedVisualRenderer::Property::DEFAULT_DECORATED_VISUAL_RENDERER_PROPERTY_START_INDEX)
+ {
+ return VisualRenderer::GetSceneObjectInputProperty(index);
+ }
+ switch(index)
+ {
+ case Dali::DecoratedVisualRenderer::Property::CORNER_RADIUS_POLICY:
+ {
+ auto visualProperties = GetVisualRendererSceneObject().GetVisualProperties();
+ if(visualProperties)
+ {
+ auto decoratedVisualProperties = static_cast<AnimatableDecoratedVisualProperties*>(visualProperties->mExtendedProperties);
+ if(decoratedVisualProperties)
+ {
+ return &decoratedVisualProperties->mCornerRadiusPolicy;
+ }
+ }
+ break;
+ }
+ default:
+ {
+ return GetSceneObjectAnimatableProperty(index);
+ }
+ }
+ return nullptr;
+}
+
+void DecoratedVisualRenderer::RegisterCornerRadiusUniform()
+{
+ AddUniformFlag(DECORATED_VISUAL_RENDERER_USE_CORNER_RADIUS);
+}
+
+void DecoratedVisualRenderer::RegisterBorderlineUniform()
+{
+ AddUniformFlag(DECORATED_VISUAL_RENDERER_USE_BORDERLINE);
+}
+
+void DecoratedVisualRenderer::RegisterBlurRadiusUniform()
+{
+ AddUniformFlag(DECORATED_VISUAL_RENDERER_USE_BLUR_RADIUS);
+}
+
+void DecoratedVisualRenderer::AddUniformFlag(uint8_t newAddFlag)
+{
+ const uint8_t diffUniformFlag = (~mAddUniformFlag) & newAddFlag;
+ if(diffUniformFlag)
+ {
+ if(diffUniformFlag & DECORATED_VISUAL_RENDERER_USE_CORNER_RADIUS)
+ {
+ AddUniformMapping(Dali::DecoratedVisualRenderer::Property::CORNER_RADIUS, ConstString("cornerRadius"));
+ AddUniformMapping(Dali::DecoratedVisualRenderer::Property::CORNER_RADIUS_POLICY, ConstString("cornerRadiusPolicy"));
+ }
+ if(diffUniformFlag & DECORATED_VISUAL_RENDERER_USE_BORDERLINE)
+ {
+ AddUniformMapping(Dali::DecoratedVisualRenderer::Property::BORDERLINE_WIDTH, ConstString("borderlineWidth"));
+ AddUniformMapping(Dali::DecoratedVisualRenderer::Property::BORDERLINE_COLOR, ConstString("borderlineColor"));
+ AddUniformMapping(Dali::DecoratedVisualRenderer::Property::BORDERLINE_OFFSET, ConstString("borderlineOffset"));
+ }
+ if(diffUniformFlag & DECORATED_VISUAL_RENDERER_USE_BLUR_RADIUS)
+ {
+ AddUniformMapping(Dali::DecoratedVisualRenderer::Property::BLUR_RADIUS, ConstString("blurRadius"));
+ }
+
+ // Note. Let we don't remove UniformMapping due to the performane issue.
+ mAddUniformFlag |= newAddFlag;
+ }
+}
+
+} // namespace Internal
+
+} // namespace Dali
--- /dev/null
+#ifndef DALI_INTERNAL_DECORATED_VISUAL_RENDERER_H
+#define DALI_INTERNAL_DECORATED_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/visual-renderer-impl.h> // Dali::Internal::VisualRenderer
+#include <dali/public-api/rendering/decorated-visual-renderer.h> // Dali::DecoratedVisualRenderer
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+class Renderer;
+}
+
+class DecoratedVisualRenderer;
+using DecoratedVisualRendererPtr = IntrusivePtr<DecoratedVisualRenderer>;
+
+/**
+ * DecoratedVisualRenderer is a VisualRenderer that has additional default properties for toolkit
+ */
+class DecoratedVisualRenderer : public VisualRenderer
+{
+public:
+ /**
+ * Create a new DecoratedVisualRenderer.
+ * @return A smart-pointer to the newly allocated DecoratedVisualRenderer.
+ */
+ static DecoratedVisualRendererPtr New();
+
+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;
+
+public:
+ /**
+ * @copydoc Dali::DecoratedVisualRenderer::RegisterCornerRadiusUniform()
+ */
+ void RegisterCornerRadiusUniform();
+
+ /**
+ * @copydoc Dali::DecoratedVisualRenderer::RegisterBorderlineUniform()
+ */
+ void RegisterBorderlineUniform();
+
+ /**
+ * @copydoc Dali::DecoratedVisualRenderer::RegisterBlurRadiusUniform()
+ */
+ void RegisterBlurRadiusUniform();
+
+protected: // implementation
+ /**
+ * @brief Constructor.
+ *
+ * @param sceneObject the scene graph renderer
+ */
+ DecoratedVisualRenderer(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;
+
+ /**
+ * @brief Add the uniforms for DecoratedVisualRendererUseType.
+ * If that flag didn't appended yet, It will add the uniforms map
+ *
+ * @param[in] newFlag one of DecoratedVisualRendererUseType
+ */
+ void AddUniformFlag(uint8_t newAddFlag);
+
+protected:
+ /**
+ * A reference counted object may only be deleted by calling Unreference()
+ */
+ ~DecoratedVisualRenderer() override;
+
+private:
+ DecoratedVisualRenderer(const DecoratedVisualRenderer&) = delete;
+ DecoratedVisualRenderer& operator=(const DecoratedVisualRenderer&) = delete;
+
+public:
+ enum DecoratedVisualRendererUseType
+ {
+ DECORATED_VISUAL_RENDERER_USE_CORNER_RADIUS = 1,
+ DECORATED_VISUAL_RENDERER_USE_BORDERLINE = 2,
+ DECORATED_VISUAL_RENDERER_USE_BLUR_RADIUS = 4,
+ };
+
+ struct DecoratedVisualPropertyCache
+ {
+ Vector4 mCornerRadius{Vector4::ZERO};
+ float mCornerRadiusPolicy{1.0f};
+ float mBorderlineWidth{0.0f};
+ Vector4 mBorderlineColor{Color::BLACK};
+ float mBorderlineOffset{0.0f};
+ float mBlurRadius{0.0f};
+ };
+
+ struct AnimatableDecoratedVisualProperties
+ {
+ AnimatableDecoratedVisualProperties()
+ : mCornerRadius(Vector4::ZERO),
+ mCornerRadiusPolicy(1.0f),
+ mBorderlineWidth(0.0f),
+ mBorderlineColor(Color::BLACK),
+ mBorderlineOffset(0.0f),
+ mBlurRadius(0.0f),
+ mExtendedPropertiesDeleteFunction(nullptr)
+ {
+ }
+ ~AnimatableDecoratedVisualProperties()
+ {
+ if(mExtendedProperties && mExtendedPropertiesDeleteFunction)
+ {
+ mExtendedPropertiesDeleteFunction(mExtendedProperties);
+ }
+ }
+
+ // Delete function of AnimatableDecoratedVisualProperties* converted as void*
+ constexpr static void DeleteFunction(void* data)
+ {
+ delete static_cast<AnimatableDecoratedVisualProperties*>(data);
+ }
+
+ SceneGraph::AnimatableProperty<Vector4> mCornerRadius;
+ SceneGraph::AnimatableProperty<float> mCornerRadiusPolicy;
+ SceneGraph::AnimatableProperty<float> mBorderlineWidth;
+ SceneGraph::AnimatableProperty<Vector4> mBorderlineColor;
+ SceneGraph::AnimatableProperty<float> mBorderlineOffset;
+ SceneGraph::AnimatableProperty<float> mBlurRadius;
+
+ void* mExtendedProperties{nullptr}; // Enable derived class to extend properties further
+ void (*mExtendedPropertiesDeleteFunction)(void*){nullptr}; // Derived class's custom delete functor
+ };
+
+private:
+ DecoratedVisualPropertyCache mDecoratedPropertyCache;
+
+ uint8_t mAddUniformFlag : 4;
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+inline Internal::DecoratedVisualRenderer& GetImplementation(Dali::DecoratedVisualRenderer& handle)
+{
+ DALI_ASSERT_ALWAYS(handle && "DecoratedVisualRenderer handle is empty");
+
+ BaseObject& object = handle.GetBaseObject();
+
+ return static_cast<Internal::DecoratedVisualRenderer&>(object);
+}
+
+inline const Internal::DecoratedVisualRenderer& GetImplementation(const Dali::DecoratedVisualRenderer& handle)
+{
+ DALI_ASSERT_ALWAYS(handle && "DecoratedVisualRenderer handle is empty");
+
+ const BaseObject& object = handle.GetBaseObject();
+
+ return static_cast<const Internal::DecoratedVisualRenderer&>(object);
+}
+
+} // namespace Dali
+
+#endif // DALI_INTERNAL_DECORATED_VISUAL_RENDERER_H
VisualRenderer::~VisualRenderer()
{
- if(EventThreadServices::IsCoreRunning())
- {
- EventThreadServices& eventThreadServices = GetEventThreadServices();
- SceneGraph::UpdateManager& updateManager = eventThreadServices.GetUpdateManager();
- RemoveRendererMessage(updateManager, GetVisualRendererSceneObject());
-
- eventThreadServices.UnregisterObject(this);
- }
+ // The scene object will be deleted by ~Renderer
}
const SceneGraph::Renderer& VisualRenderer::GetVisualRendererSceneObject() const
*/
const PropertyInputImpl* GetSceneObjectInputProperty(Property::Index index) const override;
-private: // implementation
+protected: // implementation
/**
* @brief Constructor.
*
*/
bool GetCurrentPropertyValue(Property::Index index, Property::Value& value) const;
+ /**
+ * @brief Ensure that properties are mapped to uniforms
+ */
+ void AddUniformMappings();
+
protected:
/**
* A reference counted object may only be deleted by calling Unreference()
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 mTransformSize{Vector2::ONE};
Vector2 mTransformOrigin{Vector2::ZERO};
Vector2 mTransformAnchorPoint{Vector2::ZERO};
Vector4 mTransformOffsetSizeMode{Vector2::ZERO};
{
AnimatableVisualProperties()
: mTransformOffset(Vector2::ZERO),
- mTransformSize(Vector2::ZERO),
+ mTransformSize(Vector2::ONE),
mTransformOrigin(Vector2::ZERO),
mTransformAnchorPoint(Vector2::ZERO),
mTransformOffsetSizeMode(Vector4::ZERO),
mExtraSize(Vector2::ZERO),
mMixColor(Vector3::ONE),
- mPreMultipliedAlpha(0.0f)
+ mPreMultipliedAlpha(0.0f),
+ mExtendedPropertiesDeleteFunction(nullptr)
+ {
+ }
+
+ ~AnimatableVisualProperties()
{
+ if(mExtendedProperties && mExtendedPropertiesDeleteFunction)
+ {
+ mExtendedPropertiesDeleteFunction(mExtendedProperties);
+ }
}
SceneGraph::AnimatableProperty<Vector2> mTransformOffset;
SceneGraph::AnimatableProperty<Vector3> mMixColor;
SceneGraph::AnimatableProperty<float> mPreMultipliedAlpha;
- void* mExtendedProperties{nullptr}; // Enable derived class to extend properties further
+ void* mExtendedProperties{nullptr}; // Enable derived class to extend properties further
+ void (*mExtendedPropertiesDeleteFunction)(void*){nullptr}; // Derived class's custom delete functor
};
private:
} // namespace Dali
-#endif // DALI_INTERNAL_RENDERER_H
+#endif // DALI_INTERNAL_VISUAL_RENDERER_H
${internal_src_dir}/event/images/pixel-data-impl.cpp
${internal_src_dir}/event/render-tasks/render-task-impl.cpp
${internal_src_dir}/event/render-tasks/render-task-list-impl.cpp
+ ${internal_src_dir}/event/rendering/decorated-visual-renderer-impl.cpp
${internal_src_dir}/event/rendering/frame-buffer-impl.cpp
${internal_src_dir}/event/rendering/geometry-impl.cpp
${internal_src_dir}/event/rendering/texture-impl.cpp
// Usual case is to only have 1 node, however we do allow multiple nodes to reuse the same
// renderer, so we have to cache uniform map per render item (node / renderer pair).
- const void* nodePtr = static_cast<const void*>(&node);
- auto iter = std::find_if(mNodeIndexMap.begin(), mNodeIndexMap.end(), [nodePtr](RenderItemLookup& element) { return element.node == nodePtr; });
+ // Specially, if node don't have uniformMap, we mark nodePtr as nullptr.
+ // So, all nodes without uniformMap will share same UniformIndexMap, contains only render data providers.
+ const auto nodePtr = uniformMapNode.Count() ? &node : nullptr;
+
+ const auto nodeChangeCounter = nodePtr ? uniformMapNode.GetChangeCounter() : 0;
+ const auto renderItemMapChangeCounter = uniformMap.GetChangeCounter();
+
+ auto iter = std::find_if(mNodeIndexMap.begin(), mNodeIndexMap.end(), [nodePtr](RenderItemLookup& element) { return element.node == nodePtr; });
int renderItemMapIndex;
if(iter == mNodeIndexMap.end())
{
renderItemMapIndex = mUniformIndexMaps.size();
RenderItemLookup renderItemLookup;
- renderItemLookup.node = &node;
+ renderItemLookup.node = nodePtr;
renderItemLookup.index = renderItemMapIndex;
- renderItemLookup.nodeChangeCounter = uniformMapNode.GetChangeCounter();
- renderItemLookup.renderItemMapChangeCounter = uniformMap.GetChangeCounter();
+ renderItemLookup.nodeChangeCounter = nodeChangeCounter;
+ renderItemLookup.renderItemMapChangeCounter = renderItemMapChangeCounter;
mNodeIndexMap.emplace_back(renderItemLookup);
updateMaps = true;
{
renderItemMapIndex = iter->index;
- updateMaps = (uniformMapNode.GetChangeCounter() != iter->nodeChangeCounter) ||
- (uniformMap.GetChangeCounter() != iter->renderItemMapChangeCounter) ||
+ updateMaps = (nodeChangeCounter != iter->nodeChangeCounter) ||
+ (renderItemMapChangeCounter != iter->renderItemMapChangeCounter) ||
(mUniformIndexMaps[renderItemMapIndex].size() == 0);
- iter->nodeChangeCounter = uniformMapNode.GetChangeCounter();
- iter->renderItemMapChangeCounter = uniformMap.GetChangeCounter();
+ iter->nodeChangeCounter = nodeChangeCounter;
+ iter->renderItemMapChangeCounter = renderItemMapChangeCounter;
}
if(updateMaps || mShaderChanged)
/** Struct to map node to index into mNodeMapCounters and mUniformIndexMaps */
struct RenderItemLookup
{
- const SceneGraph::NodeDataProvider* node{nullptr}; ///<Node key
+ const SceneGraph::NodeDataProvider* node{nullptr}; ///<Node key. It can be nullptr if this NodeIndex don't need node uniform
std::size_t index{0}; ///<Index into mUniformIndexMap
std::size_t nodeChangeCounter{0}; ///<The last known change counter for this node's uniform map
/*
- * 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.
{
// Destroy some discarded objects; these should no longer own any GL resources
mNodeQueue[updateBufferIndex].Clear();
- mShaderQueue[updateBufferIndex].Clear();
mRendererQueue[updateBufferIndex].Clear();
+ mShaderQueue[updateBufferIndex].Clear();
mCameraQueue[updateBufferIndex].Clear();
mSceneQueue[updateBufferIndex].Clear();
}
* @param[in,out] nodeWorldMatrix The world matrix of the node
* @param[in,out] nodeSize The size of the node
* @param[in,out] nodeUpdateSize The update size of the node
+ *
+ * @return True if node use it's own UpdateSizeHint, or z transform occured. False if we use nodeUpdateSize equal with nodeSize.
*/
-inline void SetNodeUpdateSize(Node* node, bool isLayer3d, Matrix& nodeWorldMatrix, Vector3& nodeSize, Vector3& nodeUpdateSize)
+inline bool SetNodeUpdateSize(Node* node, bool isLayer3d, Matrix& nodeWorldMatrix, Vector3& nodeSize, Vector3& nodeUpdateSize)
{
node->GetWorldMatrixAndSize(nodeWorldMatrix, nodeSize);
if(!isLayer3d && nodeWorldMatrix.GetZAxis() == Vector3(0.0f, 0.0f, 1.0f))
{
nodeUpdateSize = nodeSize;
+ return false;
}
+ // Keep nodeUpdateSize as Vector3::ZERO, and return true.
+ return true;
}
else
{
nodeUpdateSize = node->GetUpdateSizeHint();
+ return true;
}
}
Vector3 nodeSize;
Vector3 nodeUpdateSize;
bool nodeUpdateSizeSet(false);
+ bool nodeUpdateSizeUseHint(false);
Matrix nodeModelViewMatrix(false);
bool nodeModelViewMatrixSet(false);
if(inside && !isLayer3d && viewportSet)
{
- SetNodeUpdateSize(node, isLayer3d, nodeWorldMatrix, nodeSize, nodeUpdateSize);
- nodeUpdateSizeSet = true;
+ nodeUpdateSizeUseHint = SetNodeUpdateSize(node, isLayer3d, nodeWorldMatrix, nodeSize, nodeUpdateSize);
+ nodeUpdateSizeSet = true;
const Vector3& scale = node->GetWorldScale(updateBufferIndex);
const Vector3& size = nodeUpdateSize * scale;
item.mTextureSet = renderable.mRenderer->GetTextureSet();
item.mDepthIndex += renderable.mRenderer->GetDepthIndex();
- // Ensure collected map is up to date
- item.mIsUpdated |= renderable.mRenderer->UpdateUniformMap();
+ // Get whether collected map is up to date
+ item.mIsUpdated |= renderable.mRenderer->UniformMapUpdated();
}
else
{
if(!nodeUpdateSizeSet)
{
- SetNodeUpdateSize(node, isLayer3d, nodeWorldMatrix, nodeSize, nodeUpdateSize);
+ nodeUpdateSizeUseHint = SetNodeUpdateSize(node, isLayer3d, nodeWorldMatrix, nodeSize, nodeUpdateSize);
}
item.mSize = nodeSize;
item.mUpdateSize = nodeUpdateSize;
item.mModelMatrix = nodeWorldMatrix;
+ // Apply transform informations if node doesn't have update size hint and use VisualRenderer.
+ if(!nodeUpdateSizeUseHint && renderable.mRenderer && renderable.mRenderer->GetVisualProperties())
+ {
+ item.mUpdateSize = renderable.mRenderer->CalculateVisualTransformedUpdateSize(updateBufferIndex, item.mUpdateSize);
+ }
+
if(!nodeModelViewMatrixSet)
{
Matrix::Multiply(nodeModelViewMatrix, nodeWorldMatrix, viewMatrix);
scenes.clear();
delete sceneController;
+
+ // Ensure to clear renderers
+ renderers.Clear();
+ shaders.Clear();
}
/**
#include <dali/internal/common/blending-options.h>
#include <dali/internal/common/internal-constants.h>
#include <dali/internal/common/memory-pool-object-allocator.h>
+#include <dali/internal/event/rendering/decorated-visual-renderer-impl.h> // For DecoratedVisualRenderer::AnimatableDecoratedVisualProperties
#include <dali/internal/render/data-providers/node-data-provider.h>
#include <dali/internal/render/data-providers/render-data-provider.h>
#include <dali/internal/render/queue/render-queue.h>
#include <dali/internal/update/nodes/node.h>
#include <dali/internal/update/rendering/scene-graph-texture-set.h>
+#include <dali/integration-api/debug.h>
+
namespace Dali
{
namespace Internal
{
namespace // unnamed namespace
{
+#ifdef DEBUG_ENABLED
+Debug::Filter* gSceneGraphRendererLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_SG_RENDERER");
+#endif
+
//Memory pool used to allocate new renderers. Memory used by this pool will be released when shutting down DALi
MemoryPoolObjectAllocator<Renderer> gRendererMemoryPool;
mRenderingBehavior(DevelRenderer::Rendering::IF_REQUIRED),
mUpdateDecay(Renderer::Decay::INITIAL),
mRegenerateUniformMap(false),
+ mUniformMapUpdated(false),
mPremultipledAlphaEnabled(false),
mOpacity(1.0f),
mDepthIndex(0)
mResendFlag = 0;
}
+ // Ensure collected map is up to date
+ UpdateUniformMap();
+
return rendererUpdated;
}
return opacityType;
}
-bool Renderer::UpdateUniformMap()
+void Renderer::UpdateUniformMap()
{
- bool updated = false;
-
if(mRegenerateUniformMap)
{
CollectedUniformMap& localMap = mCollectedUniformMap;
}
localMap.UpdateChangeCounter();
mRegenerateUniformMap = false;
- updated = true;
+ mUniformMapUpdated = true;
}
- return updated;
}
void Renderer::SetDrawCommands(Dali::DevelRenderer::DrawCommand* pDrawCommands, uint32_t size)
return mCollectedUniformMap;
}
+Vector3 Renderer::CalculateVisualTransformedUpdateSize(BufferIndex updateBufferIndex, const Vector3& originalSize)
+{
+ if(mVisualProperties)
+ {
+ // TODO : We may need to get some method that visual properties changed, without hash.
+ // Or, need to call this API in PreRender side.
+
+ uint64_t hash = 0xc70f6907UL;
+
+ hash = mVisualProperties->mTransformOffset.Hash(updateBufferIndex, hash);
+ hash = mVisualProperties->mTransformOffsetSizeMode.Hash(updateBufferIndex, hash);
+ hash = mVisualProperties->mTransformSize.Hash(updateBufferIndex, hash);
+ hash = mVisualProperties->mTransformOrigin.Hash(updateBufferIndex, hash);
+ hash = mVisualProperties->mTransformAnchorPoint.Hash(updateBufferIndex, hash);
+ hash = mVisualProperties->mExtraSize.Hash(updateBufferIndex, hash);
+
+ if(mVisualPropertiesCoefficient.hash != hash)
+ {
+ mVisualPropertiesCoefficient.hash = hash;
+
+ // VisualProperty
+ const Vector2 transformOffset = mVisualProperties->mTransformOffset.Get(updateBufferIndex);
+ const Vector4 transformOffsetSizeMode = mVisualProperties->mTransformOffsetSizeMode.Get(updateBufferIndex);
+ const Vector2 transformSize = mVisualProperties->mTransformSize.Get(updateBufferIndex);
+ const Vector2 transformOrigin = mVisualProperties->mTransformOrigin.Get(updateBufferIndex);
+ const Vector2 transformAnchorPoint = mVisualProperties->mTransformAnchorPoint.Get(updateBufferIndex);
+ const Vector2 extraSize = mVisualProperties->mExtraSize.Get(updateBufferIndex);
+
+ DALI_LOG_INFO(gSceneGraphRendererLogFilter, Debug::Verbose, "transform size %5.3f %5.3f\n", transformSize.x, transformSize.y);
+ DALI_LOG_INFO(gSceneGraphRendererLogFilter, Debug::Verbose, "transform offset %5.3f %5.3f\n", transformOffset.x, transformOffset.y);
+ DALI_LOG_INFO(gSceneGraphRendererLogFilter, Debug::Verbose, "transform origin %5.3f %5.3f\n", transformOrigin.x, transformOrigin.y);
+ DALI_LOG_INFO(gSceneGraphRendererLogFilter, Debug::Verbose, "transform anchor %5.3f %5.3f\n", transformAnchorPoint.x, transformAnchorPoint.y);
+ DALI_LOG_INFO(gSceneGraphRendererLogFilter, Debug::Verbose, "extra size %5.3f %5.3f\n", extraSize.x, extraSize.y);
+
+ // const Vector2 visualSize = Vector2(Dali::Lerp(transformOffsetSizeMode.z, originalSize.x * transformSize.x, transformSize.x),
+ // Dali::Lerp(transformOffsetSizeMode.w, originalSize.y * transformSize.y, transformSize.y)) +
+ // extraSize;
+ // const Vector2 visualOffset = Vector2(Dali::Lerp(transformOffsetSizeMode.x, originalSize.x * transformOffset.x, transformOffset.x),
+ // Dali::Lerp(transformOffsetSizeMode.y, originalSize.y * transformOffset.y, transformOffset.y));
+
+ // const float decoratedBorderlineWidth = std::max((1.0f + Dali::Clamp(borderlineOffset, -1.0f, 1.0f)) * borderlineWidth, 2.0f * blurRadius);
+ // const Vector2 decoratedVisualSize = visualSize + Vector2(decoratedBorderlineWidth, decoratedBorderlineWidth);
+
+ // Note : vertexPositoin.xy = aPosition * decoratedVisualSize
+ // + anchorPoint * visualSize
+ // + origin * uSize.xy
+ // + visualOffset;
+
+ // Calculate same logic of visual's vertex shader transform.
+ // minVertexPosition = -0.5f * decoratedVisualSize + transformAnchorPoint * visualSize + transformOrigin * originalSize.xy + visualOffset
+ // maxVertexPosition = 0.5f * decoratedVisualSize + transformAnchorPoint * visualSize + transformOrigin * originalSize.xy + visualOffset
+
+ // Update cached VisualTransformedUpdateSizeCoefficientCache
+
+ // Note : vertexPosition = (XA * aPosition + XB) * originalSize + (CA * aPosition + CB) + Vector2(D, D) * aPosition
+
+ // XA = transformSize * (1.0 - transformOffsetSizeMode.zw)
+ // XB = transformSize * (1.0 - transformOffsetSizeMode.zw) * transformAnchorPoint
+ // + transformOffset * (1.0 - transformOffsetSizeMode.xy)
+ // + transformOrigin
+ // CA = transformSize * transformOffsetSizeMode.zw + extraSize
+ // CB = (transformSize * transformOffsetSizeMode.zw + extraSize) * transformAnchorPoint
+ // + transformOffset * transformOffsetSizeMode.xy
+ // D = max((1.0 + clamp(borderlineOffset, -1.0, 1.0)) * borderlineWidth, 2.0 * blurRadius)
+
+ mVisualPropertiesCoefficient.coefXA = transformSize * Vector2(1.0f - transformOffsetSizeMode.z, 1.0f - transformOffsetSizeMode.w);
+ mVisualPropertiesCoefficient.coefXB = mVisualPropertiesCoefficient.coefXA * transformAnchorPoint + transformOffset * Vector2(1.0f - transformOffsetSizeMode.x, 1.0f - transformOffsetSizeMode.y) + transformOrigin;
+ mVisualPropertiesCoefficient.coefCA = transformSize * Vector2(transformOffsetSizeMode.z, transformOffsetSizeMode.w) + extraSize;
+ mVisualPropertiesCoefficient.coefCB = mVisualPropertiesCoefficient.coefCA * transformAnchorPoint + transformOffset * Vector2(transformOffsetSizeMode.x, transformOffsetSizeMode.y);
+ }
+ if(mVisualProperties->mExtendedProperties)
+ {
+ const auto decoratedVisualProperties = static_cast<DecoratedVisualRenderer::AnimatableDecoratedVisualProperties*>(mVisualProperties->mExtendedProperties);
+
+ uint64_t decoratedHash = 0xc70f6907UL;
+
+ decoratedHash = decoratedVisualProperties->mBorderlineWidth.Hash(updateBufferIndex, decoratedHash);
+ decoratedHash = decoratedVisualProperties->mBorderlineOffset.Hash(updateBufferIndex, decoratedHash);
+ decoratedHash = decoratedVisualProperties->mBlurRadius.Hash(updateBufferIndex, decoratedHash);
+
+ if(mVisualPropertiesCoefficient.decoratedHash != decoratedHash)
+ {
+ mVisualPropertiesCoefficient.decoratedHash = decoratedHash;
+
+ // DecoratedVisualProperty
+ const float borderlineWidth = decoratedVisualProperties->mBorderlineWidth.Get(updateBufferIndex);
+ const float borderlineOffset = decoratedVisualProperties->mBorderlineOffset.Get(updateBufferIndex);
+ const float blurRadius = decoratedVisualProperties->mBlurRadius.Get(updateBufferIndex);
+
+ DALI_LOG_INFO(gSceneGraphRendererLogFilter, Debug::Verbose, "borderline width %5.3f\n", borderlineWidth);
+ DALI_LOG_INFO(gSceneGraphRendererLogFilter, Debug::Verbose, "borderline offset %5.3f\n", borderlineOffset);
+ DALI_LOG_INFO(gSceneGraphRendererLogFilter, Debug::Verbose, "blur radius %5.3f\n", blurRadius);
+
+ // D coefficients be used only decoratedVisual.
+ // It can be calculated parallely with transform.
+
+ mVisualPropertiesCoefficient.coefD = std::max((1.0f + Dali::Clamp(borderlineOffset, -1.0f, 1.0f)) * borderlineWidth, 2.0f * blurRadius);
+ }
+ }
+
+ // Calculate vertex position by coefficient
+ // It will reduce the number of operations
+
+ // const Vector2 minVertexPosition = (XA * -0.5 + XB) * originalSize + (CA * -0.5 + CB) + Vector2(D, D) * -0.5;
+ // const Vector2 maxVertexPosition = (XA * +0.5 + XB) * originalSize + (CA * +0.5 + CB) + Vector2(D, D) * +0.5;
+
+ // When we set
+ // basicVertexPosition = XB * originalSize + CB
+ // scaleVertexPosition = XA * originalSize + CA + D
+
+ // --> minVertexPosition = basicVertexPosition + scaleVertexPosition * -0.5
+ // maxVertexPosition = basicVertexPosition + scaleVertexPosition * +0.5
+
+ // Then, resultSize = 2.0f * max(-minVertexPosition, maxVertexPosition);
+ // = 2.0f * max(scaleVertexPosition * 0.5 - basicVertexPosition, scaleVertexPosition * 0.5 + basicVertexPosition)
+ // = scaleVertexPosition + 2.0f * abs(basicVertexPosition)
+ // Cause transform matrix will think center of vertex is (0, 0)
+
+ const Vector2 basicVertexPosition = mVisualPropertiesCoefficient.coefXB * originalSize.GetVectorXY() + mVisualPropertiesCoefficient.coefCB;
+ const Vector2 scaleVertexPosition = mVisualPropertiesCoefficient.coefXA * originalSize.GetVectorXY() + mVisualPropertiesCoefficient.coefCA;
+
+ // VisualTransform don't set z value. Just copy from original z size
+ const Vector3 resultSize = Vector3(scaleVertexPosition.x + 2.0f * abs(basicVertexPosition.x) + mVisualPropertiesCoefficient.coefD,
+ scaleVertexPosition.y + 2.0f * abs(basicVertexPosition.y) + mVisualPropertiesCoefficient.coefD,
+ originalSize.z);
+
+ DALI_LOG_INFO(gSceneGraphRendererLogFilter, Debug::Verbose, "%f %f --> %f %f\n", originalSize.x, originalSize.y, resultSize.x, resultSize.y);
+
+ return resultSize;
+ }
+ return originalSize;
+}
+
} // namespace SceneGraph
} // namespace Internal
} // namespace Dali
* Merge shader uniform map into renderer uniform map if any of the
* maps have changed. Only update uniform map if added to render
* instructions.
- *
- * @return true if map has been updated, false otherwise
*/
- bool UpdateUniformMap();
+ void UpdateUniformMap();
+
+ /**
+ * @brief CHeck if the uniformMap regenerated
+ * @return True if the uniformMap changed after latest checkup.
+ * @note The uniform map updated flag is reset after calling this.
+ */
+ [[nodiscard]] inline bool UniformMapUpdated() noexcept
+ {
+ if(mUniformMapUpdated)
+ {
+ mUniformMapUpdated = false;
+ return true;
+ }
+ return false;
+ }
/**
* Set the given external draw commands on this renderer.
return mVisualProperties.Get();
}
+ /**
+ * @brief Recalculate size after visual properties applied.
+ *
+ * @param[in] updateBufferIndex The current update buffer index.
+ * @param[in] originalSize The original size before apply the visual properties.
+ *
+ * @return The recalculated size after visual properties applied.
+ */
+ Vector3 CalculateVisualTransformedUpdateSize(BufferIndex updateBufferIndex, const Vector3& originalSize);
+
private:
/**
* Protected constructor; See also Renderer::New()
Decay mUpdateDecay : 2; ///< Update decay (aging)
bool mRegenerateUniformMap : 1; ///< true if the map should be regenerated
+ bool mUniformMapUpdated : 1; ///< true if the map regenerated recently.
bool mPremultipledAlphaEnabled : 1; ///< Flag indicating whether the Pre-multiplied Alpha Blending is required
std::vector<Dali::DevelRenderer::DrawCommand> mDrawCommands;
Dali::RenderCallback* mRenderCallback{nullptr};
+ /**
+ * @brief Cached coefficient value when we calculate visual transformed update size.
+ * It can reduce complexity of calculate the vertex position.
+ *
+ * Vector2 vertexPosition = (XA * aPosition + XB) * originalSize + (CA * aPosition + CB) + Vector2(D, D) * aPosition
+ */
+ struct VisualTransformedUpdateSizeCoefficientCache
+ {
+ Vector2 coefXA{Vector2::ZERO};
+ Vector2 coefXB{Vector2::ZERO};
+ Vector2 coefCA{Vector2::ZERO};
+ Vector2 coefCB{Vector2::ZERO};
+ float coefD{0.0f};
+
+ uint64_t hash{0u};
+ uint64_t decoratedHash{0u};
+ };
+ VisualTransformedUpdateSizeCoefficientCache mVisualPropertiesCoefficient; ///< Coefficient value to calculate visual transformed update size by VisualProperties more faster.
+
public:
AnimatableProperty<float> mOpacity; ///< The opacity value
int32_t mDepthIndex; ///< Used only in PrepareRenderInstructions
#define DALI_VECTOR_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.
#include <dali/public-api/common/type-traits.h>
#include <dali/public-api/math/math-utils.h>
+/**
+ * @brief For DALi internal use, asserts are enabled in debug builds.
+ *
+ * For Application use, asserts can be enabled manually.
+ * @SINCE_2_1.23
+ */
+#if defined(DEBUG_ENABLED)
+#define ENABLE_VECTOR_ASSERTS
+#endif
+
+#if defined(ENABLE_VECTOR_ASSERTS)
#define DALI_ASSERT_VECTOR(cond) DALI_ASSERT_ALWAYS(cond)
+#else
+#define DALI_ASSERT_VECTOR(cond)
+#endif
namespace Dali
{
{
const uint32_t CORE_MAJOR_VERSION = 2;
const uint32_t CORE_MINOR_VERSION = 1;
-const uint32_t CORE_MICRO_VERSION = 21;
+const uint32_t CORE_MICRO_VERSION = 23;
const char* const CORE_BUILD_DATE = __DATE__ " " __TIME__;
#ifdef DEBUG_ENABLED
#include <dali/public-api/render-tasks/render-task-list.h>
#include <dali/public-api/render-tasks/render-task.h>
+#include <dali/public-api/rendering/decorated-visual-renderer.h>
#include <dali/public-api/rendering/frame-buffer.h>
#include <dali/public-api/rendering/geometry.h>
#include <dali/public-api/rendering/renderer.h>
${public_api_src_dir}/object/ref-object.cpp
${public_api_src_dir}/render-tasks/render-task.cpp
${public_api_src_dir}/render-tasks/render-task-list.cpp
+ ${public_api_src_dir}/rendering/decorated-visual-renderer.cpp
${public_api_src_dir}/rendering/frame-buffer.cpp
${public_api_src_dir}/rendering/geometry.cpp
${public_api_src_dir}/rendering/vertex-buffer.cpp
SET( public_api_core_rendering_header_files
+ ${public_api_src_dir}/rendering/decorated-visual-renderer.h
${public_api_src_dir}/rendering/frame-buffer.h
${public_api_src_dir}/rendering/geometry.h
${public_api_src_dir}/rendering/vertex-buffer.h
--- /dev/null
+/*
+ * 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/decorated-visual-renderer.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/rendering/decorated-visual-renderer-impl.h>
+
+namespace Dali
+{
+DecoratedVisualRenderer DecoratedVisualRenderer::New(Geometry& geometry, Shader& shader)
+{
+ Internal::DecoratedVisualRendererPtr renderer = Internal::DecoratedVisualRenderer::New();
+ renderer->SetGeometry(GetImplementation(geometry));
+ renderer->SetShader(GetImplementation(shader));
+ return DecoratedVisualRenderer(renderer.Get());
+}
+
+DecoratedVisualRenderer::DecoratedVisualRenderer() = default;
+
+DecoratedVisualRenderer::~DecoratedVisualRenderer() = default;
+
+DecoratedVisualRenderer::DecoratedVisualRenderer(const DecoratedVisualRenderer& handle) = default;
+
+DecoratedVisualRenderer DecoratedVisualRenderer::DownCast(BaseHandle handle)
+{
+ return DecoratedVisualRenderer(dynamic_cast<Dali::Internal::DecoratedVisualRenderer*>(handle.GetObjectPtr()));
+}
+
+DecoratedVisualRenderer& DecoratedVisualRenderer::operator=(const DecoratedVisualRenderer& handle) = default;
+
+DecoratedVisualRenderer::DecoratedVisualRenderer(DecoratedVisualRenderer&& rhs) = default;
+
+DecoratedVisualRenderer& DecoratedVisualRenderer::operator=(DecoratedVisualRenderer&& rhs) = default;
+
+void DecoratedVisualRenderer::RegisterCornerRadiusUniform()
+{
+ GetImplementation(*this).RegisterCornerRadiusUniform();
+}
+
+void DecoratedVisualRenderer::RegisterBorderlineUniform()
+{
+ GetImplementation(*this).RegisterBorderlineUniform();
+}
+
+void DecoratedVisualRenderer::RegisterBlurRadiusUniform()
+{
+ GetImplementation(*this).RegisterBlurRadiusUniform();
+}
+
+DecoratedVisualRenderer::DecoratedVisualRenderer(Internal::DecoratedVisualRenderer* pointer)
+: Dali::VisualRenderer(pointer)
+{
+}
+
+} //namespace Dali
--- /dev/null
+#ifndef DALI_DECOREATED_VISUAL_RENDERER_H
+#define DALI_DECOREATED_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/visual-renderer.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_rendering_effects
+ * @{
+ */
+
+namespace Internal DALI_INTERNAL
+{
+class DecoratedVisualRenderer;
+}
+
+/**
+ * @brief DecoratedVisualRenderer is a handle to a Renderer with extra properties for Toolkit::Visuals with some decoration
+ *
+ * @SINCE_2_1.21
+ */
+class DALI_CORE_API DecoratedVisualRenderer : public VisualRenderer
+{
+public:
+ /**
+ * @brief Enumeration for instances of properties belonging to the DecoratedVisualRenderer class.
+ * @SINCE_2_1.21
+ */
+ struct Property
+ {
+ static constexpr Dali::Property::Index DEFAULT_DECORATED_VISUAL_RENDERER_PROPERTY_START_INDEX = VisualRenderer::Property::DEFAULT_VISUAL_RENDERER_PROPERTY_START_INDEX + DEFAULT_PROPERTY_MAX_COUNT_PER_DERIVATION;
+
+ /**
+ * @brief Enumeration for instances of properties belonging to the DecoratedVisualRenderer class.
+ * @SINCE_2_1.21
+ */
+ enum
+ {
+ /**
+ * @brief The radius for the rounded corners of the visual.
+ * @details Name "cornerRadius", type Property::Vector4, animatable.
+ *
+ * @see Dali::Toolkit::DevelVisual::Property::CORNER_RADIUS
+ * @SINCE_2_1.21
+ * @note The default value is (0, 0, 0, 0).
+ */
+ CORNER_RADIUS = DEFAULT_DECORATED_VISUAL_RENDERER_PROPERTY_START_INDEX,
+
+ /**
+ * @brief Whether the CORNER_RADIUS values are relative (percentage [0.0f to 0.5f] of the control) or absolute (in world units).
+ * @details Name "cornerRadiusPolicy", type Property::FLOAT
+ *
+ * @code
+ * decoratedVisualRenderer.SetProperty( DecoratedVisualRenderer::Property::CORNER_RADIUS_POLICY, Policy::ABSOLUTE );
+ * @endcode
+ *
+ * @see Policy::Type
+ * @see Dali::Toolkit::DevelVisual::Property::CORNER_RADIUS_POLICY
+ * @SINCE_2_1.21
+ * @note The default value is Policy::RELATIVE.
+ */
+ CORNER_RADIUS_POLICY,
+
+ /**
+ * @brief The width for the borderline of the visual.
+ * @details Name "borderlineWidth", type Property::FLOAT, animatable.
+ *
+ * @see Dali::Toolkit::DevelVisual::Property::BORDERLINE_WIDTH
+ * @SINCE_2_1.21
+ * @note The default value is 0.0.
+ */
+ BORDERLINE_WIDTH,
+
+ /**
+ * @brief The color for the borderline of the visual.
+ * @details Name "borderlineColor", type Property::Vector4, animatable.
+ *
+ * @see Dali::Toolkit::DevelVisual::Property::BORDERLINE_COLOR
+ * @SINCE_2_1.21
+ * @note The default value is Color::BLACK.
+ */
+ BORDERLINE_COLOR,
+
+ /**
+ * @brief The offset from the visual borderline (recommend [-1.0f to 1.0f]).
+ * @details Name "borderlineOffset", type Property::FLOAT, animatable.
+ *
+ * @see Dali::Toolkit::DevelVisual::Property::BORDERLINE_OFFSET
+ * @SINCE_2_1.21
+ * @note The default value is 0.0f.
+ */
+ BORDERLINE_OFFSET,
+
+ /**
+ * @brief The blur radius of the visual.
+ * @details Name "blurRadius", type Property::FLOAT, animatable.
+ * If the value is 0, the edge is sharp. Otherwise, the larger the value, the more the edge is blurred.
+ *
+ * @see Dali::Toolkit::DevelColorVisual::Property::BLUR_RADIUS
+ * @SINCE_2_1.21
+ * @note The default value is 0.0f.
+ */
+ BLUR_RADIUS,
+ };
+ };
+
+ /**
+ * @brief Creates a new DecoratedVisualRenderer object.
+ *
+ * @SINCE_2_1.21
+ * @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 DecoratedVisualRenderer New(Geometry& geometry, Shader& shader);
+
+ /**
+ * @brief Default constructor, creates an empty handle
+ *
+ * @SINCE_2_1.21
+ */
+ DecoratedVisualRenderer();
+
+ /**
+ * @brief Destructor.
+ *
+ * @SINCE_2_1.21
+ */
+ ~DecoratedVisualRenderer();
+
+ /**
+ * @brief Copy constructor, creates a new handle to the same object.
+ *
+ * @SINCE_2_1.21
+ * @param[in] handle Handle to an object
+ */
+ DecoratedVisualRenderer(const DecoratedVisualRenderer& handle);
+
+ /**
+ * @brief Downcasts to a decorated visual renderer handle.
+ * If not, a renderer the returned decorated visual renderer handle is left uninitialized.
+ *
+ * @SINCE_2_1.21
+ * @param[in] handle Handle to an object
+ * @return Renderer handle or an uninitialized handle
+ */
+ static DecoratedVisualRenderer DownCast(BaseHandle handle);
+
+ /**
+ * @brief Assignment operator, changes this handle to point at the same object.
+ *
+ * @SINCE_2_1.21
+ * @param[in] handle Handle to an object
+ * @return Reference to the assigned object
+ */
+ DecoratedVisualRenderer& operator=(const DecoratedVisualRenderer& handle);
+
+ /**
+ * @brief Register relate with corner radius uniforms so we can use it as uniform properties.
+ *
+ * @SINCE_2_1.21
+ */
+ void RegisterCornerRadiusUniform();
+
+ /**
+ * @brief Register relate with borderline uniforms so we can use it as uniform properties.
+ *
+ * @SINCE_2_1.21
+ */
+ void RegisterBorderlineUniform();
+
+ /**
+ * @brief Register relate with blur radius uniforms so we can use it as uniform properties.
+ *
+ * @SINCE_2_1.21
+ */
+ void RegisterBlurRadiusUniform();
+
+ /**
+ * @brief Move constructor.
+ *
+ * @SINCE_2_1.21
+ * @param[in] rhs A reference to the moved handle
+ */
+ DecoratedVisualRenderer(DecoratedVisualRenderer&& rhs);
+
+ /**
+ * @brief Move assignment operator.
+ *
+ * @SINCE_2_1.21
+ * @param[in] rhs A reference to the moved handle
+ * @return A reference to this handle
+ */
+ DecoratedVisualRenderer& operator=(DecoratedVisualRenderer&& rhs);
+
+public:
+ /// @cond internal
+ /**
+ * @brief The constructor.
+ * @note Not intended for application developers.
+ * @SINCE_2_1.21
+ * @param[in] pointer A pointer to a newly allocated DecoratedVisualRenderer
+ */
+ explicit DALI_INTERNAL DecoratedVisualRenderer(Internal::DecoratedVisualRenderer* pointer);
+ /// @endcond
+};
+
+/**
+ * @}
+ */
+} //namespace Dali
+
+#endif // DALI_DECOREATED_VISUAL_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.
#include <dali/public-api/signals/base-signal.h>
// EXTERNAL INCLUDES
-#include <algorithm> // remove_if
+#include <unordered_map>
// INTERNAL INCLUDES
#include <dali/integration-api/debug.h>
namespace
{
-const int32_t INVALID_CALLBACK_INDEX = -1;
-
+struct CallbackBasePtrHash
+{
+ std::size_t operator()(const Dali::CallbackBase* callback) const noexcept
+ {
+ std::size_t functionHash = reinterpret_cast<std::size_t>(reinterpret_cast<void*>(callback->mFunction));
+ std::size_t objectHash = reinterpret_cast<std::size_t>(reinterpret_cast<void*>(callback->mImpl.mObjectPointer));
+ return functionHash ^ objectHash;
+ }
+};
+struct CallbackBasePtrEqual
+{
+ bool operator()(const Dali::CallbackBase* lhs, const Dali::CallbackBase* rhs) const noexcept
+ {
+ return (*lhs) == (*rhs);
+ }
+};
} // unnamed namespace
namespace Dali
{
+/**
+ * @brief Extra struct for callback base cache.
+ */
+struct BaseSignal::Impl
+{
+ Impl() = default;
+ ~Impl() = default;
+
+ /**
+ * @brief Get the iterator of connections list by the callback base pointer.
+ * Note that we should compare the 'value' of callback, not pointer.
+ * So, we need to define custom hash & compare functor of callback base pointer.
+ */
+ std::unordered_map<const CallbackBase*, std::list<SignalConnection>::iterator, CallbackBasePtrHash, CallbackBasePtrEqual> mCallbackCache;
+};
+
BaseSignal::BaseSignal()
-: mEmittingFlag(false)
+: mCacheImpl(new BaseSignal::Impl()),
+ mEmittingFlag(false)
{
}
// The signal is being destroyed. We have to inform any slots
// that are connected, that the signal is dead.
- const std::size_t count(mSignalConnections.size());
- for(std::size_t i = 0; i < count; i++)
+ for(auto iter = mSignalConnections.begin(), iterEnd = mSignalConnections.end(); iter != iterEnd; ++iter)
{
- auto& connection = mSignalConnections[i];
+ auto& connection = *iter;
// Note that values are set to NULL in DeleteConnection
if(connection)
connection.Disconnect(this);
}
}
+
+ delete mCacheImpl;
}
void BaseSignal::OnConnect(CallbackBase* callback)
{
DALI_ASSERT_ALWAYS(nullptr != callback && "Invalid member function pointer passed to Connect()");
- int32_t index = FindCallback(callback);
+ auto iter = FindCallback(callback);
// Don't double-connect the same callback
- if(INVALID_CALLBACK_INDEX == index)
+ if(iter == mSignalConnections.end())
{
- // create a new signal connection object, to allow the signal to track the connection.
- //SignalConnection* connection = new SignalConnection(callback);
+ auto newIter = mSignalConnections.insert(mSignalConnections.end(), SignalConnection(callback));
- mSignalConnections.push_back(SignalConnection(callback));
+ // Store inserted iterator for this callback
+ mCacheImpl->mCallbackCache[callback] = newIter;
}
else
{
{
DALI_ASSERT_ALWAYS(nullptr != callback && "Invalid member function pointer passed to Disconnect()");
- int32_t index = FindCallback(callback);
+ auto iter = FindCallback(callback);
- if(index > INVALID_CALLBACK_INDEX)
+ if(iter != mSignalConnections.end())
{
- DeleteConnection(index);
+ DeleteConnection(iter);
}
// call back is a temporary created to find which slot should be disconnected.
DALI_ASSERT_ALWAYS(nullptr != tracker && "Invalid ConnectionTrackerInterface pointer passed to Connect()");
DALI_ASSERT_ALWAYS(nullptr != callback && "Invalid member function pointer passed to Connect()");
- int32_t index = FindCallback(callback);
+ auto iter = FindCallback(callback);
// Don't double-connect the same callback
- if(INVALID_CALLBACK_INDEX == index)
+ if(iter == mSignalConnections.end())
{
- // create a new signal connection object, to allow the signal to track the connection.
- //SignalConnection* connection = new SignalConnection(tracker, callback);
+ auto newIter = mSignalConnections.insert(mSignalConnections.end(), {tracker, callback});
- mSignalConnections.push_back({tracker, callback});
+ // Store inserted iterator for this callback
+ mCacheImpl->mCallbackCache[callback] = newIter;
// Let the connection tracker know that a connection between a signal and a slot has been made.
tracker->SignalConnected(this, callback);
DALI_ASSERT_ALWAYS(nullptr != tracker && "Invalid ConnectionTrackerInterface pointer passed to Disconnect()");
DALI_ASSERT_ALWAYS(nullptr != callback && "Invalid member function pointer passed to Disconnect()");
- int32_t index = FindCallback(callback);
+ auto iter = FindCallback(callback);
- if(index > INVALID_CALLBACK_INDEX)
+ if(iter != mSignalConnections.end())
{
// temporary pointer to disconnected callback
- CallbackBase* disconnectedCallback = mSignalConnections[index].GetCallback();
+ // Note that (*iter).GetCallback() != callback is possible.
+ CallbackBase* disconnectedCallback = (*iter).GetCallback();
// close the signal side connection first.
- DeleteConnection(index);
+ DeleteConnection(iter);
// close the slot side connection
tracker->SignalDisconnected(this, disconnectedCallback);
// for SlotObserver::SlotDisconnected
void BaseSignal::SlotDisconnected(CallbackBase* callback)
{
- const std::size_t count(mSignalConnections.size());
- for(std::size_t i = 0; i < count; ++i)
- {
- const CallbackBase* connectionCallback = GetCallback(i);
-
- // Pointer comparison i.e. SignalConnection contains pointer to same callback instance
- if(connectionCallback &&
- connectionCallback == callback)
- {
- DeleteConnection(i);
+ DALI_ASSERT_ALWAYS(nullptr != callback && "Invalid callback function passed to SlotObserver::SlotDisconnected()");
- // Disconnection complete
- return;
- }
+ auto iter = FindCallback(callback);
+ if(DALI_LIKELY(iter != mSignalConnections.end()))
+ {
+ DeleteConnection(iter);
+ return;
}
DALI_ABORT("Callback lost in SlotDisconnected()");
}
-int32_t BaseSignal::FindCallback(CallbackBase* callback) const noexcept
+std::list<SignalConnection>::iterator BaseSignal::FindCallback(CallbackBase* callback) noexcept
{
- int32_t index(INVALID_CALLBACK_INDEX);
+ const auto& convertorIter = mCacheImpl->mCallbackCache.find(callback);
- // A signal can have multiple slots connected to it.
- // We need to search for the slot which has the same call back function (if it's static)
- // Or the same object / member function (for non-static)
- for(auto i = 0u; i < mSignalConnections.size(); ++i)
+ if(convertorIter != mCacheImpl->mCallbackCache.end())
{
- const CallbackBase* connectionCallback = GetCallback(i);
+ const auto& iter = convertorIter->second; // std::list<SignalConnection>::iterator
- // Note that values are set to NULL in DeleteConnection
- if(connectionCallback && (*connectionCallback == *callback))
+ if(*iter) // the value of iterator can be null.
{
- index = static_cast<int>(i); // only 2,147,483,647 connections supported, no error check
- break;
+ if(*(iter->GetCallback()) == *callback)
+ {
+ return iter;
+ }
}
}
-
- return index;
+ return mSignalConnections.end();
}
-void BaseSignal::DeleteConnection(std::size_t connectionIndex)
+void BaseSignal::DeleteConnection(std::list<SignalConnection>::iterator iter)
{
+ // Erase cache first.
+ mCacheImpl->mCallbackCache.erase(iter->GetCallback());
+
if(mEmittingFlag)
{
// IMPORTANT - do not remove from items from mSignalConnections, reset instead.
// Signal Emit() methods require that connection count is not reduced while iterating
// i.e. DeleteConnection can be called from within callbacks, while iterating through mSignalConnections.
- mSignalConnections[connectionIndex] = {nullptr};
+ (*iter) = {nullptr};
++mNullConnections;
}
else
{
// If application connects and disconnects without the signal never emitting,
// the mSignalConnections vector keeps growing and growing as CleanupConnections() is done from Emit.
- mSignalConnections.erase(mSignalConnections.begin() + connectionIndex);
+ mSignalConnections.erase(iter);
}
}
if(!mSignalConnections.empty())
{
//Remove Signals that are already markeed nullptr.
- mSignalConnections.erase(std::remove_if(mSignalConnections.begin(),
- mSignalConnections.end(),
- [](auto& elm) { return (elm) ? false : true; }),
- mSignalConnections.end());
+ mSignalConnections.remove_if([](auto& elem) { return (elem) ? false : true; });
}
mNullConnections = 0;
}
#define DALI_BASE_SIGNAL_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.
*/
// EXTERNAL INCLUDES
-#include <vector>
+#include <stdint.h> // for uint32_t
// INTERNAL INCLUDES
#include <dali/public-api/common/dali-common.h>
-#include <dali/public-api/common/dali-vector.h>
+#include <dali/public-api/common/list-wrapper.h>
#include <dali/public-api/signals/callback.h>
#include <dali/public-api/signals/connection-tracker-interface.h>
#include <dali/public-api/signals/signal-slot-connections.h>
// If more connections are added by callbacks, these are ignore until the next Emit()
// Note that count cannot be reduced while iterating
- const std::size_t initialCount(mSignalConnections.size());
-
- for(std::size_t i = 0; i < initialCount; ++i)
+ auto count = mSignalConnections.size();
+ auto iter = mSignalConnections.begin();
+ while(count--)
{
- CallbackBase* callback(GetCallback(i));
-
- // Note that connections will be set to NULL when disconnected
- // This is preferable to reducing the connection count while iterating
+ CallbackBase* callback((*iter) ? iter->GetCallback() : nullptr);
+ ++iter;
if(callback)
{
returnVal = CallbackBase::ExecuteReturn<Ret, Args...>(*callback, args...);
// If more connections are added by callbacks, these are ignore until the next Emit()
// Note that count cannot be reduced while iterating
- const std::size_t initialCount(mSignalConnections.size());
-
- for(std::size_t i = 0; i < initialCount; ++i)
+ auto count = mSignalConnections.size();
+ auto iter = mSignalConnections.begin();
+ while(count--)
{
- CallbackBase* callback(GetCallback(i));
-
- // Note that connections will be set to NULL when disconnected
- // This is preferable to reducing the connection count while iterating
+ CallbackBase* callback((*iter) ? iter->GetCallback() : nullptr);
+ ++iter;
if(callback)
{
CallbackBase::Execute<Args...>(*callback, args...);
private:
/**
- * @brief Returns a callback given an index in to the connection array.
- *
- * @SINCE_1_0.0
- * @param[in] connectionIndex The index of the callback
- * @return The callback, or NULL if the connection has been deleted
- */
- CallbackBase* GetCallback(std::size_t connectionIndex) const noexcept
- {
- return mSignalConnections[connectionIndex].GetCallback();
- }
-
- /**
* @brief Helper to find whether a callback is connected.
*
- * @SINCE_1_0.0
+ * @SINCE_2_1.22
* @param[in] callback The call back object
* @return A valid index if the callback is connected
*/
- int32_t FindCallback(CallbackBase* callback) const noexcept;
+ std::list<SignalConnection>::iterator FindCallback(CallbackBase* callback) noexcept;
/**
* @brief Deletes a connection object from the list of connections.
*
- * @SINCE_1_0.0
- * @param[in] connectionIndex The index of the callback
+ * @SINCE_2_1.22
+ * @param[in] iter The index of the callback
*/
- void DeleteConnection(std::size_t connectionIndex);
+ void DeleteConnection(std::list<SignalConnection>::iterator iter);
/**
* @brief Helper to remove NULL items from mSignalConnections, which is only safe at the end of Emit()
BaseSignal& operator=(BaseSignal&&) = delete; ///< Deleted move assignment operator. @SINCE_1_9.25
private:
- std::vector<SignalConnection> mSignalConnections; ///< Array of connections
- uint32_t mNullConnections{0}; ///< Empty Connections in the array.
- bool mEmittingFlag{false}; ///< Used to guard against nested Emit() calls.
- bool* mSignalDeleted{nullptr}; ///< Used to guard against deletion during Emit() calls.
+ struct DALI_INTERNAL Impl;
+ Impl* mCacheImpl; ///< Private internal extra data.
+
+private:
+ std::list<SignalConnection> mSignalConnections{}; ///< List of connections
+ uint32_t mNullConnections{0}; ///< Empty Connections in the array.
+ bool mEmittingFlag{false}; ///< Used to guard against nested Emit() calls.
+ bool* mSignalDeleted{nullptr}; ///< Used to guard against deletion during Emit() calls.
};
/**
/*
- * 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.
// CLASS HEADER
#include <dali/public-api/signals/connection-tracker.h>
+// EXTERNAL INCLUDES
+#include <unordered_map>
+
+// INTERNAL INCLUDES
#include <dali/public-api/signals/callback.h>
-#include <dali/public-api/signals/signal-slot-connections.h>
#include <dali/public-api/signals/signal-slot-observers.h>
namespace Dali
{
-ConnectionTracker::ConnectionTracker() = default;
+/**
+ * @brief Extra struct for callback base cache.
+ */
+struct ConnectionTracker::Impl
+{
+ Impl() = default;
+ ~Impl() = default;
+
+ std::unordered_map<CallbackBase*, SlotObserver*> mCallbackCache;
+};
+
+ConnectionTracker::ConnectionTracker()
+: mCacheImpl(new ConnectionTracker::Impl())
+{
+}
ConnectionTracker::~ConnectionTracker()
{
DisconnectAll();
+ delete mCacheImpl;
}
void ConnectionTracker::DisconnectAll()
{
- std::size_t size = mConnections.Size();
-
- for(std::size_t i = 0; i < size; ++i)
+ // Iterate unordered list of CallbackBase / SlotObserver.
+ // Note that we don't need to keep order of ConnectionTracker::SignalConnected
+ for(auto iter = mCacheImpl->mCallbackCache.begin(), iterEnd = mCacheImpl->mCallbackCache.end(); iter != iterEnd; ++iter)
{
- auto& connection = mConnections[i];
+ auto& callbackBase = iter->first;
+ auto& slotObserver = iter->second;
// Tell the signal that the slot is disconnected
- connection.GetSlotObserver()->SlotDisconnected(connection.GetCallback());
+ slotObserver->SlotDisconnected(callbackBase);
}
- mConnections.Clear();
+ mCacheImpl->mCallbackCache.clear();
+ mCacheImpl->mCallbackCache.rehash(0); ///< Note : unordered_map.clear() didn't deallocate memory.
}
void ConnectionTracker::SignalConnected(SlotObserver* slotObserver, CallbackBase* callback)
{
- mConnections.PushBack(SlotConnection(slotObserver, callback));
+ // We can assume that there is no duplicated callback come here
+ mCacheImpl->mCallbackCache[callback] = slotObserver;
}
-void ConnectionTracker::SignalDisconnected(SlotObserver* signal, CallbackBase* callback)
+void ConnectionTracker::SignalDisconnected(SlotObserver* slotObserver, CallbackBase* callback)
{
- std::size_t size = mConnections.Size();
-
- for(std::size_t i = 0; i < size; ++i)
+ // Remove from CallbackBase / SlotObserver list
+ const bool isRemoved = mCacheImpl->mCallbackCache.erase(callback);
+ if(DALI_LIKELY(isRemoved))
{
- auto& connection = mConnections[i];
-
- // Pointer comparison i.e. SignalConnection contains pointer to same callback instance
- if(connection.GetCallback() == callback)
- {
- // Remove from connection list
- mConnections.Erase(mConnections.Begin() + i);
-
- // Disconnection complete
- return;
- }
+ // Disconnection complete
+ return;
}
DALI_ABORT("Callback lost in SignalDisconnected()");
std::size_t ConnectionTracker::GetConnectionCount() const
{
- return mConnections.Size();
+ return mCacheImpl->mCallbackCache.size();
}
} // namespace Dali
#define DALI_CONNECTION_TRACKER_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.
*
*/
+// EXTERNAL INCLUDES
+#include <cstddef> // for std::size_t
+
// INTERNAL INCLUDES
#include <dali/public-api/common/dali-common.h>
-#include <dali/public-api/common/dali-vector.h>
#include <dali/public-api/signals/connection-tracker-interface.h>
-#include <dali/public-api/signals/signal-slot-connections.h>
+#include <dali/public-api/signals/signal-slot-observers.h>
namespace Dali
{
class CallbackBase;
class SlotObserver;
-class SlotConnection;
/**
* @brief Connection tracker concrete implementation.
ConnectionTracker& operator=(ConnectionTracker&&) = delete; ///< Deleted move assignment operator. @SINCE_1_9.25
private:
- Dali::Vector<SlotConnection> mConnections; ///< Vector of connection
+ struct DALI_INTERNAL Impl;
+ Impl* mCacheImpl; ///< Private internal extra data.
};
/**
#define DALI_SIGNAL_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.
// INTERNAL INCLUDES
#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/common/vector-wrapper.h>
#include <dali/public-api/signals/base-signal.h>
#include <dali/public-api/signals/callback.h>
#include <dali/public-api/signals/signal-slot-connections.h>
Name: dali2
Summary: DALi 3D Engine
-Version: 2.1.21
+Version: 2.1.23
Release: 1
Group: System/Libraries
License: Apache-2.0 and BSD-3-Clause and MIT