aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkPathRef.h
diff options
context:
space:
mode:
authorGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-10-03 19:57:01 +0000
committerGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-10-03 19:57:01 +0000
commitae09f2dc3fb1e8a8db99b214c8a71d0b9613a856 (patch)
tree00800814251bea8b8005c4bf098ffd9dc83ecb43 /src/core/SkPathRef.h
parent2fc2359aaa8807606854f44a3f38c836a03977cd (diff)
Adds extra debugging to SkPathRef that can optionally be turned on in a release build.
This is pretty hacky but hopefully will be quite short-lived. Review URL: https://codereview.appspot.com/6584074 git-svn-id: http://skia.googlecode.com/svn/trunk@5793 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/core/SkPathRef.h')
-rw-r--r--src/core/SkPathRef.h87
1 files changed, 74 insertions, 13 deletions
diff --git a/src/core/SkPathRef.h b/src/core/SkPathRef.h
index 339166340e..80ca50cabc 100644
--- a/src/core/SkPathRef.h
+++ b/src/core/SkPathRef.h
@@ -32,13 +32,29 @@
* verb array use ref.verbs()[~i] (because verbs() returns a pointer just beyond the first
* logical verb or the last verb in memory).
*/
+
+class SkPathRef;
+SkPathRef* gEmptyPathRef; // This path ref should never be deleted once it is created.
+
+// Temporary hackery to try to nail down http://code.google.com/p/chromium/issues/detail?id=148637
+#if SK_DEBUG_PATH_REF
+ #define PR_CONTAINER SkPath::PathRefDebugRef
+ #define SkDEBUGCODE_X(code) code
+ #define SkASSERT_X(cond) SK_DEBUGBREAK(cond)
+ SK_DECLARE_STATIC_MUTEX(gOwnersMutex);
+#else
+ #define PR_CONTAINER SkAutoTUnref<SkPathRef>
+ #define SkDEBUGCODE_X(code) SkDEBUGCODE(code)
+ #define SkASSERT_X(cond) SkASSERT(cond)
+#endif
+
class SkPathRef : public ::SkRefCnt {
public:
SK_DECLARE_INST_COUNT(SkPathRef);
class Editor {
public:
- Editor(SkAutoTUnref<SkPathRef>* pathRef,
+ Editor(PR_CONTAINER* pathRef,
int incReserveVerbs = 0,
int incReservePoints = 0) {
if (pathRef->get()->getRefCnt() > 1) {
@@ -50,10 +66,10 @@ public:
}
fPathRef = pathRef->get();
fPathRef->fGenerationID = 0;
- SkDEBUGCODE(sk_atomic_inc(&fPathRef->fEditorsAttached);)
+ SkDEBUGCODE_X(sk_atomic_inc(&fPathRef->fEditorsAttached);)
}
- ~Editor() { SkDEBUGCODE(sk_atomic_dec(&fPathRef->fEditorsAttached);) }
+ ~Editor() { SkDEBUGCODE_X(sk_atomic_dec(&fPathRef->fEditorsAttached);) }
/**
* Returns the array of points.
@@ -112,28 +128,56 @@ public:
};
public:
+#if SK_DEBUG_PATH_REF
+ void addOwner(SkPath* owner) {
+ gOwnersMutex.acquire();
+ for (int i = 0; i < fOwners.count(); ++i) {
+ SkASSERT_X(fOwners[i] != owner);
+ }
+ *fOwners.append() = owner;
+ SkASSERT_X((this->getRefCnt() == fOwners.count()) ||
+ (this == gEmptyPathRef && this->getRefCnt() == fOwners.count() + 1));
+ gOwnersMutex.release();
+ }
+
+ void removeOwner(SkPath* owner) {
+ gOwnersMutex.acquire();
+ SkASSERT_X((this->getRefCnt() == fOwners.count()) ||
+ (this == gEmptyPathRef && this->getRefCnt() == fOwners.count() + 1));
+ bool found = false;
+ for (int i = 0; !found && i < fOwners.count(); ++i) {
+ found = (owner == fOwners[i]);
+ if (found) {
+ fOwners.remove(i);
+ }
+ }
+ SkASSERT_X(found);
+ gOwnersMutex.release();
+ }
+#endif
/**
* Gets a path ref with no verbs or points.
*/
static SkPathRef* CreateEmpty() {
- static SkAutoTUnref<SkPathRef> gEmptyPathRef(SkNEW(SkPathRef));
- gEmptyPathRef.get()->ref();
- return gEmptyPathRef.get();
+ if (!gEmptyPathRef) {
+ gEmptyPathRef = SkNEW(SkPathRef); // leak!
+ }
+ return SkRef(gEmptyPathRef);
}
/**
* Transforms a path ref by a matrix, allocating a new one only if necessary.
*/
- static void CreateTransformedCopy(SkAutoTUnref<SkPathRef>* dst,
+ static void CreateTransformedCopy(PR_CONTAINER* dst,
const SkPathRef& src,
const SkMatrix& matrix) {
src.validate();
if (matrix.isIdentity()) {
if (dst->get() != &src) {
+ src.ref();
dst->reset(const_cast<SkPathRef*>(&src));
(*dst)->validate();
- src.ref();
}
return;
}
@@ -184,7 +228,7 @@ public:
* repopulated with approximately the same number of verbs and points. A new path ref is created
* only if necessary.
*/
- static void Rewind(SkAutoTUnref<SkPathRef>* pathRef) {
+ static void Rewind(PR_CONTAINER* pathRef) {
if (1 == (*pathRef)->getRefCnt()) {
(*pathRef)->validate();
(*pathRef)->fVerbCnt = 0;
@@ -201,8 +245,21 @@ public:
}
virtual ~SkPathRef() {
+ SkASSERT_X(this != gEmptyPathRef);
+#if SK_DEBUG_PATH_REF
+ SkASSERT_X(!fOwners.count());
+#endif
+
this->validate();
sk_free(fPoints);
+
+ SkDEBUGCODE_X(fPoints = NULL;)
+ SkDEBUGCODE_X(fVerbs = NULL;)
+ SkDEBUGCODE_X(fVerbCnt = 0x9999999;)
+ SkDEBUGCODE_X(fPointCnt = 0xAAAAAAA;)
+ SkDEBUGCODE_X(fPointCnt = 0xBBBBBBB;)
+ SkDEBUGCODE_X(fGenerationID = 0xEEEEEEEE;)
+ SkDEBUGCODE_X(fEditorsAttached = 0x7777777;)
}
int countPoints() const { this->validate(); return fPointCnt; }
@@ -282,7 +339,7 @@ public:
#if NEW_PICTURE_FORMAT
void writeToBuffer(SkWBuffer* buffer) {
this->validate();
- SkDEBUGCODE(size_t beforePos = buffer->pos();)
+ SkDEBUGCODE_X(size_t beforePos = buffer->pos();)
// TODO: write gen ID here. Problem: We don't know if we're cross process or not from
// SkWBuffer. Until this is fixed we write 0.
@@ -319,7 +376,7 @@ private:
fPoints = NULL;
fFreeSpace = 0;
fGenerationID = kEmptyGenID;
- SkDEBUGCODE(fEditorsAttached = 0;)
+ SkDEBUGCODE_X(fEditorsAttached = 0;)
this->validate();
}
@@ -480,7 +537,7 @@ private:
* for the path ref.
*/
int32_t genID() const {
- SkDEBUGCODE(SkASSERT(!fEditorsAttached));
+ SkASSERT_X(!fEditorsAttached);
if (!fGenerationID) {
if (0 == fPointCnt && 0 == fVerbCnt) {
fGenerationID = kEmptyGenID;
@@ -521,7 +578,11 @@ private:
kEmptyGenID = 1, // GenID reserved for path ref with zero points and zero verbs.
};
mutable int32_t fGenerationID;
- SkDEBUGCODE(int32_t fEditorsAttached;) // assert that only one editor in use at any time.
+ SkDEBUGCODE_X(int32_t fEditorsAttached;) // assert that only one editor in use at any time.
+
+#if SK_DEBUG_PATH_REF
+ SkTDArray<SkPath*> fOwners;
+#endif
typedef SkRefCnt INHERITED;
};