OSDN Git Service

Fix issue with freeing allocation with circular references.
authorJason Sams <rjsams@android.com>
Fri, 19 Aug 2011 01:01:33 +0000 (18:01 -0700)
committerJason Sams <rjsams@android.com>
Fri, 19 Aug 2011 01:01:33 +0000 (18:01 -0700)
Change-Id: I45871c20a192815eafee77f95e17a025f6dcf9d1

libs/rs/rsAllocation.cpp
libs/rs/rsAllocation.h
libs/rs/rsContext.cpp
libs/rs/rsObjectBase.cpp
libs/rs/rsObjectBase.h
libs/rs/rsProgram.cpp
libs/rs/rsProgram.h

index a366d49..4359d95 100644 (file)
@@ -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) {
 }
 
index f2589c0..67fc3b5 100644 (file)
@@ -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);
 };
 
index 8996ad1..e3a9cf8 100644 (file)
@@ -312,6 +312,7 @@ void Context::destroyWorkerThreadResources() {
          mStateSampler.deinit(this);
          mFBOCache.deinit(this);
     }
+    ObjectBase::freeAllChildren(this);
     //LOGV("destroyWorkerThreadResources 2");
     mExit = true;
 }
index f428f94..f5ced26 100644 (file)
@@ -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();
 
index c7cfb0e..d9f5f3b 100644 (file)
@@ -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;
index 33eb422..4178aa5 100644 (file)
@@ -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;
 
index 948ba3e..3237a72 100644 (file)
@@ -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);