GrGradientBitmapCache.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. /*
  2. * Copyright 2018 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 "src/gpu/gradients/GrGradientBitmapCache.h"
  8. #include "include/private/SkFloatBits.h"
  9. #include "include/private/SkHalf.h"
  10. #include "include/private/SkMalloc.h"
  11. #include "include/private/SkTemplates.h"
  12. #include <functional>
  13. struct GrGradientBitmapCache::Entry {
  14. Entry* fPrev;
  15. Entry* fNext;
  16. void* fBuffer;
  17. size_t fSize;
  18. SkBitmap fBitmap;
  19. Entry(const void* buffer, size_t size, const SkBitmap& bm)
  20. : fPrev(nullptr),
  21. fNext(nullptr),
  22. fBitmap(bm) {
  23. fBuffer = sk_malloc_throw(size);
  24. fSize = size;
  25. memcpy(fBuffer, buffer, size);
  26. }
  27. ~Entry() { sk_free(fBuffer); }
  28. bool equals(const void* buffer, size_t size) const {
  29. return (fSize == size) && !memcmp(fBuffer, buffer, size);
  30. }
  31. };
  32. GrGradientBitmapCache::GrGradientBitmapCache(int max, int res)
  33. : fMaxEntries(max)
  34. , fResolution(res) {
  35. fEntryCount = 0;
  36. fHead = fTail = nullptr;
  37. this->validate();
  38. }
  39. GrGradientBitmapCache::~GrGradientBitmapCache() {
  40. this->validate();
  41. Entry* entry = fHead;
  42. while (entry) {
  43. Entry* next = entry->fNext;
  44. delete entry;
  45. entry = next;
  46. }
  47. }
  48. GrGradientBitmapCache::Entry* GrGradientBitmapCache::release(Entry* entry) const {
  49. if (entry->fPrev) {
  50. SkASSERT(fHead != entry);
  51. entry->fPrev->fNext = entry->fNext;
  52. } else {
  53. SkASSERT(fHead == entry);
  54. fHead = entry->fNext;
  55. }
  56. if (entry->fNext) {
  57. SkASSERT(fTail != entry);
  58. entry->fNext->fPrev = entry->fPrev;
  59. } else {
  60. SkASSERT(fTail == entry);
  61. fTail = entry->fPrev;
  62. }
  63. return entry;
  64. }
  65. void GrGradientBitmapCache::attachToHead(Entry* entry) const {
  66. entry->fPrev = nullptr;
  67. entry->fNext = fHead;
  68. if (fHead) {
  69. fHead->fPrev = entry;
  70. } else {
  71. fTail = entry;
  72. }
  73. fHead = entry;
  74. }
  75. bool GrGradientBitmapCache::find(const void* buffer, size_t size, SkBitmap* bm) const {
  76. AutoValidate av(this);
  77. Entry* entry = fHead;
  78. while (entry) {
  79. if (entry->equals(buffer, size)) {
  80. if (bm) {
  81. *bm = entry->fBitmap;
  82. }
  83. // move to the head of our list, so we purge it last
  84. this->release(entry);
  85. this->attachToHead(entry);
  86. return true;
  87. }
  88. entry = entry->fNext;
  89. }
  90. return false;
  91. }
  92. void GrGradientBitmapCache::add(const void* buffer, size_t len, const SkBitmap& bm) {
  93. AutoValidate av(this);
  94. if (fEntryCount == fMaxEntries) {
  95. SkASSERT(fTail);
  96. delete this->release(fTail);
  97. fEntryCount -= 1;
  98. }
  99. Entry* entry = new Entry(buffer, len, bm);
  100. this->attachToHead(entry);
  101. fEntryCount += 1;
  102. }
  103. ///////////////////////////////////////////////////////////////////////////////
  104. void GrGradientBitmapCache::fillGradient(const SkPMColor4f* colors, const SkScalar* positions,
  105. int count, SkColorType colorType, SkBitmap* bitmap) {
  106. SkHalf* pixelsF16 = reinterpret_cast<SkHalf*>(bitmap->getPixels());
  107. uint32_t* pixels32 = reinterpret_cast<uint32_t*>(bitmap->getPixels());
  108. typedef std::function<void(const Sk4f&, int)> pixelWriteFn_t;
  109. pixelWriteFn_t writeF16Pixel = [&](const Sk4f& x, int index) {
  110. Sk4h c = SkFloatToHalf_finite_ftz(x);
  111. pixelsF16[4*index+0] = c[0];
  112. pixelsF16[4*index+1] = c[1];
  113. pixelsF16[4*index+2] = c[2];
  114. pixelsF16[4*index+3] = c[3];
  115. };
  116. pixelWriteFn_t write8888Pixel = [&](const Sk4f& c, int index) {
  117. pixels32[index] = Sk4f_toL32(c);
  118. };
  119. pixelWriteFn_t writePixel =
  120. (colorType == kRGBA_F16_SkColorType) ? writeF16Pixel : write8888Pixel;
  121. int prevIndex = 0;
  122. for (int i = 1; i < count; i++) {
  123. // Historically, stops have been mapped to [0, 256], with 256 then nudged to the next
  124. // smaller value, then truncate for the texture index. This seems to produce the best
  125. // results for some common distributions, so we preserve the behavior.
  126. int nextIndex = SkTMin(positions[i] * fResolution,
  127. SkIntToScalar(fResolution - 1));
  128. if (nextIndex > prevIndex) {
  129. Sk4f c0 = Sk4f::Load(colors[i - 1].vec()),
  130. c1 = Sk4f::Load(colors[i ].vec());
  131. Sk4f step = Sk4f(1.0f / static_cast<float>(nextIndex - prevIndex));
  132. Sk4f delta = (c1 - c0) * step;
  133. for (int curIndex = prevIndex; curIndex <= nextIndex; ++curIndex) {
  134. writePixel(c0, curIndex);
  135. c0 += delta;
  136. }
  137. }
  138. prevIndex = nextIndex;
  139. }
  140. SkASSERT(prevIndex == fResolution - 1);
  141. }
  142. void GrGradientBitmapCache::getGradient(const SkPMColor4f* colors, const SkScalar* positions,
  143. int count, SkColorType colorType, SkAlphaType alphaType, SkBitmap* bitmap) {
  144. // build our key: [numColors + colors[] + positions[] + alphaType + colorType ]
  145. static_assert(sizeof(SkPMColor4f) % sizeof(int32_t) == 0, "");
  146. const int colorsAsIntCount = count * sizeof(SkPMColor4f) / sizeof(int32_t);
  147. int keyCount = 1 + colorsAsIntCount + 1 + 1;
  148. if (count > 2) {
  149. keyCount += count - 1;
  150. }
  151. SkAutoSTMalloc<64, int32_t> storage(keyCount);
  152. int32_t* buffer = storage.get();
  153. *buffer++ = count;
  154. memcpy(buffer, colors, count * sizeof(SkPMColor4f));
  155. buffer += colorsAsIntCount;
  156. if (count > 2) {
  157. for (int i = 1; i < count; i++) {
  158. *buffer++ = SkFloat2Bits(positions[i]);
  159. }
  160. }
  161. *buffer++ = static_cast<int32_t>(alphaType);
  162. *buffer++ = static_cast<int32_t>(colorType);
  163. SkASSERT(buffer - storage.get() == keyCount);
  164. ///////////////////////////////////
  165. // acquire lock for checking/adding to cache
  166. SkAutoMutexExclusive ama(fMutex);
  167. size_t size = keyCount * sizeof(int32_t);
  168. if (!this->find(storage.get(), size, bitmap)) {
  169. SkImageInfo info = SkImageInfo::Make(fResolution, 1, colorType, alphaType);
  170. bitmap->allocPixels(info);
  171. GrGradientBitmapCache::fillGradient(colors, positions, count, colorType, bitmap);
  172. bitmap->setImmutable();
  173. this->add(storage.get(), size, *bitmap);
  174. }
  175. }
  176. ///////////////////////////////////////////////////////////////////////////////
  177. #ifdef SK_DEBUG
  178. void GrGradientBitmapCache::validate() const {
  179. SkASSERT(fEntryCount >= 0 && fEntryCount <= fMaxEntries);
  180. if (fEntryCount > 0) {
  181. SkASSERT(nullptr == fHead->fPrev);
  182. SkASSERT(nullptr == fTail->fNext);
  183. if (fEntryCount == 1) {
  184. SkASSERT(fHead == fTail);
  185. } else {
  186. SkASSERT(fHead != fTail);
  187. }
  188. Entry* entry = fHead;
  189. int count = 0;
  190. while (entry) {
  191. count += 1;
  192. entry = entry->fNext;
  193. }
  194. SkASSERT(count == fEntryCount);
  195. entry = fTail;
  196. while (entry) {
  197. count -= 1;
  198. entry = entry->fPrev;
  199. }
  200. SkASSERT(0 == count);
  201. } else {
  202. SkASSERT(nullptr == fHead);
  203. SkASSERT(nullptr == fTail);
  204. }
  205. }
  206. #endif