SkPixelRef.cpp 4.0 KB

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