aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/core/SkPixelRef.h23
-rw-r--r--include/core/SkThread_platform.h7
-rw-r--r--src/core/SkBitmap.cpp4
-rw-r--r--src/core/SkBitmapProcShader.cpp4
-rw-r--r--src/core/SkMallocPixelRef.cpp4
-rw-r--r--src/core/SkPixelRef.cpp79
-rw-r--r--src/images/SkImageRefPool.cpp6
-rw-r--r--src/ports/SkImageRef_ashmem.cpp3
8 files changed, 101 insertions, 29 deletions
diff --git a/include/core/SkPixelRef.h b/include/core/SkPixelRef.h
index c9027653cf..5c24d67520 100644
--- a/include/core/SkPixelRef.h
+++ b/include/core/SkPixelRef.h
@@ -43,9 +43,10 @@ public:
*/
SkColorTable* colorTable() const { return fColorTable; }
- /** Return the current lockcount (defaults to 0)
- */
- int getLockCount() const { return fLockCount; }
+ /**
+ * Returns true if the lockcount > 0
+ */
+ bool isLocked() const { return fLockCount > 0; }
/** Call to access the pixel memory, which is returned. Balance with a call
to unlockPixels().
@@ -169,6 +170,18 @@ protected:
SkPixelRef(SkFlattenableReadBuffer&, SkBaseMutex*);
virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+ // only call from constructor. Flags this to always be locked, removing
+ // the need to grab the mutex and call onLockPixels/onUnlockPixels.
+ // Performance tweak to avoid those calls (esp. in multi-thread use case).
+ void setPreLocked(void* pixels, SkColorTable* ctable);
+
+ /**
+ * If a subclass passed a particular mutex to the base constructor, it can
+ * override that to go back to the default mutex by calling this. However,
+ * this should only be called from within the subclass' constructor.
+ */
+ void useDefaultMutex() { this->setMutex(NULL); }
+
private:
SkBaseMutex* fMutex; // must remain in scope for the life of this object
@@ -182,6 +195,10 @@ private:
// can go from false to true, but never from true to false
bool fIsImmutable;
+ // only ever set in constructor, const after that
+ bool fPreLocked;
+
+ void setMutex(SkBaseMutex* mutex);
typedef SkFlattenable INHERITED;
};
diff --git a/include/core/SkThread_platform.h b/include/core/SkThread_platform.h
index 351477569d..7041aa4e9a 100644
--- a/include/core/SkThread_platform.h
+++ b/include/core/SkThread_platform.h
@@ -140,6 +140,8 @@ struct SkBaseMutex {
// Special case used when the static mutex must be available globally.
#define SK_DECLARE_GLOBAL_MUTEX(name) SkBaseMutex name = { PTHREAD_MUTEX_INITIALIZER }
+#define SK_DECLARE_MUTEX_ARRAY(name, count) SkBaseMutex name[count] = { PTHREAD_MUTEX_INITIALIZER }
+
// A normal mutex that requires to be initialized through normal C++ construction,
// i.e. when it's a member of another class, or allocated on the heap.
class SkMutex : public SkBaseMutex, SkNoncopyable {
@@ -171,8 +173,9 @@ private:
typedef SkMutex SkBaseMutex;
-#define SK_DECLARE_STATIC_MUTEX(name) static SkBaseMutex name
-#define SK_DECLARE_GLOBAL_MUTEX(name) SkBaseMutex name
+#define SK_DECLARE_STATIC_MUTEX(name) static SkBaseMutex name
+#define SK_DECLARE_GLOBAL_MUTEX(name) SkBaseMutex name
+#define SK_DECLARE_MUTEX_ARRAY(name, count) SkBaseMutex name[count]
#endif // !SK_USE_POSIX_THREADS
diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp
index da87e77159..6b9914535e 100644
--- a/src/core/SkBitmap.cpp
+++ b/src/core/SkBitmap.cpp
@@ -297,7 +297,7 @@ err:
void SkBitmap::updatePixelsFromRef() const {
if (NULL != fPixelRef) {
if (fPixelLockCount > 0) {
- SkASSERT(fPixelRef->getLockCount() > 0);
+ SkASSERT(fPixelRef->isLocked());
void* p = fPixelRef->pixels();
if (NULL != p) {
@@ -1525,7 +1525,7 @@ void SkBitmap::validate() const {
#if 0 // these asserts are not thread-correct, so disable for now
if (fPixelRef) {
if (fPixelLockCount > 0) {
- SkASSERT(fPixelRef->getLockCount() > 0);
+ SkASSERT(fPixelRef->isLocked());
} else {
SkASSERT(NULL == fPixels);
SkASSERT(NULL == fColorTable);
diff --git a/src/core/SkBitmapProcShader.cpp b/src/core/SkBitmapProcShader.cpp
index 3abfc8d230..f76bc09547 100644
--- a/src/core/SkBitmapProcShader.cpp
+++ b/src/core/SkBitmapProcShader.cpp
@@ -173,7 +173,7 @@ void SkBitmapProcShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
SkASSERT(state.fBitmap->getPixels());
SkASSERT(state.fBitmap->pixelRef() == NULL ||
- state.fBitmap->pixelRef()->getLockCount());
+ state.fBitmap->pixelRef()->isLocked());
for (;;) {
int n = count;
@@ -217,7 +217,7 @@ void SkBitmapProcShader::shadeSpan16(int x, int y, uint16_t dstC[], int count) {
SkASSERT(state.fBitmap->getPixels());
SkASSERT(state.fBitmap->pixelRef() == NULL ||
- state.fBitmap->pixelRef()->getLockCount());
+ state.fBitmap->pixelRef()->isLocked());
for (;;) {
int n = count;
diff --git a/src/core/SkMallocPixelRef.cpp b/src/core/SkMallocPixelRef.cpp
index 313a26eeaa..14a064654f 100644
--- a/src/core/SkMallocPixelRef.cpp
+++ b/src/core/SkMallocPixelRef.cpp
@@ -18,6 +18,8 @@ SkMallocPixelRef::SkMallocPixelRef(void* storage, size_t size,
fSize = size;
fCTable = ctable;
SkSafeRef(ctable);
+
+ this->setPreLocked(fStorage, fCTable);
}
SkMallocPixelRef::~SkMallocPixelRef() {
@@ -57,6 +59,8 @@ SkMallocPixelRef::SkMallocPixelRef(SkFlattenableReadBuffer& buffer)
} else {
fCTable = NULL;
}
+
+ this->setPreLocked(fStorage, fCTable);
}
SK_DEFINE_FLATTENABLE_REGISTRAR(SkMallocPixelRef)
diff --git a/src/core/SkPixelRef.cpp b/src/core/SkPixelRef.cpp
index f01fbea81d..88ce76fb6a 100644
--- a/src/core/SkPixelRef.cpp
+++ b/src/core/SkPixelRef.cpp
@@ -9,7 +9,28 @@
#include "SkFlattenable.h"
#include "SkThread.h"
-SK_DECLARE_STATIC_MUTEX(gPixelRefMutex);
+// must be a power-of-2. undef to just use 1 mutex
+#define PIXELREF_MUTEX_RING_COUNT 32
+
+#ifdef PIXELREF_MUTEX_RING_COUNT
+ static int32_t gPixelRefMutexRingIndex;
+ static SK_DECLARE_MUTEX_ARRAY(gPixelRefMutexRing, PIXELREF_MUTEX_RING_COUNT);
+#else
+ SK_DECLARE_STATIC_MUTEX(gPixelRefMutex);
+#endif
+
+SkBaseMutex* get_default_mutex() {
+#ifdef PIXELREF_MUTEX_RING_COUNT
+ // atomic_inc might be overkill here. It may be fine if once in a while
+ // we hit a race-condition and two subsequent calls get the same index...
+ int index = sk_atomic_inc(&gPixelRefMutexRingIndex);
+ return &gPixelRefMutexRing[index & (PIXELREF_MUTEX_RING_COUNT - 1)];
+#else
+ return &gPixelRefMutex;
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////////
extern int32_t SkNextPixelRefGenerationID();
int32_t SkNextPixelRefGenerationID() {
@@ -23,30 +44,46 @@ int32_t SkNextPixelRefGenerationID() {
return genID;
}
+///////////////////////////////////////////////////////////////////////////////
-SkPixelRef::SkPixelRef(SkBaseMutex* mutex) {
+void SkPixelRef::setMutex(SkBaseMutex* mutex) {
if (NULL == mutex) {
- mutex = &gPixelRefMutex;
+ mutex = get_default_mutex();
}
fMutex = mutex;
+}
+
+// just need a > 0 value, so pick a funny one to aid in debugging
+#define SKPIXELREF_PRELOCKED_LOCKCOUNT 123456789
+
+SkPixelRef::SkPixelRef(SkBaseMutex* mutex) : fPreLocked(false) {
+ this->setMutex(mutex);
fPixels = NULL;
fColorTable = NULL; // we do not track ownership of this
fLockCount = 0;
fGenerationID = 0; // signal to rebuild
fIsImmutable = false;
+ fPreLocked = false;
}
SkPixelRef::SkPixelRef(SkFlattenableReadBuffer& buffer, SkBaseMutex* mutex)
: INHERITED(buffer) {
- if (NULL == mutex) {
- mutex = &gPixelRefMutex;
- }
- fMutex = mutex;
+ this->setMutex(mutex);
fPixels = NULL;
fColorTable = NULL; // we do not track ownership of this
fLockCount = 0;
fGenerationID = 0; // signal to rebuild
fIsImmutable = buffer.readBool();
+ fPreLocked = false;
+}
+
+void SkPixelRef::setPreLocked(void* pixels, SkColorTable* ctable) {
+ // only call me in your constructor, otherwise fLockCount tracking can get
+ // out of sync.
+ fPixels = pixels;
+ fColorTable = ctable;
+ fLockCount = SKPIXELREF_PRELOCKED_LOCKCOUNT;
+ fPreLocked = true;
}
void SkPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
@@ -55,21 +92,29 @@ void SkPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
}
void SkPixelRef::lockPixels() {
- SkAutoMutexAcquire ac(*fMutex);
+ SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount);
- if (1 == ++fLockCount) {
- fPixels = this->onLockPixels(&fColorTable);
+ if (!fPreLocked) {
+ SkAutoMutexAcquire ac(*fMutex);
+
+ if (1 == ++fLockCount) {
+ fPixels = this->onLockPixels(&fColorTable);
+ }
}
}
void SkPixelRef::unlockPixels() {
- SkAutoMutexAcquire ac(*fMutex);
-
- SkASSERT(fLockCount > 0);
- if (0 == --fLockCount) {
- this->onUnlockPixels();
- fPixels = NULL;
- fColorTable = NULL;
+ SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount);
+
+ if (!fPreLocked) {
+ SkAutoMutexAcquire ac(*fMutex);
+
+ SkASSERT(fLockCount > 0);
+ if (0 == --fLockCount) {
+ this->onUnlockPixels();
+ fPixels = NULL;
+ fColorTable = NULL;
+ }
}
}
diff --git a/src/images/SkImageRefPool.cpp b/src/images/SkImageRefPool.cpp
index bfa933e997..c24dba0da8 100644
--- a/src/images/SkImageRefPool.cpp
+++ b/src/images/SkImageRefPool.cpp
@@ -59,7 +59,7 @@ void SkImageRefPool::setRAMUsed(size_t limit) {
while (NULL != ref && fRAMUsed > limit) {
// only purge it if its pixels are unlocked
- if (0 == ref->getLockCount() && ref->fBitmap.getPixels()) {
+ if (!ref->isLocked() && ref->fBitmap.getPixels()) {
size_t size = ref->ramUsed();
SkASSERT(size <= fRAMUsed);
fRAMUsed -= size;
@@ -181,10 +181,10 @@ void SkImageRefPool::dump() const {
SkImageRef* ref = fHead;
while (ref != NULL) {
- SkDebugf(" [%3d %3d %d] ram=%d data=%d locks=%d %s\n", ref->fBitmap.width(),
+ SkDebugf(" [%3d %3d %d] ram=%d data=%d locked=%d %s\n", ref->fBitmap.width(),
ref->fBitmap.height(), ref->fBitmap.config(),
ref->ramUsed(), (int)ref->fStream->getLength(),
- ref->getLockCount(), ref->getURI());
+ ref->isLocked(), ref->getURI());
ref = ref->fNext;
}
diff --git a/src/ports/SkImageRef_ashmem.cpp b/src/ports/SkImageRef_ashmem.cpp
index f1fb829fc9..6ea5c95e78 100644
--- a/src/ports/SkImageRef_ashmem.cpp
+++ b/src/ports/SkImageRef_ashmem.cpp
@@ -41,6 +41,8 @@ SkImageRef_ashmem::SkImageRef_ashmem(SkStream* stream,
fRec.fPinned = false;
fCT = NULL;
+
+ this->useDefaultMutex(); // we don't need/want the shared imageref mutex
}
SkImageRef_ashmem::~SkImageRef_ashmem() {
@@ -235,6 +237,7 @@ SkImageRef_ashmem::SkImageRef_ashmem(SkFlattenableReadBuffer& buffer)
buffer.read(buf, length);
setURI(buf, length);
}
+ this->useDefaultMutex(); // we don't need/want the shared imageref mutex
}
SkPixelRef* SkImageRef_ashmem::Create(SkFlattenableReadBuffer& buffer) {