summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandreykproductengine <andreykproductengine@lindenlab.com>2019-08-13 17:22:58 +0300
committerandreykproductengine <andreykproductengine@lindenlab.com>2019-08-13 17:22:58 +0300
commit1233842012a257b7eb49eab354bb945593c974ed (patch)
tree0e672d401fe9d1b3fa89ec82134b192b90260fb1
parent5196af8663653fb345394733bf4bf88185a7565a (diff)
SL-11718 Crash in LLRender2D
-rw-r--r--indra/llrender/llrender2dutils.cpp43
-rw-r--r--indra/llrender/llrender2dutils.h19
2 files changed, 61 insertions, 1 deletions
diff --git a/indra/llrender/llrender2dutils.cpp b/indra/llrender/llrender2dutils.cpp
index 508bccec11..4eb0203245 100644
--- a/indra/llrender/llrender2dutils.cpp
+++ b/indra/llrender/llrender2dutils.cpp
@@ -1570,6 +1570,10 @@ LLRender2D::LLRender2D(LLImageProviderInterface* image_provider)
{
mGLScaleFactor = LLVector2(1.f, 1.f);
mImageProvider = image_provider;
+ if(mImageProvider)
+ {
+ mImageProvider->addOnRemovalCallback(resetProvider);
+ }
}
LLRender2D::~LLRender2D()
@@ -1577,6 +1581,7 @@ LLRender2D::~LLRender2D()
if(mImageProvider)
{
mImageProvider->cleanUp();
+ mImageProvider->deleteOnRemovalCallback(resetProvider);
}
}
@@ -1642,3 +1647,41 @@ LLPointer<LLUIImage> LLRender2D::getUIImage(const std::string& name, S32 priorit
return NULL;
}
+// static
+void LLRender2D::resetProvider()
+{
+ if (LLRender2D::instanceExists)
+ {
+ LLRender2D::getInstance()->mImageProvider = NULL;
+ }
+}
+
+// class LLImageProviderInterface
+
+LLImageProviderInterface::~LLImageProviderInterface()
+{
+ for (callback_list_t::iterator iter = mCallbackList.begin(); iter != mCallbackList.end();)
+ {
+ callback_list_t::iterator curiter = iter++;
+ (*curiter)();
+ }
+}
+
+void LLImageProviderInterface::addOnRemovalCallback(callback_t func)
+{
+ if (!func)
+ {
+ return;
+ }
+ mCallbackList.push_back(func);
+}
+
+void LLImageProviderInterface::deleteOnRemovalCallback(callback_t func)
+{
+ callback_list_t::iterator iter = std::find(mCallbackList.begin(), mCallbackList.end(), func);
+ if (iter != mCallbackList.end())
+ {
+ mCallbackList.erase(iter);
+ }
+}
+
diff --git a/indra/llrender/llrender2dutils.h b/indra/llrender/llrender2dutils.h
index cf408336e6..70ab006fd6 100644
--- a/indra/llrender/llrender2dutils.h
+++ b/indra/llrender/llrender2dutils.h
@@ -139,6 +139,13 @@ public:
LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority = 0);
LLVector2 mGLScaleFactor;
+
+protected:
+ // since LLRender2D has no control of image provider's lifecycle
+ // we need a way to tell LLRender2D that provider died and
+ // LLRender2D needs to be updated.
+ static void resetProvider();
+
private:
LLImageProviderInterface* mImageProvider;
};
@@ -147,11 +154,21 @@ class LLImageProviderInterface
{
protected:
LLImageProviderInterface() {};
- virtual ~LLImageProviderInterface() {};
+ virtual ~LLImageProviderInterface();
public:
virtual LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority) = 0;
virtual LLPointer<LLUIImage> getUIImageByID(const LLUUID& id, S32 priority) = 0;
virtual void cleanUp() = 0;
+
+ // to notify holders when pointer gets deleted
+ typedef void(*callback_t)();
+ void addOnRemovalCallback(callback_t func);
+ void deleteOnRemovalCallback(callback_t func);
+
+private:
+
+ typedef std::list< callback_t > callback_list_t;
+ callback_list_t mCallbackList;
};