From: Eunki, Hong Date: Wed, 16 Oct 2024 06:59:18 +0000 (+0900) Subject: Revert "[Tizen] Reset To 2.3.41" X-Git-Tag: accepted/tizen/unified/x/20241017.075831~5 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ddcbf16b4c803d36e1133cf447768ff75516e47b;p=platform%2Fcore%2Fuifw%2Fdali-core.git Revert "[Tizen] Reset To 2.3.41" This reverts commit 5c3baae50c9d362421d2c055dd41cecc9070d7f0. --- diff --git a/automated-tests/src/dali-internal/utc-Dali-Internal-Shader.cpp b/automated-tests/src/dali-internal/utc-Dali-Internal-Shader.cpp index 64fcd7331..5f294a4d1 100644 --- a/automated-tests/src/dali-internal/utc-Dali-Internal-Shader.cpp +++ b/automated-tests/src/dali-internal/utc-Dali-Internal-Shader.cpp @@ -16,6 +16,7 @@ */ #include +#include #include // DALI_PROPERTY_TABLE_BEGIN, DALI_PROPERTY, DALI_PROPERTY_TABLE_END #include #include @@ -97,6 +98,49 @@ int UtcDaliShaderWithPrefixTestVersion(void) END_TEST; } +int UtcDaliShaderWithPrefixTestVersion2(void) +{ + TestApplication application; + + tet_infoline("Test same case of UtcDaliShaderWithPrefixTestVersion with integration api"); + + std::string vertexShader = + "//@version 100\n" + "some code\n"; + std::string fragmentShader = + "//@version 101\n" + "some code\n"; + + // Get prefix from graphics config. + auto vertexPrefix = application.GetGlAbstraction().GetVertexShaderPrefix(); + auto fragmentPrefix = application.GetGlAbstraction().GetFragmentShaderPrefix(); + + // And use GenerateTaggedShaderPrefix from integration-api. + vertexPrefix = Dali::Integration::GenerateTaggedShaderPrefix(vertexPrefix); + fragmentPrefix = Dali::Integration::GenerateTaggedShaderPrefix(fragmentPrefix); + + Dali::Shader shader = Dali::Shader::New( + vertexPrefix + vertexShader, + fragmentPrefix + fragmentShader); + + DALI_TEST_EQUALS(vertexPrefix.substr(0, 20), "//@legacy-prefix-end", TEST_LOCATION); + DALI_TEST_EQUALS(fragmentPrefix.substr(0, 20), "//@legacy-prefix-end", TEST_LOCATION); + + // Test version number in the shader data + Dali::Internal::ThreadLocalStorage& tls = Dali::Internal::ThreadLocalStorage::Get(); + Dali::Internal::ShaderFactory& shaderFactory = tls.GetShaderFactory(); + size_t shaderHash; + Internal::ShaderDataPtr shaderData = shaderFactory.Load(vertexShader, fragmentShader, {}, {}, "", shaderHash); + + bool dataValid = (shaderData != nullptr); + DALI_TEST_EQUALS(dataValid, true, TEST_LOCATION); + + DALI_TEST_EQUALS(shaderData->GetVertexShaderVersion(), 100, TEST_LOCATION); + DALI_TEST_EQUALS(shaderData->GetFragmentShaderVersion(), 101, TEST_LOCATION); + + END_TEST; +} + int UtcDaliInternalShaderSaveAndLoad01(void) { TestApplication application; diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-custom-actor.h b/automated-tests/src/dali/dali-test-suite-utils/test-custom-actor.h index db0c78fbf..dcb2cd88a 100644 --- a/automated-tests/src/dali/dali-test-suite-utils/test-custom-actor.h +++ b/automated-tests/src/dali/dali-test-suite-utils/test-custom-actor.h @@ -169,6 +169,10 @@ public: float TestCalculateChildSizeBase(const Dali::Actor& child, Dali::Dimension::Type dimension); bool TestRelayoutDependentOnChildrenBase(Dali::Dimension::Type dimension); + void GetOffScreenRenderTasks(std::vector& tasks, bool isForward) override + { + } + public: Dali::Property::Index mDaliProperty; std::vector mMethodsCalled; @@ -515,6 +519,10 @@ public: { return false; } + + void GetOffScreenRenderTasks(std::vector& tasks, bool isForward) override + { + } }; } //namespace Impl diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-graphics-controller.cpp b/automated-tests/src/dali/dali-test-suite-utils/test-graphics-controller.cpp index f0bc4d6d5..114879fb4 100644 --- a/automated-tests/src/dali/dali-test-suite-utils/test-graphics-controller.cpp +++ b/automated-tests/src/dali/dali-test-suite-utils/test-graphics-controller.cpp @@ -1505,4 +1505,22 @@ Graphics::UniquePtr TestGraphicsController::ReleaseTextureFro return texture; } +bool TestGraphicsController::HasClipMatrix() const +{ + return true; +} + +const Matrix& TestGraphicsController::GetClipMatrix() const +{ + // This matrix transforms from GL -> Vulkan clip space + constexpr float VULKAN_CLIP_MATRIX_DATA[] = { + 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.5f, 0.0f, 0.0f, 0.0f, 0.5f, 1.0f}; + static const Matrix VULKAN_CLIP_MATRIX(VULKAN_CLIP_MATRIX_DATA); + static const Matrix IDENTITY = Matrix::IDENTITY; + + // For now, return IDENTITY to stay in GL clip space. + // @todo Add test toggle + return IDENTITY; +} + } // namespace Dali diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-graphics-controller.h b/automated-tests/src/dali/dali-test-suite-utils/test-graphics-controller.h index e21c30400..2b0a9b97a 100644 --- a/automated-tests/src/dali/dali-test-suite-utils/test-graphics-controller.h +++ b/automated-tests/src/dali/dali-test-suite-utils/test-graphics-controller.h @@ -422,6 +422,9 @@ public: // ResourceId relative API. */ Graphics::UniquePtr ReleaseTextureFromResourceId(uint32_t resourceId) override; + bool HasClipMatrix() const override; + const Matrix& GetClipMatrix() const override; + public: // Test Functions void SetAutoAttrCreation(bool v) { @@ -499,14 +502,14 @@ public: // Test Functions uint32_t elementStrideInBytes) { TestGraphicsReflection::TestUniformInfo info; - info.name = std::move(name); - info.type = type; - info.uniformClass = Graphics::UniformClass::UNIFORM; - info.numElements = elementCount; - info.locations = {0}; - info.bufferIndex = 0; // this will update when AddCustomUniformBlock called - - auto retval= GetUniformBufferArrayStrideAndTypeSize(info, elementStrideInBytes); + info.name = std::move(name); + info.type = type; + info.uniformClass = Graphics::UniformClass::UNIFORM; + info.numElements = elementCount; + info.locations = {0}; + info.bufferIndex = 0; // this will update when AddCustomUniformBlock called + + auto retval = GetUniformBufferArrayStrideAndTypeSize(info, elementStrideInBytes); info.elementStride = std::max(retval.first, retval.second); info.offsets = {blockInfo.size}; blockInfo.size += (elementCount == 0 ? 1 : elementCount) * std::max(retval.first, retval.second); @@ -567,4 +570,4 @@ public: } // namespace Dali -#endif //TEST_GRAPHICS_CONTROLLER_H +#endif // TEST_GRAPHICS_CONTROLLER_H diff --git a/automated-tests/src/dali/utc-Dali-Animation.cpp b/automated-tests/src/dali/utc-Dali-Animation.cpp index 79855870f..cfbac54e9 100644 --- a/automated-tests/src/dali/utc-Dali-Animation.cpp +++ b/automated-tests/src/dali/utc-Dali-Animation.cpp @@ -24,8 +24,11 @@ #include #include +#include + #include #include +#include using std::max; using namespace Dali; @@ -14564,14 +14567,14 @@ int UtcDaliAnimationAnimateByInvalidParameters(void) // not mathing properties (VECTOR3, FLOAT) animation.AnimateBy(Property(actor, Actor::Property::POSITION), Property::Value(10.f)); }, - "Property and target types don't match"); + "Target types could not be convert to Property type"); DALI_TEST_ASSERTION( { // not mathing properties (VECTOR3.A, VECTOR2) animation.AnimateBy(Property(actor, Actor::Property::COLOR_ALPHA), Property::Value(Property::VECTOR2)); }, - "Property and target types don't match"); + "Target types could not be convert to Property type"); DALI_TEST_ASSERTION( { @@ -14623,19 +14626,12 @@ int UtcDaliAnimationAnimateToInvalidParameters(void) }, "Target value is not animatable"); - DALI_TEST_ASSERTION( - { - // not mathing properties (FLOAT, INT) - animation.AnimateTo(Property(actor, Actor::Property::SCALE_Y), Property::Value(10)); - }, - "Property and target types don't match"); - DALI_TEST_ASSERTION( { // not mathing properties (VECTOR3, VECTOR2) animation.AnimateTo(Property(actor, Actor::Property::COLOR), Property::Value(Property::VECTOR2)); }, - "Property and target types don't match"); + "Target types could not be convert to Property type"); DALI_TEST_ASSERTION( { @@ -14702,7 +14698,7 @@ int UtcDaliAnimationAnimateBetweenInvalidParameters(void) keyframes.Add(0.5f, Property::Value(Vector4(1, 2, 3, 4))); animation.AnimateBetween(Property(actor, Actor::Property::MAXIMUM_SIZE), keyframes); }, - "Property and target types don't match"); + "Target types could not be convert to Property type"); DALI_TEST_ASSERTION( { @@ -14716,6 +14712,130 @@ int UtcDaliAnimationAnimateBetweenInvalidParameters(void) END_TEST; } +int UtcDaliAnimationAnimateConvertPropertyValueParameters(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + application.GetScene().Add(actor); + + // Create the animation + Animation animation = Animation::New(1.0f); + + Property::Index indexBoolean = actor.RegisterProperty("animationBoolean", Property::Value(false), Property::ANIMATABLE); + Property::Index indexFloat = actor.RegisterProperty("animationFloat", Property::Value(0.0f), Property::ANIMATABLE); + Property::Index indexInteger = actor.RegisterProperty("animationInteger", Property::Value(0), Property::ANIMATABLE); + + // clang-format off + const std::vector> indexValueList = + { + {indexBoolean, actor.GetProperty(indexBoolean)}, + {indexFloat, actor.GetProperty(indexFloat)}, + {indexInteger, actor.GetProperty(indexInteger)}, + }; + + // Piar of relative value - {except value as relative value per each type of properties} + const std::vector>> testExceptValueList = + { + { + Property::Value(true), + { + Property::Value(true), Property::Value(1.0f), Property::Value(1), + } + }, + { + Property::Value(2.0f), + { + Property::Value(true), Property::Value(2.0f), Property::Value(2), + } + }, + { + Property::Value(3), + { + Property::Value(true), Property::Value(3.0f), Property::Value(3), + } + }, + }; + // clang-format on + + // Let we test both AnimateBy and AnimateTo and AnimateBetween as one UTC. + for(auto animateType = 0; animateType < 3; ++animateType) + { + tet_printf("Animation type test : %s\n", std::vector({"AnimateBy", "AnimateTo", "AnimateBetween"})[animateType].c_str()); + for(const auto& valueExceptPair : testExceptValueList) + { + { + std::ostringstream oss; + oss << valueExceptPair.first; + tet_printf("Animate required value : %s\n", oss.str().c_str()); + } + for(const auto& indexValuePair : indexValueList) + { + if(animateType == 0u) + { + animation.AnimateBy(Property(actor, indexValuePair.first), valueExceptPair.first); + } + else if(animateType == 1u) + { + animation.AnimateTo(Property(actor, indexValuePair.first), valueExceptPair.first); + } + else if(animateType == 2u) + { + Dali::KeyFrames keyFrames = Dali::KeyFrames::New(); + + // Convert original value type as excepted type. + auto originalValue = indexValuePair.second; + originalValue.ConvertType(valueExceptPair.first.GetType()); + + keyFrames.Add(0.0f, originalValue); + keyFrames.Add(1.0f, valueExceptPair.first); + animation.AnimateBetween(Property(actor, indexValuePair.first), keyFrames); + } + } + animation.Play(); + + const auto& exceptValueList = valueExceptPair.second; + + // Test except value list size is same as index value list size. (All property should have except value) + DALI_TEST_EQUALS(exceptValueList.size(), indexValueList.size(), TEST_LOCATION); + + // Check cached event thread values are expect. + for(auto i = 0u; i < indexValueList.size(); ++i) + { + DALI_TEST_EQUALS(actor.GetProperty(indexValueList[i].first), exceptValueList[i], TEST_LOCATION); + } + + // Check current vaules are not animated yet. + for(auto i = 0u; i < indexValueList.size(); ++i) + { + DALI_TEST_EQUALS(actor.GetCurrentProperty(indexValueList[i].first), indexValueList[i].second, TEST_LOCATION); + } + + application.SendNotification(); + application.Render(500); + application.SendNotification(); + application.Render(500 + 10); ///< Note, we don't allow 1 frame animation finished. To fair test, render 2 frames. + + // Check current vaules are except. + for(auto i = 0u; i < indexValueList.size(); ++i) + { + DALI_TEST_EQUALS(actor.GetCurrentProperty(indexValueList[i].first), exceptValueList[i], TEST_LOCATION); + } + + animation.Clear(); + // Reset to base value, for fair test. + for(const auto& indexValuePair : indexValueList) + { + actor.SetProperty(indexValuePair.first, indexValuePair.second); + } + application.SendNotification(); + application.Render(); + } + } + + END_TEST; +} + namespace // Purposefully left this in the middle as the values in this namespace are only used for the subsequent two test cases { enum TestFunction diff --git a/automated-tests/src/dali/utc-Dali-ConditionalWait.cpp b/automated-tests/src/dali/utc-Dali-ConditionalWait.cpp index 71fe305a9..8641d2d4c 100644 --- a/automated-tests/src/dali/utc-Dali-ConditionalWait.cpp +++ b/automated-tests/src/dali/utc-Dali-ConditionalWait.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * Copyright (c) 2024 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. @@ -77,6 +77,29 @@ class WorkerThreadWaitN : public Thread } }; +class WorkerThreadWaitUntilN : public Thread +{ +public: + WorkerThreadWaitUntilN() + : Thread() + { + auto now = std::chrono::steady_clock::now(); + auto waitDuration = std::chrono::milliseconds(100); // 0.1 second + + mWaitUntilTimePoint = std::chrono::time_point_cast(now + waitDuration); + } + + virtual void Run() + { + ConditionalWait::ScopedLock lock(*gConditionalWait); + + gConditionalWait->WaitUntil(lock, mWaitUntilTimePoint); + } + +private: + ConditionalWait::TimePoint mWaitUntilTimePoint; +}; + } // namespace int UtcConditionalWait1P(void) @@ -254,6 +277,77 @@ int UtcConditionalWait6P(void) END_TEST; } +int UtcConditionalWaitUntilP1(void) +{ + tet_infoline("Testing ConditionalWait - scenario: waituntil now + 100 ms - with 4 threads. No notify"); + + auto utcStartTime = std::chrono::steady_clock::now(); + + // initialize values + gConditionalWait = new ConditionalWait(); + + WorkerThreadWaitUntilN thread1; + thread1.Start(); + WorkerThreadWaitUntilN thread2; + thread2.Start(); + WorkerThreadWaitUntilN thread3; + thread3.Start(); + WorkerThreadWaitUntilN thread4; + thread4.Start(); + + // Let we check thread join well without any notification + + thread1.Join(); + thread2.Join(); + thread3.Join(); + thread4.Join(); + + DALI_TEST_EQUALS(0u, gConditionalWait->GetWaitCount(), TEST_LOCATION); + + auto utcFinishedTime = std::chrono::steady_clock::now(); + + // Check thread join spened at least 100ms + auto elapsedTime = std::chrono::duration_cast(utcFinishedTime - utcStartTime).count(); + + DALI_TEST_GREATER(elapsedTime, static_cast(100 - 1), TEST_LOCATION); // 100ms is the minimum time for the threads to wait + + delete gConditionalWait; + END_TEST; +} + +int UtcConditionalWaitUntilP2(void) +{ + tet_infoline("Testing ConditionalWait - scenario: waituntil now + 100 ms - notify with 4 threads"); + + // initialize values + gConditionalWait = new ConditionalWait(); + + WorkerThreadWaitUntilN thread1; + thread1.Start(); + WorkerThreadWaitUntilN thread2; + thread2.Start(); + WorkerThreadWaitUntilN thread3; + thread3.Start(); + WorkerThreadWaitUntilN thread4; + thread4.Start(); + + // Notify with scoped lock + { + ConditionalWait::ScopedLock lock(*gConditionalWait); + gConditionalWait->Notify(lock); + } + + thread1.Join(); + thread2.Join(); + thread3.Join(); + thread4.Join(); + + DALI_TEST_EQUALS(0u, gConditionalWait->GetWaitCount(), TEST_LOCATION); + + delete gConditionalWait; + END_TEST; +} + int UtcConditionalWaitNonCopyable(void) { // we want to make sure that ConditionalWait is not copyable (its copy constructor is not defined) diff --git a/automated-tests/src/dali/utc-Dali-CustomActor.cpp b/automated-tests/src/dali/utc-Dali-CustomActor.cpp index 1df10a6df..43ffeac65 100644 --- a/automated-tests/src/dali/utc-Dali-CustomActor.cpp +++ b/automated-tests/src/dali/utc-Dali-CustomActor.cpp @@ -1464,6 +1464,10 @@ struct UnregisteredCustomActor : public Dali::CustomActorImpl virtual void OnLayoutNegotiated(float size, Dimension::Type dimension) { } + + void GetOffScreenRenderTasks(std::vector& tasks, bool isForward) override + { + } }; } // namespace Impl struct UnregisteredCustomActor : public Dali::CustomActor @@ -1709,3 +1713,184 @@ int UtcDaliCustomActorComponentPropertyConstraintsP(void) END_TEST; } + +namespace Impl +{ + +class OffScreenCustomActor : public UnregisteredCustomActor +{ +public: + void OnSceneConnection(int depth) override + { + tet_printf("tyty : %d\n", GetOffScreenRenderableType()); + Dali::Integration::Scene scene = Dali::Integration::Scene::Get(Self()); + if(scene) + { + mScene = scene; + RenderTaskList taskList = scene.GetRenderTaskList(); + mForwardRenderTask = taskList.CreateTask(); + mBackwardRenderTask = taskList.CreateTask(); + FrameBuffer forwardFrameBuffer = FrameBuffer::New(1, 1); + FrameBuffer backwardFrameBuffer = FrameBuffer::New(1, 1); + + mForwardRenderTask.SetFrameBuffer(forwardFrameBuffer); + mBackwardRenderTask.SetFrameBuffer(backwardFrameBuffer); + } + } + + void OnSceneDisconnection() override + { + Dali::Integration::Scene scene = mScene.GetHandle(); + if(scene) + { + RenderTaskList taskList = scene.GetRenderTaskList(); + taskList.RemoveTask(mForwardRenderTask); + taskList.RemoveTask(mBackwardRenderTask); + } + mForwardRenderTask.Reset(); + mBackwardRenderTask.Reset(); + mScene.Reset(); + } + + void GetOffScreenRenderTasks(std::vector& tasks, bool isForward) override + { + tasks.clear(); + if(isForward && GetOffScreenRenderableType() & OffScreenRenderable::Type::FORWARD && mForwardRenderTask) + { + tasks.push_back(mForwardRenderTask); + } + if(!isForward && GetOffScreenRenderableType() & OffScreenRenderable::Type::BACKWARD && mBackwardRenderTask) + { + tasks.push_back(mBackwardRenderTask); + } + } + + Dali::WeakHandle mScene; + Dali::RenderTask mForwardRenderTask; + Dali::RenderTask mBackwardRenderTask; +}; + +} // namespace Impl + +class OffScreenCustomActor : public UnregisteredCustomActor +{ +public: + static OffScreenCustomActor New(OffScreenRenderable::Type type) + { + Impl::OffScreenCustomActor* impl = new Impl::OffScreenCustomActor; + OffScreenCustomActor custom(*impl, type); // takes ownership + return custom; + } + OffScreenCustomActor() + { + } + ~OffScreenCustomActor() + { + } + OffScreenCustomActor(Internal::CustomActor* impl) + : UnregisteredCustomActor(impl) + { + } + OffScreenCustomActor(Impl::OffScreenCustomActor& impl, OffScreenRenderable::Type type) + : UnregisteredCustomActor(impl) + { + mImpl = &impl; + mImpl->SetOffScreenRenderableType(type); + } + Dali::RenderTask GetForwardRenderTask() + { + return mImpl->mForwardRenderTask; + } + Dali::RenderTask GetBackwardRenderTask() + { + return mImpl->mBackwardRenderTask; + } + OffScreenRenderable::Type GetOffScreenRenderableType() + { + tet_printf("type : %d\n", mImpl->GetOffScreenRenderableType()); + return mImpl->GetOffScreenRenderableType(); + } + + Impl::OffScreenCustomActor* mImpl; +}; + +int UtcDaliCustomActorReordering(void) +{ + TestApplication application; // Need the type registry + + DALI_TEST_EQUALS(application.GetScene().GetRenderTaskList().GetTaskCount(), 1, TEST_LOCATION); + + /** + * Al + * / \ + * Bb Cl + * / \ / \ + * D Efb Jb K + * / \ + * Fb Gf + * / \ + * H I + * + * A, C are Layer. C has smaller Depth value than A. + * B, E, F, G, and J are OffScreenCustomActor. + * B, F, and J are Type BACKWARD. + * E and G are Type FORWARD. + * + * After reordering, The order of OrderIndex of each RenderTask becomes + * G(Forward) - F(Backward) - E(Forward) - J(BACKWARD) - B(BACKWARD) - E(BACKWARD) + */ + + Layer A_layer = Layer::New(); + OffScreenCustomActor B_offScreenCustomActor = OffScreenCustomActor::New(OffScreenRenderable::Type::BACKWARD); + Layer C_layer = Layer::New(); + Actor D_actor = Actor::New(); + OffScreenCustomActor E_offScreenCustomActor = OffScreenCustomActor::New(OffScreenRenderable::Type::BOTH); + OffScreenCustomActor F_offScreenCustomActor = OffScreenCustomActor::New(OffScreenRenderable::Type::BACKWARD); + OffScreenCustomActor G_offScreenCustomActor = OffScreenCustomActor::New(OffScreenRenderable::Type::FORWARD); + Actor H_actor = Actor::New(); + Actor I_actor = Actor::New(); + OffScreenCustomActor J_offScreenCustomActor = OffScreenCustomActor::New(OffScreenRenderable::Type::BACKWARD); + + A_layer.Add(B_offScreenCustomActor); + A_layer.Add(C_layer); + B_offScreenCustomActor.Add(D_actor); + B_offScreenCustomActor.Add(E_offScreenCustomActor); + E_offScreenCustomActor.Add(F_offScreenCustomActor); + E_offScreenCustomActor.Add(G_offScreenCustomActor); + G_offScreenCustomActor.Add(H_actor); + G_offScreenCustomActor.Add(I_actor); + C_layer.Add(J_offScreenCustomActor); + + DALI_TEST_EQUALS(application.GetScene().GetRenderTaskList().GetTaskCount(), 1, TEST_LOCATION); + tet_printf("task cnt before : %d\n", application.GetScene().GetRenderTaskList().GetTaskCount()); + + application.GetScene().Add(A_layer); + + DALI_TEST_EQUALS(application.GetScene().GetRenderTaskList().GetTaskCount(), 11, TEST_LOCATION); + + C_layer.MoveBelow(A_layer); + + application.GetScene().GetRenderTaskList().GetTaskCount(); + + tet_printf("task cnt after : %d\n", application.GetScene().GetRenderTaskList().GetTaskCount()); + tet_printf("c depth : %d, a depth : %d\n", C_layer.GetProperty(Dali::Layer::Property::DEPTH), A_layer.GetProperty(Dali::Layer::Property::DEPTH)); + tet_printf("c id : %d, a id : %d\n", C_layer.GetProperty(Dali::Actor::Property::ID), A_layer.GetProperty(Dali::Actor::Property::ID)); + + DALI_TEST_CHECK(C_layer.GetProperty(Dali::Layer::Property::DEPTH) < A_layer.GetProperty(Dali::Layer::Property::DEPTH)); + + application.SendNotification(); + + tet_printf("B task order F : %d, task order B : %d\n", B_offScreenCustomActor.GetForwardRenderTask().GetOrderIndex(), B_offScreenCustomActor.GetBackwardRenderTask().GetOrderIndex()); + tet_printf("E task order F : %d, task order B : %d\n", E_offScreenCustomActor.GetForwardRenderTask().GetOrderIndex(), E_offScreenCustomActor.GetBackwardRenderTask().GetOrderIndex()); + tet_printf("F task order F : %d, task order B : %d\n", F_offScreenCustomActor.GetForwardRenderTask().GetOrderIndex(), F_offScreenCustomActor.GetBackwardRenderTask().GetOrderIndex()); + tet_printf("G task order F : %d, task order B : %d\n", G_offScreenCustomActor.GetForwardRenderTask().GetOrderIndex(), G_offScreenCustomActor.GetBackwardRenderTask().GetOrderIndex()); + tet_printf("J task order F : %d, task order B : %d\n", J_offScreenCustomActor.GetForwardRenderTask().GetOrderIndex(), J_offScreenCustomActor.GetBackwardRenderTask().GetOrderIndex()); + + DALI_TEST_CHECK(G_offScreenCustomActor.GetForwardRenderTask().GetOrderIndex() < F_offScreenCustomActor.GetBackwardRenderTask().GetOrderIndex()); + DALI_TEST_CHECK(F_offScreenCustomActor.GetBackwardRenderTask().GetOrderIndex() < E_offScreenCustomActor.GetForwardRenderTask().GetOrderIndex()); + DALI_TEST_CHECK(E_offScreenCustomActor.GetForwardRenderTask().GetOrderIndex() < J_offScreenCustomActor.GetBackwardRenderTask().GetOrderIndex()); + DALI_TEST_CHECK(J_offScreenCustomActor.GetBackwardRenderTask().GetOrderIndex() < B_offScreenCustomActor.GetBackwardRenderTask().GetOrderIndex()); + DALI_TEST_CHECK(B_offScreenCustomActor.GetBackwardRenderTask().GetOrderIndex() < E_offScreenCustomActor.GetBackwardRenderTask().GetOrderIndex()); + + END_TEST; +} \ No newline at end of file diff --git a/automated-tests/src/dali/utc-Dali-PropertyValue.cpp b/automated-tests/src/dali/utc-Dali-PropertyValue.cpp index 449fce250..75401d6b7 100644 --- a/automated-tests/src/dali/utc-Dali-PropertyValue.cpp +++ b/automated-tests/src/dali/utc-Dali-PropertyValue.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Samsung Electronics Co., Ltd. + * Copyright (c) 2024 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. @@ -19,8 +19,12 @@ #include #include +#include + +#include #include #include +#include using namespace Dali; @@ -238,7 +242,7 @@ int UtcDaliPropertyValueConstructorsRectP(void) Property::Value value(v); DALI_TEST_EQUALS(value.GetType(), Property::RECTANGLE, TEST_LOCATION); - DALI_TEST_CHECK(value.Get >() == v); + DALI_TEST_CHECK(value.Get>() == v); END_TEST; } @@ -248,7 +252,7 @@ int UtcDaliPropertyValueConstructorsRectTypeP(void) Property::Value value(Property::RECTANGLE); DALI_TEST_CHECK(value.GetType() == Property::RECTANGLE); - DALI_TEST_CHECK(value.Get >() == Rect(0, 0, 0, 0)); + DALI_TEST_CHECK(value.Get>() == Rect(0, 0, 0, 0)); END_TEST; } @@ -456,7 +460,7 @@ int UtcDaliPropertyValueCopyConstructorMatrixP(void) int UtcDaliPropertyValueCopyConstructorRectP(void) { - CheckCopyCtorP > check(Rect(1.0, 1.0, 1.0, 1.0)); + CheckCopyCtorP> check(Rect(1.0, 1.0, 1.0, 1.0)); END_TEST; } @@ -813,7 +817,7 @@ int UtcDaliPropertyValueMoveAssignmentOperator(void) DALI_TEST_EQUALS(valueFloat, 1.0f, TEST_LOCATION); // Self std::move assignment make compile warning over gcc-13. Let we ignore the warning. -#if (__GNUC__ >= 13) +#if(__GNUC__ >= 13) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wself-move" #endif @@ -821,7 +825,7 @@ int UtcDaliPropertyValueMoveAssignmentOperator(void) value2 = std::move(value2); DALI_TEST_EQUALS(true, value2.Get(valueFloat), TEST_LOCATION); DALI_TEST_EQUALS(valueFloat, 1.0f, TEST_LOCATION); -#if (__GNUC__ >= 13) +#if(__GNUC__ >= 13) #pragma GCC diagnostic pop #endif @@ -918,7 +922,7 @@ int UtcDaliPropertyValueGetRectP(void) { Property::Value value(Rect(1, 2, 3, 4)); Rect result(4, 3, 2, 1); - DALI_TEST_EQUALS(Rect(1, 2, 3, 4), value.Get >(), TEST_LOCATION); + DALI_TEST_EQUALS(Rect(1, 2, 3, 4), value.Get>(), TEST_LOCATION); DALI_TEST_EQUALS(true, value.Get(result), TEST_LOCATION); DALI_TEST_EQUALS(Rect(1, 2, 3, 4), result, TEST_LOCATION); END_TEST; @@ -928,7 +932,7 @@ int UtcDaliPropertyValueGetRectN(void) { Property::Value value; Rect result(4, 3, 2, 1); - DALI_TEST_EQUALS(Rect(0, 0, 0, 0), value.Get >(), TEST_LOCATION); + DALI_TEST_EQUALS(Rect(0, 0, 0, 0), value.Get>(), TEST_LOCATION); DALI_TEST_EQUALS(false, value.Get(result), TEST_LOCATION); DALI_TEST_EQUALS(Rect(4, 3, 2, 1), result, TEST_LOCATION); Property::Value value2(""); @@ -1483,6 +1487,122 @@ int UtcDaliPropertyValueEqualMapType(void) END_TEST; } +int UtcDaliPropertyValueConvertScalarType(void) +{ + tet_infoline("Check Property::Value type conversion."); + + // Piar of input value - {except value as relative value per each type of properties} + // clang-format off + const std::vector testConvertTypeList = + { + Property::BOOLEAN, Property::FLOAT, Property::INTEGER, + }; + const std::vector>> testExceptValueList = + { + { + Property::Value(true), + { + Property::Value(true), Property::Value(1.0f), Property::Value(1), + } + }, + { + Property::Value(2.0f), + { + Property::Value(true), Property::Value(2.0f), Property::Value(2), + } + }, + { + Property::Value(3), + { + Property::Value(true), Property::Value(3.0f), Property::Value(3), + } + }, + }; + // clang-format on + + for(auto& valueExceptPair : testExceptValueList) + { + const auto& exceptValueList = valueExceptPair.second; + + // Test except value list size is same as conversion type list size. (All property should have except value) + DALI_TEST_EQUALS(exceptValueList.size(), testConvertTypeList.size(), TEST_LOCATION); + + // Check cached event thread values are expect. + for(auto i = 0u; i < testConvertTypeList.size(); ++i) + { + // Check expect type is valid. + const Property::Type convertType = testConvertTypeList[i]; + DALI_TEST_EQUALS(convertType, exceptValueList[i].GetType(), TEST_LOCATION); + + Property::Value convertedValue = valueExceptPair.first; + + tet_printf("Test convert from %d to %d\n", static_cast(convertedValue.GetType()), static_cast(convertType)); + + DALI_TEST_CHECK(convertedValue.ConvertType(convertType)); + DALI_TEST_EQUALS(convertedValue, exceptValueList[i], TEST_LOCATION); + } + } + END_TEST; +} + +int UtcDaliPropertyValueConvertFailed(void) +{ + tet_infoline("Check Property::Value type conversion failed."); + + float a[] = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f}; + Property::Array array; + Property::Map map; + + // clang-format off + const std::vector scalarValueList = + { + Property::Value(false), Property::Value(1.0f), Property::Value(2) + }; + const std::vector conversionInvalidValueList = + { + Property::Value(), + Property::Value(Vector2()), Property::Value(Vector3()), Property::Value(Vector4()), + + Property::Value(Matrix(a)), + Property::Value(Matrix3(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f)), + + Property::Value(Rect(2, 3, 4, 5)), + Property::Value(AngleAxis(Radian(20.0f), Vector3(0.0f, 1.0f, 0.0f))), + Property::Value(std::string("Hell, o, World!")), + Property::Value(Extents(4, 8, 5, 2)), + + Property::Value(array), + Property::Value(map), + }; + // clang-format on + + for(int i = Property::Type::NONE; i <= Property::Type::EXTENTS; ++i) + { + Property::Type type(static_cast(i)); + + // Test convert for scalar value type + for(auto& value : scalarValueList) + { + // Copy value + Property::Value convertedValue = value; + bool expectConvertResult = (type == Property::BOOLEAN || type == Property::FLOAT || type == Property::INTEGER); + + DALI_TEST_EQUALS(convertedValue.ConvertType(type), expectConvertResult, TEST_LOCATION); + } + + // Test convert invalid for conversion invalid types + for(auto& value : conversionInvalidValueList) + { + // Copy value + Property::Value convertedValue = value; + bool expectConvertResult = (type == convertedValue.GetType()); + + DALI_TEST_EQUALS(convertedValue.ConvertType(type), expectConvertResult, TEST_LOCATION); + } + } + END_TEST; +} + int UtcDaliPropertyValueOutputStream(void) { TestApplication application; diff --git a/automated-tests/src/dali/utc-Dali-RenderTask.cpp b/automated-tests/src/dali/utc-Dali-RenderTask.cpp index 72b3893dc..db59e4257 100644 --- a/automated-tests/src/dali/utc-Dali-RenderTask.cpp +++ b/automated-tests/src/dali/utc-Dali-RenderTask.cpp @@ -5138,7 +5138,7 @@ int UtcDaliRenderTaskOrderIndex01(void) RenderTask renderTask1 = renderTaskList.CreateTask(); application.SendNotification(); - uint32_t answer1[2] = {0u, 0u}; + int32_t answer1[2] = {INT32_MIN, 0}; DALI_TEST_EQUALS(2, renderTaskList.GetTaskCount(), TEST_LOCATION); for(uint32_t i = 0; i < 2; ++i) { @@ -5147,7 +5147,7 @@ int UtcDaliRenderTaskOrderIndex01(void) RenderTask renderTask2 = renderTaskList.CreateTask(); application.SendNotification(); - int32_t answer2[3] = {0u, 0u, 0u}; + int32_t answer2[3] = {INT32_MIN, 0, 0}; DALI_TEST_EQUALS(3, renderTaskList.GetTaskCount(), TEST_LOCATION); for(uint32_t i = 0; i < 3; ++i) { @@ -5156,7 +5156,7 @@ int UtcDaliRenderTaskOrderIndex01(void) RenderTask renderTask3 = renderTaskList.CreateTask(); application.SendNotification(); - int32_t answer3[4] = {0u, 0u, 0u, 0u}; + int32_t answer3[4] = {INT32_MIN, 0, 0, 0}; DALI_TEST_EQUALS(4, renderTaskList.GetTaskCount(), TEST_LOCATION); for(uint32_t i = 0; i < 4; ++i) { @@ -5165,7 +5165,7 @@ int UtcDaliRenderTaskOrderIndex01(void) renderTask1.SetOrderIndex(3); application.SendNotification(); - int32_t answer4[4] = {0u, 0u, 0u, 3u}; + int32_t answer4[4] = {INT32_MIN, 0, 0, 3}; for(uint32_t i = 0; i < 4; ++i) { DALI_TEST_EQUALS(answer4[i], renderTaskList.GetTask(i).GetOrderIndex(), TEST_LOCATION); @@ -5173,7 +5173,7 @@ int UtcDaliRenderTaskOrderIndex01(void) renderTask2.SetOrderIndex(7); application.SendNotification(); - int32_t answer5[4] = {0u, 0u, 3u, 7u}; + int32_t answer5[4] = {INT32_MIN, 0, 3, 7}; for(uint32_t i = 0; i < 4; ++i) { DALI_TEST_EQUALS(answer5[i], renderTaskList.GetTask(i).GetOrderIndex(), TEST_LOCATION); @@ -5183,7 +5183,7 @@ int UtcDaliRenderTaskOrderIndex01(void) scene.GetOverlayLayer(); application.SendNotification(); DALI_TEST_EQUALS(5, renderTaskList.GetTaskCount(), TEST_LOCATION); - int32_t answer6[5] = {0u, 0u, 3u, 7u, INT32_MAX}; + int32_t answer6[5] = {INT32_MIN, 0, 3, 7, INT32_MAX}; for(uint32_t i = 0; i < 5; ++i) { DALI_TEST_EQUALS(answer6[i], renderTaskList.GetTask(i).GetOrderIndex(), TEST_LOCATION); @@ -5191,7 +5191,7 @@ int UtcDaliRenderTaskOrderIndex01(void) renderTask3.SetOrderIndex(4); application.SendNotification(); - int32_t answer7[5] = {0u, 3u, 4u, 7u, INT32_MAX}; + int32_t answer7[5] = {INT32_MIN, 3, 4, 7, INT32_MAX}; for(uint32_t i = 0; i < 5; ++i) { DALI_TEST_EQUALS(answer7[i], renderTaskList.GetTask(i).GetOrderIndex(), TEST_LOCATION); @@ -5199,7 +5199,7 @@ int UtcDaliRenderTaskOrderIndex01(void) renderTask2.SetOrderIndex(2); application.SendNotification(); - int32_t answer8[5] = {0u, 2u, 3u, 4u, INT32_MAX}; + int32_t answer8[5] = {INT32_MIN, 2, 3, 4, INT32_MAX}; for(uint32_t i = 0; i < 5; ++i) { DALI_TEST_EQUALS(answer8[i], renderTaskList.GetTask(i).GetOrderIndex(), TEST_LOCATION); diff --git a/automated-tests/src/dali/utc-Dali-TypeRegistry.cpp b/automated-tests/src/dali/utc-Dali-TypeRegistry.cpp index 9a2ab5852..c1899a621 100644 --- a/automated-tests/src/dali/utc-Dali-TypeRegistry.cpp +++ b/automated-tests/src/dali/utc-Dali-TypeRegistry.cpp @@ -204,6 +204,10 @@ struct MyTestCustomActor : public CustomActorImpl return false; } + void GetOffScreenRenderTasks(std::vector& tasks, bool isForward) override + { + } + public: SignalType mSignal; }; diff --git a/automated-tests/src/dali/utc-Dali-WeakHandle.cpp b/automated-tests/src/dali/utc-Dali-WeakHandle.cpp index 49467005f..77d698120 100644 --- a/automated-tests/src/dali/utc-Dali-WeakHandle.cpp +++ b/automated-tests/src/dali/utc-Dali-WeakHandle.cpp @@ -113,6 +113,10 @@ struct MyTestCustomActor : public CustomActorImpl return false; } + void GetOffScreenRenderTasks(std::vector& tasks, bool isForward) override + { + } + public: SignalType mSignal; }; diff --git a/build/scripts/dali_env b/build/scripts/dali_env index 8ff18c6a2..adabf677d 100755 --- a/build/scripts/dali_env +++ b/build/scripts/dali_env @@ -165,7 +165,7 @@ my $opt_help=0; my $opt_man=0; my $opt_vk_version="1.3.280.1"; my $opt_vulkan=undef; -my $VULKAN_ENV=""; +my $opt_usd=0; GetOptions("create" => \$opt_create, "envfile=s" => \$opt_envfile, @@ -173,6 +173,7 @@ GetOptions("create" => \$opt_create, "setenv" => \$opt_setenv, "help" => \$opt_help, "vulkan:s" => \$opt_vulkan, + "usd" => \$opt_usd, "man" => \$opt_man) or pod2usage(2); pod2usage(1) if $opt_help; @@ -293,8 +294,23 @@ EOF } ################################################################################ -sub vulkan_env +sub download_archive { + my ($archive, $url, $download_info) = @_; + + # Avoid excessive downloading of the same file + if(! -e "/tmp/$archive") + { + print "Downloading $download_info\nfrom: $url\n"; + system('wget','-P','/tmp',$url); + die "Can't download archive" if(! -e "/tmp/$archive"); + } +} + +sub untar_archive +{ + my $archive=shift; + system('tar','-xf',"/tmp/$archive", '--checkpoint=5000', '--checkpoint-action=ttyout=.'); } sub install_vulkan @@ -303,20 +319,13 @@ sub install_vulkan { my $archive="vulkansdk-linux-x86_64-${opt_vk_version}.tar.xz"; my $url="https://sdk.lunarg.com/sdk/download/${opt_vk_version}/linux/$archive"; - - # Avoid excessive downloading of the same file - if(! -e "/tmp/$archive") - { - print "Downloading Vulkan SDK version ${opt_vk_version}\nfrom: $url\n"; - system('wget','-P','/tmp',$url); - die "Can't download archive" if(! -e "/tmp/$archive"); - } + download_archive($archive, $url, "Vulkan SDK version ${opt_vk_version}"); my $vulkan_install_path="$root_path/vulkan"; - print "Unpacking archive\n"; + print "Unpacking vulkan archive\n"; mkpath($vulkan_install_path); chdir($vulkan_install_path); - system('tar','-xf',"/tmp/$archive", '--checkpoint=5000', '--checkpoint-action=ttyout=.'); + untar_archive($archive); print("\n"); chdir("$root_path/.."); @@ -373,6 +382,84 @@ EOF } } +sub install_usd +{ + if($opt_usd) + { + my $boost_archive="boost-1.84.0.tar.gz"; + my $boost_url="https://github.com/boostorg/boost/releases/download/boost-1.84.0/$boost_archive"; + download_archive($boost_archive, $boost_url, "Boost"); + + my $tbb_archive="2019_U9.tar.gz"; + my $tbb_url="https://github.com/oneapi-src/oneTBB/archive/refs/tags/$tbb_archive"; + download_archive($tbb_archive, $tbb_url, "LibTBB"); + + my $openusd_archive="32-bit-arm-and-tizen-support.tar.gz"; + my $openusd_url="https://github.com/dalihub/OpenUSD/archive/refs/tags/$openusd_archive"; + download_archive($openusd_archive, $openusd_url, "OpenUSD"); + + my $usd_install_path=$install_path; + my $usd_source_path="$src_path/usd"; + + print "Unpacking Boost, TBB & OpenUSD archives\n"; + mkpath($usd_source_path); + chdir($usd_source_path); + untar_archive($boost_archive); + untar_archive($tbb_archive); + untar_archive($openusd_archive); + + mkpath("$usd_install_path/lib"); + mkpath("$usd_install_path/include"); + + my $boost_source_path="$usd_source_path/boost-1.84.0"; + print "Building Boost\n"; + chdir("$boost_source_path"); + system('cmake',"-DCMAKE_INSTALL_PREFIX=$usd_install_path", '.'); + system('make','-j8','install'); + + my $tbb_source_path="$usd_source_path/oneTBB-2019_U9"; + print "Building TBB\n"; + chdir("$tbb_source_path"); + system('make','-j8'); + my $tbbBuildFolder=`make info | grep tbb_build_prefix | cut -d= -f 2`; + chomp($tbbBuildFolder); + $tbbBuildFolder=$tbbBuildFolder . "_release"; + print "$tbbBuildFolder Hello"; + system("install -m 644 ./build/$tbbBuildFolder/*.so* $usd_install_path/lib/"); + system('cp','-rf','include/tbb',"$usd_install_path/include/"); + + my $openusd_source_path="$usd_source_path/OpenUSD-32-bit-arm-and-tizen-support"; + print "Building USD\n"; + chdir("$openusd_source_path"); + system('cmake', + '-DPXR_ENABLE_PYTHON_SUPPORT=OFF', + '-DPXR_ENABLE_PTEX_SUPPORT=OFF', + '-DPXR_ENABLE_OPENVDB_SUPPORT=OFF', + '-DPXR_ENABLE_HDF5_SUPPORT=OFF', + '-DPXR_ENABLE_MATERIALX_SUPPORT=OFF', + '-DPXR_BUILD_IMAGING=OFF', + '-DPXR_BUILD_USD_IMAGING=OFF', + '-DPXR_BUILD_USDVIEW=OFF', + '-DPXR_BUILD_DOCUMENTATION=OFF', + '-DPXR_BUILD_HTML_DOCUMENTATION=OFF', + '-DPXR_BUILD_PYTHON_DOCUMENTATION=OFF', + '-DPXR_BUILD_TESTS=OFF', + '-DPXR_BUILD_EXAMPLES=OFF', + '-DPXR_BUILD_TUTORIALS=OFF', + '-DPXR_BUILD_USD_TOOLS=OFF', + '-DPXR_BUILD_MAYAPY_TESTS=OFF', + '-DPXR_BUILD_ANIMX_TESTS=OFF', + "-DTBB_ROOT_DIR=$usd_install_path", + "-DBOOST_ROOT=$usd_install_path", + "-DCMAKE_INSTALL_PREFIX=$usd_install_path", + '.' + ); + system('make','-j8','install'); + + print("\n"); + chdir("$root_path/.."); + } +} sub check_system_package { @@ -433,7 +520,7 @@ sub check_source_packages { print "Attempting to build $pkg\n"; # from https://www.eriksmistad.no/getting-started-with-google-test-on-ubuntu/ - run_command("cd /usr/src/gtest; sudo cmake CMakeLists.txt; sudo make; sudo cp *.a /usr/lib; cd -;"); + run_command("cd /usr/src/gtest; sudo cmake CMakeLists.txt; sudo make; sudo cp lib/*.a /usr/lib; cd -;"); } } } @@ -755,6 +842,7 @@ if($opt_create) check_source_packages(); install_vulkan(); + install_usd(); create_setenv(); } elsif($opt_setenv) @@ -811,6 +899,10 @@ Install the Vulkan SDK (By default, uses 1.3.280.1) with the optional version number. Adds several .pc files into dali-env/opt/lib/pkg-config directory, and requires a new environment file to be written. +=item B<-u|--usd> + +Installs the OpenUSD library and its dependencies. + =item B<-h|--help> Display this help diff --git a/dali/devel-api/threading/conditional-wait.cpp b/dali/devel-api/threading/conditional-wait.cpp index 325920364..3d6ec9bf7 100644 --- a/dali/devel-api/threading/conditional-wait.cpp +++ b/dali/devel-api/threading/conditional-wait.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * Copyright (c) 2024 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. @@ -98,7 +98,7 @@ void ConditionalWait::Notify() void ConditionalWait::Notify(const ScopedLock& scope) { // Scope must be locked: - DALI_ASSERT_DEBUG(&scope.GetLockedWait() == this); + DALI_ASSERT_ALWAYS(&scope.GetLockedWait() == this); volatile unsigned int previousCount = mImpl->count; @@ -127,7 +127,7 @@ void ConditionalWait::Wait() void ConditionalWait::Wait(const ScopedLock& scope) { // Scope must be locked: - DALI_ASSERT_DEBUG(&scope.GetLockedWait() == this); + DALI_ASSERT_ALWAYS(&scope.GetLockedWait() == this); ++(mImpl->count); @@ -142,6 +142,32 @@ void ConditionalWait::Wait(const ScopedLock& scope) // passed in will unlock it in the caller. } +void ConditionalWait::WaitUntil(const ScopedLock& scope, ConditionalWait::TimePoint timePoint) +{ + // Scope must be locked: + DALI_ASSERT_ALWAYS(&scope.GetLockedWait() == this); + + ++(mImpl->count); + + // conditional wait may wake up without anyone calling Notify + do + { + // wait while condition changes + if(mImpl->condition.wait_until(scope.mImpl->lock, timePoint) == std::cv_status::timeout) + { + // Pass-through for this wait request. + // Note that we should not wake-up other wait requests. + if(mImpl->count > 0u) + { + --mImpl->count; + } + } + } while(0 != mImpl->count); + + // We return with our mutex locked safe in the knowledge that the ScopedLock + // passed in will unlock it in the caller. +} + unsigned int ConditionalWait::GetWaitCount() const { return mImpl->count; diff --git a/dali/devel-api/threading/conditional-wait.h b/dali/devel-api/threading/conditional-wait.h index a18b93f5b..f0ea102df 100644 --- a/dali/devel-api/threading/conditional-wait.h +++ b/dali/devel-api/threading/conditional-wait.h @@ -2,7 +2,7 @@ #define DALI_CONDITIONAL_WAIT_H /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * Copyright (c) 2024 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. @@ -18,6 +18,9 @@ * */ +// EXTERNAL INCLUDES +#include ///< for std::chrono::time_point + // INTERNAL INCLUDES #include @@ -65,6 +68,8 @@ public: const ScopedLock& operator=(const ScopedLock&); }; + using TimePoint = std::chrono::time_point; + /** * @brief Constructor, creates the internal synchronization objects */ @@ -114,6 +119,19 @@ public: */ void Wait(const ScopedLock& scope); + /** + * @brief Wait until specific time point or another thread to notify us when the condition is true and we can continue + * + * Will always block current thread until Notify is called. + * Assumes that the ScopedLock object passed in has already locked the internal state of + * this object. Releases the lock while waiting and re-acquires it when returning + * from the wait. + * @param[in] scope A pre-existing lock on the internal state of this object. + * @param[in] timePoint Maximum time point to wait. + * @pre scope must have been passed this ConditionalWait during its construction. + */ + void WaitUntil(const ScopedLock& scope, TimePoint timePoint); + /** * @brief Return the count of threads waiting for this conditional * @return count of waits diff --git a/dali/graphics-api/graphics-controller.h b/dali/graphics-api/graphics-controller.h index 466edfa82..19009339b 100644 --- a/dali/graphics-api/graphics-controller.h +++ b/dali/graphics-api/graphics-controller.h @@ -412,6 +412,20 @@ public: // ResourceId relative API. */ virtual UniquePtr ReleaseTextureFromResourceId(uint32_t resourceId) = 0; + /** + * @brief Determine if the backend needs to multiply the projection matrix by a clip matrix + * + * @return TRUE if the graphics backend requires an alternative clip matrix + */ + virtual bool HasClipMatrix() const = 0; + + /** + * @brief Get the alternative clipping matrix. + * + * @return the clipping matrix + */ + virtual const Matrix& GetClipMatrix() const = 0; + protected: /** * Creates controller diff --git a/dali/graphics-api/graphics-types.h b/dali/graphics-api/graphics-types.h index 4fd4adcb6..dab4ab641 100644 --- a/dali/graphics-api/graphics-types.h +++ b/dali/graphics-api/graphics-types.h @@ -37,6 +37,9 @@ class Framebuffer; class Program; class Shader; class Texture; +class RenderTarget; +class RenderPass; +class Sampler; /** * @brief Structure describes 2D offset @@ -77,7 +80,7 @@ struct Viewport float width = 0.0f; float height = 0.0f; float minDepth = 0.0f; - float maxDepth = 0.0f; + float maxDepth = 1.0f; }; /** @@ -575,7 +578,7 @@ struct RasterizationState struct InputAssemblyState { PrimitiveTopology topology{}; - bool primitiveRestartEnable{true}; + bool primitiveRestartEnable{false}; auto& SetTopology(PrimitiveTopology value) { @@ -585,7 +588,7 @@ struct InputAssemblyState auto& SetPrimitiveRestartEnable(bool value) { - primitiveRestartEnable = true; + primitiveRestartEnable = value; return *this; } }; @@ -1293,10 +1296,59 @@ inline CommandBufferUsageFlags operator|(T flags, CommandBufferUsageFlagBits bit return static_cast(flags) | static_cast(bit); } +enum class ResourceType +{ + PROGRAM, + BUFFER, + SAMPLER, + TEXTURE +}; + +struct ProgramResourceBindingInfo +{ + Graphics::Program* program; + uint32_t count; +}; + +struct BufferResourceBindingInfo; +struct TextureResourceBindingInfo; +struct SamplerResourceBindingInfo; + +struct CommandBufferResourceBinding +{ + ResourceType type; ///< Type of resource + + union + { + ProgramResourceBindingInfo* programBinding{nullptr}; + BufferResourceBindingInfo* bufferBinding; + TextureResourceBindingInfo* textureBinding; + SamplerResourceBindingInfo* samplerBinding; + }; +}; + struct CommandBufferBeginInfo { CommandBufferUsageFlags usage; - // Don't care about inheritance yet. Can extend as required. + + std::vector* resourceBindings{nullptr}; ///< Sets resource binding hints + const RenderPass* renderPass{nullptr}; + const RenderTarget* renderTarget{nullptr}; + auto& SetUsage(CommandBufferUsageFlags flags) + { + usage = flags; + return *this; + } + auto& SetRenderPass(const RenderPass& value) + { + renderPass = &value; + return *this; + } + auto& SetRenderTarget(const RenderTarget& value) + { + renderTarget = &value; + return *this; + } }; /** @@ -1517,8 +1569,7 @@ struct DefaultDeleter template typename U> DefaultDeleter(const U

