aboutsummaryrefslogtreecommitdiffstats
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/SkPictureRecord.cpp6
-rw-r--r--src/core/SkPixelRef.cpp79
-rw-r--r--src/images/SkImageRefPool.cpp6
-rw-r--r--src/ports/SkImageRef_ashmem.cpp3
9 files changed, 104 insertions, 32 deletions
diff --git a/include/core/SkPixelRef.h b/include/core/SkPixelRef.h
index d5f6ab2..f01ba15 100644
--- a/include/core/SkPixelRef.h
+++ b/include/core/SkPixelRef.h
@@ -63,9 +63,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().
@@ -205,6 +206,18 @@ protected:
SkPixelRef(SkFlattenableReadBuffer&, SkBaseMutex*);
+ // 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);
+
+ // only call from constructor. Specify a (possibly) different mutex, or
+ // null to use the default. Use with caution.
+ // The default logic is to provide a mutex, but possibly one that is
+ // shared with other instances, though this sharing is implementation
+ // specific, and it is legal for each instance to have its own mutex.
+ void useDefaultMutex() { this->setMutex(NULL); }
+
private:
#if !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
static void InitializeFlattenables();
@@ -221,6 +234,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);
friend class SkGraphics;
};
diff --git a/include/core/SkThread_platform.h b/include/core/SkThread_platform.h
index 863f6e3..58311e1 100644
--- a/include/core/SkThread_platform.h
+++ b/include/core/SkThread_platform.h
@@ -75,6 +75,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 {
@@ -106,8 +108,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 58d0bd8..0b98513 100644
--- a/src/core/SkBitmap.cpp
+++ b/src/core/SkBitmap.cpp
@@ -284,7 +284,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) {
@@ -1533,7 +1533,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 32b6f9e..6d64716 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 3e22075..72dbb3d 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_PIXEL_REF_REGISTRAR(SkMallocPixelRef)
diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp
index ba49b72..fdeec3f 100644
--- a/src/core/SkPictureRecord.cpp
+++ b/src/core/SkPictureRecord.cpp
@@ -319,7 +319,7 @@ void SkPictureRecord::addFontMetricsTopBottom(const SkPaint& paint,
void SkPictureRecord::drawText(const void* text, size_t byteLength, SkScalar x,
SkScalar y, const SkPaint& paint) {
- bool fast = paint.canComputeFastBounds();
+ bool fast = !paint.isVerticalText() && paint.canComputeFastBounds();
addDraw(fast ? DRAW_TEXT_TOP_BOTTOM : DRAW_TEXT);
addPaint(paint);
@@ -356,7 +356,7 @@ void SkPictureRecord::drawPosText(const void* text, size_t byteLength,
}
}
- bool fastBounds = paint.canComputeFastBounds();
+ bool fastBounds = !paint.isVerticalText() && paint.canComputeFastBounds();
bool fast = canUseDrawH && fastBounds;
if (fast) {
@@ -404,7 +404,7 @@ void SkPictureRecord::drawPosTextH(const void* text, size_t byteLength,
if (0 == points)
return;
- bool fast = paint.canComputeFastBounds();
+ bool fast = !paint.isVerticalText() && paint.canComputeFastBounds();
addDraw(fast ? DRAW_POS_TEXT_H_TOP_BOTTOM : DRAW_POS_TEXT_H);
addPaint(paint);
diff --git a/src/core/SkPixelRef.cpp b/src/core/SkPixelRef.cpp
index d5e1b81..1279f06 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,29 +44,45 @@ 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) {
- 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 {
@@ -53,21 +90,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 bfa933e..c24dba0 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 f9c6aff..46ebb0d 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) {