OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkPictureShader.h" | 8 #include "SkPictureShader.h" |
9 | 9 |
10 #include "SkBitmap.h" | 10 #include "SkBitmap.h" |
11 #include "SkBitmapProcShader.h" | 11 #include "SkBitmapProcShader.h" |
12 #include "SkCanvas.h" | 12 #include "SkCanvas.h" |
13 #include "SkDiscardableMemory.h" | |
14 #include "SkMatrixUtils.h" | 13 #include "SkMatrixUtils.h" |
15 #include "SkPicture.h" | 14 #include "SkPicture.h" |
16 #include "SkReadBuffer.h" | 15 #include "SkReadBuffer.h" |
17 #include "SkResourceCache.h" | 16 #include "SkResourceCache.h" |
18 #include "SkThread.h" | |
19 | 17 |
20 #if SK_SUPPORT_GPU | 18 #if SK_SUPPORT_GPU |
21 #include "GrContext.h" | 19 #include "GrContext.h" |
22 #endif | 20 #endif |
23 | 21 |
| 22 namespace { |
| 23 static unsigned gBitmapSkaderKeyNamespaceLabel; |
| 24 |
24 struct BitmapShaderKey : public SkResourceCache::Key { | 25 struct BitmapShaderKey : public SkResourceCache::Key { |
25 public: | 26 public: |
26 BitmapShaderKey(uint32_t pictureID, | 27 BitmapShaderKey(uint32_t pictureID, |
27 const SkRect& tile, | 28 const SkRect& tile, |
28 SkShader::TileMode tmx, | 29 SkShader::TileMode tmx, |
29 SkShader::TileMode tmy, | 30 SkShader::TileMode tmy, |
30 const SkSize& scale, | 31 const SkSize& scale, |
31 const SkMatrix& localMatrix) | 32 const SkMatrix& localMatrix) |
32 : fPictureID(pictureID) | 33 : fPictureID(pictureID) |
33 , fTile(tile) | 34 , fTile(tile) |
34 , fTmx(tmx) | 35 , fTmx(tmx) |
35 , fTmy(tmy) | 36 , fTmy(tmy) |
36 , fScale(scale) | 37 , fScale(scale) |
37 , fLocalMatrix(localMatrix) { | 38 , fLocalMatrix(localMatrix) { |
38 | 39 |
39 static const size_t keySize = sizeof(fPictureID) + | 40 static const size_t keySize = sizeof(fPictureID) + |
40 sizeof(fTile) + | 41 sizeof(fTile) + |
41 sizeof(fTmx) + sizeof(fTmy) + | 42 sizeof(fTmx) + sizeof(fTmy) + |
42 sizeof(fScale) + | 43 sizeof(fScale) + |
43 sizeof(fLocalMatrix); | 44 sizeof(fLocalMatrix); |
44 // This better be packed. | 45 // This better be packed. |
45 SkASSERT(sizeof(uint32_t) * (&fEndOfStruct - &fPictureID) == keySize); | 46 SkASSERT(sizeof(uint32_t) * (&fEndOfStruct - &fPictureID) == keySize); |
46 this->init(keySize); | 47 this->init(&gBitmapSkaderKeyNamespaceLabel, keySize); |
47 } | 48 } |
48 | 49 |
49 private: | 50 private: |
50 uint32_t fPictureID; | 51 uint32_t fPictureID; |
51 SkRect fTile; | 52 SkRect fTile; |
52 SkShader::TileMode fTmx, fTmy; | 53 SkShader::TileMode fTmx, fTmy; |
53 SkSize fScale; | 54 SkSize fScale; |
54 SkMatrix fLocalMatrix; | 55 SkMatrix fLocalMatrix; |
55 | 56 |
56 SkDEBUGCODE(uint32_t fEndOfStruct;) | 57 SkDEBUGCODE(uint32_t fEndOfStruct;) |
(...skipping 16 matching lines...) Expand all Loading... |
73 | 74 |
74 static bool Visitor(const SkResourceCache::Rec& baseRec, void* contextShader
) { | 75 static bool Visitor(const SkResourceCache::Rec& baseRec, void* contextShader
) { |
75 const BitmapShaderRec& rec = static_cast<const BitmapShaderRec&>(baseRec
); | 76 const BitmapShaderRec& rec = static_cast<const BitmapShaderRec&>(baseRec
); |
76 SkAutoTUnref<SkShader>* result = reinterpret_cast<SkAutoTUnref<SkShader>
*>(contextShader); | 77 SkAutoTUnref<SkShader>* result = reinterpret_cast<SkAutoTUnref<SkShader>
*>(contextShader); |
77 | 78 |
78 result->reset(SkRef(rec.fShader.get())); | 79 result->reset(SkRef(rec.fShader.get())); |
79 return true; | 80 return true; |
80 } | 81 } |
81 }; | 82 }; |
82 | 83 |
83 // FIXME: there's considerable boilerplate/duplication here vs. the global resou
rce cache. | 84 static bool cache_try_alloc_pixels(SkBitmap* bitmap) { |
84 SK_DECLARE_STATIC_MUTEX(gBitmapShaderCacheMutex); | 85 SkBitmap::Allocator* allocator = SkResourceCache::GetAllocator(); |
85 static SkResourceCache* gBitmapShaderCache = NULL; | |
86 | 86 |
87 #ifndef SK_DEFAULT_TILE_CACHE_LIMIT | 87 return NULL != allocator |
88 #define SK_DEFAULT_TILE_CACHE_LIMIT (2 * 1024 * 1024) | 88 ? allocator->allocPixelRef(bitmap, NULL) |
89 #endif | 89 : bitmap->tryAllocPixels(); |
90 | |
91 static void cleanup_cache() { | |
92 // We'll clean this up in our own tests, but disable for clients. | |
93 // Chrome seems to have funky multi-process things going on in unit tests th
at | |
94 // makes this unsafe to delete when the main process atexit()s. | |
95 // SkLazyPtr does the same sort of thing. | |
96 #if SK_DEVELOPER | |
97 SkDELETE(gBitmapShaderCache); | |
98 #endif | |
99 } | 90 } |
100 | 91 |
101 /** Must hold gBitmapShaderCacheMutex when calling. */ | 92 } // namespace |
102 static SkResourceCache* cache() { | |
103 // gTileCacheMutex is always held when this is called, so we don't need to b
e fancy in here. | |
104 gBitmapShaderCacheMutex.assertHeld(); | |
105 if (NULL == gBitmapShaderCache) { | |
106 #ifdef SK_USE_DISCARDABLE_SCALEDIMAGECACHE | |
107 gBitmapShaderCache = SkNEW_ARGS(SkResourceCache, (SkDiscardableMemory::C
reate)); | |
108 #else | |
109 gBitmapShaderCache = SkNEW_ARGS(SkResourceCache, (SK_DEFAULT_TILE_CACHE_
LIMIT)); | |
110 #endif | |
111 atexit(cleanup_cache); | |
112 } | |
113 return gBitmapShaderCache; | |
114 } | |
115 | |
116 static bool cache_find(const BitmapShaderKey& key, SkAutoTUnref<SkShader>* resul
t) { | |
117 SkAutoMutexAcquire am(gBitmapShaderCacheMutex); | |
118 return cache()->find(key, BitmapShaderRec::Visitor, result); | |
119 } | |
120 | |
121 static void cache_add(BitmapShaderRec* rec) { | |
122 SkAutoMutexAcquire am(gBitmapShaderCacheMutex); | |
123 cache()->add(rec); | |
124 } | |
125 | |
126 static bool cache_try_alloc_pixels(SkBitmap* bitmap) { | |
127 SkAutoMutexAcquire am(gBitmapShaderCacheMutex); | |
128 SkBitmap::Allocator* allocator = cache()->allocator(); | |
129 | |
130 if (NULL != allocator) { | |
131 return allocator->allocPixelRef(bitmap, NULL); | |
132 } else { | |
133 return bitmap->tryAllocPixels(); | |
134 } | |
135 } | |
136 | 93 |
137 SkPictureShader::SkPictureShader(const SkPicture* picture, TileMode tmx, TileMod
e tmy, | 94 SkPictureShader::SkPictureShader(const SkPicture* picture, TileMode tmx, TileMod
e tmy, |
138 const SkMatrix* localMatrix, const SkRect* tile
) | 95 const SkMatrix* localMatrix, const SkRect* tile
) |
139 : INHERITED(localMatrix) | 96 : INHERITED(localMatrix) |
140 , fPicture(SkRef(picture)) | 97 , fPicture(SkRef(picture)) |
141 , fTile(tile ? *tile : picture->cullRect()) | 98 , fTile(tile ? *tile : picture->cullRect()) |
142 , fTmx(tmx) | 99 , fTmx(tmx) |
143 , fTmy(tmy) { | 100 , fTmy(tmy) { |
144 } | 101 } |
145 | 102 |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
220 SkIntToScalar(tileSize.height()) / fTile.hei
ght()); | 177 SkIntToScalar(tileSize.height()) / fTile.hei
ght()); |
221 | 178 |
222 SkAutoTUnref<SkShader> tileShader; | 179 SkAutoTUnref<SkShader> tileShader; |
223 BitmapShaderKey key(fPicture->uniqueID(), | 180 BitmapShaderKey key(fPicture->uniqueID(), |
224 fTile, | 181 fTile, |
225 fTmx, | 182 fTmx, |
226 fTmy, | 183 fTmy, |
227 tileScale, | 184 tileScale, |
228 this->getLocalMatrix()); | 185 this->getLocalMatrix()); |
229 | 186 |
230 if (!cache_find(key, &tileShader)) { | 187 if (!SkResourceCache::Find(key, BitmapShaderRec::Visitor, &tileShader)) { |
231 SkBitmap bm; | 188 SkBitmap bm; |
232 bm.setInfo(SkImageInfo::MakeN32Premul(tileSize)); | 189 bm.setInfo(SkImageInfo::MakeN32Premul(tileSize)); |
233 if (!cache_try_alloc_pixels(&bm)) { | 190 if (!cache_try_alloc_pixels(&bm)) { |
234 return NULL; | 191 return NULL; |
235 } | 192 } |
236 bm.eraseColor(SK_ColorTRANSPARENT); | 193 bm.eraseColor(SK_ColorTRANSPARENT); |
237 | 194 |
238 SkCanvas canvas(bm); | 195 SkCanvas canvas(bm); |
239 canvas.scale(tileScale.width(), tileScale.height()); | 196 canvas.scale(tileScale.width(), tileScale.height()); |
240 canvas.translate(fTile.x(), fTile.y()); | 197 canvas.translate(fTile.x(), fTile.y()); |
241 canvas.drawPicture(fPicture); | 198 canvas.drawPicture(fPicture); |
242 | 199 |
243 SkMatrix shaderMatrix = this->getLocalMatrix(); | 200 SkMatrix shaderMatrix = this->getLocalMatrix(); |
244 shaderMatrix.preScale(1 / tileScale.width(), 1 / tileScale.height()); | 201 shaderMatrix.preScale(1 / tileScale.width(), 1 / tileScale.height()); |
245 tileShader.reset(CreateBitmapShader(bm, fTmx, fTmy, &shaderMatrix)); | 202 tileShader.reset(CreateBitmapShader(bm, fTmx, fTmy, &shaderMatrix)); |
246 | 203 |
247 cache_add(SkNEW_ARGS(BitmapShaderRec, (key, tileShader.get(), bm.getSize
()))); | 204 SkResourceCache::Add(SkNEW_ARGS(BitmapShaderRec, (key, tileShader.get(),
bm.getSize()))); |
248 } | 205 } |
249 | 206 |
250 return tileShader.detach(); | 207 return tileShader.detach(); |
251 } | 208 } |
252 | 209 |
253 size_t SkPictureShader::contextSize() const { | 210 size_t SkPictureShader::contextSize() const { |
254 return sizeof(PictureShaderContext); | 211 return sizeof(PictureShaderContext); |
255 } | 212 } |
256 | 213 |
257 SkShader::Context* SkPictureShader::onCreateContext(const ContextRec& rec, void*
storage) const { | 214 SkShader::Context* SkPictureShader::onCreateContext(const ContextRec& rec, void*
storage) const { |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
340 } | 297 } |
341 return bitmapShader->asFragmentProcessor(context, paint, NULL, paintColor, f
p); | 298 return bitmapShader->asFragmentProcessor(context, paint, NULL, paintColor, f
p); |
342 } | 299 } |
343 #else | 300 #else |
344 bool SkPictureShader::asFragmentProcessor(GrContext*, const SkPaint&, const SkMa
trix*, GrColor*, | 301 bool SkPictureShader::asFragmentProcessor(GrContext*, const SkPaint&, const SkMa
trix*, GrColor*, |
345 GrFragmentProcessor**) const { | 302 GrFragmentProcessor**) const { |
346 SkDEBUGFAIL("Should not call in GPU-less build"); | 303 SkDEBUGFAIL("Should not call in GPU-less build"); |
347 return false; | 304 return false; |
348 } | 305 } |
349 #endif | 306 #endif |
OLD | NEW |