& deleter) { - deleteFunction = [](T* object) - { U

()(static_cast(object)); }; + deleteFunction = [](T* object) { U

()(static_cast(object)); }; } /** diff --git a/dali/integration-api/file.list b/dali/integration-api/file.list index bf08a162b..d7feadfef 100644 --- a/dali/integration-api/file.list +++ b/dali/integration-api/file.list @@ -13,6 +13,7 @@ SET( platform_abstraction_src_files ${platform_abstraction_src_dir}/profiling.cpp ${platform_abstraction_src_dir}/render-task-list-integ.cpp ${platform_abstraction_src_dir}/scene.cpp + ${platform_abstraction_src_dir}/shader-integ.cpp ${platform_abstraction_src_dir}/testing.cpp ${platform_abstraction_src_dir}/texture-integ.cpp ${platform_abstraction_src_dir}/trace.cpp @@ -53,6 +54,7 @@ SET( platform_abstraction_header_files ${platform_abstraction_src_dir}/resource-policies.h ${platform_abstraction_src_dir}/resource-types.h ${platform_abstraction_src_dir}/scene.h + ${platform_abstraction_src_dir}/shader-integ.h ${platform_abstraction_src_dir}/testing.h ${platform_abstraction_src_dir}/texture-integ.h ${platform_abstraction_src_dir}/trace.h diff --git a/dali/integration-api/shader-integ.cpp b/dali/integration-api/shader-integ.cpp new file mode 100644 index 000000000..421939533 --- /dev/null +++ b/dali/integration-api/shader-integ.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024 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. + * + */ + +// FILE HEADER +#include + +// INTERNAL INCLUDES +#include + +namespace Dali::Integration +{ +std::string GenerateTaggedShaderPrefix(const std::string& shaderPrefix) +{ + return Dali::Internal::Shader::GenerateTaggedShaderPrefix(shaderPrefix); +} +} // namespace Dali::Integration diff --git a/dali/integration-api/shader-integ.h b/dali/integration-api/shader-integ.h new file mode 100644 index 000000000..fea64a8ce --- /dev/null +++ b/dali/integration-api/shader-integ.h @@ -0,0 +1,40 @@ +#ifndef DALI_SHADER_INTEG_H +#define DALI_SHADER_INTEG_H + +/* + * Copyright (c) 2024 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 // std::string + +// INTERNAL INCLUDES +#include + +namespace Dali::Integration +{ +/** + * @brief Generates tag 'legacy-prefix-end' with end position of + * prefix text to make shader code parsing easier. + * + * @SINCE_2_3.43 + * @return Generated string with tag. + */ +DALI_CORE_API std::string GenerateTaggedShaderPrefix(const std::string& shaderPrefix); + +} // namespace Dali::Integration + +#endif // DALI_SHADER_INTEG_H diff --git a/dali/internal/common/core-impl.cpp b/dali/internal/common/core-impl.cpp index 1aafb5861..9725a85ab 100644 --- a/dali/internal/common/core-impl.cpp +++ b/dali/internal/common/core-impl.cpp @@ -366,6 +366,13 @@ void Core::RelayoutAndFlush(SceneContainer& scenes) scene->RebuildDepthTree(); } + // process events in all scenes + for(auto scene : scenes) + { + auto& renderTaskList = scene->GetRenderTaskList(); + renderTaskList.ReorderTasks(scene->GetLayerList()); + } + // Flush any queued messages for the update-thread const bool messagesToProcess = mUpdateManager->FlushQueue(); @@ -492,9 +499,8 @@ void Core::RunProcessors() { if(mProcessorsOnce[mProcessorOnceIndex].Count() != 0) { - DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSORS_ONCE", [&](std::ostringstream& oss) { - oss << "[" << mProcessorOnceIndex << ":" << mProcessorsOnce[mProcessorOnceIndex].Count() << "]"; - }); + DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSORS_ONCE", [&](std::ostringstream& oss) + { oss << "[" << mProcessorOnceIndex << ":" << mProcessorsOnce[mProcessorOnceIndex].Count() << "]"; }); // Swap processor index. uint32_t currentIndex = mProcessorOnceIndex; @@ -530,21 +536,20 @@ void Core::RunProcessors() // Clear once processor. mProcessorsOnce[currentIndex].Clear(); - DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSORS_ONCE", [&](std::ostringstream& oss) { + DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSORS_ONCE", [&](std::ostringstream& oss) + { oss << "[" << currentIndex; if(mProcessorUnregistered) { oss << ", processor changed"; } - oss << "]"; - }); + oss << "]"; }); } if(mProcessors.Count() != 0) { - DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSORS", [&](std::ostringstream& oss) { - oss << "[" << mProcessors.Count() << "]"; - }); + DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSORS", [&](std::ostringstream& oss) + { oss << "[" << mProcessors.Count() << "]"; }); // Copy processor pointers to prevent changes to vector affecting loop iterator. Dali::Vector processors(mProcessors); @@ -558,13 +563,11 @@ void Core::RunProcessors() { if(!mProcessorUnregistered) { - DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSOR", [&](std::ostringstream& oss) { - oss << "[" << processor->GetProcessorName() << "]"; - }); + DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSOR", [&](std::ostringstream& oss) + { oss << "[" << processor->GetProcessorName() << "]"; }); processor->Process(false); - DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSOR", [&](std::ostringstream& oss) { - oss << "[" << processor->GetProcessorName() << "]"; - }); + DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSOR", [&](std::ostringstream& oss) + { oss << "[" << processor->GetProcessorName() << "]"; }); } else { @@ -573,25 +576,23 @@ void Core::RunProcessors() auto iter = std::find(mProcessors.Begin(), mProcessors.End(), processor); if(iter != mProcessors.End()) { - DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSOR", [&](std::ostringstream& oss) { - oss << "[" << processor->GetProcessorName() << "]"; - }); + DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSOR", [&](std::ostringstream& oss) + { oss << "[" << processor->GetProcessorName() << "]"; }); processor->Process(false); - DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSOR", [&](std::ostringstream& oss) { - oss << "[" << processor->GetProcessorName() << "]"; - }); + DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSOR", [&](std::ostringstream& oss) + { oss << "[" << processor->GetProcessorName() << "]"; }); } } } } - DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSORS", [&](std::ostringstream& oss) { + DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSORS", [&](std::ostringstream& oss) + { oss << "[" << mProcessors.Count(); if(mProcessorUnregistered) { oss << ", processor changed"; } - oss << "]"; - }); + oss << "]"; }); } } @@ -599,9 +600,8 @@ void Core::RunPostProcessors() { if(mPostProcessorsOnce[mPostProcessorOnceIndex].Count() != 0) { - DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSORS_ONCE", [&](std::ostringstream& oss) { - oss << "[" << mPostProcessorOnceIndex << ":" << mPostProcessorsOnce[mPostProcessorOnceIndex].Count() << "]"; - }); + DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSORS_ONCE", [&](std::ostringstream& oss) + { oss << "[" << mPostProcessorOnceIndex << ":" << mPostProcessorsOnce[mPostProcessorOnceIndex].Count() << "]"; }); // Swap processor index. uint32_t currentIndex = mPostProcessorOnceIndex; @@ -637,21 +637,20 @@ void Core::RunPostProcessors() // Clear once processor. mPostProcessorsOnce[currentIndex].Clear(); - DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSORS_ONCE", [&](std::ostringstream& oss) { + DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSORS_ONCE", [&](std::ostringstream& oss) + { oss << "[" << currentIndex; if(mPostProcessorUnregistered) { oss << ", processor changed"; } - oss << "]"; - }); + oss << "]"; }); } if(mPostProcessors.Count() != 0) { - DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSORS", [&](std::ostringstream& oss) { - oss << "[" << mPostProcessors.Count() << "]"; - }); + DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSORS", [&](std::ostringstream& oss) + { oss << "[" << mPostProcessors.Count() << "]"; }); // Copy processor pointers to prevent changes to vector affecting loop iterator. Dali::Vector processors(mPostProcessors); @@ -665,13 +664,11 @@ void Core::RunPostProcessors() { if(!mPostProcessorUnregistered) { - DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSOR", [&](std::ostringstream& oss) { - oss << "[" << processor->GetProcessorName() << "]"; - }); + DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSOR", [&](std::ostringstream& oss) + { oss << "[" << processor->GetProcessorName() << "]"; }); processor->Process(true); - DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSOR", [&](std::ostringstream& oss) { - oss << "[" << processor->GetProcessorName() << "]"; - }); + DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSOR", [&](std::ostringstream& oss) + { oss << "[" << processor->GetProcessorName() << "]"; }); } else { @@ -680,26 +677,24 @@ void Core::RunPostProcessors() auto iter = std::find(mPostProcessors.Begin(), mPostProcessors.End(), processor); if(iter != mPostProcessors.End()) { - DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSOR", [&](std::ostringstream& oss) { - oss << "[" << processor->GetProcessorName() << "]"; - }); + DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSOR", [&](std::ostringstream& oss) + { oss << "[" << processor->GetProcessorName() << "]"; }); processor->Process(true); - DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSOR", [&](std::ostringstream& oss) { - oss << "[" << processor->GetProcessorName() << "]"; - }); + DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSOR", [&](std::ostringstream& oss) + { oss << "[" << processor->GetProcessorName() << "]"; }); } } } } - DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSORS", [&](std::ostringstream& oss) { + DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSORS", [&](std::ostringstream& oss) + { oss << "[" << mPostProcessors.Count(); if(mPostProcessorUnregistered) { oss << ", processor changed"; } - oss << "]"; - }); + oss << "]"; }); } } diff --git a/dali/internal/common/image-attributes.cpp b/dali/internal/common/image-attributes.cpp index 3a3b12e25..a92db2afd 100644 --- a/dali/internal/common/image-attributes.cpp +++ b/dali/internal/common/image-attributes.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Samsung Electronics Co., Ltd. + * Copyright (c) 2024 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. @@ -57,8 +57,8 @@ struct ImageAttributes::ImageAttributesImpl uint16_t width; ///< image width in pixels uint16_t height; ///< image height in pixels - ScalingMode scaling : 3; ///< scaling option, ShrinkToFit is default - FilterMode filtering : 4; ///< filtering option. Box is the default + ScalingMode scaling : 4; ///< scaling option, ShrinkToFit is default + FilterMode filtering : 5; ///< filtering option. Box is the default bool mOrientationCorrection : 1; ///< If true, image pixels are reordered according to orientation metadata on load. }; diff --git a/dali/internal/event/actors/actor-impl.cpp b/dali/internal/event/actors/actor-impl.cpp index c35b7b184..88e77414d 100644 --- a/dali/internal/event/actors/actor-impl.cpp +++ b/dali/internal/event/actors/actor-impl.cpp @@ -1111,6 +1111,28 @@ DevelActor::ChildOrderChangedSignalType& Actor::ChildOrderChangedSignal() return mParentImpl.ChildOrderChangedSignal(); } +void Actor::GetOffScreenRenderTasks(std::vector& tasks, bool isForward) +{ +} + +void Actor::SetOffScreenRenderableType(OffScreenRenderable::Type offScreenRenderableType) +{ + mOffScreenRenderableType = offScreenRenderableType; +} + +OffScreenRenderable::Type Actor::GetOffScreenRenderableType() const +{ + return mOffScreenRenderableType; +} + +void Actor::RequestRenderTaskReorder() +{ + if(mScene && GetOffScreenRenderableType() != OffScreenRenderable::Type::NONE) + { + mScene->GetRenderTaskList().RequestReorder(); + } +} + Actor::Actor(DerivedType derivedType, const SceneGraph::Node& node) : Object(&node), mParentImpl(*this), @@ -1170,7 +1192,8 @@ Actor::Actor(DerivedType derivedType, const SceneGraph::Node& node) mColorMode(Node::DEFAULT_COLOR_MODE), mClippingMode(ClippingMode::DISABLED), mHoverState(PointState::FINISHED), - mBlendEquation(DevelBlendEquation::ADD) + mBlendEquation(DevelBlendEquation::ADD), + mOffScreenRenderableType(OffScreenRenderable::Type::NONE) { } diff --git a/dali/internal/event/actors/actor-impl.h b/dali/internal/event/actors/actor-impl.h index f9aa9708c..99dcf9c7e 100644 --- a/dali/internal/event/actors/actor-impl.h +++ b/dali/internal/event/actors/actor-impl.h @@ -22,19 +22,9 @@ #include // INTERNAL INCLUDES -#include -#include -#include -#include -#include -#include -#include - #include #include - #include - #include #include #include @@ -46,6 +36,14 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include namespace Dali { @@ -1577,6 +1575,46 @@ public: { } +public: + // For Internal RenderTask Ordering + + /** + * @brief Retrieves the off-screen RenderTasks associated with the Actor. + * This method returns the internal RenderTasks held by the Actor. This tasks are + * used for off-screen rendering, and the system will assign order index to each + * tasks based on the render order. + * + * Actor with a non-NONE OffScreenRenderableType should override this method to + * provide their render tasks. + * + * @param[out] tasks A list of RenderTasks to be populated with the Actor's forward + * or backward off-screen RenderTask. + * @param[in] isForward Indicates whether to retrieve forward (true) or backward (false) + * RenderTasks. + */ + virtual void GetOffScreenRenderTasks(std::vector& tasks, bool isForward); + + /** + * @brief Sets OffScreenRenderableType of this Actor. + * This method is called by child class to set type itself. + * + * @param[in] offScreenRenderableType OffScreenRenderableType for this Actor. + * It could be one of NONE, FORWARD, BACKWARD, and BOTH. + */ + void SetOffScreenRenderableType(OffScreenRenderable::Type offScreenRenderableType); + + /** + * @brief Retrieves OffScreenRenderableType of this Actor. + * + * @return OffScreenRenderableType for this Actor. + */ + OffScreenRenderable::Type GetOffScreenRenderableType() const; + + /** + * @brief Requests RenderTask reordering when the offscreen properties of this Actor are changed. + */ + void RequestRenderTaskReorder(); + protected: enum DerivedType { @@ -2027,6 +2065,9 @@ protected: private: static ActorContainer mNullChildren; ///< Empty container (shared by all actors, returned by GetChildren() const) + // OffScreenRenderable + OffScreenRenderable::Type mOffScreenRenderableType; + struct PropertyHandler; struct SiblingHandler; diff --git a/dali/internal/event/actors/actor-parent-impl.cpp b/dali/internal/event/actors/actor-parent-impl.cpp index 9ccabff83..31def8cab 100644 --- a/dali/internal/event/actors/actor-parent-impl.cpp +++ b/dali/internal/event/actors/actor-parent-impl.cpp @@ -451,6 +451,8 @@ void ActorParentImpl::RecursiveConnectToScene(ActorContainer& connectionList, ui mOwner.mLayer3DParentsCount = static_cast(layer3DParentsCount); // overflow ignored, not expected in practice mOwner.ConnectToSceneGraph(); + mOwner.RequestRenderTaskReorder(); + // Notification for internal derived classes mOwner.OnSceneConnectionInternal(); diff --git a/dali/internal/event/actors/custom-actor-internal.h b/dali/internal/event/actors/custom-actor-internal.h index a70d88454..969cb6955 100644 --- a/dali/internal/event/actors/custom-actor-internal.h +++ b/dali/internal/event/actors/custom-actor-internal.h @@ -128,6 +128,11 @@ private: mImpl->OnSizeAnimation(animationHandle, targetSize); } + void GetOffScreenRenderTasks(std::vector& tasks, bool isForward) + { + mImpl->GetOffScreenRenderTasks(tasks, isForward); + } + /** * @copydoc Internal::Actor::OnRelayout */ diff --git a/dali/internal/event/animation/animation-impl.cpp b/dali/internal/event/animation/animation-impl.cpp index 908126e56..831a61d94 100644 --- a/dali/internal/event/animation/animation-impl.cpp +++ b/dali/internal/event/animation/animation-impl.cpp @@ -118,19 +118,20 @@ inline bool IsAnimatable(Property::Type type) } /** - * Helper to validate animation input values + * Helper to validate and convert animation input values * - * @param propertyType type of the property that is being animated - * @param destinationType type of the target - * @param period time period of the animation + * @param[in] propertyType type of the property that is being animated + * @param[in] period time period of the animation + * @param[in, out] convertedValue if the value needs conversion, this will contain the converted value. */ -void ValidateParameters(Property::Type propertyType, Property::Type destinationType, const TimePeriod& period) +void ValidateAndConvertParameters(Property::Type propertyType, const TimePeriod& period, Property::Value& convertedValue) { // destination value has to be animatable DALI_ASSERT_ALWAYS(IsAnimatable(propertyType) && "Property type is not animatable"); - DALI_ASSERT_ALWAYS(IsAnimatable(destinationType) && "Target value is not animatable"); - DALI_ASSERT_ALWAYS(propertyType == destinationType && "Property and target types don't match"); + DALI_ASSERT_ALWAYS(IsAnimatable(convertedValue.GetType()) && "Target value is not animatable"); DALI_ASSERT_ALWAYS(period.durationSeconds >= 0 && "Duration must be >=0"); + + DALI_ASSERT_ALWAYS(convertedValue.ConvertType(propertyType) && "Target types could not be convert to Property type"); } /** @@ -566,22 +567,18 @@ void Animation::AnimateBy(Property& target, Property::Value relativeValue, TimeP void Animation::AnimateBy(Property& target, Property::Value relativeValue, AlphaFunction alpha, TimePeriod period) { - Object& object = GetImplementation(target.object); - const Property::Type propertyType = object.GetPropertyType(target.propertyIndex); - const Property::Type destinationType = relativeValue.GetType(); + Object& object = GetImplementation(target.object); + const Property::Type propertyType = (target.componentIndex == Property::INVALID_COMPONENT_INDEX) ? object.GetPropertyType(target.propertyIndex) : Property::FLOAT; - // validate animation parameters, if component index is set then use float as checked type - ValidateParameters((target.componentIndex == Property::INVALID_COMPONENT_INDEX) ? propertyType : Property::FLOAT, - destinationType, - period); + // validate and convert animation parameters, if component index is set then use float as checked type + ValidateAndConvertParameters(propertyType, period, relativeValue); ExtendDuration(period); // keep the current count. auto connectorIndex = mConnectors.Count(); - // using destination type so component animation gets correct type - switch(destinationType) + switch(propertyType) { case Property::BOOLEAN: { @@ -688,22 +685,18 @@ void Animation::AnimateTo(Property& target, Property::Value destinationValue, Ti void Animation::AnimateTo(Property& target, Property::Value destinationValue, AlphaFunction alpha, TimePeriod period) { - Object& object = GetImplementation(target.object); - const Property::Type propertyType = object.GetPropertyType(target.propertyIndex); - const Property::Type destinationType = destinationValue.GetType(); + Object& object = GetImplementation(target.object); + const Property::Type propertyType = (target.componentIndex == Property::INVALID_COMPONENT_INDEX) ? object.GetPropertyType(target.propertyIndex) : Property::FLOAT; - // validate animation parameters, if component index is set then use float as checked type - ValidateParameters((target.componentIndex == Property::INVALID_COMPONENT_INDEX) ? propertyType : Property::FLOAT, - destinationType, - period); + // validate and convert animation parameters, if component index is set then use float as checked type + ValidateAndConvertParameters(propertyType, period, destinationValue); ExtendDuration(period); // keep the current count. auto connectorIndex = mConnectors.Count(); - // using destination type so component animation gets correct type - switch(destinationType) + switch(propertyType) { case Property::BOOLEAN: { @@ -831,20 +824,36 @@ void Animation::AnimateBetween(Property target, Dali::KeyFrames keyFrames, Alpha Object& object = GetImplementation(target.object); const KeyFrames& keyFramesImpl = GetImplementation(keyFrames); - const Property::Type propertyType = object.GetPropertyType(target.propertyIndex); - const Property::Type destinationType = keyFramesImpl.GetType(); + const Property::Type propertyType = (target.componentIndex == Property::INVALID_COMPONENT_INDEX) ? object.GetPropertyType(target.propertyIndex) : Property::FLOAT; + + auto lastKeyFrameValue = keyFramesImpl.GetLastKeyFrameValue(); + ValidateAndConvertParameters(propertyType, period, lastKeyFrameValue); + + if(DALI_UNLIKELY(propertyType != keyFramesImpl.GetType())) + { + // Test for conversion valid, and convert keyframe values to matched property type. + Dali::KeyFrames convertedKeyFrames = Dali::KeyFrames::New(); + auto keyFrameCount = keyFramesImpl.GetKeyFrameCount(); + for(auto frameIndex = 0u; frameIndex < keyFrameCount; ++frameIndex) + { + float progress; + Property::Value value; + keyFramesImpl.GetKeyFrame(frameIndex, progress, value); + DALI_ASSERT_ALWAYS(value.ConvertType(propertyType) && "Target types could not be convert to Property type"); - // validate animation parameters, if component index is set then use float as checked type - ValidateParameters((target.componentIndex == Property::INVALID_COMPONENT_INDEX) ? propertyType : Property::FLOAT, - destinationType, - period); + convertedKeyFrames.Add(progress, value); + } + + // Retry to animation as the converted keyframes. + AnimateBetween(target, convertedKeyFrames, alpha, period, interpolation); + return; + } ExtendDuration(period); - AppendConnectorTargetValues({keyFramesImpl.GetLastKeyFrameValue(), period, mConnectors.Count(), BETWEEN}); + AppendConnectorTargetValues({lastKeyFrameValue, period, mConnectors.Count(), BETWEEN}); - // using destination type so component animation gets correct type - switch(destinationType) + switch(propertyType) { case Dali::Property::BOOLEAN: { diff --git a/dali/internal/event/common/scene-impl.cpp b/dali/internal/event/common/scene-impl.cpp index 0ae6fdaff..5133ea2c6 100644 --- a/dali/internal/event/common/scene-impl.cpp +++ b/dali/internal/event/common/scene-impl.cpp @@ -138,6 +138,7 @@ void Scene::Initialize(Size size, int32_t windowOrientation, int32_t screenOrien // Create the default render-task and ensure clear is enabled on it to show the background color RenderTaskPtr renderTask = mRenderTaskList->CreateTask(mRootLayer.Get(), mDefaultCamera.Get()); + renderTask->SetOrderIndex(INT32_MIN); renderTask->SetClearEnabled(true); // Create scene graph object diff --git a/dali/internal/event/effects/shader-factory.cpp b/dali/internal/event/effects/shader-factory.cpp index 678ae4971..f3f54fd7e 100644 --- a/dali/internal/event/effects/shader-factory.cpp +++ b/dali/internal/event/effects/shader-factory.cpp @@ -33,6 +33,8 @@ namespace { const char* VERSION_SEPARATOR = "-"; const char* SHADER_SUFFIX = ".dali-bin"; + +constexpr uint32_t MAXIMUM_STRING_SHADER_DATA_CACHE_CLEAN_THRESHOLD = 128u; } // namespace namespace Dali @@ -188,6 +190,11 @@ void ShaderFactory::MemoryCacheInsert(ShaderData& shaderData, const bool isBinar } else { + if(DALI_UNLIKELY(mTotalStringCachedShadersCount >= MAXIMUM_STRING_SHADER_DATA_CACHE_CLEAN_THRESHOLD)) + { + // Reset string cache, to avoid memory leak problem. + ResetStringShaderData(); + } auto& cacheList = mShaderStringCache[shaderHash]; ///< Get or create a new cache list. // Ignore shaderdata with string if it already exists: @@ -202,6 +209,8 @@ void ShaderFactory::MemoryCacheInsert(ShaderData& shaderData, const bool isBinar } shaderData.Reference(); cacheList.PushBack(&shaderData); + + ++mTotalStringCachedShadersCount; DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "CACHED NON-BINARY SHADER FOR HASH: %u, HINT: %d, TAG: %u\n", shaderHash, static_cast(shaderData.GetHints()), shaderData.GetRenderPassTag()); } } @@ -222,6 +231,8 @@ void ShaderFactory::RemoveStringShaderData(ShaderData& shaderData) // Reduce reference before erase (*iter)->Unreference(); cacheList.Erase(iter); + + --mTotalStringCachedShadersCount; break; } } @@ -232,6 +243,25 @@ void ShaderFactory::RemoveStringShaderData(ShaderData& shaderData) } } +void ShaderFactory::ResetStringShaderData() +{ + DALI_LOG_RELEASE_INFO("Trigger StringShaderData GC. shader : [%u]\n", mTotalStringCachedShadersCount); + for(auto&& iter : mShaderStringCache) + { + auto& cacheList = iter.second; + for(auto&& shaderData : cacheList) + { + shaderData->Unreference(); + } + } + + // Reset cache after unreference. + mShaderStringCache.clear(); + + mTotalStringCachedShadersCount = 0u; + DALI_LOG_RELEASE_INFO("StringShaderData GC done\n"); +} + } // namespace Internal } // namespace Dali diff --git a/dali/internal/event/effects/shader-factory.h b/dali/internal/event/effects/shader-factory.h index 0662c31c7..afadccd8f 100644 --- a/dali/internal/event/effects/shader-factory.h +++ b/dali/internal/event/effects/shader-factory.h @@ -90,6 +90,11 @@ private: */ void RemoveStringShaderData(Internal::ShaderData& shaderData); + /** + * @brief Remove all the string shader data from the cache. + */ + void ResetStringShaderData(); + // Undefined ShaderFactory(const ShaderFactory&) = delete; @@ -102,6 +107,8 @@ private: ShaderCacheContainer mShaderBinaryCache; ///< Cache of pre-compiled shaders. ShaderCacheContainer mShaderStringCache; ///< Cache of non-pre-compiled shaders. (TODO : Could we clean up this cache by user management?) + uint32_t mTotalStringCachedShadersCount{0u}; ///< Total number of cached shaders that are not pre-compiled. + }; // class ShaderFactory inline MessageBase* ShaderCompiledMessage(ShaderSaver& factory, Internal::ShaderDataPtr shaderData) diff --git a/dali/internal/event/render-tasks/render-task-list-impl.cpp b/dali/internal/event/render-tasks/render-task-list-impl.cpp index 990776115..09db52ebb 100644 --- a/dali/internal/event/render-tasks/render-task-list-impl.cpp +++ b/dali/internal/event/render-tasks/render-task-list-impl.cpp @@ -42,6 +42,11 @@ namespace Dali { namespace Internal { + +typedef std::vector OffScreenRenderableContainer; +typedef std::pair ForwardOffScreenRenderableSubTree; +typedef std::vector OffScreenRenderableData; + namespace { static constexpr uint32_t ORDER_INDEX_OVERLAY_RENDER_TASK = INT32_MAX; @@ -187,6 +192,172 @@ void RenderTaskList::SortTasks() mIsRequestedToSortTask = false; } +bool IsWithinSourceActors(const Actor& sourceActor, Actor& actor) +{ + bool isInside = false; + Actor* currentActor = &actor; + while(currentActor) + { + if(&sourceActor == currentActor) + { + isInside = true; + break; + } + + if(currentActor->GetOffScreenRenderableType() & OffScreenRenderable::Type::FORWARD) + { + isInside = false; + break; + } + currentActor = currentActor->GetParent(); + } + return isInside; +} + +void FindOffScreenRenderableWithinSubTree(Actor& rootActor, Actor& actor, uint32_t subTreeIndex, std::vector& onScreenSources, OffScreenRenderableData& renderableData, std::vector& traverseFinished) +{ + if(&actor != renderableData[subTreeIndex].first) + { + + // New BACKWARD OffScreen Renderable + if(actor.GetOffScreenRenderableType() & OffScreenRenderable::Type::BACKWARD) + { + renderableData[subTreeIndex].second.push_back(&actor); + } + + // New FORWARD OffScreen Renderable. It makes new subTree. + if(actor.GetOffScreenRenderableType() & OffScreenRenderable::Type::FORWARD) + { + ForwardOffScreenRenderableSubTree newSubTree; + newSubTree.first = &actor; + renderableData.push_back(newSubTree); + traverseFinished.push_back(false); + return; + } + + // OnScreen Source and its child will be traversed by next loop. + if(std::find(onScreenSources.begin(), onScreenSources.end(), &actor) != onScreenSources.end()) + { + return; + } + + if(rootActor.GetId() != actor.GetId() && actor.GetLayer().GetProperty(Dali::Actor::Property::ID) == static_cast(actor.GetId())) + { + return; + } + } + + uint32_t childCount = actor.GetChildCount(); + for(uint32_t i = 0; i < childCount; ++i) + { + auto child = actor.GetChildAt(i); + FindOffScreenRenderableWithinSubTree(rootActor, *(child.Get()), subTreeIndex, onScreenSources, renderableData, traverseFinished); + } +} + +void RenderTaskList::ReorderTasks(Dali::Internal::LayerList& layerList) +{ + if(mIsRequestedToReorderTask) + { + std::vector traverseFinished; + OffScreenRenderableData renderableData; + uint32_t layerCount = layerList.GetLayerCount(); + uint32_t taskCount = GetTaskCount(); + std::vector onScreenSources; + for(uint32_t i = 0; i < taskCount; ++i) + { + auto renderTask = GetTask(i); + if(!renderTask->GetFrameBuffer()) + { + onScreenSources.push_back(renderTask->GetSourceActor()); + } + } + + for(uint32_t i = 0; i < taskCount; ++i) + { + auto renderTask = GetTask(i); + if(renderTask->GetFrameBuffer()) + { + continue; + } + + auto* sourceActor = renderTask->GetSourceActor(); + ForwardOffScreenRenderableSubTree subTree; + subTree.first = sourceActor; + renderableData.push_back(subTree); + traverseFinished.push_back(false); + + uint32_t currentSubTreeIndex = 0; + Actor* root = subTree.first; + while(root) + { + Dali::Layer sourceLayer = root->GetLayer(); + const uint32_t sourceLayerDepth = sourceLayer.GetProperty(Dali::Layer::Property::DEPTH); + for(uint32_t currentLayerIndex = 0; currentLayerIndex < layerCount; ++currentLayerIndex) + { + auto* layer = layerList.GetLayer(currentLayerIndex); + Dali::Internal::Actor* rootActor = nullptr; + if(sourceLayerDepth == currentLayerIndex) + { + rootActor = root; + } + else + { + if(!IsWithinSourceActors(*root, *layer)) + { + continue; + } + rootActor = layer; + } + FindOffScreenRenderableWithinSubTree(*rootActor, *rootActor, currentSubTreeIndex, onScreenSources, renderableData, traverseFinished); + } + + traverseFinished[currentSubTreeIndex] = true; + + root = nullptr; + for(currentSubTreeIndex = 0; currentSubTreeIndex < traverseFinished.size(); ++currentSubTreeIndex) + { + if(!traverseFinished[currentSubTreeIndex]) + { + root = renderableData[currentSubTreeIndex].first; + break; + } + } + } + } + + // Default Task should have the lowest OrderIndex number. + int32_t orderIndex = GetTask(0u)->GetOrderIndex(); + uint32_t subTreeCount = renderableData.size(); + for(uint32_t i = subTreeCount - 1; i < subTreeCount; --i) + { + auto subTree = renderableData[i]; + for(auto&& actor : subTree.second) + { + std::vector tasks; + actor->GetOffScreenRenderTasks(tasks, false); + for(auto&& task : tasks) + { + GetImplementation(task).SetOrderIndex(orderIndex++); + } + } + + if(subTree.first && subTree.first->GetOffScreenRenderableType() & OffScreenRenderable::Type::FORWARD) + { + std::vector tasks; + subTree.first->GetOffScreenRenderTasks(tasks, true); + for(auto&& task : tasks) + { + GetImplementation(task).SetOrderIndex(orderIndex++); + } + } + } + + SortTasks(); + } + mIsRequestedToReorderTask = false; +} + RenderTaskList::RenderTaskList() : mEventThreadServices(EventThreadServices::Get()), mDefaults(*Stage::GetCurrent()), diff --git a/dali/internal/event/render-tasks/render-task-list-impl.h b/dali/internal/event/render-tasks/render-task-list-impl.h index 8fce92f10..af0253381 100644 --- a/dali/internal/event/render-tasks/render-task-list-impl.h +++ b/dali/internal/event/render-tasks/render-task-list-impl.h @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -162,6 +163,21 @@ public: */ void SortTasks(); + /** + * @brief Requests to reorder the RenderTasks of this RenderTaskList. + */ + void RequestReorder() + { + mIsRequestedToReorderTask = true; + } + + /** + * @brief Reorder RenderTasks along the priority of OffScreenRenderableType of each Actor. + * + * @param[in] layerList layerList that used for tasks reordering. + */ + void ReorderTasks(Dali::Internal::LayerList& layerList); + /** * Provide notification signals for a "Finished" render task. * This method should be called in the event-thread @@ -215,6 +231,7 @@ private: RenderTaskPtr mOverlayRenderTask{nullptr}; bool mIsRequestedToSortTask{false}; + bool mIsRequestedToReorderTask{false}; }; } // namespace Internal diff --git a/dali/internal/event/rendering/shader-impl.cpp b/dali/internal/event/rendering/shader-impl.cpp index 44a12cc22..fb32ee0d8 100644 --- a/dali/internal/event/rendering/shader-impl.cpp +++ b/dali/internal/event/rendering/shader-impl.cpp @@ -348,13 +348,13 @@ std::string Shader::GetShaderVersionPrefix() std::string Shader::GetVertexShaderPrefix() { Dali::Internal::ThreadLocalStorage& tls = Dali::Internal::ThreadLocalStorage::Get(); - return tls.GetVertexShaderPrefix(); + return GenerateTaggedShaderPrefix(tls.GetVertexShaderPrefix()); } std::string Shader::GetFragmentShaderPrefix() { Dali::Internal::ThreadLocalStorage& tls = Dali::Internal::ThreadLocalStorage::Get(); - return tls.GetFragmentShaderPrefix(); + return GenerateTaggedShaderPrefix(tls.GetFragmentShaderPrefix()); } std::string Shader::GenerateTaggedShaderPrefix(const std::string& shaderPrefix) diff --git a/dali/internal/event/rendering/shader-impl.h b/dali/internal/event/rendering/shader-impl.h index 0f597d1f7..1b46fc234 100644 --- a/dali/internal/event/rendering/shader-impl.h +++ b/dali/internal/event/rendering/shader-impl.h @@ -146,7 +146,7 @@ public: /** * Generates tag 'legacy-prefix-end' with end position of * prefix text to make shader code parsing easier. - * Function is public to be testable + * Function is public to be testable and integration api. */ static std::string GenerateTaggedShaderPrefix(const std::string& shaderPrefix); }; diff --git a/dali/internal/render/common/render-algorithms.cpp b/dali/internal/render/common/render-algorithms.cpp index 3b53f4891..7f067c177 100644 --- a/dali/internal/render/common/render-algorithms.cpp +++ b/dali/internal/render/common/render-algorithms.cpp @@ -40,6 +40,7 @@ namespace Render { namespace { + struct GraphicsDepthCompareOp { constexpr explicit GraphicsDepthCompareOp(DepthFunction::Type compareOp) @@ -147,7 +148,7 @@ struct GraphicsStencilOp inline Graphics::Viewport ViewportFromClippingBox(const Uint16Pair& sceneSize, ClippingBox clippingBox, int orientation) { - Graphics::Viewport viewport{static_cast(clippingBox.x), static_cast(clippingBox.y), static_cast(clippingBox.width), static_cast(clippingBox.height), 0.0f, 0.0f}; + Graphics::Viewport viewport{static_cast(clippingBox.x), static_cast(clippingBox.y), static_cast(clippingBox.width), static_cast(clippingBox.height), 0.0f, 1.0f}; if(orientation == 90 || orientation == 270) { @@ -169,6 +170,8 @@ inline Graphics::Viewport ViewportFromClippingBox(const Uint16Pair& sceneSize, C viewport.x = sceneSize.GetX() - (clippingBox.x + clippingBox.width); viewport.y = sceneSize.GetY() - (clippingBox.y + clippingBox.height); } + viewport.minDepth = 0; + viewport.maxDepth = 1; return viewport; } @@ -593,6 +596,7 @@ inline void RenderAlgorithms::ProcessRenderList(const RenderList& const Rect& rootClippingRect, int orientation, const Uint16Pair& sceneSize, + Graphics::RenderPass* renderPass, Graphics::RenderTarget* renderTarget) { DALI_PRINT_RENDER_LIST(renderList); @@ -616,7 +620,9 @@ inline void RenderAlgorithms::ProcessRenderList(const RenderList& // We are always "inside" a render pass here. Graphics::CommandBufferBeginInfo info; - info.usage = 0 | Graphics::CommandBufferUsageFlagBits::ONE_TIME_SUBMIT; + info.SetUsage(0 | Graphics::CommandBufferUsageFlagBits::RENDER_PASS_CONTINUE) + .SetRenderPass(*renderPass) + .SetRenderTarget(*renderTarget); secondaryCommandBuffer.Begin(info); secondaryCommandBuffer.SetViewport(ViewportFromClippingBox(sceneSize, mViewportRectangle, orientation)); @@ -627,9 +633,9 @@ inline void RenderAlgorithms::ProcessRenderList(const RenderList& // Add root clipping rect (set manually for Render function by partial update for example) // on the bottom of the stack + Graphics::Viewport graphicsViewport = ViewportFromClippingBox(sceneSize, mViewportRectangle, 0); if(!rootClippingRect.IsEmpty()) { - Graphics::Viewport graphicsViewport = ViewportFromClippingBox(sceneSize, mViewportRectangle, 0); secondaryCommandBuffer.SetScissorTestEnable(true); secondaryCommandBuffer.SetScissor(Rect2DFromRect(rootClippingRect, orientation, graphicsViewport)); mScissorStack.push_back(rootClippingRect); @@ -638,12 +644,13 @@ inline void RenderAlgorithms::ProcessRenderList(const RenderList& else if(!renderList.IsClipping()) { secondaryCommandBuffer.SetScissorTestEnable(false); + //@todo Vk requires a scissor to be set, as we have turned on dynamic state scissor in the pipelines. + secondaryCommandBuffer.SetScissor(Rect2DFromClippingBox(mViewportRectangle, orientation, graphicsViewport)); mScissorStack.push_back(mViewportRectangle); } if(renderList.IsClipping()) { - Graphics::Viewport graphicsViewport = ViewportFromClippingBox(sceneSize, mViewportRectangle, 0); secondaryCommandBuffer.SetScissorTestEnable(true); const ClippingBox& layerScissorBox = renderList.GetClippingBox(); secondaryCommandBuffer.SetScissor(Rect2DFromClippingBox(layerScissorBox, orientation, graphicsViewport)); @@ -654,6 +661,13 @@ inline void RenderAlgorithms::ProcessRenderList(const RenderList& // Prepare Render::Renderer Render for this secondary command buffer. Renderer::PrepareCommandBuffer(); + // Modify by the clip matrix if necessary (transforms from GL clip space to alternative clip space) + Matrix clippedProjectionMatrix(projectionMatrix); + if(mGraphicsController.HasClipMatrix()) + { + Matrix::Multiply(clippedProjectionMatrix, projectionMatrix, mGraphicsController.GetClipMatrix()); + } + // Loop through all RenderItems in the RenderList, set up any prerequisites to render them, then perform the render. for(uint32_t index = 0u; index < count; ++index) { @@ -705,7 +719,7 @@ inline void RenderAlgorithms::ProcessRenderList(const RenderList& for(auto queue = 0u; queue < MAX_QUEUE; ++queue) { // Render the item. It will write into the command buffer everything it has to render - item.mRenderer->Render(secondaryCommandBuffer, bufferIndex, *item.mNode, item.mModelMatrix, item.mModelViewMatrix, viewMatrix, projectionMatrix, item.mScale, item.mSize, !item.mIsOpaque, instruction, renderTarget, queue); + item.mRenderer->Render(secondaryCommandBuffer, bufferIndex, *item.mNode, item.mModelMatrix, item.mModelViewMatrix, viewMatrix, clippedProjectionMatrix, item.mScale, item.mSize, !item.mIsOpaque, instruction, renderTarget, queue); } } } @@ -720,7 +734,7 @@ RenderAlgorithms::RenderAlgorithms(Graphics::Controller& graphicsController) { } -void RenderAlgorithms::ResetCommandBuffer() +void RenderAlgorithms::ResetCommandBuffer(std::vector* resourceBindings) { // Reset main command buffer if(!mGraphicsCommandBuffer) @@ -736,7 +750,8 @@ void RenderAlgorithms::ResetCommandBuffer() } Graphics::CommandBufferBeginInfo info; - info.usage = 0 | Graphics::CommandBufferUsageFlagBits::ONE_TIME_SUBMIT; + info.resourceBindings = resourceBindings; // set resource bindings, currently only programs + info.usage = 0 | Graphics::CommandBufferUsageFlagBits::ONE_TIME_SUBMIT; mGraphicsCommandBuffer->Begin(info); } @@ -764,6 +779,7 @@ void RenderAlgorithms::ProcessRenderInstruction(const RenderInstruction& const Rect& rootClippingRect, int orientation, const Uint16Pair& sceneSize, + Graphics::RenderPass* renderPass, Graphics::RenderTarget* renderTarget) { DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_RENDER_INSTRUCTION_PROCESS", [&](std::ostringstream& oss) { oss << "[" << instruction.RenderListCount() << "]"; }); @@ -800,6 +816,7 @@ void RenderAlgorithms::ProcessRenderInstruction(const RenderInstruction& rootClippingRect, orientation, sceneSize, + renderPass, renderTarget); // Execute command buffer diff --git a/dali/internal/render/common/render-algorithms.h b/dali/internal/render/common/render-algorithms.h index 8f9196404..7acbad1ac 100644 --- a/dali/internal/render/common/render-algorithms.h +++ b/dali/internal/render/common/render-algorithms.h @@ -71,12 +71,15 @@ public: const Rect& rootClippingRect, int orientation, const Uint16Pair& sceneSize, + Graphics::RenderPass* renderPass, Graphics::RenderTarget* renderTarget); /** * Resets main command buffer (per scene) + * + * @param[in] bindings list of resource bindings (optional, can be null) */ - void ResetCommandBuffer(); + void ResetCommandBuffer(std::vector* bindings); /** * Submits main command buffer (per scene) @@ -166,6 +169,7 @@ private: const Rect& rootClippingRect, int orientation, const Uint16Pair& sceneSize, + Graphics::RenderPass* renderPass, Graphics::RenderTarget* renderTarget); // Member variables: diff --git a/dali/internal/render/common/render-manager.cpp b/dali/internal/render/common/render-manager.cpp index 4f72d397c..5aff37e3d 100644 --- a/dali/internal/render/common/render-manager.cpp +++ b/dali/internal/render/common/render-manager.cpp @@ -960,11 +960,6 @@ void RenderManager::RenderScene(Integration::RenderStatus& status, Integration:: return; } - // Reset main algorithms command buffer - mImpl->renderAlgorithms.ResetCommandBuffer(); - - auto mainCommandBuffer = mImpl->renderAlgorithms.GetMainCommandBuffer(); - Internal::Scene& sceneInternal = GetImplementation(scene); SceneGraph::Scene* sceneObject = sceneInternal.GetSceneObject(); if(!sceneObject) @@ -991,6 +986,8 @@ void RenderManager::RenderScene(Integration::RenderStatus& status, Integration:: auto totalSizeCPU = 0u; auto totalSizeGPU = 0u; + std::unordered_map programUsageCount; + for(uint32_t i = 0; i < instructionCount; ++i) { RenderInstruction& instruction = sceneObject->GetRenderInstructions().At(mImpl->renderBufferIndex, i); @@ -1012,6 +1009,18 @@ void RenderManager::RenderScene(Integration::RenderStatus& status, Integration:: { const auto& memoryRequirements = program->GetUniformBlocksMemoryRequirements(); + // collect how many programs we use in this frame + auto key = &program->GetGraphicsProgram(); + auto it = programUsageCount.find(key); + if(it == programUsageCount.end()) + { + programUsageCount[key] = Graphics::ProgramResourceBindingInfo{.program = key, .count = 1}; + } + else + { + (*it).second.count++; + } + totalSizeCPU += memoryRequirements.totalCpuSizeRequired; totalSizeGPU += memoryRequirements.totalGpuSizeRequired; } @@ -1021,6 +1030,25 @@ void RenderManager::RenderScene(Integration::RenderStatus& status, Integration:: } } + // Fill resource binding for the command buffer + std::vector commandBufferResourceBindings; + if(!programUsageCount.empty()) + { + commandBufferResourceBindings.resize(programUsageCount.size()); + auto iter = commandBufferResourceBindings.begin(); + for(auto& item : programUsageCount) + { + iter->type = Graphics::ResourceType::PROGRAM; + iter->programBinding = &item.second; + ++iter; + } + } + + // Reset main algorithms command buffer + mImpl->renderAlgorithms.ResetCommandBuffer(commandBufferResourceBindings.empty() ? nullptr : &commandBufferResourceBindings); + + auto mainCommandBuffer = mImpl->renderAlgorithms.GetMainCommandBuffer(); + DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Render scene (%s), CPU:%d GPU:%d\n", renderToFbo ? "Offscreen" : "Onscreen", totalSizeCPU, totalSizeGPU); auto& uboManager = mImpl->uniformBufferManager; @@ -1229,10 +1257,7 @@ void RenderManager::RenderScene(Integration::RenderStatus& status, Integration:: scissorArea, currentClearValues); - mainCommandBuffer->SetViewport({float(viewportRect.x), - float(viewportRect.y), - float(viewportRect.width), - float(viewportRect.height)}); + // Note, don't set the viewport/scissor on the primary command buffer. mImpl->renderAlgorithms.ProcessRenderInstruction( instruction, @@ -1243,6 +1268,7 @@ void RenderManager::RenderScene(Integration::RenderStatus& status, Integration:: clippingRect, surfaceOrientation, Uint16Pair(surfaceRect.width, surfaceRect.height), + currentRenderPass, currentRenderTarget); Graphics::SyncObject* syncObject{nullptr}; @@ -1259,7 +1285,8 @@ void RenderManager::RenderScene(Integration::RenderStatus& status, Integration:: if(targetsToPresent.size() > 0u) { - DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_RENDER_FINISHED", [&](std::ostringstream& oss) { oss << "[" << targetsToPresent.size() << "]"; }); + DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_RENDER_FINISHED", [&](std::ostringstream& oss) + { oss << "[" << targetsToPresent.size() << "]"; }); } // Flush UBOs diff --git a/dali/public-api/actors/actor-enumerations.h b/dali/public-api/actors/actor-enumerations.h index 14c98210f..3edcfdfa0 100644 --- a/dali/public-api/actors/actor-enumerations.h +++ b/dali/public-api/actors/actor-enumerations.h @@ -188,6 +188,21 @@ enum Type } // namespace LayoutDirection +/** + * @brief Enumeration for the OffScreenRenderable of the Actor + * @SINCE_2_3.43 + */ +namespace OffScreenRenderable +{ +enum Type +{ + NONE = 0, // The Actor has no OffScreenRenderables. @SINCE_2_3.43 + FORWARD = 1, // The Actor has RenderTasks those need reorder. And the Tasks will draw Actors those placed in front of the Actor. @SINCE_2_3.43 + BACKWARD = 2, // The Actor has RenderTasks those need reorder, And the Tasks will draw Actors those placed behinde of the Actor. @SINCE_2_3.43 + BOTH = FORWARD | BACKWARD, // The Actor has RenderTasks for the both of FORWARD and BACKWARD. @SINCE_2_3.43 +}; +} // namespace OffScreenRenderables + /** * @} */ diff --git a/dali/public-api/actors/custom-actor-impl.cpp b/dali/public-api/actors/custom-actor-impl.cpp index ad000b8ec..12a1d1f06 100644 --- a/dali/public-api/actors/custom-actor-impl.cpp +++ b/dali/public-api/actors/custom-actor-impl.cpp @@ -33,6 +33,21 @@ void CustomActorImpl::OnPropertySet(Property::Index index, const Property::Value { } +void CustomActorImpl::SetOffScreenRenderableType(OffScreenRenderable::Type offScreenRenderableType) +{ + mOwner->SetOffScreenRenderableType(offScreenRenderableType); +} + +OffScreenRenderable::Type CustomActorImpl::GetOffScreenRenderableType() +{ + return mOwner->GetOffScreenRenderableType(); +} + +void CustomActorImpl::RequestRenderTaskReorder() +{ + mOwner->RequestRenderTaskReorder(); +} + CustomActorImpl::CustomActorImpl(ActorFlags flags) : mOwner(nullptr), mFlags(flags) diff --git a/dali/public-api/actors/custom-actor-impl.h b/dali/public-api/actors/custom-actor-impl.h index cc1a53e22..21af81865 100644 --- a/dali/public-api/actors/custom-actor-impl.h +++ b/dali/public-api/actors/custom-actor-impl.h @@ -23,9 +23,12 @@ // INTERNAL INCLUDES #include +#include +#include #include #include #include +#include namespace Dali { @@ -39,7 +42,6 @@ namespace Internal DALI_INTERNAL class CustomActor; } -class Actor; class Animation; class CustomActor; class CustomActorImpl; @@ -172,6 +174,47 @@ public: */ virtual void OnSizeAnimation(Animation& animation, const Vector3& targetSize) = 0; + /** + * @brief Retrieves the off-screen RenderTasks associated with the Actor. + * This method returns the internal RenderTasks held by the Actor. This tasks are + * used for off-screen rendering, and the system will assign order index to each + * tasks based on the render order. + * + * Actor with a non-NONE OffScreenRenderableType should override this method to + * provide their render tasks. + * + * @SINCE_2_3.43 + * @param[out] tasks A list of RenderTasks to be populated with the Actor's forward + * or backward off-screen RenderTask. + * @param[in] isForward Indicates whether to retrieve forward (true) or backward (false) + * RenderTasks. + */ + virtual void GetOffScreenRenderTasks(std::vector& tasks, bool isForward) = 0; + + /** + * @brief Sets OffScreenRenderableType of this Actor. + * This method is called by child class to set type itself. + * + * @SINCE_2_3.43 + * @param[in] offScreenRenderableType OffScreenRenderableType for this Actor. + * It could be one of NONE, FORWARD, BACKWARD, and BOTH. + */ + void SetOffScreenRenderableType(OffScreenRenderable::Type offScreenRenderableType); + + /** + * @brief Retrieves OffScreenRenderableType of this Actor. + * + * @SINCE_2_3.43 + * @return OffScreenRenderableType for this Actor. + */ + OffScreenRenderable::Type GetOffScreenRenderableType(); + + /** + * @brief Requests RenderTask reordering when the offscreen properties of this Actor are changed. + * @SINCE_2_3.43 + */ + void RequestRenderTaskReorder(); + /** * @brief Called after the size negotiation has been finished for this control. * diff --git a/dali/public-api/dali-core-version.cpp b/dali/public-api/dali-core-version.cpp index e48c5534d..aa9e1ccbe 100644 --- a/dali/public-api/dali-core-version.cpp +++ b/dali/public-api/dali-core-version.cpp @@ -27,7 +27,7 @@ namespace Dali { const uint32_t CORE_MAJOR_VERSION = 2; const uint32_t CORE_MINOR_VERSION = 3; -const uint32_t CORE_MICRO_VERSION = 41; +const uint32_t CORE_MICRO_VERSION = 44; const char* const CORE_BUILD_DATE = __DATE__ " " __TIME__; #ifdef DEBUG_ENABLED diff --git a/dali/public-api/images/image-operations.h b/dali/public-api/images/image-operations.h index 8642976cf..6af7cba54 100644 --- a/dali/public-api/images/image-operations.h +++ b/dali/public-api/images/image-operations.h @@ -2,7 +2,7 @@ #define DALI_IMAGE_OPERATIONS_H /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * Copyright (c) 2024 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. @@ -92,9 +92,9 @@ const Type DEFAULT = SHRINK_TO_FIT; namespace SamplingMode { /** - * @brief Enumeration for SamplingMode type. - * @SINCE_1_0.0 - */ + * @brief Enumeration for SamplingMode type. + * @SINCE_1_0.0 + */ enum Type { BOX, ///< Iteratively box filter to generate an image of 1/2, 1/4, @@ -119,9 +119,15 @@ enum Type /// is enabled, the borders of the image may be trimmed to /// match the aspect ratio of the desired dimensions. /// @SINCE_1_0.0 - DONT_CARE ///< For caching algorithms where a client strongly prefers a + DONT_CARE, ///< For caching algorithms where a client strongly prefers a /// cache-hit to reuse a cached image. /// @SINCE_1_0.0 + LANCZOS, ///< Use filter with Lanczos resample algorithm. + /// @SINCE_2_3.43 + BOX_THEN_LANCZOS, ///< Iteratively box filter to generate an image of 1/2, 1/4, + /// 1/8 etc width and height and approximately the desired + /// size, then apply Lanczos resample algorithm. + /// @SINCE_2_3.43 }; const Type DEFAULT = BOX; } // namespace SamplingMode diff --git a/dali/public-api/object/property-value.cpp b/dali/public-api/object/property-value.cpp index 79381b40f..f1c633212 100644 --- a/dali/public-api/object/property-value.cpp +++ b/dali/public-api/object/property-value.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * Copyright (c) 2024 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. @@ -500,6 +500,106 @@ struct Property::Value::Impl mData.mType.type = typeValue; } + bool ConvertType(const Property::Type targetType) + { + bool converted = false; + const Property::Type inputType = mData.mType.type; + + if(inputType == targetType) + { + // We don't need conversion for same type. + return true; + } + + switch(inputType) + { + // Try to convert only for scalar types + case Property::BOOLEAN: + { + bool value = mData.mBool.member; + switch(targetType) + { + case Property::FLOAT: + { + SetType(targetType); + mData.mFloat.member = static_cast(value); + converted = true; + break; + } + case Property::INTEGER: + { + SetType(targetType); + mData.mInt.member = static_cast(value); + converted = true; + break; + } + default: + { + break; + } + } + break; + } + case Property::FLOAT: + { + float value = mData.mFloat.member; + switch(targetType) + { + case Property::BOOLEAN: + { + SetType(targetType); + mData.mBool.member = static_cast(!Dali::EqualsZero(value)); + converted = true; + break; + } + case Property::INTEGER: + { + SetType(targetType); + mData.mInt.member = static_cast(value); + converted = true; + break; + } + default: + { + break; + } + } + break; + } + case Property::INTEGER: + { + int32_t value = mData.mInt.member; + switch(targetType) + { + case Property::BOOLEAN: + { + SetType(targetType); + mData.mBool.member = static_cast(value); + converted = true; + break; + } + case Property::FLOAT: + { + SetType(targetType); + mData.mFloat.member = static_cast(value); + converted = true; + break; + } + default: + { + break; + } + } + break; + } + default: + { + break; + } + } + return converted; + } + private: /** * This helper function takes a typed(Tp) memory location( member) @@ -917,6 +1017,11 @@ Property::Type Property::Value::GetType() const return Read().GetType(); } +bool Property::Value::ConvertType(const Property::Type targetType) +{ + return Write().ConvertType(targetType); +} + bool Property::Value::Get(bool& booleanValue) const { bool converted = false; diff --git a/dali/public-api/object/property-value.h b/dali/public-api/object/property-value.h index 5260f4f35..74eea20ca 100644 --- a/dali/public-api/object/property-value.h +++ b/dali/public-api/object/property-value.h @@ -2,7 +2,7 @@ #define DALI_PROPERTY_VALUE_H /* - * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * Copyright (c) 2024 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. @@ -299,6 +299,16 @@ public: */ Type GetType() const; + /** + * @brief Convert value to another type. + * @note It will be works only if both input and output are scalar type. - Property::BOOLEAN, Property::FLOAT, Property::INTEGER. + * + * @SINCE_2_3.41 + * @param[in] targetType Target type of the conversion. + * @return True if convert is successful, false otherwise. If the conversion fails, the original value is not modified. + */ + bool ConvertType(const Property::Type targetType); + /** * @brief Retrieves a specific value. * diff --git a/packaging/dali.spec b/packaging/dali.spec index 6e96d0d3b..d78ecc348 100644 --- a/packaging/dali.spec +++ b/packaging/dali.spec @@ -1,6 +1,6 @@ Name: dali2 Summary: DALi 3D Engine -Version: 2.3.41 +Version: 2.3.44 Release: 1 Group: System/Libraries License: Apache-2.0 and BSD-3-Clause and MIT