Flutter Engine
The Flutter Engine
GrGradientBitmapCache.cpp
Go to the documentation of this file.
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
8
10
14#include "src/base/SkHalf.h"
18
19#include <functional>
20
21using namespace skia_private;
22
26
27 void* fBuffer;
28 size_t fSize;
30
31 Entry(const void* buffer, size_t size, const SkBitmap& bm)
32 : fPrev(nullptr),
33 fNext(nullptr),
34 fBitmap(bm) {
36 fSize = size;
37 memcpy(fBuffer, buffer, size);
38 }
39
41
42 bool equals(const void* buffer, size_t size) const {
43 return (fSize == size) && !memcmp(fBuffer, buffer, size);
44 }
45};
46
48 : fMaxEntries(max)
49 , fResolution(res) {
50 fEntryCount = 0;
51 fHead = fTail = nullptr;
52
53 this->validate();
54}
55
57 this->validate();
58
59 Entry* entry = fHead;
60 while (entry) {
61 Entry* next = entry->fNext;
62 delete entry;
63 entry = next;
64 }
65}
66
67GrGradientBitmapCache::Entry* GrGradientBitmapCache::release(Entry* entry) const {
68 if (entry->fPrev) {
69 SkASSERT(fHead != entry);
70 entry->fPrev->fNext = entry->fNext;
71 } else {
72 SkASSERT(fHead == entry);
73 fHead = entry->fNext;
74 }
75 if (entry->fNext) {
76 SkASSERT(fTail != entry);
77 entry->fNext->fPrev = entry->fPrev;
78 } else {
79 SkASSERT(fTail == entry);
80 fTail = entry->fPrev;
81 }
82 return entry;
83}
84
85void GrGradientBitmapCache::attachToHead(Entry* entry) const {
86 entry->fPrev = nullptr;
87 entry->fNext = fHead;
88 if (fHead) {
89 fHead->fPrev = entry;
90 } else {
91 fTail = entry;
92 }
93 fHead = entry;
94}
95
96bool GrGradientBitmapCache::find(const void* buffer, size_t size, SkBitmap* bm) const {
97 AutoValidate av(this);
98
99 Entry* entry = fHead;
100 while (entry) {
101 if (entry->equals(buffer, size)) {
102 if (bm) {
103 *bm = entry->fBitmap;
104 }
105 // move to the head of our list, so we purge it last
106 this->release(entry);
107 this->attachToHead(entry);
108 return true;
109 }
110 entry = entry->fNext;
111 }
112 return false;
113}
114
115void GrGradientBitmapCache::add(const void* buffer, size_t len, const SkBitmap& bm) {
116 AutoValidate av(this);
117
118 if (fEntryCount == fMaxEntries) {
119 SkASSERT(fTail);
120 delete this->release(fTail);
121 fEntryCount -= 1;
122 }
123
124 Entry* entry = new Entry(buffer, len, bm);
125 this->attachToHead(entry);
126 fEntryCount += 1;
127}
128
129///////////////////////////////////////////////////////////////////////////////
130
131void GrGradientBitmapCache::fillGradient(const SkPMColor4f* colors,
132 const SkScalar* positions,
133 int count,
134 bool colorsAreOpaque,
135 const SkGradientShader::Interpolation& interpolation,
136 const SkColorSpace* intermediateColorSpace,
137 const SkColorSpace* dstColorSpace,
138 SkBitmap* bitmap) {
139 SkArenaAlloc alloc(/*firstHeapAllocation=*/0);
140 SkRasterPipeline p(&alloc);
141 SkRasterPipeline_MemoryCtx ctx = { bitmap->getPixels(), 0 };
142
143 p.append(SkRasterPipelineOp::seed_shader);
144 p.appendMatrix(&alloc, SkMatrix::Scale(1.0f / bitmap->width(), 1.0f));
147 &p, &alloc, colorsAreOpaque, interpolation, intermediateColorSpace, dstColorSpace);
148 p.appendStore(bitmap->colorType(), &ctx);
149 p.run(0, 0, bitmap->width(), 1);
150}
151
153 const SkScalar* positions,
154 int count,
155 bool colorsAreOpaque,
156 const SkGradientShader::Interpolation& interpolation,
157 const SkColorSpace* intermediateColorSpace,
158 const SkColorSpace* dstColorSpace,
160 SkAlphaType alphaType,
161 SkBitmap* bitmap) {
162 // Build our key:
163 // [numColors + colors[] + positions[] + alphaType + colorType + interpolation + dstColorSpace]
164 // NOTE: colorsAreOpaque is redundant with the actual colors. intermediateColorSpace is fully
165 // determined by interpolation and dstColorSpace.
166 static_assert(sizeof(SkPMColor4f) % sizeof(int32_t) == 0, "");
167 const int colorsAsIntCount = count * sizeof(SkPMColor4f) / sizeof(int32_t);
168 SkASSERT(count > 2); // Otherwise, we should have used the single-interval colorizer
169 const int keyCount = 1 + // count
170 colorsAsIntCount + // colors
171 (count - 2) + // positions
172 1 + // alphaType
173 1 + // colorType
174 3 + // interpolation
175 (dstColorSpace ? 2 : 0); // dstColorSpace
176
177 AutoSTMalloc<64, int32_t> storage(keyCount);
178 int32_t* buffer = storage.get();
179
180 *buffer++ = count;
181 memcpy(buffer, colors, count * sizeof(SkPMColor4f));
182 buffer += colorsAsIntCount;
183 for (int i = 1; i < count - 1; i++) {
184 *buffer++ = SkFloat2Bits(positions[i]);
185 }
186 *buffer++ = static_cast<int32_t>(alphaType);
187 *buffer++ = static_cast<int32_t>(colorType);
188 *buffer++ = static_cast<int32_t>(interpolation.fInPremul);
189 *buffer++ = static_cast<int32_t>(interpolation.fColorSpace);
190 *buffer++ = static_cast<int32_t>(interpolation.fHueMethod);
191 if (dstColorSpace) {
192 *buffer++ = dstColorSpace->toXYZD50Hash();
193 *buffer++ = dstColorSpace->transferFnHash();
194 }
195 SkASSERT(buffer - storage.get() == keyCount);
196
197 ///////////////////////////////////
198
199 // acquire lock for checking/adding to cache
200 SkAutoMutexExclusive ama(fMutex);
201 size_t size = keyCount * sizeof(int32_t);
202 if (!this->find(storage.get(), size, bitmap)) {
203 SkImageInfo info = SkImageInfo::Make(fResolution, 1, colorType, alphaType);
204 bitmap->allocPixels(info);
205 this->fillGradient(colors,
206 positions,
207 count,
208 colorsAreOpaque,
209 interpolation,
210 intermediateColorSpace,
211 dstColorSpace,
212 bitmap);
213 bitmap->setImmutable();
214 this->add(storage.get(), size, *bitmap);
215 }
216}
217
218///////////////////////////////////////////////////////////////////////////////
219
220#ifdef SK_DEBUG
221
222void GrGradientBitmapCache::validate() const {
223 SkASSERT(fEntryCount >= 0 && fEntryCount <= fMaxEntries);
224
225 if (fEntryCount > 0) {
226 SkASSERT(nullptr == fHead->fPrev);
227 SkASSERT(nullptr == fTail->fNext);
228
229 if (fEntryCount == 1) {
230 SkASSERT(fHead == fTail);
231 } else {
232 SkASSERT(fHead != fTail);
233 }
234
235 Entry* entry = fHead;
236 int count = 0;
237 while (entry) {
238 count += 1;
239 entry = entry->fNext;
240 }
241 SkASSERT(count == fEntryCount);
242
243 entry = fTail;
244 while (entry) {
245 count -= 1;
246 entry = entry->fPrev;
247 }
248 SkASSERT(0 == count);
249 } else {
250 SkASSERT(nullptr == fHead);
251 SkASSERT(nullptr == fTail);
252 }
253}
254
255#endif
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
int count
Definition: FontMgrTest.cpp:50
static float next(float f)
SkAlphaType
Definition: SkAlphaType.h:26
#define SkASSERT(cond)
Definition: SkAssert.h:116
SkRGBA4f< kPremul_SkAlphaType > SkPMColor4f
Definition: SkColorData.h:376
SkColorType
Definition: SkColorType.h:19
static uint32_t SkFloat2Bits(float value)
Definition: SkFloatBits.h:41
static SkColorType colorType(AImageDecoder *decoder, const AImageDecoderHeaderInfo *headerInfo)
SK_API void sk_free(void *)
static void * sk_malloc_throw(size_t size)
Definition: SkMalloc.h:67
void getGradient(const SkPMColor4f *colors, const SkScalar *positions, int count, bool colorsAreOpaque, const SkGradientShader::Interpolation &interpolation, const SkColorSpace *intermediateColorSpace, const SkColorSpace *dstColorSpace, SkColorType colorType, SkAlphaType alphaType, SkBitmap *bitmap)
GrGradientBitmapCache(int maxEntries, int resolution)
uint32_t toXYZD50Hash() const
Definition: SkColorSpace.h:161
uint32_t transferFnHash() const
Definition: SkColorSpace.h:221
static void AppendGradientFillStages(SkRasterPipeline *p, SkArenaAlloc *alloc, const SkPMColor4f *colors, const SkScalar *positions, int count)
static void AppendInterpolatedToDstStages(SkRasterPipeline *p, SkArenaAlloc *alloc, bool colorsAreOpaque, const Interpolation &interpolation, const SkColorSpace *intermediateColorSpace, const SkColorSpace *dstColorSpace)
static SkMatrix Scale(SkScalar sx, SkScalar sy)
Definition: SkMatrix.h:75
float SkScalar
Definition: extension.cpp:12
static float max(float r, float g, float b)
Definition: hsl.cpp:49
PODArray< SkColor > colors
Definition: SkRecords.h:276
Definition: bitmap.py:1
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
bool equals(const void *buffer, size_t size) const
Entry(const void *buffer, size_t size, const SkBitmap &bm)
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)