xref: /aosp_15_r20/external/skia/src/gpu/ganesh/gradients/GrGradientBitmapCache.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2018 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/gradients/GrGradientBitmapCache.h"
8*c8dee2aaSAndroid Build Coastguard Worker 
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkAlphaType.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBitmap.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorSpace.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImageInfo.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkMatrix.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkMalloc.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTemplates.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkArenaAlloc.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkFloatBits.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkRasterPipeline.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkRasterPipelineOpContexts.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkRasterPipelineOpList.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "src/shaders/gradients/SkGradientBaseShader.h"
23*c8dee2aaSAndroid Build Coastguard Worker 
24*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint>
25*c8dee2aaSAndroid Build Coastguard Worker #include <cstring>
26*c8dee2aaSAndroid Build Coastguard Worker 
27*c8dee2aaSAndroid Build Coastguard Worker using namespace skia_private;
28*c8dee2aaSAndroid Build Coastguard Worker 
29*c8dee2aaSAndroid Build Coastguard Worker struct GrGradientBitmapCache::Entry {
30*c8dee2aaSAndroid Build Coastguard Worker     Entry*      fPrev;
31*c8dee2aaSAndroid Build Coastguard Worker     Entry*      fNext;
32*c8dee2aaSAndroid Build Coastguard Worker 
33*c8dee2aaSAndroid Build Coastguard Worker     void*       fBuffer;
34*c8dee2aaSAndroid Build Coastguard Worker     size_t      fSize;
35*c8dee2aaSAndroid Build Coastguard Worker     SkBitmap    fBitmap;
36*c8dee2aaSAndroid Build Coastguard Worker 
EntryGrGradientBitmapCache::Entry37*c8dee2aaSAndroid Build Coastguard Worker     Entry(const void* buffer, size_t size, const SkBitmap& bm)
38*c8dee2aaSAndroid Build Coastguard Worker             : fPrev(nullptr),
39*c8dee2aaSAndroid Build Coastguard Worker               fNext(nullptr),
40*c8dee2aaSAndroid Build Coastguard Worker               fBitmap(bm) {
41*c8dee2aaSAndroid Build Coastguard Worker         fBuffer = sk_malloc_throw(size);
42*c8dee2aaSAndroid Build Coastguard Worker         fSize = size;
43*c8dee2aaSAndroid Build Coastguard Worker         memcpy(fBuffer, buffer, size);
44*c8dee2aaSAndroid Build Coastguard Worker     }
45*c8dee2aaSAndroid Build Coastguard Worker 
~EntryGrGradientBitmapCache::Entry46*c8dee2aaSAndroid Build Coastguard Worker     ~Entry() { sk_free(fBuffer); }
47*c8dee2aaSAndroid Build Coastguard Worker 
equalsGrGradientBitmapCache::Entry48*c8dee2aaSAndroid Build Coastguard Worker     bool equals(const void* buffer, size_t size) const {
49*c8dee2aaSAndroid Build Coastguard Worker         return (fSize == size) && !memcmp(fBuffer, buffer, size);
50*c8dee2aaSAndroid Build Coastguard Worker     }
51*c8dee2aaSAndroid Build Coastguard Worker };
52*c8dee2aaSAndroid Build Coastguard Worker 
GrGradientBitmapCache(int max,int res)53*c8dee2aaSAndroid Build Coastguard Worker GrGradientBitmapCache::GrGradientBitmapCache(int max, int res)
54*c8dee2aaSAndroid Build Coastguard Worker         : fMaxEntries(max)
55*c8dee2aaSAndroid Build Coastguard Worker         , fResolution(res) {
56*c8dee2aaSAndroid Build Coastguard Worker     fEntryCount = 0;
57*c8dee2aaSAndroid Build Coastguard Worker     fHead = fTail = nullptr;
58*c8dee2aaSAndroid Build Coastguard Worker 
59*c8dee2aaSAndroid Build Coastguard Worker     this->validate();
60*c8dee2aaSAndroid Build Coastguard Worker }
61*c8dee2aaSAndroid Build Coastguard Worker 
~GrGradientBitmapCache()62*c8dee2aaSAndroid Build Coastguard Worker GrGradientBitmapCache::~GrGradientBitmapCache() {
63*c8dee2aaSAndroid Build Coastguard Worker     this->validate();
64*c8dee2aaSAndroid Build Coastguard Worker 
65*c8dee2aaSAndroid Build Coastguard Worker     Entry* entry = fHead;
66*c8dee2aaSAndroid Build Coastguard Worker     while (entry) {
67*c8dee2aaSAndroid Build Coastguard Worker         Entry* next = entry->fNext;
68*c8dee2aaSAndroid Build Coastguard Worker         delete entry;
69*c8dee2aaSAndroid Build Coastguard Worker         entry = next;
70*c8dee2aaSAndroid Build Coastguard Worker     }
71*c8dee2aaSAndroid Build Coastguard Worker }
72*c8dee2aaSAndroid Build Coastguard Worker 
release(Entry * entry) const73*c8dee2aaSAndroid Build Coastguard Worker GrGradientBitmapCache::Entry* GrGradientBitmapCache::release(Entry* entry) const {
74*c8dee2aaSAndroid Build Coastguard Worker     if (entry->fPrev) {
75*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(fHead != entry);
76*c8dee2aaSAndroid Build Coastguard Worker         entry->fPrev->fNext = entry->fNext;
77*c8dee2aaSAndroid Build Coastguard Worker     } else {
78*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(fHead == entry);
79*c8dee2aaSAndroid Build Coastguard Worker         fHead = entry->fNext;
80*c8dee2aaSAndroid Build Coastguard Worker     }
81*c8dee2aaSAndroid Build Coastguard Worker     if (entry->fNext) {
82*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(fTail != entry);
83*c8dee2aaSAndroid Build Coastguard Worker         entry->fNext->fPrev = entry->fPrev;
84*c8dee2aaSAndroid Build Coastguard Worker     } else {
85*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(fTail == entry);
86*c8dee2aaSAndroid Build Coastguard Worker         fTail = entry->fPrev;
87*c8dee2aaSAndroid Build Coastguard Worker     }
88*c8dee2aaSAndroid Build Coastguard Worker     return entry;
89*c8dee2aaSAndroid Build Coastguard Worker }
90*c8dee2aaSAndroid Build Coastguard Worker 
attachToHead(Entry * entry) const91*c8dee2aaSAndroid Build Coastguard Worker void GrGradientBitmapCache::attachToHead(Entry* entry) const {
92*c8dee2aaSAndroid Build Coastguard Worker     entry->fPrev = nullptr;
93*c8dee2aaSAndroid Build Coastguard Worker     entry->fNext = fHead;
94*c8dee2aaSAndroid Build Coastguard Worker     if (fHead) {
95*c8dee2aaSAndroid Build Coastguard Worker         fHead->fPrev = entry;
96*c8dee2aaSAndroid Build Coastguard Worker     } else {
97*c8dee2aaSAndroid Build Coastguard Worker         fTail = entry;
98*c8dee2aaSAndroid Build Coastguard Worker     }
99*c8dee2aaSAndroid Build Coastguard Worker     fHead = entry;
100*c8dee2aaSAndroid Build Coastguard Worker }
101*c8dee2aaSAndroid Build Coastguard Worker 
find(const void * buffer,size_t size,SkBitmap * bm) const102*c8dee2aaSAndroid Build Coastguard Worker bool GrGradientBitmapCache::find(const void* buffer, size_t size, SkBitmap* bm) const {
103*c8dee2aaSAndroid Build Coastguard Worker     AutoValidate av(this);
104*c8dee2aaSAndroid Build Coastguard Worker 
105*c8dee2aaSAndroid Build Coastguard Worker     Entry* entry = fHead;
106*c8dee2aaSAndroid Build Coastguard Worker     while (entry) {
107*c8dee2aaSAndroid Build Coastguard Worker         if (entry->equals(buffer, size)) {
108*c8dee2aaSAndroid Build Coastguard Worker             if (bm) {
109*c8dee2aaSAndroid Build Coastguard Worker                 *bm = entry->fBitmap;
110*c8dee2aaSAndroid Build Coastguard Worker             }
111*c8dee2aaSAndroid Build Coastguard Worker             // move to the head of our list, so we purge it last
112*c8dee2aaSAndroid Build Coastguard Worker             this->release(entry);
113*c8dee2aaSAndroid Build Coastguard Worker             this->attachToHead(entry);
114*c8dee2aaSAndroid Build Coastguard Worker             return true;
115*c8dee2aaSAndroid Build Coastguard Worker         }
116*c8dee2aaSAndroid Build Coastguard Worker         entry = entry->fNext;
117*c8dee2aaSAndroid Build Coastguard Worker     }
118*c8dee2aaSAndroid Build Coastguard Worker     return false;
119*c8dee2aaSAndroid Build Coastguard Worker }
120*c8dee2aaSAndroid Build Coastguard Worker 
add(const void * buffer,size_t len,const SkBitmap & bm)121*c8dee2aaSAndroid Build Coastguard Worker void GrGradientBitmapCache::add(const void* buffer, size_t len, const SkBitmap& bm) {
122*c8dee2aaSAndroid Build Coastguard Worker     AutoValidate av(this);
123*c8dee2aaSAndroid Build Coastguard Worker 
124*c8dee2aaSAndroid Build Coastguard Worker     if (fEntryCount == fMaxEntries) {
125*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(fTail);
126*c8dee2aaSAndroid Build Coastguard Worker         delete this->release(fTail);
127*c8dee2aaSAndroid Build Coastguard Worker         fEntryCount -= 1;
128*c8dee2aaSAndroid Build Coastguard Worker     }
129*c8dee2aaSAndroid Build Coastguard Worker 
130*c8dee2aaSAndroid Build Coastguard Worker     Entry* entry = new Entry(buffer, len, bm);
131*c8dee2aaSAndroid Build Coastguard Worker     this->attachToHead(entry);
132*c8dee2aaSAndroid Build Coastguard Worker     fEntryCount += 1;
133*c8dee2aaSAndroid Build Coastguard Worker }
134*c8dee2aaSAndroid Build Coastguard Worker 
135*c8dee2aaSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
136*c8dee2aaSAndroid Build Coastguard Worker 
fillGradient(const SkPMColor4f * colors,const SkScalar * positions,int count,bool colorsAreOpaque,const SkGradientShader::Interpolation & interpolation,const SkColorSpace * intermediateColorSpace,const SkColorSpace * dstColorSpace,SkBitmap * bitmap)137*c8dee2aaSAndroid Build Coastguard Worker void GrGradientBitmapCache::fillGradient(const SkPMColor4f* colors,
138*c8dee2aaSAndroid Build Coastguard Worker                                          const SkScalar* positions,
139*c8dee2aaSAndroid Build Coastguard Worker                                          int count,
140*c8dee2aaSAndroid Build Coastguard Worker                                          bool colorsAreOpaque,
141*c8dee2aaSAndroid Build Coastguard Worker                                          const SkGradientShader::Interpolation& interpolation,
142*c8dee2aaSAndroid Build Coastguard Worker                                          const SkColorSpace* intermediateColorSpace,
143*c8dee2aaSAndroid Build Coastguard Worker                                          const SkColorSpace* dstColorSpace,
144*c8dee2aaSAndroid Build Coastguard Worker                                          SkBitmap* bitmap) {
145*c8dee2aaSAndroid Build Coastguard Worker     SkArenaAlloc alloc(/*firstHeapAllocation=*/0);
146*c8dee2aaSAndroid Build Coastguard Worker     SkRasterPipeline p(&alloc);
147*c8dee2aaSAndroid Build Coastguard Worker     SkRasterPipeline_MemoryCtx ctx = { bitmap->getPixels(), 0 };
148*c8dee2aaSAndroid Build Coastguard Worker 
149*c8dee2aaSAndroid Build Coastguard Worker     p.append(SkRasterPipelineOp::seed_shader);
150*c8dee2aaSAndroid Build Coastguard Worker     p.appendMatrix(&alloc, SkMatrix::Scale(1.0f / bitmap->width(), 1.0f));
151*c8dee2aaSAndroid Build Coastguard Worker     SkGradientBaseShader::AppendGradientFillStages(&p, &alloc, colors, positions, count);
152*c8dee2aaSAndroid Build Coastguard Worker     SkGradientBaseShader::AppendInterpolatedToDstStages(
153*c8dee2aaSAndroid Build Coastguard Worker             &p, &alloc, colorsAreOpaque, interpolation, intermediateColorSpace, dstColorSpace);
154*c8dee2aaSAndroid Build Coastguard Worker     p.appendStore(bitmap->colorType(), &ctx);
155*c8dee2aaSAndroid Build Coastguard Worker     p.run(0, 0, bitmap->width(), 1);
156*c8dee2aaSAndroid Build Coastguard Worker }
157*c8dee2aaSAndroid Build Coastguard Worker 
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)158*c8dee2aaSAndroid Build Coastguard Worker void GrGradientBitmapCache::getGradient(const SkPMColor4f* colors,
159*c8dee2aaSAndroid Build Coastguard Worker                                         const SkScalar* positions,
160*c8dee2aaSAndroid Build Coastguard Worker                                         int count,
161*c8dee2aaSAndroid Build Coastguard Worker                                         bool colorsAreOpaque,
162*c8dee2aaSAndroid Build Coastguard Worker                                         const SkGradientShader::Interpolation& interpolation,
163*c8dee2aaSAndroid Build Coastguard Worker                                         const SkColorSpace* intermediateColorSpace,
164*c8dee2aaSAndroid Build Coastguard Worker                                         const SkColorSpace* dstColorSpace,
165*c8dee2aaSAndroid Build Coastguard Worker                                         SkColorType colorType,
166*c8dee2aaSAndroid Build Coastguard Worker                                         SkAlphaType alphaType,
167*c8dee2aaSAndroid Build Coastguard Worker                                         SkBitmap* bitmap) {
168*c8dee2aaSAndroid Build Coastguard Worker     // Build our key:
169*c8dee2aaSAndroid Build Coastguard Worker     // [numColors + colors[] + positions[] + alphaType + colorType + interpolation + dstColorSpace]
170*c8dee2aaSAndroid Build Coastguard Worker     // NOTE: colorsAreOpaque is redundant with the actual colors. intermediateColorSpace is fully
171*c8dee2aaSAndroid Build Coastguard Worker     //       determined by interpolation and dstColorSpace.
172*c8dee2aaSAndroid Build Coastguard Worker     static_assert(sizeof(SkPMColor4f) % sizeof(int32_t) == 0, "");
173*c8dee2aaSAndroid Build Coastguard Worker     const int colorsAsIntCount = count * sizeof(SkPMColor4f) / sizeof(int32_t);
174*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(count > 2);  // Otherwise, we should have used the single-interval colorizer
175*c8dee2aaSAndroid Build Coastguard Worker     const int keyCount = 1 +                      // count
176*c8dee2aaSAndroid Build Coastguard Worker                          colorsAsIntCount +       // colors
177*c8dee2aaSAndroid Build Coastguard Worker                          (count - 2) +            // positions
178*c8dee2aaSAndroid Build Coastguard Worker                          1 +                      // alphaType
179*c8dee2aaSAndroid Build Coastguard Worker                          1 +                      // colorType
180*c8dee2aaSAndroid Build Coastguard Worker                          3 +                      // interpolation
181*c8dee2aaSAndroid Build Coastguard Worker                          (dstColorSpace ? 2 : 0); // dstColorSpace
182*c8dee2aaSAndroid Build Coastguard Worker 
183*c8dee2aaSAndroid Build Coastguard Worker     AutoSTMalloc<64, int32_t> storage(keyCount);
184*c8dee2aaSAndroid Build Coastguard Worker     int32_t* buffer = storage.get();
185*c8dee2aaSAndroid Build Coastguard Worker 
186*c8dee2aaSAndroid Build Coastguard Worker     *buffer++ = count;
187*c8dee2aaSAndroid Build Coastguard Worker     memcpy(buffer, colors, count * sizeof(SkPMColor4f));
188*c8dee2aaSAndroid Build Coastguard Worker     buffer += colorsAsIntCount;
189*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 1; i < count - 1; i++) {
190*c8dee2aaSAndroid Build Coastguard Worker         *buffer++ = SkFloat2Bits(positions[i]);
191*c8dee2aaSAndroid Build Coastguard Worker     }
192*c8dee2aaSAndroid Build Coastguard Worker     *buffer++ = static_cast<int32_t>(alphaType);
193*c8dee2aaSAndroid Build Coastguard Worker     *buffer++ = static_cast<int32_t>(colorType);
194*c8dee2aaSAndroid Build Coastguard Worker     *buffer++ = static_cast<int32_t>(interpolation.fInPremul);
195*c8dee2aaSAndroid Build Coastguard Worker     *buffer++ = static_cast<int32_t>(interpolation.fColorSpace);
196*c8dee2aaSAndroid Build Coastguard Worker     *buffer++ = static_cast<int32_t>(interpolation.fHueMethod);
197*c8dee2aaSAndroid Build Coastguard Worker     if (dstColorSpace) {
198*c8dee2aaSAndroid Build Coastguard Worker         *buffer++ = dstColorSpace->toXYZD50Hash();
199*c8dee2aaSAndroid Build Coastguard Worker         *buffer++ = dstColorSpace->transferFnHash();
200*c8dee2aaSAndroid Build Coastguard Worker     }
201*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(buffer - storage.get() == keyCount);
202*c8dee2aaSAndroid Build Coastguard Worker 
203*c8dee2aaSAndroid Build Coastguard Worker     ///////////////////////////////////
204*c8dee2aaSAndroid Build Coastguard Worker 
205*c8dee2aaSAndroid Build Coastguard Worker     // acquire lock for checking/adding to cache
206*c8dee2aaSAndroid Build Coastguard Worker     SkAutoMutexExclusive ama(fMutex);
207*c8dee2aaSAndroid Build Coastguard Worker     size_t size = keyCount * sizeof(int32_t);
208*c8dee2aaSAndroid Build Coastguard Worker     if (!this->find(storage.get(), size, bitmap)) {
209*c8dee2aaSAndroid Build Coastguard Worker         SkImageInfo info = SkImageInfo::Make(fResolution, 1, colorType, alphaType);
210*c8dee2aaSAndroid Build Coastguard Worker         bitmap->allocPixels(info);
211*c8dee2aaSAndroid Build Coastguard Worker         this->fillGradient(colors,
212*c8dee2aaSAndroid Build Coastguard Worker                            positions,
213*c8dee2aaSAndroid Build Coastguard Worker                            count,
214*c8dee2aaSAndroid Build Coastguard Worker                            colorsAreOpaque,
215*c8dee2aaSAndroid Build Coastguard Worker                            interpolation,
216*c8dee2aaSAndroid Build Coastguard Worker                            intermediateColorSpace,
217*c8dee2aaSAndroid Build Coastguard Worker                            dstColorSpace,
218*c8dee2aaSAndroid Build Coastguard Worker                            bitmap);
219*c8dee2aaSAndroid Build Coastguard Worker         bitmap->setImmutable();
220*c8dee2aaSAndroid Build Coastguard Worker         this->add(storage.get(), size, *bitmap);
221*c8dee2aaSAndroid Build Coastguard Worker     }
222*c8dee2aaSAndroid Build Coastguard Worker }
223*c8dee2aaSAndroid Build Coastguard Worker 
224*c8dee2aaSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
225*c8dee2aaSAndroid Build Coastguard Worker 
226*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
227*c8dee2aaSAndroid Build Coastguard Worker 
validate() const228*c8dee2aaSAndroid Build Coastguard Worker void GrGradientBitmapCache::validate() const {
229*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(fEntryCount >= 0 && fEntryCount <= fMaxEntries);
230*c8dee2aaSAndroid Build Coastguard Worker 
231*c8dee2aaSAndroid Build Coastguard Worker     if (fEntryCount > 0) {
232*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(nullptr == fHead->fPrev);
233*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(nullptr == fTail->fNext);
234*c8dee2aaSAndroid Build Coastguard Worker 
235*c8dee2aaSAndroid Build Coastguard Worker         if (fEntryCount == 1) {
236*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(fHead == fTail);
237*c8dee2aaSAndroid Build Coastguard Worker         } else {
238*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(fHead != fTail);
239*c8dee2aaSAndroid Build Coastguard Worker         }
240*c8dee2aaSAndroid Build Coastguard Worker 
241*c8dee2aaSAndroid Build Coastguard Worker         Entry* entry = fHead;
242*c8dee2aaSAndroid Build Coastguard Worker         int count = 0;
243*c8dee2aaSAndroid Build Coastguard Worker         while (entry) {
244*c8dee2aaSAndroid Build Coastguard Worker             count += 1;
245*c8dee2aaSAndroid Build Coastguard Worker             entry = entry->fNext;
246*c8dee2aaSAndroid Build Coastguard Worker         }
247*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(count == fEntryCount);
248*c8dee2aaSAndroid Build Coastguard Worker 
249*c8dee2aaSAndroid Build Coastguard Worker         entry = fTail;
250*c8dee2aaSAndroid Build Coastguard Worker         while (entry) {
251*c8dee2aaSAndroid Build Coastguard Worker             count -= 1;
252*c8dee2aaSAndroid Build Coastguard Worker             entry = entry->fPrev;
253*c8dee2aaSAndroid Build Coastguard Worker         }
254*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(0 == count);
255*c8dee2aaSAndroid Build Coastguard Worker     } else {
256*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(nullptr == fHead);
257*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(nullptr == fTail);
258*c8dee2aaSAndroid Build Coastguard Worker     }
259*c8dee2aaSAndroid Build Coastguard Worker }
260*c8dee2aaSAndroid Build Coastguard Worker 
261*c8dee2aaSAndroid Build Coastguard Worker #endif
262