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.
Change-Id: Ibeab31bc309869aa7c2ee65cbff8789e7bb2a721
Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
void Model::OnModelLoadComplete()
{
+ IntrusivePtr<Model> self = this; // Keep reference until this API finished
+
if(!mModelLoadTask->HasSucceeded())
{
ResetResourceTasks();
Self().SetProperty(Dali::Actor::Property::ANCHOR_POINT, Vector3(mModelPivot.x, 1.0f - mModelPivot.y, mModelPivot.z));
mModelResourceReady = true;
- NotifyResourceReady();
ResetResourceTask(mModelLoadTask);
+ NotifyResourceReady();
}
void Model::OnIblDiffuseLoadComplete()
void AnimatedVectorImageVisual::OnResourceReady(VectorAnimationTask::ResourceStatus status)
{
+ AnimatedVectorImageVisualPtr self = this; // Keep reference until this API finished
+
if(status == VectorAnimationTask::ResourceStatus::LOADED)
{
if(mImpl->mEventObserver)
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());
#include <dali-toolkit/internal/visuals/npatch-data.h>
// INTERNAL HEADERS
+#include <dali-toolkit/internal/visuals/npatch-loader.h> ///< for NPatchLoader
#include <dali-toolkit/internal/visuals/rendering-addon.h>
// EXTERNAL HEADERS
{
namespace Internal
{
-NPatchData::NPatchData()
+NPatchData::NPatchData(NPatchLoader& loader)
: mId(INVALID_NPATCH_DATA_ID),
+ mNPatchLoader(loader),
mUrl(),
mTextureSet(),
mHash(0),
void NPatchData::LoadComplete(bool loadSuccess, TextureInformation textureInformation)
{
+ // Increase reference count of itself
+ mNPatchLoader.IncreaseReference(mId);
+
if(loadSuccess)
{
if(mLoadingState != LoadingState::LOAD_COMPLETE)
// (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)
{
namespace Internal
{
+class NPatchLoader;
+
class NPatchData : public ConnectionTracker, public Dali::Toolkit::TextureUploadObserver
{
public:
public:
/**
* Constructor
+ *
+ * @param[in] loader NPatchLoader who create this data.
*/
- NPatchData();
+ NPatchData(NPatchLoader& loader);
/**
* Destructor, non-virtual as not a base class
private:
using ObserverListType = Dali::Vector<TextureUploadObserver*>;
- 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
- VisualUrl mUrl; ///< Url of the N-Patch
- TextureSet mTextureSet; ///< Texture containing the cropped image
- NPatchUtility::StretchRanges mStretchPixelsX; ///< X stretch pixels
- NPatchUtility::StretchRanges mStretchPixelsY; ///< Y stretch pixels
- std::size_t mHash; ///< Hash code for the Url
- uint32_t mCroppedWidth; ///< Width of the cropped middle part of N-patch
- uint32_t mCroppedHeight; ///< Height of the cropped middle part of N-patch
- Rect<int> mBorder; ///< The size of the border
- LoadingState mLoadingState; ///< True if the data loading is completed
- void* mRenderingMap; ///< NPatch rendering data
+ 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
+ NPatchUtility::StretchRanges mStretchPixelsX; ///< X stretch pixels
+ NPatchUtility::StretchRanges mStretchPixelsY; ///< Y stretch pixels
+ std::size_t mHash; ///< Hash code for the Url
+ uint32_t mCroppedWidth; ///< Width of the cropped middle part of N-patch
+ uint32_t mCroppedHeight; ///< Height of the cropped middle part of N-patch
+ Rect<int> mBorder; ///< The size of the border
+ LoadingState mLoadingState; ///< True if the data loading is completed
+ void* mRenderingMap; ///< NPatch rendering data
bool mPreMultiplyOnLoad : 1; ///< Whether to multiply alpha into color channels on load
bool mObserverNotifying : 1; ///< Whether this NPatchData notifying observers or not.
}
}
+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);
// If this is new image loading, make new cache data
if(infoPtr == nullptr)
{
- NPatchInfo info(std::make_shared<NPatchData>());
+ NPatchInfo info(std::make_shared<NPatchData>(*this));
info.mData->SetId(GenerateUniqueNPatchDataId());
info.mData->SetHash(hash);
info.mData->SetUrl(url);
// 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<NPatchData>());
+ NPatchInfo info(std::make_shared<NPatchData>(*this));
info.mData->SetId(GenerateUniqueNPatchDataId());
info.mData->SetHash(hash);
*/
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()
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;
}
+
+ // We don't need to keep tasks anymore. reset now.
+ if(task == mLoadingTask)
+ {
+ mLoadingTask.Reset();
+ }
+ if(task == mRasterizingTask)
+ {
+ mRasterizingTask.Reset();
+ }
+
if(task->HasSucceeded())
{
PixelData rasterizedPixelData = task->GetPixelData();
ResourceReady(Toolkit::Visual::ResourceStatus::FAILED);
}
-
- // We don't need to keep tasks anymore. reset now.
- if(task == mLoadingTask)
- {
- mLoadingTask.Reset();
- }
- if(task == mRasterizingTask)
- {
- mRasterizingTask.Reset();
- }
}
void SvgVisual::OnSetTransform()