1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2011 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "include/core/SkPixelRef.h" 9cb93a386Sopenharmony_ci#include "include/private/SkMutex.h" 10cb93a386Sopenharmony_ci#include "src/core/SkBitmapCache.h" 11cb93a386Sopenharmony_ci#include "src/core/SkNextID.h" 12cb93a386Sopenharmony_ci#include "src/core/SkPixelRefPriv.h" 13cb93a386Sopenharmony_ci#include "src/core/SkTraceEvent.h" 14cb93a386Sopenharmony_ci 15cb93a386Sopenharmony_ci#include <atomic> 16cb93a386Sopenharmony_ci 17cb93a386Sopenharmony_ciuint32_t SkNextID::ImageID() { 18cb93a386Sopenharmony_ci // We never set the low bit.... see SkPixelRef::genIDIsUnique(). 19cb93a386Sopenharmony_ci static std::atomic<uint32_t> nextID{2}; 20cb93a386Sopenharmony_ci 21cb93a386Sopenharmony_ci uint32_t id; 22cb93a386Sopenharmony_ci do { 23cb93a386Sopenharmony_ci id = nextID.fetch_add(2, std::memory_order_relaxed); 24cb93a386Sopenharmony_ci } while (id == 0); 25cb93a386Sopenharmony_ci return id; 26cb93a386Sopenharmony_ci} 27cb93a386Sopenharmony_ci 28cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 29cb93a386Sopenharmony_ci 30cb93a386Sopenharmony_ciSkPixelRef::SkPixelRef(int width, int height, void* pixels, size_t rowBytes) 31cb93a386Sopenharmony_ci : fWidth(width) 32cb93a386Sopenharmony_ci , fHeight(height) 33cb93a386Sopenharmony_ci , fPixels(pixels) 34cb93a386Sopenharmony_ci , fRowBytes(rowBytes) 35cb93a386Sopenharmony_ci , fAddedToCache(false) 36cb93a386Sopenharmony_ci{ 37cb93a386Sopenharmony_ci this->needsNewGenID(); 38cb93a386Sopenharmony_ci fMutability = kMutable; 39cb93a386Sopenharmony_ci} 40cb93a386Sopenharmony_ci 41cb93a386Sopenharmony_ciSkPixelRef::~SkPixelRef() { 42cb93a386Sopenharmony_ci this->callGenIDChangeListeners(); 43cb93a386Sopenharmony_ci} 44cb93a386Sopenharmony_ci 45cb93a386Sopenharmony_ci// This is undefined if there are clients in-flight trying to use us 46cb93a386Sopenharmony_civoid SkPixelRef::android_only_reset(int width, int height, size_t rowBytes) { 47cb93a386Sopenharmony_ci fWidth = width; 48cb93a386Sopenharmony_ci fHeight = height; 49cb93a386Sopenharmony_ci fRowBytes = rowBytes; 50cb93a386Sopenharmony_ci // note: we do not change fPixels 51cb93a386Sopenharmony_ci 52cb93a386Sopenharmony_ci // conservative, since its possible the "new" settings are the same as the old. 53cb93a386Sopenharmony_ci this->notifyPixelsChanged(); 54cb93a386Sopenharmony_ci} 55cb93a386Sopenharmony_ci 56cb93a386Sopenharmony_civoid SkPixelRef::needsNewGenID() { 57cb93a386Sopenharmony_ci fTaggedGenID.store(0); 58cb93a386Sopenharmony_ci SkASSERT(!this->genIDIsUnique()); // This method isn't threadsafe, so the assert should be fine. 59cb93a386Sopenharmony_ci} 60cb93a386Sopenharmony_ci 61cb93a386Sopenharmony_ciuint32_t SkPixelRef::getGenerationID() const { 62cb93a386Sopenharmony_ci uint32_t id = fTaggedGenID.load(); 63cb93a386Sopenharmony_ci if (0 == id) { 64cb93a386Sopenharmony_ci uint32_t next = SkNextID::ImageID() | 1u; 65cb93a386Sopenharmony_ci if (fTaggedGenID.compare_exchange_strong(id, next)) { 66cb93a386Sopenharmony_ci id = next; // There was no race or we won the race. fTaggedGenID is next now. 67cb93a386Sopenharmony_ci } else { 68cb93a386Sopenharmony_ci // We lost a race to set fTaggedGenID. compare_exchange() filled id with the winner. 69cb93a386Sopenharmony_ci } 70cb93a386Sopenharmony_ci // We can't quite SkASSERT(this->genIDIsUnique()). It could be non-unique 71cb93a386Sopenharmony_ci // if we got here via the else path (pretty unlikely, but possible). 72cb93a386Sopenharmony_ci } 73cb93a386Sopenharmony_ci return id & ~1u; // Mask off bottom unique bit. 74cb93a386Sopenharmony_ci} 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_civoid SkPixelRef::addGenIDChangeListener(sk_sp<SkIDChangeListener> listener) { 77cb93a386Sopenharmony_ci if (!listener || !this->genIDIsUnique()) { 78cb93a386Sopenharmony_ci // No point in tracking this if we're not going to call it. 79cb93a386Sopenharmony_ci return; 80cb93a386Sopenharmony_ci } 81cb93a386Sopenharmony_ci SkASSERT(!listener->shouldDeregister()); 82cb93a386Sopenharmony_ci fGenIDChangeListeners.add(std::move(listener)); 83cb93a386Sopenharmony_ci} 84cb93a386Sopenharmony_ci 85cb93a386Sopenharmony_ci// we need to be called *before* the genID gets changed or zerod 86cb93a386Sopenharmony_civoid SkPixelRef::callGenIDChangeListeners() { 87cb93a386Sopenharmony_ci // We don't invalidate ourselves if we think another SkPixelRef is sharing our genID. 88cb93a386Sopenharmony_ci if (this->genIDIsUnique()) { 89cb93a386Sopenharmony_ci fGenIDChangeListeners.changed(); 90cb93a386Sopenharmony_ci if (fAddedToCache.exchange(false)) { 91cb93a386Sopenharmony_ci SkNotifyBitmapGenIDIsStale(this->getGenerationID()); 92cb93a386Sopenharmony_ci } 93cb93a386Sopenharmony_ci } else { 94cb93a386Sopenharmony_ci // Listeners get at most one shot, so even though these weren't triggered or not, blow them 95cb93a386Sopenharmony_ci // away. 96cb93a386Sopenharmony_ci fGenIDChangeListeners.reset(); 97cb93a386Sopenharmony_ci } 98cb93a386Sopenharmony_ci} 99cb93a386Sopenharmony_ci 100cb93a386Sopenharmony_civoid SkPixelRef::notifyPixelsChanged() { 101cb93a386Sopenharmony_ci#ifdef SK_DEBUG 102cb93a386Sopenharmony_ci if (this->isImmutable()) { 103cb93a386Sopenharmony_ci SkDebugf("========== notifyPixelsChanged called on immutable pixelref"); 104cb93a386Sopenharmony_ci } 105cb93a386Sopenharmony_ci#endif 106cb93a386Sopenharmony_ci this->callGenIDChangeListeners(); 107cb93a386Sopenharmony_ci this->needsNewGenID(); 108cb93a386Sopenharmony_ci} 109cb93a386Sopenharmony_ci 110cb93a386Sopenharmony_civoid SkPixelRef::setImmutable() { 111cb93a386Sopenharmony_ci fMutability = kImmutable; 112cb93a386Sopenharmony_ci} 113cb93a386Sopenharmony_ci 114cb93a386Sopenharmony_civoid SkPixelRef::setImmutableWithID(uint32_t genID) { 115cb93a386Sopenharmony_ci /* 116cb93a386Sopenharmony_ci * We are forcing the genID to match an external value. The caller must ensure that this 117cb93a386Sopenharmony_ci * value does not conflict with other content. 118cb93a386Sopenharmony_ci * 119cb93a386Sopenharmony_ci * One use is to force this pixelref's id to match an SkImage's id 120cb93a386Sopenharmony_ci */ 121cb93a386Sopenharmony_ci fMutability = kImmutable; 122cb93a386Sopenharmony_ci fTaggedGenID.store(genID); 123cb93a386Sopenharmony_ci} 124cb93a386Sopenharmony_ci 125cb93a386Sopenharmony_civoid SkPixelRef::setTemporarilyImmutable() { 126cb93a386Sopenharmony_ci SkASSERT(fMutability != kImmutable); 127cb93a386Sopenharmony_ci fMutability = kTemporarilyImmutable; 128cb93a386Sopenharmony_ci} 129cb93a386Sopenharmony_ci 130cb93a386Sopenharmony_civoid SkPixelRef::restoreMutability() { 131cb93a386Sopenharmony_ci SkASSERT(fMutability != kImmutable); 132cb93a386Sopenharmony_ci fMutability = kMutable; 133cb93a386Sopenharmony_ci} 134cb93a386Sopenharmony_ci 135cb93a386Sopenharmony_cisk_sp<SkPixelRef> SkMakePixelRefWithProc(int width, int height, size_t rowBytes, void* addr, 136cb93a386Sopenharmony_ci void (*releaseProc)(void* addr, void* ctx), void* ctx) { 137cb93a386Sopenharmony_ci SkASSERT(width >= 0 && height >= 0); 138cb93a386Sopenharmony_ci if (nullptr == releaseProc) { 139cb93a386Sopenharmony_ci return sk_make_sp<SkPixelRef>(width, height, addr, rowBytes); 140cb93a386Sopenharmony_ci } 141cb93a386Sopenharmony_ci struct PixelRef final : public SkPixelRef { 142cb93a386Sopenharmony_ci void (*fReleaseProc)(void*, void*); 143cb93a386Sopenharmony_ci void* fReleaseProcContext; 144cb93a386Sopenharmony_ci PixelRef(int w, int h, void* s, size_t r, void (*proc)(void*, void*), void* ctx) 145cb93a386Sopenharmony_ci : SkPixelRef(w, h, s, r), fReleaseProc(proc), fReleaseProcContext(ctx) {} 146cb93a386Sopenharmony_ci ~PixelRef() override { fReleaseProc(this->pixels(), fReleaseProcContext); } 147cb93a386Sopenharmony_ci }; 148cb93a386Sopenharmony_ci return sk_sp<SkPixelRef>(new PixelRef(width, height, addr, rowBytes, releaseProc, ctx)); 149cb93a386Sopenharmony_ci} 150