summaryrefslogtreecommitdiffstats
path: root/libs/rs
diff options
context:
space:
mode:
authorJason Sams <rjsams@android.com>2011-08-18 18:01:33 -0700
committerJason Sams <rjsams@android.com>2011-08-18 18:01:33 -0700
commit777ec2662ef5ee8b0a501e0b8a9b2d7a2b84ffe7 (patch)
treed1c4914169163c551f1eee01081528d29aee5aa0 /libs/rs
parent85deb781658e870556c305c523fa7f2bf679efe3 (diff)
downloadframeworks_base-777ec2662ef5ee8b0a501e0b8a9b2d7a2b84ffe7.zip
frameworks_base-777ec2662ef5ee8b0a501e0b8a9b2d7a2b84ffe7.tar.gz
frameworks_base-777ec2662ef5ee8b0a501e0b8a9b2d7a2b84ffe7.tar.bz2
Fix issue with freeing allocation with circular references.
Change-Id: I45871c20a192815eafee77f95e17a025f6dcf9d1
Diffstat (limited to 'libs/rs')
-rw-r--r--libs/rs/rsAllocation.cpp27
-rw-r--r--libs/rs/rsAllocation.h2
-rw-r--r--libs/rs/rsContext.cpp1
-rw-r--r--libs/rs/rsObjectBase.cpp26
-rw-r--r--libs/rs/rsObjectBase.h2
-rw-r--r--libs/rs/rsProgram.cpp21
-rw-r--r--libs/rs/rsProgram.h1
7 files changed, 59 insertions, 21 deletions
diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp
index a366d49..4359d95 100644
--- a/libs/rs/rsAllocation.cpp
+++ b/libs/rs/rsAllocation.cpp
@@ -58,19 +58,7 @@ void Allocation::updateCache() {
}
Allocation::~Allocation() {
- if (mHal.state.hasReferences &&
- (mHal.state.hasFaces || mHal.state.hasMipmaps)) {
- LOGE("Cube/mip allocation with references unsupported, memory not cleaned up!");
- }
-
- uint32_t elemCount = mHal.state.dimensionX;
- if (mHal.state.dimensionY > 1) {
- elemCount *= mHal.state.dimensionY;
- }
- if (mHal.state.dimensionZ > 1) {
- elemCount *= mHal.state.dimensionZ;
- }
- decRefs(getPtr(), elemCount, 0);
+ freeChildrenUnlocked();
mRSC->mHal.funcs.allocation.destroy(mRSC, this);
}
@@ -299,6 +287,19 @@ void Allocation::decRefs(const void *ptr, size_t ct, size_t startOff) const {
}
}
+void Allocation::freeChildrenUnlocked () {
+ decRefs(getPtr(), mHal.state.type->getSizeBytes() / mHal.state.type->getElementSizeBytes(), 0);
+}
+
+bool Allocation::freeChildren() {
+ if (mHal.state.hasReferences) {
+ incSysRef();
+ freeChildrenUnlocked();
+ return decSysRef();
+ }
+ return false;
+}
+
void Allocation::copyRange1D(Context *rsc, const Allocation *src, int32_t srcOff, int32_t destOff, int32_t len) {
}
diff --git a/libs/rs/rsAllocation.h b/libs/rs/rsAllocation.h
index f2589c0..67fc3b5 100644
--- a/libs/rs/rsAllocation.h
+++ b/libs/rs/rsAllocation.h
@@ -116,6 +116,7 @@ public:
void incRefs(const void *ptr, size_t ct, size_t startOff = 0) const;
void decRefs(const void *ptr, size_t ct, size_t startOff = 0) const;
+ virtual bool freeChildren();
void sendDirty(const Context *rsc) const;
bool getHasGraphicsMipmaps() const {
@@ -127,6 +128,7 @@ protected:
Vector<const Program *> mToDirtyList;
private:
+ void freeChildrenUnlocked();
Allocation(Context *rsc, const Type *, uint32_t usages, RsAllocationMipmapControl mc);
};
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index 8996ad1..e3a9cf8 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -312,6 +312,7 @@ void Context::destroyWorkerThreadResources() {
mStateSampler.deinit(this);
mFBOCache.deinit(this);
}
+ ObjectBase::freeAllChildren(this);
//LOGV("destroyWorkerThreadResources 2");
mExit = true;
}
diff --git a/libs/rs/rsObjectBase.cpp b/libs/rs/rsObjectBase.cpp
index f428f94..f5ced26 100644
--- a/libs/rs/rsObjectBase.cpp
+++ b/libs/rs/rsObjectBase.cpp
@@ -81,6 +81,10 @@ void ObjectBase::incSysRef() const {
void ObjectBase::preDestroy() const {
}
+bool ObjectBase::freeChildren() {
+ return false;
+}
+
bool ObjectBase::checkDelete(const ObjectBase *ref) {
if (!ref) {
return false;
@@ -217,6 +221,28 @@ void ObjectBase::zeroAllUserRef(Context *rsc) {
}
}
+void ObjectBase::freeAllChildren(Context *rsc) {
+ if (rsc->props.mLogObjects) {
+ LOGV("Forcing release of all child objects.");
+ }
+
+ // This operation can be slow, only to be called during context cleanup.
+ ObjectBase * o = (ObjectBase *)rsc->mObjHead;
+ while (o) {
+ if (o->freeChildren()) {
+ // deleted ref to self and possibly others, restart from head.
+ o = (ObjectBase *)rsc->mObjHead;
+ } else {
+ o = (ObjectBase *)o->mNext;
+ }
+ }
+
+ if (rsc->props.mLogObjects) {
+ LOGV("Objects remaining.");
+ dumpAll(rsc);
+ }
+}
+
void ObjectBase::dumpAll(Context *rsc) {
asyncLock();
diff --git a/libs/rs/rsObjectBase.h b/libs/rs/rsObjectBase.h
index c7cfb0e..d9f5f3b 100644
--- a/libs/rs/rsObjectBase.h
+++ b/libs/rs/rsObjectBase.h
@@ -50,8 +50,10 @@ public:
void setName(const char *, uint32_t len);
Context * getContext() const {return mRSC;}
+ virtual bool freeChildren();
static void zeroAllUserRef(Context *rsc);
+ static void freeAllChildren(Context *rsc);
static void dumpAll(Context *rsc);
virtual void dumpLOGV(const char *prefix) const;
diff --git a/libs/rs/rsProgram.cpp b/libs/rs/rsProgram.cpp
index 33eb422..4178aa5 100644
--- a/libs/rs/rsProgram.cpp
+++ b/libs/rs/rsProgram.cpp
@@ -70,15 +70,8 @@ Program::Program(Context *rsc, const char * shaderText, uint32_t shaderLength,
}
Program::~Program() {
+ freeChildren();
- for (uint32_t ct=0; ct < mHal.state.constantsCount; ct++) {
- bindAllocation(NULL, NULL, ct);
- }
-
- for (uint32_t ct=0; ct < mHal.state.texturesCount; ct++) {
- bindTexture(NULL, ct, NULL);
- bindSampler(NULL, ct, NULL);
- }
delete[] mHal.state.textures;
delete[] mHal.state.samplers;
delete[] mHal.state.textureTargets;
@@ -90,6 +83,18 @@ Program::~Program() {
mHal.state.texturesCount = 0;
}
+bool Program::freeChildren() {
+ for (uint32_t ct=0; ct < mHal.state.constantsCount; ct++) {
+ bindAllocation(NULL, NULL, ct);
+ }
+
+ for (uint32_t ct=0; ct < mHal.state.texturesCount; ct++) {
+ bindTexture(NULL, ct, NULL);
+ bindSampler(NULL, ct, NULL);
+ }
+ return false;
+}
+
void Program::initMemberVars() {
mDirty = true;
diff --git a/libs/rs/rsProgram.h b/libs/rs/rsProgram.h
index 948ba3e..3237a72 100644
--- a/libs/rs/rsProgram.h
+++ b/libs/rs/rsProgram.h
@@ -34,6 +34,7 @@ public:
Program(Context *, const char * shaderText, uint32_t shaderLength,
const uint32_t * params, uint32_t paramLength);
virtual ~Program();
+ virtual bool freeChildren();
void bindAllocation(Context *, Allocation *, uint32_t slot);