From 65a66e2a1d512363bef4f9f3af065eb27a17fcbc Mon Sep 17 00:00:00 2001 From: "Eunki, Hong" Date: Thu, 19 Oct 2023 11:34:34 +0900 Subject: [PATCH] [Tizen] Destroy removal visuals after idler This is a combination of 3 commits. Revert "[Tizen] Keep reference when member callback excute" Keep reference when member callback excute + Make NPatchData as RefObject Some CallbackBase didn't hold the reference of itself. So it was possible to call destructor of itself during it's API was running. It might makes some unknown issues. So let we keep reference for some issue-comes known APIs : SvgVisual, NPatchData, and lottie It future, we should discard visuals rather than delate it directly. Destroy removal visuals after idler There was some bug when visual destructor called during it's emit ResourceReady. To avoid this case, Let we keep visuals more long term, and Discard + Destroy after some idler called. To avoid multiple Idler callback register, let we make that idler callback in VisualFactory. Change-Id: I4156f1af3cf40ffb30235dc9e6c55f9c7633f21d --- .../dali-toolkit-test-utils/toolkit-adaptor.cpp | 4 +- .../src/dali-toolkit/utc-Dali-Slider.cpp | 6 +- .../controls/scene-view/scene-view-impl.cpp | 254 ++++++++++----------- dali-toolkit/devel-api/utility/npatch-helper.cpp | 7 +- dali-toolkit/devel-api/utility/npatch-helper.h | 22 +- .../devel-api/visual-factory/visual-factory.cpp | 7 +- .../devel-api/visual-factory/visual-factory.h | 9 +- .../controls/control/control-data-impl.cpp | 42 +++- .../rolling-animated-image-cache.cpp | 2 + .../animated-vector-image-visual.cpp | 4 +- dali-toolkit/internal/visuals/npatch-data.cpp | 10 +- dali-toolkit/internal/visuals/npatch-data.h | 11 +- dali-toolkit/internal/visuals/npatch-loader.cpp | 27 +-- dali-toolkit/internal/visuals/npatch-loader.h | 18 +- .../internal/visuals/npatch/npatch-visual.cpp | 30 +-- dali-toolkit/internal/visuals/svg/svg-visual.cpp | 3 +- .../internal/visuals/visual-factory-cache.cpp | 18 +- .../internal/visuals/visual-factory-impl.cpp | 70 ++++-- .../internal/visuals/visual-factory-impl.h | 29 ++- 19 files changed, 321 insertions(+), 252 deletions(-) diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-adaptor.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-adaptor.cpp index 7c887f8..c675fef 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-adaptor.cpp +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-adaptor.cpp @@ -92,8 +92,8 @@ bool Adaptor::AddIdle(CallbackBase* callback, bool hasReturnValue) void Adaptor::RemoveIdle(CallbackBase* callback) { - mCallbacks.Erase(std::find_if(mCallbacks.Begin(), mCallbacks.End(), [&callback](CallbackBase* current) { return callback == current; })); - mReturnCallbacks.Erase(std::find_if(mReturnCallbacks.Begin(), mReturnCallbacks.End(), [&callback](CallbackBase* current) { return callback == current; })); + mCallbacks.Erase(std::remove_if(mCallbacks.Begin(), mCallbacks.End(), [&callback](CallbackBase* current) { return callback == current; }), mCallbacks.End()); + mReturnCallbacks.Erase(std::remove_if(mReturnCallbacks.Begin(), mReturnCallbacks.End(), [&callback](CallbackBase* current) { return callback == current; }), mReturnCallbacks.End()); } void Adaptor::RunIdles() diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Slider.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Slider.cpp index 22b4d2f..1e86e0d 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-Slider.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-Slider.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * Copyright (c) 2023 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. @@ -346,10 +346,10 @@ int UtcDaliSliderSignals2(void) END_TEST; } -int UtcDaliSetPropertyP(void) +int UtcDaliSliderSetPropertyP(void) { ToolkitTestApplication application; - tet_infoline("UtcDaliSetPropertyP"); + tet_infoline("UtcDaliSliderSetPropertyP"); Slider slider = Slider::New(); slider.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT); diff --git a/dali-scene3d/internal/controls/scene-view/scene-view-impl.cpp b/dali-scene3d/internal/controls/scene-view/scene-view-impl.cpp index d630b24..75c9b51 100644 --- a/dali-scene3d/internal/controls/scene-view/scene-view-impl.cpp +++ b/dali-scene3d/internal/controls/scene-view/scene-view-impl.cpp @@ -160,123 +160,122 @@ void SetShadowLightConstraint(Dali::CameraActor selectedCamera, Dali::CameraActo shadowLightCamera.RemoveConstraints(); // Compute ViewProjectionMatrix and store it to "tempViewProjectionMatrix" property - auto tempViewProjectionMatrixIndex = shadowLightCamera.RegisterProperty("tempViewProjectionMatrix", Matrix::IDENTITY); - Constraint projectionMatrixConstraint = Constraint::New(shadowLightCamera, tempViewProjectionMatrixIndex, [](Matrix& output, const PropertyInputContainer& inputs) - { - Matrix worldMatrix = inputs[0]->GetMatrix(); - float tangentFov_2 = tanf(inputs[4]->GetFloat()); - float nearDistance = inputs[5]->GetFloat(); - float farDistance = inputs[6]->GetFloat(); - float aspectRatio = inputs[7]->GetFloat(); - float nearY = 0.0f; - float nearX = 0.0f; - float farY = 0.0f; - float farX = 0.0f; - if(inputs[1]->GetInteger() == Dali::Camera::ProjectionMode::PERSPECTIVE_PROJECTION) - { - if(inputs[2]->GetInteger() == Dali::DevelCameraActor::ProjectionDirection::VERTICAL) - { - nearY = tangentFov_2 * nearDistance; - nearX = nearY * aspectRatio; - farY = tangentFov_2 * farDistance; - farX = farY * aspectRatio; - } - else - { - nearX = tangentFov_2 * nearDistance; - nearY = nearX / aspectRatio; - farX = tangentFov_2 * farDistance; - farY = farX / aspectRatio; - } - } - else - { - if(inputs[2]->GetInteger() == Dali::DevelCameraActor::ProjectionDirection::VERTICAL) - { - nearY = inputs[3]->GetFloat(); - nearX = nearY * aspectRatio; - } - else - { - nearX = inputs[3]->GetFloat(); - nearY = nearX / aspectRatio; - } - farX = nearX; - farY = nearY; - } - - std::vector points; - points.push_back(Vector4(nearX, nearY, nearDistance, 1.0f)); - points.push_back(Vector4(-nearX, nearY, nearDistance, 1.0f)); - points.push_back(Vector4(-nearX, -nearY, nearDistance, 1.0f)); - points.push_back(Vector4(nearX, -nearY, nearDistance, 1.0f)); - points.push_back(Vector4(farX, farY, farDistance, 1.0f)); - points.push_back(Vector4(-farX, farY, farDistance, 1.0f)); - points.push_back(Vector4(-farX, -farY, farDistance, 1.0f)); - points.push_back(Vector4(farX, -farY, farDistance, 1.0f)); - - Matrix shadowCameraWorldMatrix = inputs[8]->GetMatrix(); - Vector4 worldCenter; - for(auto&& point : points) - { - point = worldMatrix * point; - worldCenter += point; - } - worldCenter /= 8.0f; - shadowCameraWorldMatrix.SetTranslation(Vector3(worldCenter)); - Matrix shadowCameraViewMatrix = shadowCameraWorldMatrix; - shadowCameraViewMatrix.Invert(); - - Vector3 areaMin = Vector3::ONE * MAXFLOAT, areaMax = Vector3::ONE * -MAXFLOAT; - for(auto&& point : points) - { - Vector4 pointV = shadowCameraViewMatrix * point; - areaMin.x = std::min(areaMin.x, pointV.x); - areaMin.y = std::min(areaMin.y, pointV.y); - areaMin.z = std::min(areaMin.z, pointV.z); - areaMax.x = std::max(areaMax.x, pointV.x); - areaMax.y = std::max(areaMax.y, pointV.y); - areaMax.z = std::max(areaMax.z, pointV.z); - } - - Vector2 center = Vector2(areaMax + areaMin) * 0.5; - float delta = std::max(std::abs(areaMax.x - areaMin.x), std::abs(areaMax.y - areaMin.y)); - float delta_2 = delta * 0.5f; - Vector2 squareAreaMin = center - Vector2::ONE * delta_2; - Vector2 squareAreaMax = center + Vector2::ONE * delta_2; - float deltaZ = areaMax.z - areaMin.z; - - float right = -squareAreaMin.x; - float left = -squareAreaMax.x; - float top = squareAreaMin.y; - float bottom = squareAreaMax.y; - float near = areaMin.z; - float far = areaMax.z; - - float* projMatrix = output.AsFloat(); - - projMatrix[0] = -2.0f / delta; - projMatrix[1] = 0.0f; - projMatrix[2] = 0.0f; - projMatrix[3] = 0.0f; - - projMatrix[4] = 0.0f; - projMatrix[5] = -2.0f / delta; - projMatrix[6] = 0.0f; - projMatrix[7] = 0.0f; - - projMatrix[8] = 0.0f; - projMatrix[9] = 0.0f; - projMatrix[10] = 2.0f / deltaZ; - projMatrix[11] = 0.0f; - - projMatrix[12] = -(right + left) / delta; - projMatrix[13] = -(top + bottom) / delta; - projMatrix[14] = -(near + far) / deltaZ; - projMatrix[15] = 1.0f; - - output = output * shadowCameraViewMatrix; - }); + auto tempViewProjectionMatrixIndex = shadowLightCamera.RegisterProperty("tempViewProjectionMatrix", Matrix::IDENTITY); + Constraint projectionMatrixConstraint = Constraint::New(shadowLightCamera, tempViewProjectionMatrixIndex, [](Matrix& output, const PropertyInputContainer& inputs) { + Matrix worldMatrix = inputs[0]->GetMatrix(); + float tangentFov_2 = tanf(inputs[4]->GetFloat()); + float nearDistance = inputs[5]->GetFloat(); + float farDistance = inputs[6]->GetFloat(); + float aspectRatio = inputs[7]->GetFloat(); + float nearY = 0.0f; + float nearX = 0.0f; + float farY = 0.0f; + float farX = 0.0f; + if(inputs[1]->GetInteger() == Dali::Camera::ProjectionMode::PERSPECTIVE_PROJECTION) + { + if(inputs[2]->GetInteger() == Dali::DevelCameraActor::ProjectionDirection::VERTICAL) + { + nearY = tangentFov_2 * nearDistance; + nearX = nearY * aspectRatio; + farY = tangentFov_2 * farDistance; + farX = farY * aspectRatio; + } + else + { + nearX = tangentFov_2 * nearDistance; + nearY = nearX / aspectRatio; + farX = tangentFov_2 * farDistance; + farY = farX / aspectRatio; + } + } + else + { + if(inputs[2]->GetInteger() == Dali::DevelCameraActor::ProjectionDirection::VERTICAL) + { + nearY = inputs[3]->GetFloat(); + nearX = nearY * aspectRatio; + } + else + { + nearX = inputs[3]->GetFloat(); + nearY = nearX / aspectRatio; + } + farX = nearX; + farY = nearY; + } + + std::vector points; + points.push_back(Vector4(nearX, nearY, nearDistance, 1.0f)); + points.push_back(Vector4(-nearX, nearY, nearDistance, 1.0f)); + points.push_back(Vector4(-nearX, -nearY, nearDistance, 1.0f)); + points.push_back(Vector4(nearX, -nearY, nearDistance, 1.0f)); + points.push_back(Vector4(farX, farY, farDistance, 1.0f)); + points.push_back(Vector4(-farX, farY, farDistance, 1.0f)); + points.push_back(Vector4(-farX, -farY, farDistance, 1.0f)); + points.push_back(Vector4(farX, -farY, farDistance, 1.0f)); + + Matrix shadowCameraWorldMatrix = inputs[8]->GetMatrix(); + Vector4 worldCenter; + for(auto&& point : points) + { + point = worldMatrix * point; + worldCenter += point; + } + worldCenter /= 8.0f; + shadowCameraWorldMatrix.SetTranslation(Vector3(worldCenter)); + Matrix shadowCameraViewMatrix = shadowCameraWorldMatrix; + shadowCameraViewMatrix.Invert(); + + Vector3 areaMin = Vector3::ONE * MAXFLOAT, areaMax = Vector3::ONE * -MAXFLOAT; + for(auto&& point : points) + { + Vector4 pointV = shadowCameraViewMatrix * point; + areaMin.x = std::min(areaMin.x, pointV.x); + areaMin.y = std::min(areaMin.y, pointV.y); + areaMin.z = std::min(areaMin.z, pointV.z); + areaMax.x = std::max(areaMax.x, pointV.x); + areaMax.y = std::max(areaMax.y, pointV.y); + areaMax.z = std::max(areaMax.z, pointV.z); + } + + Vector2 center = Vector2(areaMax + areaMin) * 0.5; + float delta = std::max(std::abs(areaMax.x - areaMin.x), std::abs(areaMax.y - areaMin.y)); + float delta_2 = delta * 0.5f; + Vector2 squareAreaMin = center - Vector2::ONE * delta_2; + Vector2 squareAreaMax = center + Vector2::ONE * delta_2; + float deltaZ = areaMax.z - areaMin.z; + + float right = -squareAreaMin.x; + float left = -squareAreaMax.x; + float top = squareAreaMin.y; + float bottom = squareAreaMax.y; + float near = areaMin.z; + float far = areaMax.z; + + float* projMatrix = output.AsFloat(); + + projMatrix[0] = -2.0f / delta; + projMatrix[1] = 0.0f; + projMatrix[2] = 0.0f; + projMatrix[3] = 0.0f; + + projMatrix[4] = 0.0f; + projMatrix[5] = -2.0f / delta; + projMatrix[6] = 0.0f; + projMatrix[7] = 0.0f; + + projMatrix[8] = 0.0f; + projMatrix[9] = 0.0f; + projMatrix[10] = 2.0f / deltaZ; + projMatrix[11] = 0.0f; + + projMatrix[12] = -(right + left) / delta; + projMatrix[13] = -(top + bottom) / delta; + projMatrix[14] = -(near + far) / deltaZ; + projMatrix[15] = 1.0f; + + output = output * shadowCameraViewMatrix; + }); projectionMatrixConstraint.AddSource(Source{selectedCamera, Dali::Actor::Property::WORLD_MATRIX}); projectionMatrixConstraint.AddSource(Source{selectedCamera, Dali::CameraActor::Property::PROJECTION_MODE}); projectionMatrixConstraint.AddSource(Source{selectedCamera, Dali::DevelCameraActor::Property::PROJECTION_DIRECTION}); @@ -622,8 +621,7 @@ void SceneView::SetShadow(Scene3D::Light light) return; } - auto foundLight = std::find_if(mLights.begin(), mLights.end(), [light](std::pair lightEntity) -> bool - { return (lightEntity.second && lightEntity.first == light); }); + auto foundLight = std::find_if(mLights.begin(), mLights.end(), [light](std::pair lightEntity) -> bool { return (lightEntity.second && lightEntity.first == light); }); if(foundLight == mLights.end()) { @@ -638,7 +636,7 @@ void SceneView::SetShadow(Scene3D::Light light) SetShadowLightConstraint(selectedCamera, lightCamera); // make framebuffer for depth map and set it to render task. - Vector3 size = Self().GetProperty(Dali::Actor::Property::SIZE); + Vector3 size = Self().GetProperty(Dali::Actor::Property::SIZE); uint32_t shadowMapBufferSize = std::min(static_cast(std::max(size.width, size.height)), MAXIMUM_SIZE_SHADOW_MAP); UpdateShadowMapBuffer(shadowMapBufferSize); @@ -1112,12 +1110,7 @@ void SceneView::OnSkyboxLoadComplete() } mSkyboxResourceReady = true; - if(IsResourceReady()) - { - Control::SetResourceReady(); - } - - mSkyboxTexture = mSkyboxLoadTask->GetLoadedTexture(); + mSkyboxTexture = mSkyboxLoadTask->GetLoadedTexture(); Shader skyboxShader; if(mSkyboxLoadTask->GetEnvironmentMapType() == Scene3D::EnvironmentMapType::CUBEMAP) { @@ -1138,17 +1131,22 @@ void SceneView::OnSkyboxLoadComplete() } mSkyboxLoadTask.Reset(); + + if(IsResourceReady()) + { + Control::SetResourceReady(); + } } void SceneView::OnIblDiffuseLoadComplete() { mDiffuseTexture = mIblDiffuseLoadTask->GetLoadedTexture(); mIblDiffuseResourceReady = true; + mIblDiffuseLoadTask.Reset(); if(mIblDiffuseResourceReady && mIblSpecularResourceReady) { OnIblLoadComplete(); } - mIblDiffuseLoadTask.Reset(); } void SceneView::OnIblSpecularLoadComplete() @@ -1156,11 +1154,11 @@ void SceneView::OnIblSpecularLoadComplete() mSpecularTexture = mIblSpecularLoadTask->GetLoadedTexture(); mSpecularMipmapLevels = mIblSpecularLoadTask->GetMipmapLevels(); mIblSpecularResourceReady = true; + mIblSpecularLoadTask.Reset(); if(mIblDiffuseResourceReady && mIblSpecularResourceReady) { OnIblLoadComplete(); } - mIblSpecularLoadTask.Reset(); } void SceneView::OnIblLoadComplete() diff --git a/dali-toolkit/devel-api/utility/npatch-helper.cpp b/dali-toolkit/devel-api/utility/npatch-helper.cpp index 382ef23..fed5316 100644 --- a/dali-toolkit/devel-api/utility/npatch-helper.cpp +++ b/dali-toolkit/devel-api/utility/npatch-helper.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022 Samsung Electronics Co., Ltd. +* Copyright (c) 2023 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +21,9 @@ // EXTERNAL INCLUDES #include +// INTERNAL INCLUDES +#include + namespace Dali { namespace Toolkit @@ -250,7 +253,7 @@ void RegisterStretchProperties(Renderer& renderer, const char* uniformName, cons } } -void ApplyTextureAndUniforms(Renderer& renderer, const std::shared_ptr data) +void ApplyTextureAndUniforms(Renderer& renderer, const Internal::NPatchData* data) { TextureSet textureSet; textureSet = data->GetTextures(); diff --git a/dali-toolkit/devel-api/utility/npatch-helper.h b/dali-toolkit/devel-api/utility/npatch-helper.h index 2427063..da1f55a 100644 --- a/dali-toolkit/devel-api/utility/npatch-helper.h +++ b/dali-toolkit/devel-api/utility/npatch-helper.h @@ -2,7 +2,7 @@ #define DALI_TOOLKIT_NPATCH_HELPER_H /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2023 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,26 +19,25 @@ */ // EXTERNAL INCLUDES +#include #include #include -#include -#include ///< for std::shared_ptr // INTERNAL INCLUDES +#include #include -#include namespace Dali { namespace Toolkit { -namespace NPatchHelper +namespace Internal { -/** - * The list that includes stretch pixel ranges - */ -using StretchRanges = Dali::Vector; +class NPatchData; +} +namespace NPatchHelper +{ /** * @brief Creates a Npatch Geometry object * @@ -70,7 +69,6 @@ DALI_TOOLKIT_API Geometry CreateGridGeometry(Uint16Pair gridSize); */ DALI_TOOLKIT_API Geometry CreateBorderGeometry(Uint16Pair gridSize); - /** * @brief Registers a properties for Stretch Ranges * @@ -87,9 +85,9 @@ void RegisterStretchProperties(Renderer& renderer, const char* uniformName, cons * @param[in,out] renderer The renderer for broken image * @param[in] data The pointer of npatch-data */ -void ApplyTextureAndUniforms(Renderer& renderer, const std::shared_ptr data); +void ApplyTextureAndUniforms(Renderer& renderer, const Internal::NPatchData* data); -} // namespace NPatchUtility +} // namespace NPatchHelper } // namespace Toolkit diff --git a/dali-toolkit/devel-api/visual-factory/visual-factory.cpp b/dali-toolkit/devel-api/visual-factory/visual-factory.cpp index dce3109..7fca5cf 100644 --- a/dali-toolkit/devel-api/visual-factory/visual-factory.cpp +++ b/dali-toolkit/devel-api/visual-factory/visual-factory.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * Copyright (c) 2023 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. @@ -116,6 +116,11 @@ void VisualFactory::UsePreCompiledShader() GetImplementation(*this).UsePreCompiledShader(); } +void VisualFactory::DiscardVisual(Visual::Base visual) +{ + GetImplementation(*this).DiscardVisual(visual); +} + } // namespace Toolkit } // namespace Dali diff --git a/dali-toolkit/devel-api/visual-factory/visual-factory.h b/dali-toolkit/devel-api/visual-factory/visual-factory.h index bf861f7..a7919f4 100644 --- a/dali-toolkit/devel-api/visual-factory/visual-factory.h +++ b/dali-toolkit/devel-api/visual-factory/visual-factory.h @@ -2,7 +2,7 @@ #define DALI_TOOLKIT_VISUAL_FACTORY_H /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * Copyright (c) 2023 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. @@ -137,6 +137,13 @@ public: */ void UsePreCompiledShader(); + /** + * @brief Discard visual base. It will keep reference of visual until idle callback called. + * + * @param[in] visual Discarded visual base. + */ + void DiscardVisual(Visual::Base visual); + private: explicit DALI_INTERNAL VisualFactory(Internal::VisualFactory* impl); }; diff --git a/dali-toolkit/internal/controls/control/control-data-impl.cpp b/dali-toolkit/internal/controls/control/control-data-impl.cpp index a151d11..c33ae6e 100644 --- a/dali-toolkit/internal/controls/control/control-data-impl.cpp +++ b/dali-toolkit/internal/controls/control/control-data-impl.cpp @@ -233,6 +233,23 @@ void MoveVisual(RegisteredVisualContainer::Iterator sourceIter, RegisteredVisual } /** + * Discard visual from source to visual factory. + */ +void DiscardVisual(RegisteredVisualContainer::Iterator sourceIter, RegisteredVisualContainer& source) +{ + Toolkit::Visual::Base visual = (*sourceIter)->visual; + if(visual) + { + if(Stage::IsInstalled()) + { + Toolkit::VisualFactory::Get().DiscardVisual(visual); + } + } + + source.Erase(sourceIter); +} + +/** * Performs actions as requested using the action name. * @param[in] object The object on which to perform the action. * @param[in] actionName The action to perform. @@ -873,8 +890,9 @@ void Control::Impl::UnregisterVisual(Property::Index index) Actor self(mControlImpl.Self()); Toolkit::GetImplementation((*iter)->visual).SetOffScene(self); (*iter)->pending = false; - (*iter)->visual.Reset(); - mRemoveVisuals.Erase(iter); + + // Discard removed visual. It will be destroyed at next Idle time. + DiscardVisual(iter, mRemoveVisuals); } } @@ -1005,7 +1023,9 @@ void Control::Impl::ResourceReady(Visual::Base& object) { Toolkit::GetImplementation((*visualToRemoveIter)->visual).SetOffScene(self); } - mRemoveVisuals.Erase(visualToRemoveIter); + + // Discard removed visual. It will be destroyed at next Idle time. + DiscardVisual(visualToRemoveIter, mRemoveVisuals); } // A visual is ready so control may need relayouting if staged @@ -2001,17 +2021,25 @@ void Control::Impl::OnSceneDisconnection() // Visuals pending replacement can now be taken out of the removal list and set off scene // Iterate through all replacement visuals and add to a move queue then set off scene - for(auto removalIter = mRemoveVisuals.Begin(), end = mRemoveVisuals.End(); removalIter != end; removalIter++) + + if(!mRemoveVisuals.Empty()) { - Toolkit::GetImplementation((*removalIter)->visual).SetOffScene(self); + std::reverse(mRemoveVisuals.Begin(), mRemoveVisuals.End()); + + while(!mRemoveVisuals.Empty()) + { + auto removalIter = mRemoveVisuals.End() - 1u; + Toolkit::GetImplementation((*removalIter)->visual).SetOffScene(self); + + // Discard removed visual. It will be destroyed at next Idle time. + DiscardVisual(removalIter, mRemoveVisuals); + } } for(auto replacedIter = mVisuals.Begin(), end = mVisuals.End(); replacedIter != end; replacedIter++) { (*replacedIter)->pending = false; } - - mRemoveVisuals.Clear(); } void Control::Impl::SetMargin(Extents margin) diff --git a/dali-toolkit/internal/visuals/animated-image/rolling-animated-image-cache.cpp b/dali-toolkit/internal/visuals/animated-image/rolling-animated-image-cache.cpp index abe5581..370a678 100644 --- a/dali-toolkit/internal/visuals/animated-image/rolling-animated-image-cache.cpp +++ b/dali-toolkit/internal/visuals/animated-image/rolling-animated-image-cache.cpp @@ -362,6 +362,8 @@ void RollingAnimatedImageCache::LoadComplete(bool loadSuccess, TextureInformatio MakeFrameReady(loadSuccess, textureInformation.textureSet, textureInformation.interval, textureInformation.preMultiplied); + // TODO : We need to remove some below logics, since user can remove Visual during ResourceReady callback. + if(loadSuccess) { // The frames of a single animated image can not be loaded parallelly. diff --git a/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp b/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp index 4f093ad..e56bba2 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp +++ b/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp @@ -628,14 +628,14 @@ void AnimatedVectorImageVisual::OnResourceReady(VectorAnimationTask::ResourceSta void AnimatedVectorImageVisual::OnAnimationFinished() { - AnimatedVectorImageVisualPtr self = this; // Keep reference until this API finished - if(DALI_UNLIKELY(mImpl == nullptr)) { DALI_LOG_ERROR("Fatal error!! already destroyed object callback called! AnimatedVectorImageVisual : %p, url : %s\n", this, mUrl.GetUrl().c_str()); return; } + AnimatedVectorImageVisualPtr self = this; // Keep reference until this API finished + DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "AnimatedVectorImageVisual::OnAnimationFinished: action state = %d [%p]\n", mPlayState, this); if(mPlayState != DevelImageVisual::PlayState::STOPPED) diff --git a/dali-toolkit/internal/visuals/npatch-data.cpp b/dali-toolkit/internal/visuals/npatch-data.cpp index 72f058b..28c3ebd 100644 --- a/dali-toolkit/internal/visuals/npatch-data.cpp +++ b/dali-toolkit/internal/visuals/npatch-data.cpp @@ -19,7 +19,6 @@ #include // INTERNAL HEADERS -#include ///< for NPatchLoader #include // EXTERNAL HEADERS @@ -31,9 +30,8 @@ namespace Toolkit { namespace Internal { -NPatchData::NPatchData(NPatchLoader& loader) +NPatchData::NPatchData() : mId(INVALID_NPATCH_DATA_ID), - mNPatchLoader(loader), mUrl(), mTextureSet(), mHash(0), @@ -259,8 +257,7 @@ void NPatchData::NotifyObserver(TextureUploadObserver* observer, const bool& loa void NPatchData::LoadComplete(bool loadSuccess, TextureInformation textureInformation) { - // Increase reference count of itself - mNPatchLoader.IncreaseReference(mId); + NPatchDataPtr self = this; // Keep reference until this API finished if(loadSuccess) { @@ -305,9 +302,6 @@ void NPatchData::LoadComplete(bool loadSuccess, TextureInformation textureInform // (If mLoadingState was LOAD_COMPLETE, NotifyObserver will be called directly. @todo : Should we fix this logic, matched with texture manager?) // So LoadComplete will be called. mObserverList.Swap(mQueuedObservers); - - // Decrease reference count of itself - mNPatchLoader.RequestRemove(mId, nullptr); } void NPatchData::ObserverDestroyed(TextureUploadObserver* observer) diff --git a/dali-toolkit/internal/visuals/npatch-data.h b/dali-toolkit/internal/visuals/npatch-data.h index f50392b..99c4d08 100644 --- a/dali-toolkit/internal/visuals/npatch-data.h +++ b/dali-toolkit/internal/visuals/npatch-data.h @@ -19,6 +19,7 @@ // EXTERNAL INCLUDES #include +#include #include #include @@ -33,9 +34,10 @@ namespace Toolkit { namespace Internal { -class NPatchLoader; +class NPatchData; +typedef IntrusivePtr NPatchDataPtr; -class NPatchData : public ConnectionTracker, public Dali::Toolkit::TextureUploadObserver +class NPatchData : public ConnectionTracker, public Dali::Toolkit::TextureUploadObserver, public Dali::RefObject { public: typedef int32_t NPatchDataId; ///< The NPatchDataId type. This is used as a handle to refer to a particular Npatch Data. @@ -55,10 +57,8 @@ public: public: /** * Constructor - * - * @param[in] loader NPatchLoader who create this data. */ - NPatchData(NPatchLoader& loader); + NPatchData(); /** * Destructor, non-virtual as not a base class @@ -286,7 +286,6 @@ private: NPatchDataId mId; ObserverListType mObserverList; ///< Container used to store all observer clients of this Texture ObserverListType mQueuedObservers; ///< Container observers when user try to add during notify observers - NPatchLoader& mNPatchLoader; ///< NPatchLoader who keep this data VisualUrl mUrl; ///< Url of the N-Patch TextureSet mTextureSet; ///< Texture containing the cropped image diff --git a/dali-toolkit/internal/visuals/npatch-loader.cpp b/dali-toolkit/internal/visuals/npatch-loader.cpp index 340188b..16b49be 100644 --- a/dali-toolkit/internal/visuals/npatch-loader.cpp +++ b/dali-toolkit/internal/visuals/npatch-loader.cpp @@ -66,9 +66,9 @@ NPatchData::NPatchDataId NPatchLoader::GenerateUniqueNPatchDataId() NPatchData::NPatchDataId NPatchLoader::Load(TextureManager& textureManager, TextureUploadObserver* textureObserver, const VisualUrl& url, const Rect& border, bool& preMultiplyOnLoad, bool synchronousLoading) { - std::shared_ptr data = GetNPatchData(url, border, preMultiplyOnLoad); + NPatchDataPtr data = GetNPatchData(url, border, preMultiplyOnLoad); - DALI_ASSERT_ALWAYS(data.get() && "NPatchData creation failed!"); + DALI_ASSERT_ALWAYS(data.Get() && "NPatchData creation failed!"); if(data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE) { @@ -97,7 +97,7 @@ NPatchData::NPatchDataId NPatchLoader::Load(TextureManager& textureManager, Text auto preMultiplyOnLoading = preMultiplyOnLoad ? TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD : TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY; - Devel::PixelBuffer pixelBuffer = textureManager.LoadPixelBuffer(url, Dali::ImageDimensions(), FittingMode::DEFAULT, SamplingMode::BOX_THEN_LINEAR, synchronousLoading, data.get(), true, preMultiplyOnLoading); + Devel::PixelBuffer pixelBuffer = textureManager.LoadPixelBuffer(url, Dali::ImageDimensions(), FittingMode::DEFAULT, SamplingMode::BOX_THEN_LINEAR, synchronousLoading, data.Get(), true, preMultiplyOnLoading); if(pixelBuffer) { @@ -127,7 +127,7 @@ int32_t NPatchLoader::GetCacheIndexFromId(const NPatchData::NPatchDataId id) return INVALID_CACHE_INDEX; } -bool NPatchLoader::GetNPatchData(const NPatchData::NPatchDataId id, std::shared_ptr& data) +bool NPatchLoader::GetNPatchData(const NPatchData::NPatchDataId id, NPatchDataPtr& data) { int32_t cacheIndex = GetCacheIndexFromId(id); if(cacheIndex != INVALID_CACHE_INDEX) @@ -162,19 +162,6 @@ void NPatchLoader::RequestRemove(NPatchData::NPatchDataId id, TextureUploadObser } } -void NPatchLoader::IncreaseReference(NPatchData::NPatchDataId id) -{ - int32_t cacheIndex = GetCacheIndexFromId(id); - if(cacheIndex == INVALID_CACHE_INDEX) - { - return; - } - - NPatchInfo& info(mCache[cacheIndex]); - - ++info.mReferenceCount; -} - void NPatchLoader::Remove(NPatchData::NPatchDataId id, TextureUploadObserver* textureObserver) { int32_t cacheIndex = GetCacheIndexFromId(id); @@ -208,7 +195,7 @@ void NPatchLoader::Process(bool postProcessor) } } -std::shared_ptr NPatchLoader::GetNPatchData(const VisualUrl& url, const Rect& border, bool& preMultiplyOnLoad) +NPatchDataPtr NPatchLoader::GetNPatchData(const VisualUrl& url, const Rect& border, bool& preMultiplyOnLoad) { std::size_t hash = CalculateHash(url.GetUrl()); std::vector::size_type index = UNINITIALIZED_ID; @@ -260,7 +247,7 @@ std::shared_ptr NPatchLoader::GetNPatchData(const VisualUrl& url, co // If this is new image loading, make new cache data if(infoPtr == nullptr) { - NPatchInfo info(std::make_shared(*this)); + NPatchInfo info(new NPatchData()); info.mData->SetId(GenerateUniqueNPatchDataId()); info.mData->SetHash(hash); info.mData->SetUrl(url); @@ -273,7 +260,7 @@ std::shared_ptr NPatchLoader::GetNPatchData(const VisualUrl& url, co // Else if LOAD_COMPLETE, Same url but border is different - use the existing texture else if(infoPtr->mData->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE) { - NPatchInfo info(std::make_shared(*this)); + NPatchInfo info(new NPatchData()); info.mData->SetId(GenerateUniqueNPatchDataId()); info.mData->SetHash(hash); diff --git a/dali-toolkit/internal/visuals/npatch-loader.h b/dali-toolkit/internal/visuals/npatch-loader.h index 59e52dc..5890326 100644 --- a/dali-toolkit/internal/visuals/npatch-loader.h +++ b/dali-toolkit/internal/visuals/npatch-loader.h @@ -21,7 +21,6 @@ #include #include #include -#include // for std::shared_ptr #include #include // for std::pair @@ -79,7 +78,7 @@ public: * @param [out] data const pointer to the NPatchData * @return true if data matching to id was really found */ - bool GetNPatchData(const NPatchData::NPatchDataId id, std::shared_ptr& data); + bool GetNPatchData(const NPatchData::NPatchDataId id, NPatchDataPtr& data); /** * @brief Request remove a texture matching id. @@ -90,13 +89,6 @@ public: */ void RequestRemove(NPatchData::NPatchDataId id, TextureUploadObserver* textureObserver); - /** - * @brief Increase reference count of a texture matching id. - * - * @param [in] id cache data id - */ - void IncreaseReference(NPatchData::NPatchDataId id); - protected: // Implementation of Processor /** * @copydoc Dali::Integration::Processor::Process() @@ -126,7 +118,7 @@ private: */ struct NPatchInfo { - NPatchInfo(std::shared_ptr data) + NPatchInfo(NPatchDataPtr data) : mData(data), mReferenceCount(1u) { @@ -152,8 +144,8 @@ private: NPatchInfo(const NPatchInfo& info) = delete; // Do not use copy constructor NPatchInfo& operator=(const NPatchInfo& info) = delete; // Do not use copy assign - std::shared_ptr mData; - std::int16_t mReferenceCount; ///< The number of N-patch visuals that use this data. + NPatchDataPtr mData; + std::int16_t mReferenceCount; ///< The number of N-patch visuals that use this data. }; /** @@ -166,7 +158,7 @@ private: * image has no alpha channel * @return NPatchData pointer that Load function will used. */ - std::shared_ptr GetNPatchData(const VisualUrl& url, const Rect& border, bool& preMultiplyOnLoad); + NPatchDataPtr GetNPatchData(const VisualUrl& url, const Rect& border, bool& preMultiplyOnLoad); protected: /** diff --git a/dali-toolkit/internal/visuals/npatch/npatch-visual.cpp b/dali-toolkit/internal/visuals/npatch/npatch-visual.cpp index 606e040..e469297 100644 --- a/dali-toolkit/internal/visuals/npatch/npatch-visual.cpp +++ b/dali-toolkit/internal/visuals/npatch/npatch-visual.cpp @@ -80,7 +80,7 @@ void NPatchVisual::LoadImages() bool preMultiplyOnLoad = IsPreMultipliedAlphaEnabled() && !mImpl->mCustomShader ? true : false; mId = mLoader.Load(textureManager, this, mImageUrl, mBorder, preMultiplyOnLoad, synchronousLoading); - std::shared_ptr data; + NPatchDataPtr data; if(mLoader.GetNPatchData(mId, data) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE) { EnablePreMultipliedAlpha(data->IsPreMultiplied()); @@ -126,7 +126,7 @@ void NPatchVisual::GetNaturalSize(Vector2& naturalSize) naturalSize.y = 0u; // load now if not already loaded - std::shared_ptr data; + NPatchDataPtr data; if(mLoader.GetNPatchData(mId, data) && data->GetLoadingState() != NPatchData::LoadingState::LOADING) { naturalSize.x = data->GetCroppedWidth(); @@ -223,7 +223,7 @@ void NPatchVisual::DoSetOnScene(Actor& actor) // at this case, we try to SetResouce to mPlaceActor twice. so, we should avoid that case. mPlacementActor = actor; - std::shared_ptr data; + NPatchDataPtr data; if(mImpl->mRenderer && mLoader.GetNPatchData(mId, data) && data->GetLoadingState() != NPatchData::LoadingState::LOADING) { // If mAuxiliaryUrl need to be loaded, we should wait it until LoadComplete called. @@ -338,9 +338,9 @@ NPatchVisual::~NPatchVisual() void NPatchVisual::OnInitialize() { // Get basic geometry and shader - Geometry geometry = mFactoryCache.GetGeometry(VisualFactoryCache::QUAD_GEOMETRY); - auto imageVisualShaderFeatureBuilder = ImageVisualShaderFeatureBuilder(); - Shader shader = mImageVisualShaderFactory.GetShader( + Geometry geometry = mFactoryCache.GetGeometry(VisualFactoryCache::QUAD_GEOMETRY); + auto imageVisualShaderFeatureBuilder = ImageVisualShaderFeatureBuilder(); + Shader shader = mImageVisualShaderFactory.GetShader( mFactoryCache, imageVisualShaderFeatureBuilder); @@ -353,8 +353,8 @@ void NPatchVisual::OnInitialize() Geometry NPatchVisual::CreateGeometry() { - Geometry geometry; - std::shared_ptr data; + Geometry geometry; + NPatchDataPtr data; if(mLoader.GetNPatchData(mId, data) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE) { if(data->GetStretchPixelsX().Size() == 1 && data->GetStretchPixelsY().Size() == 1) @@ -408,8 +408,8 @@ Geometry NPatchVisual::CreateGeometry() Shader NPatchVisual::CreateShader() { - Shader shader; - std::shared_ptr data; + Shader shader; + NPatchDataPtr data; // 0 is either no data (load failed?) or no stretch regions on image // for both cases we use the default shader NPatchUtility::StretchRanges::SizeType xStretchCount = 0; @@ -488,13 +488,13 @@ Shader NPatchVisual::CreateShader() void NPatchVisual::ApplyTextureAndUniforms() { - std::shared_ptr data; - TextureSet textureSet; + NPatchDataPtr data; + TextureSet textureSet; if(mLoader.GetNPatchData(mId, data) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE) { textureSet = data->GetTextures(); - NPatchHelper::ApplyTextureAndUniforms(mImpl->mRenderer, data); + NPatchHelper::ApplyTextureAndUniforms(mImpl->mRenderer, data.Get()); if(mAuxiliaryResourceStatus == Toolkit::Visual::ResourceStatus::READY) { @@ -551,7 +551,7 @@ Geometry NPatchVisual::GetNinePatchGeometry(VisualFactoryCache::GeometryType sub void NPatchVisual::SetResource() { - std::shared_ptr data; + NPatchDataPtr data; if(mImpl->mRenderer && mLoader.GetNPatchData(mId, data)) { Geometry geometry = CreateGeometry(); @@ -628,7 +628,7 @@ void NPatchVisual::LoadComplete(bool loadSuccess, TextureInformation textureInfo // If auxiliaryUrl didn't required OR auxiliaryUrl load done. if(!mAuxiliaryUrl.IsValid() || mAuxiliaryResourceStatus != Toolkit::Visual::ResourceStatus::PREPARING) { - std::shared_ptr data; + NPatchDataPtr data; // and.. If Url loading done. if(mImpl->mRenderer && mLoader.GetNPatchData(mId, data) && data->GetLoadingState() != NPatchData::LoadingState::LOADING) { diff --git a/dali-toolkit/internal/visuals/svg/svg-visual.cpp b/dali-toolkit/internal/visuals/svg/svg-visual.cpp index 60c2141..8bf94ab 100644 --- a/dali-toolkit/internal/visuals/svg/svg-visual.cpp +++ b/dali-toolkit/internal/visuals/svg/svg-visual.cpp @@ -337,13 +337,12 @@ void SvgVisual::AddRasterizationTask(const Vector2& size) void SvgVisual::ApplyRasterizedImage(SvgTaskPtr task) { - SvgVisualPtr self = this; // Keep reference until this API finished - if(DALI_UNLIKELY(mImpl == nullptr)) { DALI_LOG_ERROR("Fatal error!! already destroyed object callback called! SvgVisual : %p, url : %s, task : %p\n", this, mImageUrl.GetUrl().c_str(), task.Get()); return; } + SvgVisualPtr self = this; // Keep reference until this API finished // We don't need to keep tasks anymore. reset now. if(task == mLoadingTask) diff --git a/dali-toolkit/internal/visuals/visual-factory-cache.cpp b/dali-toolkit/internal/visuals/visual-factory-cache.cpp index 9437bdc..69fbbad 100644 --- a/dali-toolkit/internal/visuals/visual-factory-cache.cpp +++ b/dali-toolkit/internal/visuals/visual-factory-cache.cpp @@ -272,8 +272,8 @@ VisualUrl::Type VisualFactoryCache::GetBrokenImageVisualType(int index) Geometry VisualFactoryCache::GetNPatchGeometry(int index) { - Geometry geometry; - std::shared_ptr data; + Geometry geometry; + NPatchDataPtr data; if(mNPatchLoader.GetNPatchData(mBrokenImageInfoContainer[index].npatchId, data) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE) { if(data->GetStretchPixelsX().Size() == 1 && data->GetStretchPixelsY().Size() == 1) @@ -306,8 +306,8 @@ Geometry VisualFactoryCache::GetNPatchGeometry(int index) Shader VisualFactoryCache::GetNPatchShader(int index) { - Shader shader; - std::shared_ptr data; + Shader shader; + NPatchDataPtr data; // 0 is either no data (load failed?) or no stretch regions on image // for both cases we use the default shader NPatchUtility::StretchRanges::SizeType xStretchCount = 0; @@ -344,13 +344,13 @@ Shader VisualFactoryCache::GetNPatchShader(int index) void VisualFactoryCache::ApplyTextureAndUniforms(Renderer& renderer, int index) { - std::shared_ptr data; - TextureSet textureSet; + NPatchDataPtr data; + TextureSet textureSet; if(mNPatchLoader.GetNPatchData(mBrokenImageInfoContainer[index].npatchId, data) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE) { textureSet = data->GetTextures(); mBrokenImageInfoContainer[index].texture = textureSet.GetTexture(0); - NPatchHelper::ApplyTextureAndUniforms(renderer, data); + NPatchHelper::ApplyTextureAndUniforms(renderer, data.Get()); renderer.SetTextures(textureSet); } } @@ -374,8 +374,8 @@ void VisualFactoryCache::UpdateBrokenImageRenderer(Renderer& renderer, const Vec mBrokenImageInfoContainer[index].visualType = visualUrl.GetType(); if(mBrokenImageInfoContainer[index].visualType == VisualUrl::Type::N_PATCH) { - std::shared_ptr data; - Rect border; + NPatchDataPtr data; + Rect border; mBrokenImageInfoContainer[index].npatchId = mNPatchLoader.Load(mTextureManager, NULL, mBrokenImageInfoContainer[index].url, border, mPreMultiplyOnLoad, true); if(mNPatchLoader.GetNPatchData(mBrokenImageInfoContainer[index].npatchId, data) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE) { diff --git a/dali-toolkit/internal/visuals/visual-factory-impl.cpp b/dali-toolkit/internal/visuals/visual-factory-impl.cpp index 4656e59..9f9eb2a 100644 --- a/dali-toolkit/internal/visuals/visual-factory-impl.cpp +++ b/dali-toolkit/internal/visuals/visual-factory-impl.cpp @@ -19,6 +19,7 @@ // EXTERNAL INCLUDES #include +#include #include #include #include @@ -28,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -41,7 +43,6 @@ #include #include #include -#include #include #include #include @@ -52,7 +53,6 @@ #include #include - namespace Dali { namespace Toolkit @@ -76,15 +76,13 @@ DALI_TYPE_REGISTRATION_BEGIN_CREATE(Toolkit::VisualFactory, Dali::BaseHandle, Cr DALI_TYPE_REGISTRATION_END() const char* const BROKEN_IMAGE_FILE_NAME = "broken.png"; ///< The file name of the broken image. -static constexpr auto SHADER_TYPE_COUNT = 2u; -const std::string_view VertexPredefines[SHADER_TYPE_COUNT] -{ - "", //VisualFactoryCache::COLOR_SHADER +static constexpr auto SHADER_TYPE_COUNT = 2u; +const std::string_view VertexPredefines[SHADER_TYPE_COUNT]{ + "", //VisualFactoryCache::COLOR_SHADER "#define IS_REQUIRED_ROUNDED_CORNER\n", //VisualFactoryCache::COLOR_SHADER_ROUNDED_CORNER }; -const std::string_view FragmentPredefines[SHADER_TYPE_COUNT] -{ - "", //VisualFactoryCache::COLOR_SHADER +const std::string_view FragmentPredefines[SHADER_TYPE_COUNT]{ + "", //VisualFactoryCache::COLOR_SHADER "#define IS_REQUIRED_ROUNDED_CORNER\n", //VisualFactoryCache::COLOR_SHADER_ROUNDED_CORNER }; @@ -95,6 +93,7 @@ VisualFactory::VisualFactory(bool debugEnabled) mImageVisualShaderFactory(), mTextVisualShaderFactory(), mSlotDelegate(this), + mIdleCallback(nullptr), mDebugEnabled(debugEnabled), mPreMultiplyOnLoad(true) { @@ -102,6 +101,12 @@ VisualFactory::VisualFactory(bool debugEnabled) VisualFactory::~VisualFactory() { + if(mIdleCallback && Adaptor::IsAvailable()) + { + // Removes the callback from the callback manager in case the control is destroyed before the callback is executed. + Adaptor::Get().RemoveIdle(mIdleCallback); + mIdleCallback = nullptr; + } } void VisualFactory::OnStyleChangedSignal(Toolkit::StyleManager styleManager, StyleChange::Type type) @@ -404,7 +409,7 @@ void VisualFactory::UsePreCompiledShader() // Get image shader std::vector rawShaderList; - RawShaderData imageShaderData; + RawShaderData imageShaderData; GetImageVisualShaderFactory().GetPrecompiledShader(imageShaderData); rawShaderList.push_back(imageShaderData); @@ -418,11 +423,17 @@ void VisualFactory::UsePreCompiledShader() GetPrecompiledShader(colorShaderData); rawShaderList.push_back(colorShaderData); - // Save all shader Integration::ShaderPrecompiler::Get().SavePrecomipleShaderList(rawShaderList); } +void VisualFactory::DiscardVisual(Toolkit::Visual::Base visual) +{ + mDiscardedVisuals.emplace_back(visual); + + RegisterDiscardCallback(); +} + Internal::TextureManager& VisualFactory::GetTextureManager() { return GetFactoryCache().GetTextureManager(); @@ -452,20 +463,20 @@ void VisualFactory::GetPrecompiledShader(RawShaderData& shaders) { std::vector vertexPrefix; std::vector fragmentPrefix; - int shaderCount = 0; - shaders.shaderCount = 0; - for(int i=0; i< SHADER_TYPE_COUNT; ++i) + int shaderCount = 0; + shaders.shaderCount = 0; + for(int i = 0; i < SHADER_TYPE_COUNT; ++i) { vertexPrefix.push_back(VertexPredefines[i]); fragmentPrefix.push_back(FragmentPredefines[i]); shaderCount++; } - shaders.vertexPrefix = vertexPrefix; + shaders.vertexPrefix = vertexPrefix; shaders.fragmentPrefix = fragmentPrefix; - shaders.vertexShader = SHADER_COLOR_VISUAL_SHADER_VERT; + shaders.vertexShader = SHADER_COLOR_VISUAL_SHADER_VERT; shaders.fragmentShader = SHADER_COLOR_VISUAL_SHADER_FRAG; - shaders.shaderCount = shaderCount; + shaders.shaderCount = shaderCount; } Internal::VisualFactoryCache& VisualFactory::GetFactoryCache() @@ -505,6 +516,31 @@ TextVisualShaderFactory& VisualFactory::GetTextVisualShaderFactory() return *mTextVisualShaderFactory; } +void VisualFactory::OnDiscardCallback() +{ + mIdleCallback = nullptr; + + // Discard visual now. + mDiscardedVisuals.clear(); +} + +void VisualFactory::RegisterDiscardCallback() +{ + if(!mIdleCallback && Adaptor::IsAvailable()) + { + // The callback manager takes the ownership of the callback object. + mIdleCallback = MakeCallback(this, &VisualFactory::OnDiscardCallback); + + Adaptor& adaptor = Adaptor::Get(); + + if(!adaptor.AddIdle(mIdleCallback, false)) + { + // Fail to add idle. (Maybe adaptor is paused.) + mIdleCallback = nullptr; + } + } +} + } // namespace Internal } // namespace Toolkit diff --git a/dali-toolkit/internal/visuals/visual-factory-impl.h b/dali-toolkit/internal/visuals/visual-factory-impl.h index f516e45..68ccb78 100644 --- a/dali-toolkit/internal/visuals/visual-factory-impl.h +++ b/dali-toolkit/internal/visuals/visual-factory-impl.h @@ -18,8 +18,9 @@ */ // EXTERNAL INCLUDES -#include #include +#include +#include // INTERNAL INCLUDES #include @@ -91,6 +92,11 @@ public: void UsePreCompiledShader(); /** + * @copydoc Toolkit::VisualFactory::DiscardVisual() + */ + void DiscardVisual(Toolkit::Visual::Base visual); + + /** * @return the reference to texture manager */ Internal::TextureManager& GetTextureManager(); @@ -129,6 +135,16 @@ private: */ TextVisualShaderFactory& GetTextVisualShaderFactory(); + /** + * @brief Callbacks called for clear discarded visuals. + */ + void OnDiscardCallback(); + + /** + * @brief Register idle callback for discard visuals if need. + */ + void RegisterDiscardCallback(); + VisualFactory(const VisualFactory&) = delete; VisualFactory& operator=(const VisualFactory& rhs) = delete; @@ -138,9 +154,14 @@ private: std::unique_ptr mImageVisualShaderFactory; std::unique_ptr mTextVisualShaderFactory; SlotDelegate mSlotDelegate; - bool mDebugEnabled : 1; - bool mPreMultiplyOnLoad : 1; ///< Local store for this flag - bool mPrecompiledShaderRequested{false}; + CallbackBase* mIdleCallback; + + using DiscardedVisualContainer = std::vector; + DiscardedVisualContainer mDiscardedVisuals{}; + + bool mDebugEnabled : 1; + bool mPreMultiplyOnLoad : 1; ///< Local store for this flag + bool mPrecompiledShaderRequested{false}; }; /** -- 2.7.4