/*
- * Copyright (c) 2018 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.
namespace Dali
{
-
/********************************************************************************
* Stub for Dali::Internal::Adaptor::LifecycleController
********************************************************************************/
class LifecycleController : public BaseObject
{
public: // Creation & Destruction
-
LifecycleController();
~LifecycleController();
static Dali::LifecycleController Get();
-
public: // Signals
Dali::LifecycleController::LifecycleSignalType& InitSignal();
+ Dali::LifecycleController::LifecycleSignalType& TerminateSignal();
private:
Dali::LifecycleController::LifecycleSignalType mInitSignal;
- static Dali::LifecycleController mLifecycleController;
+ Dali::LifecycleController::LifecycleSignalType mTerminateSignal;
+ static Dali::LifecycleController mLifecycleController;
};
Dali::LifecycleController LifecycleController::mLifecycleController;
Dali::LifecycleController LifecycleController::Get()
{
- if( ! mLifecycleController )
+ if(!mLifecycleController)
{
mLifecycleController = Dali::LifecycleController(new Internal::Adaptor::LifecycleController());
}
return mInitSignal;
}
+Dali::LifecycleController::LifecycleSignalType& LifecycleController::TerminateSignal()
+{
+ return mTerminateSignal;
+}
+
} // namespace Adaptor
} // namespace Internal
-
/********************************************************************************
* Stub for Dali::LifecycleController
********************************************************************************/
-LifecycleController::LifecycleController(){}
-LifecycleController::~LifecycleController(){}
+LifecycleController::LifecycleController()
+{
+}
+LifecycleController::~LifecycleController()
+{
+}
LifecycleController LifecycleController::Get()
{
LifecycleController::LifecycleSignalType& LifecycleController::InitSignal()
{
- BaseObject& object = GetBaseObject();
- Internal::Adaptor::LifecycleController& controller = static_cast< Internal::Adaptor::LifecycleController& >( object );
+ BaseObject& object = GetBaseObject();
+ Internal::Adaptor::LifecycleController& controller = static_cast<Internal::Adaptor::LifecycleController&>(object);
return controller.InitSignal();
}
-LifecycleController::LifecycleController( Internal::Adaptor::LifecycleController *impl )
+LifecycleController::LifecycleSignalType& LifecycleController::TerminateSignal()
+{
+ BaseObject& object = GetBaseObject();
+ Internal::Adaptor::LifecycleController& controller = static_cast<Internal::Adaptor::LifecycleController&>(object);
+ return controller.TerminateSignal();
+}
+
+LifecycleController::LifecycleController(Internal::Adaptor::LifecycleController* impl)
: BaseHandle(impl)
{
}
#define TOOLKIT_LIFECYCLE_CONTROLLER_H
/*
- * Copyright (c) 2019 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.
*/
// EXTERNAL INCLUDES
-#include <string>
#include <dali/public-api/object/base-handle.h>
#include <dali/public-api/signals/dali-signal.h>
+#include <string>
namespace Dali
{
{
class LifecycleController;
}
-}
+} // namespace Internal
class LifecycleController : public BaseHandle
{
public:
- typedef Signal< void (void) > LifecycleSignalType;
+ typedef Signal<void(void)> LifecycleSignalType;
LifecycleController();
~LifecycleController();
static LifecycleController Get();
- LifecycleSignalType& InitSignal();
- LifecycleController( Internal::Adaptor::LifecycleController* impl );
+ LifecycleSignalType& InitSignal();
+ LifecycleSignalType& TerminateSignal();
+ LifecycleController(Internal::Adaptor::LifecycleController* impl);
};
-
} // namespace Dali
#endif // TOOLKIT_LIFECYCLE_CONTROLLER_H
// Override Scene creation in TestApplication by creating a window.
// The window will create a Scene & surface and set up the scene's surface appropriately.
mMainWindow = Window::New(PositionSize(0, 0, surfaceWidth, surfaceHeight), "");
- mScene = AdaptorImpl::GetScene(mMainWindow);
+ mScene = AdaptorImpl::GetScene(mMainWindow);
mScene.SetDpi(Vector2(horizontalDpi, verticalDpi));
// Create render target for the scene
ToolkitTestApplication::~ToolkitTestApplication()
{
+ Dali::LifecycleController lifecycleController = Dali::LifecycleController::Get();
+ lifecycleController.TerminateSignal().Emit();
+
// Need to delete core before we delete the adaptor.
delete mCore;
mCore = NULL;
// EXTERNAL INCLUDES
#include <dali-toolkit/public-api/image-loader/sync-image-loader.h>
+#include <dali/devel-api/adaptor-framework/lifecycle-controller.h>
#include <dali/devel-api/common/hash.h>
#include <dali/devel-api/common/map-wrapper.h>
#include <dali/devel-api/threading/mutex.h>
#include <dali/public-api/signals/connection-tracker.h>
#include <functional> ///< for std::function
+#include <memory> ///< for std::shared_ptr
#include <mutex>
#include <string>
#include <utility> ///< for std::pair
return texture;
}
+
+// Forward declare, for signal connection.
+void DestroyCacheImpl();
+
class CacheImpl : public Dali::ConnectionTracker
{
public:
mDestroyed{false},
mFullCollectRequested{false}
{
+ DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Create CacheImpl\n");
+
+ // We should create CacheImpl at main thread, To ensure delete this cache impl
+ Dali::LifecycleController::Get().TerminateSignal().Connect(DestroyCacheImpl);
}
/**
*/
~CacheImpl()
{
+ DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Destroy CacheImpl\n");
{
mDataMutex.lock();
*/
void RequestGarbageCollect(bool fullCollect)
{
- if(DALI_LIKELY(!mDestroyed && Dali::Adaptor::IsAvailable()))
+ if(DALI_LIKELY(Dali::Adaptor::IsAvailable()))
{
if(!mTimer)
{
{
bool continueTimer = false;
- if(DALI_LIKELY(!mDestroyed))
- {
- // Try to collect Texture GC first, due to the reference count of pixelData who become key of textures.
- // After all texture GC finished, then check PixelData cache.
- uint32_t checkedCount = 0u;
- // GC Cube Texture
- continueTimer |= CollectGarbages<false>(mCubeTextureCache, fullCollect, mCubeTextureContainerUpdated, mLatestCollectedCubeTextureIter, checkedCount);
+ // Try to collect Texture GC first, due to the reference count of pixelData who become key of textures.
+ // After all texture GC finished, then check PixelData cache.
+ uint32_t checkedCount = 0u;
- // GC Texture
- continueTimer |= CollectGarbages<false>(mTextureCache, fullCollect, mTextureContainerUpdated, mLatestCollectedTextureIter, checkedCount);
+ // GC Cube Texture
+ continueTimer |= CollectGarbages<false>(mCubeTextureCache, fullCollect, mCubeTextureContainerUpdated, mLatestCollectedCubeTextureIter, checkedCount);
- // GC PixelData. We should lock mutex during GC pixelData.
- continueTimer |= CollectGarbages<true>(mPixelDataCache, fullCollect, mPixelDataContainerUpdated, mLatestCollectedPixelDataIter, checkedCount);
- }
+ // GC Texture
+ continueTimer |= CollectGarbages<false>(mTextureCache, fullCollect, mTextureContainerUpdated, mLatestCollectedTextureIter, checkedCount);
+
+ // GC PixelData. We should lock mutex during GC pixelData.
+ continueTimer |= CollectGarbages<true>(mPixelDataCache, fullCollect, mPixelDataContainerUpdated, mLatestCollectedPixelDataIter, checkedCount);
return continueTimer;
}
bool mFullCollectRequested : 1;
};
-CacheImpl& GetCacheImpl()
+static std::shared_ptr<CacheImpl> gCacheImpl{nullptr};
+
+std::shared_ptr<CacheImpl> GetCacheImpl()
{
- static CacheImpl gCacheImpl;
+ if(DALI_UNLIKELY(!gCacheImpl))
+ {
+ gCacheImpl = std::make_shared<CacheImpl>();
+ }
return gCacheImpl;
}
+void DestroyCacheImpl()
+{
+ gCacheImpl.reset();
+}
+
} // namespace
namespace Dali::Scene3D::Internal
Dali::Texture GetCachedTexture(Dali::PixelData pixelData, bool mipmapRequired)
{
- return GetCacheImpl().GetOrCreateCachedTexture(pixelData, mipmapRequired);
+ return GetCacheImpl()->GetOrCreateCachedTexture(pixelData, mipmapRequired);
}
Dali::Texture GetCachedCubeTexture(const std::vector<std::vector<Dali::PixelData>>& pixelDataList, bool mipmapRequired)
{
- return GetCacheImpl().GetOrCreateCachedCubeTexture(pixelDataList, mipmapRequired);
+ return GetCacheImpl()->GetOrCreateCachedCubeTexture(pixelDataList, mipmapRequired);
}
void RequestGarbageCollect(bool fullCollect)
{
- GetCacheImpl().RequestGarbageCollect(fullCollect);
+ GetCacheImpl()->RequestGarbageCollect(fullCollect);
+}
+
+void EnsureResourceLoaderCreated()
+{
+ GetCacheImpl();
}
// Can be called by worker thread.
bool orientationCorrection)
{
ImageInformation info(url, dimensions, fittingMode, samplingMode, orientationCorrection);
- return GetCacheImpl().GetOrCreateCachedPixelData(info);
+ if(gCacheImpl == nullptr)
+ {
+ DALI_LOG_INFO(gLogFilter, Debug::Verbose, "CacheImpl not prepared! load PixelData without cache.\n");
+ return CreatePixelDataFromImageInfo(info, false);
+ }
+ else
+ {
+ return GetCacheImpl()->GetOrCreateCachedPixelData(info);
+ }
}
} // namespace ImageResourceLoader
} // namespace Dali::Scene3D::Internal
namespace ImageResourceLoader
{
// Called by main thread.
-
-/**
- * @brief Get cached pixelData handle filled as white with RGB888 format.
- * @return A PixelData object containing the white RGB888 color.
- */
-Dali::PixelData GetEmptyPixelDataWhiteRGB();
-
/**
* @brief Get cached texture handle filled as white with RGB888 format.
* @return A Texture object containing the white RGB888 color.
*/
void RequestGarbageCollect(bool fullCollect = false);
+/**
+ * @brief Let we ensure to create a ResourceLoader cache handler.
+ */
+void EnsureResourceLoaderCreated();
+
// Can be called by worker thread.
+/**
+ * @brief Get cached pixelData handle filled as white with RGB888 format.
+ * @return A PixelData object containing the white RGB888 color.
+ */
+Dali::PixelData GetEmptyPixelDataWhiteRGB();
/**
* @brief Get cached image, or loads an image synchronously.
+ * @note If cache handler is not created yet, or destroyed due to app terminated, it will load image synchronously without cache.
* @param[in] url The URL of the image file to load
* @return A PixelData object containing the image, or an invalid object on failure
*/
/**
* @brief Get cached image, or loads an image synchronously by specifying the target dimensions and options.
+ * @note If cache handler is not created yet, or destroyed due to app terminated, it will load image synchronously without cache.
* @param[in] url The URL of the image file to load
* @param[in] dimensions The width and height to fit the loaded image to
* @param[in] fittingMode The method used to fit the shape of the image before loading to the shape defined by the size parameter
*/
Impl()
{
+ // Try to create ResourceLoader here, to ensure that we create it on main thread.
+ Dali::Scene3D::Internal::ImageResourceLoader::EnsureResourceLoaderCreated();
}
Dali::Scene3D::Loader::LoadResult GetModelLoadResult(std::string modelUri)