| Index: src/core/SkPixelRef.cpp
|
| diff --git a/src/core/SkPixelRef.cpp b/src/core/SkPixelRef.cpp
|
| index 560748c463c99dfa84cea4857085c6ff392261b8..bfee3bb549149c88bfd2846eab0b8a32857ee613 100644
|
| --- a/src/core/SkPixelRef.cpp
|
| +++ b/src/core/SkPixelRef.cpp
|
| @@ -56,15 +56,12 @@ static SkBaseMutex* get_default_mutex() {
|
|
|
| ///////////////////////////////////////////////////////////////////////////////
|
|
|
| -int32_t SkNextPixelRefGenerationID();
|
| -
|
| -int32_t SkNextPixelRefGenerationID() {
|
| - static int32_t gPixelRefGenerationID;
|
| - // do a loop in case our global wraps around, as we never want to
|
| - // return a 0
|
| - int32_t genID;
|
| +static uint32_t next_gen_id() {
|
| + static uint32_t gNextGenID = 0;
|
| + uint32_t genID;
|
| + // Loop in case our global wraps around, as we never want to return a 0.
|
| do {
|
| - genID = sk_atomic_inc(&gPixelRefGenerationID) + 1;
|
| + genID = sk_atomic_fetch_add(&gNextGenID, 2u) + 2; // Never set the low bit.
|
| } while (0 == genID);
|
| return genID;
|
| }
|
| @@ -90,7 +87,7 @@ static SkImageInfo validate_info(const SkImageInfo& info) {
|
| SkPixelRef::SkPixelRef(const SkImageInfo& info)
|
| : fInfo(validate_info(info))
|
| #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
|
| - , fStableID(SkNextPixelRefGenerationID())
|
| + , fStableID(next_gen_id())
|
| #endif
|
|
|
| {
|
| @@ -107,7 +104,7 @@ SkPixelRef::SkPixelRef(const SkImageInfo& info)
|
| SkPixelRef::SkPixelRef(const SkImageInfo& info, SkBaseMutex* mutex)
|
| : fInfo(validate_info(info))
|
| #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
|
| - , fStableID(SkNextPixelRefGenerationID())
|
| + , fStableID(next_gen_id())
|
| #endif
|
| {
|
| this->setMutex(mutex);
|
| @@ -124,15 +121,22 @@ SkPixelRef::~SkPixelRef() {
|
| }
|
|
|
| void SkPixelRef::needsNewGenID() {
|
| - fGenerationID.store(0);
|
| - fUniqueGenerationID.store(false);
|
| + fTaggedGenID.store(0);
|
| + SkASSERT(!this->genIDIsUnique()); // This method isn't threadsafe, so the assert should be fine.
|
| }
|
|
|
| void SkPixelRef::cloneGenID(const SkPixelRef& that) {
|
| // This is subtle. We must call that.getGenerationID() to make sure its genID isn't 0.
|
| - this->fGenerationID.store(that.getGenerationID());
|
| - this->fUniqueGenerationID.store(false);
|
| - that.fUniqueGenerationID.store(false);
|
| + uint32_t genID = that.getGenerationID();
|
| +
|
| + // Neither ID is unique any more.
|
| + // (These & ~1u are actually redundant. that.getGenerationID() just did it for us.)
|
| + this->fTaggedGenID.store(genID & ~1u);
|
| + that. fTaggedGenID.store(genID & ~1u);
|
| +
|
| + // This method isn't threadsafe, so these asserts should be fine.
|
| + SkASSERT(!this->genIDIsUnique());
|
| + SkASSERT(!that. genIDIsUnique());
|
| }
|
|
|
| void SkPixelRef::setPreLocked(void* pixels, size_t rowBytes, SkColorTable* ctable) {
|
| @@ -201,17 +205,17 @@ bool SkPixelRef::onLockPixelsAreWritable() const {
|
| }
|
|
|
| uint32_t SkPixelRef::getGenerationID() const {
|
| - uint32_t id = fGenerationID.load();
|
| + uint32_t id = fTaggedGenID.load();
|
| if (0 == id) {
|
| - id = SkNextPixelRefGenerationID();
|
| - fGenerationID.store(id);
|
| - fUniqueGenerationID.store(true); // The only time we can be sure of this!
|
| + id = next_gen_id();
|
| + fTaggedGenID.store(id | 1u); // TODO(mtklein): should become a compare-and-swap
|
| + SkASSERT(this->genIDIsUnique());
|
| }
|
| - return id;
|
| + return id & ~1u; // Mask off bottom unique bit.
|
| }
|
|
|
| void SkPixelRef::addGenIDChangeListener(GenIDChangeListener* listener) {
|
| - if (NULL == listener || !fUniqueGenerationID.load()) {
|
| + if (NULL == listener || !this->genIDIsUnique()) {
|
| // No point in tracking this if we're not going to call it.
|
| SkDELETE(listener);
|
| return;
|
| @@ -222,7 +226,7 @@ void SkPixelRef::addGenIDChangeListener(GenIDChangeListener* listener) {
|
| // we need to be called *before* the genID gets changed or zerod
|
| void SkPixelRef::callGenIDChangeListeners() {
|
| // We don't invalidate ourselves if we think another SkPixelRef is sharing our genID.
|
| - if (fUniqueGenerationID.load()) {
|
| + if (this->genIDIsUnique()) {
|
| for (int i = 0; i < fGenIDChangeListeners.count(); i++) {
|
| fGenIDChangeListeners[i]->onChange();
|
| }
|
|
|