| 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 |