blob: f71458b7dd1f6b32395b4d444fec286b7397f6ff [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
2/*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
reed@android.com8a1c16f2008-12-17 15:59:43 +00008#include "SkPixelRef.h"
djsollen@google.comc73dd5c2012-08-07 15:54:32 +00009#include "SkFlattenableBuffers.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000010#include "SkThread.h"
11
robertphillips@google.com0456e0b2012-06-27 14:03:26 +000012SK_DEFINE_INST_COUNT(SkPixelRef)
13
reed@google.comff0da4f2012-05-17 13:14:52 +000014// must be a power-of-2. undef to just use 1 mutex
15#define PIXELREF_MUTEX_RING_COUNT 32
16
17#ifdef PIXELREF_MUTEX_RING_COUNT
18 static int32_t gPixelRefMutexRingIndex;
19 static SK_DECLARE_MUTEX_ARRAY(gPixelRefMutexRing, PIXELREF_MUTEX_RING_COUNT);
20#else
21 SK_DECLARE_STATIC_MUTEX(gPixelRefMutex);
22#endif
23
caryclark@google.com803eceb2012-06-06 12:09:34 +000024static SkBaseMutex* get_default_mutex() {
reed@google.comff0da4f2012-05-17 13:14:52 +000025#ifdef PIXELREF_MUTEX_RING_COUNT
26 // atomic_inc might be overkill here. It may be fine if once in a while
27 // we hit a race-condition and two subsequent calls get the same index...
28 int index = sk_atomic_inc(&gPixelRefMutexRingIndex);
29 return &gPixelRefMutexRing[index & (PIXELREF_MUTEX_RING_COUNT - 1)];
30#else
31 return &gPixelRefMutex;
32#endif
33}
34
35///////////////////////////////////////////////////////////////////////////////
bsalomon@google.com586f48c2011-04-14 15:07:22 +000036
reed@google.com9c49bc32011-07-07 13:42:37 +000037int32_t SkNextPixelRefGenerationID() {
bsalomon@google.com586f48c2011-04-14 15:07:22 +000038 static int32_t gPixelRefGenerationID;
39 // do a loop in case our global wraps around, as we never want to
40 // return a 0
41 int32_t genID;
42 do {
43 genID = sk_atomic_inc(&gPixelRefGenerationID) + 1;
44 } while (0 == genID);
45 return genID;
46}
47
reed@google.comff0da4f2012-05-17 13:14:52 +000048///////////////////////////////////////////////////////////////////////////////
reed@android.com8a1c16f2008-12-17 15:59:43 +000049
reed@google.comff0da4f2012-05-17 13:14:52 +000050void SkPixelRef::setMutex(SkBaseMutex* mutex) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000051 if (NULL == mutex) {
reed@google.comff0da4f2012-05-17 13:14:52 +000052 mutex = get_default_mutex();
reed@android.com8a1c16f2008-12-17 15:59:43 +000053 }
54 fMutex = mutex;
reed@google.comff0da4f2012-05-17 13:14:52 +000055}
56
57// just need a > 0 value, so pick a funny one to aid in debugging
58#define SKPIXELREF_PRELOCKED_LOCKCOUNT 123456789
59
60SkPixelRef::SkPixelRef(SkBaseMutex* mutex) : fPreLocked(false) {
61 this->setMutex(mutex);
reed@android.com8a1c16f2008-12-17 15:59:43 +000062 fPixels = NULL;
63 fColorTable = NULL; // we do not track ownership of this
64 fLockCount = 0;
65 fGenerationID = 0; // signal to rebuild
66 fIsImmutable = false;
reed@google.comff0da4f2012-05-17 13:14:52 +000067 fPreLocked = false;
reed@android.com8a1c16f2008-12-17 15:59:43 +000068}
69
djsollen@google.com5370cd92012-03-28 20:47:01 +000070SkPixelRef::SkPixelRef(SkFlattenableReadBuffer& buffer, SkBaseMutex* mutex)
71 : INHERITED(buffer) {
reed@google.comff0da4f2012-05-17 13:14:52 +000072 this->setMutex(mutex);
reed@android.com8a1c16f2008-12-17 15:59:43 +000073 fPixels = NULL;
74 fColorTable = NULL; // we do not track ownership of this
75 fLockCount = 0;
reed@android.com8a1c16f2008-12-17 15:59:43 +000076 fIsImmutable = buffer.readBool();
djsollen@google.comc73dd5c2012-08-07 15:54:32 +000077 fGenerationID = buffer.readUInt();
reed@google.comff0da4f2012-05-17 13:14:52 +000078 fPreLocked = false;
79}
80
81void SkPixelRef::setPreLocked(void* pixels, SkColorTable* ctable) {
82 // only call me in your constructor, otherwise fLockCount tracking can get
83 // out of sync.
84 fPixels = pixels;
85 fColorTable = ctable;
86 fLockCount = SKPIXELREF_PRELOCKED_LOCKCOUNT;
87 fPreLocked = true;
reed@android.com8a1c16f2008-12-17 15:59:43 +000088}
89
djsollen@google.com54924242012-03-29 15:18:04 +000090void SkPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
djsollen@google.com5370cd92012-03-28 20:47:01 +000091 this->INHERITED::flatten(buffer);
reed@android.com8a1c16f2008-12-17 15:59:43 +000092 buffer.writeBool(fIsImmutable);
bsalomon@google.com7aa876b2012-06-21 20:13:04 +000093 // We write the gen ID into the picture for within-process recording. This
94 // is safe since the same genID will never refer to two different sets of
95 // pixels (barring overflow). However, each process has its own "namespace"
96 // of genIDs. So for cross-process recording we write a zero which will
97 // trigger assignment of a new genID in playback.
98 if (buffer.isCrossProcess()) {
djsollen@google.comc73dd5c2012-08-07 15:54:32 +000099 buffer.writeUInt(0);
bsalomon@google.com7aa876b2012-06-21 20:13:04 +0000100 } else {
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000101 buffer.writeUInt(fGenerationID);
bsalomon@google.com7aa876b2012-06-21 20:13:04 +0000102 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000103}
104
105void SkPixelRef::lockPixels() {
reed@google.comff0da4f2012-05-17 13:14:52 +0000106 SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount);
reed@google.com93c5f9e2011-02-24 18:09:46 +0000107
reed@google.comff0da4f2012-05-17 13:14:52 +0000108 if (!fPreLocked) {
109 SkAutoMutexAcquire ac(*fMutex);
110
111 if (1 == ++fLockCount) {
112 fPixels = this->onLockPixels(&fColorTable);
113 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000114 }
115}
116
117void SkPixelRef::unlockPixels() {
reed@google.comff0da4f2012-05-17 13:14:52 +0000118 SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000119
reed@google.comff0da4f2012-05-17 13:14:52 +0000120 if (!fPreLocked) {
121 SkAutoMutexAcquire ac(*fMutex);
reed@google.com93c5f9e2011-02-24 18:09:46 +0000122
reed@google.comff0da4f2012-05-17 13:14:52 +0000123 SkASSERT(fLockCount > 0);
124 if (0 == --fLockCount) {
125 this->onUnlockPixels();
126 fPixels = NULL;
127 fColorTable = NULL;
128 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000129 }
130}
131
reed@google.com9c49bc32011-07-07 13:42:37 +0000132bool SkPixelRef::lockPixelsAreWritable() const {
133 return this->onLockPixelsAreWritable();
134}
135
136bool SkPixelRef::onLockPixelsAreWritable() const {
137 return true;
138}
139
reed@android.com8a1c16f2008-12-17 15:59:43 +0000140uint32_t SkPixelRef::getGenerationID() const {
bsalomon@google.com586f48c2011-04-14 15:07:22 +0000141 if (0 == fGenerationID) {
142 fGenerationID = SkNextPixelRefGenerationID();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000143 }
bsalomon@google.com586f48c2011-04-14 15:07:22 +0000144 return fGenerationID;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000145}
146
147void SkPixelRef::notifyPixelsChanged() {
reed@android.com3eab80c2009-03-24 18:47:35 +0000148#ifdef SK_DEBUG
reed@android.com8a1c16f2008-12-17 15:59:43 +0000149 if (fIsImmutable) {
150 SkDebugf("========== notifyPixelsChanged called on immutable pixelref");
reed@android.com8a1c16f2008-12-17 15:59:43 +0000151 }
reed@android.com3eab80c2009-03-24 18:47:35 +0000152#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +0000153 // this signals us to recompute this next time around
154 fGenerationID = 0;
155}
156
157void SkPixelRef::setImmutable() {
158 fIsImmutable = true;
159}
160
reed@google.com50dfa012011-04-01 19:05:36 +0000161bool SkPixelRef::readPixels(SkBitmap* dst, const SkIRect* subset) {
162 return this->onReadPixels(dst, subset);
163}
164
165bool SkPixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) {
166 return false;
167}
168
reed@android.com8a1c16f2008-12-17 15:59:43 +0000169///////////////////////////////////////////////////////////////////////////////
170
djsollen@google.com56c69772011-11-08 19:00:26 +0000171#ifdef SK_BUILD_FOR_ANDROID
djsollen@google.com57f49692011-02-23 20:46:31 +0000172void SkPixelRef::globalRef(void* data) {
173 this->ref();
174}
175
176void SkPixelRef::globalUnref() {
177 this->unref();
178}
reed@google.com93c5f9e2011-02-24 18:09:46 +0000179#endif