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 "SkImageGenerator.h" | |
13 #include "SkMatrixUtils.h" | 14 #include "SkMatrixUtils.h" |
14 #include "SkPicture.h" | 15 #include "SkPicture.h" |
15 #include "SkReadBuffer.h" | 16 #include "SkReadBuffer.h" |
16 #include "SkResourceCache.h" | 17 #include "SkResourceCache.h" |
17 | 18 |
18 #if SK_SUPPORT_GPU | 19 #if SK_SUPPORT_GPU |
19 #include "GrContext.h" | 20 #include "GrContext.h" |
20 #endif | 21 #endif |
21 | 22 |
22 namespace { | 23 namespace { |
23 static unsigned gBitmapSkaderKeyNamespaceLabel; | 24 static unsigned gBitmapSkaderKeyNamespaceLabel; |
24 | 25 |
26 class PictureImageGenerator : public SkImageGenerator { | |
27 public: | |
28 PictureImageGenerator(const SkPicture* picture, | |
29 const SkRect& pictureTile, | |
30 const SkISize& tileSize) | |
31 : fPicture(SkRef(picture)) | |
32 , fPictureTile(pictureTile) | |
33 , fRasterTileInfo(SkImageInfo::MakeN32Premul(tileSize)) {} | |
34 | |
35 virtual ~PictureImageGenerator() {} | |
36 | |
37 protected: | |
38 virtual bool onGetInfo(SkImageInfo *info) SK_OVERRIDE { | |
39 *info = fRasterTileInfo; | |
40 return true; | |
41 } | |
42 | |
43 virtual bool onGetPixels(const SkImageInfo& info, void *pixels, size_t rowBy tes, | |
44 SkPMColor ctable[], int *ctableCount) SK_OVERRIDE { | |
45 if (info != fRasterTileInfo || SkToBool(ctable) || SkToBool(ctableCount) ) { | |
46 return false; | |
47 } | |
48 | |
49 SkSize tileScale = SkSize::Make(SkIntToScalar(info.width()) / fPictureTi le.width(), | |
50 SkIntToScalar(info.height()) / fPictureT ile.height()); | |
51 SkBitmap tileBitmap; | |
52 if (!tileBitmap.installPixels(info, pixels, rowBytes)) { | |
53 return false; | |
54 } | |
55 tileBitmap.eraseColor(SK_ColorTRANSPARENT); | |
56 | |
57 SkCanvas tileCanvas(tileBitmap); | |
58 tileCanvas.scale(tileScale.width(), tileScale.height()); | |
59 tileCanvas.translate(-fPictureTile.x(), -fPictureTile.y()); | |
60 tileCanvas.drawPicture(fPicture); | |
61 | |
62 return true; | |
63 } | |
64 | |
65 private: | |
66 SkAutoTUnref<const SkPicture> fPicture; | |
67 const SkRect fPictureTile; | |
68 const SkImageInfo fRasterTileInfo; | |
69 }; | |
70 | |
25 struct BitmapShaderKey : public SkResourceCache::Key { | 71 struct BitmapShaderKey : public SkResourceCache::Key { |
26 public: | 72 public: |
27 BitmapShaderKey(uint32_t pictureID, | 73 BitmapShaderKey(uint32_t pictureID, |
28 const SkRect& tile, | 74 const SkRect& tile, |
29 SkShader::TileMode tmx, | 75 SkShader::TileMode tmx, |
30 SkShader::TileMode tmy, | 76 SkShader::TileMode tmy, |
31 const SkSize& scale, | 77 const SkSize& scale, |
32 const SkMatrix& localMatrix) | 78 const SkMatrix& localMatrix) |
33 : fPictureID(pictureID) | 79 : fPictureID(pictureID) |
34 , fTile(tile) | 80 , fTile(tile) |
(...skipping 30 matching lines...) Expand all Loading... | |
65 : fKey(key) | 111 : fKey(key) |
66 , fShader(SkRef(tileShader)) | 112 , fShader(SkRef(tileShader)) |
67 , fBitmapBytes(bitmapBytes) {} | 113 , fBitmapBytes(bitmapBytes) {} |
68 | 114 |
69 BitmapShaderKey fKey; | 115 BitmapShaderKey fKey; |
70 SkAutoTUnref<SkShader> fShader; | 116 SkAutoTUnref<SkShader> fShader; |
71 size_t fBitmapBytes; | 117 size_t fBitmapBytes; |
72 | 118 |
73 const Key& getKey() const SK_OVERRIDE { return fKey; } | 119 const Key& getKey() const SK_OVERRIDE { return fKey; } |
74 size_t bytesUsed() const SK_OVERRIDE { | 120 size_t bytesUsed() const SK_OVERRIDE { |
75 return sizeof(fKey) + sizeof(SkShader) + fBitmapBytes; | 121 return sizeof(fKey) + sizeof(SkShader) + fBitmapBytes; |
f(malita)
2015/01/22 15:46:00
Is this a lie now? Since we use discardable pixel
| |
76 } | 122 } |
77 | 123 |
78 static bool Visitor(const SkResourceCache::Rec& baseRec, void* contextShader ) { | 124 static bool Visitor(const SkResourceCache::Rec& baseRec, void* contextShader ) { |
79 const BitmapShaderRec& rec = static_cast<const BitmapShaderRec&>(baseRec ); | 125 const BitmapShaderRec& rec = static_cast<const BitmapShaderRec&>(baseRec ); |
80 SkAutoTUnref<SkShader>* result = reinterpret_cast<SkAutoTUnref<SkShader> *>(contextShader); | 126 SkAutoTUnref<SkShader>* result = reinterpret_cast<SkAutoTUnref<SkShader> *>(contextShader); |
81 | 127 |
82 result->reset(SkRef(rec.fShader.get())); | 128 result->reset(SkRef(rec.fShader.get())); |
83 | 129 |
84 SkBitmap tile; | 130 // The bitmap shader is backed by an image generator, thus it can always re-generate its |
85 rec.fShader.get()->asABitmap(&tile, NULL, NULL); | 131 // pixels if discarded. |
86 // FIXME: this doesn't protect the pixels from being discarded as soon a s we unlock. | 132 return true; |
87 // Should be handled via a pixel ref generator instead | |
88 // (https://code.google.com/p/skia/issues/detail?id=3220). | |
89 SkAutoLockPixels alp(tile, true); | |
90 return tile.getPixels() != NULL; | |
91 } | 133 } |
92 }; | 134 }; |
93 | 135 |
94 static bool cache_try_alloc_pixels(SkBitmap* bitmap) { | |
95 SkBitmap::Allocator* allocator = SkResourceCache::GetAllocator(); | |
96 | |
97 return NULL != allocator | |
98 ? allocator->allocPixelRef(bitmap, NULL) | |
99 : bitmap->tryAllocPixels(); | |
100 } | |
101 | |
102 } // namespace | 136 } // namespace |
103 | 137 |
104 SkPictureShader::SkPictureShader(const SkPicture* picture, TileMode tmx, TileMod e tmy, | 138 SkPictureShader::SkPictureShader(const SkPicture* picture, TileMode tmx, TileMod e tmy, |
105 const SkMatrix* localMatrix, const SkRect* tile ) | 139 const SkMatrix* localMatrix, const SkRect* tile ) |
106 : INHERITED(localMatrix) | 140 : INHERITED(localMatrix) |
107 , fPicture(SkRef(picture)) | 141 , fPicture(SkRef(picture)) |
108 , fTile(tile ? *tile : picture->cullRect()) | 142 , fTile(tile ? *tile : picture->cullRect()) |
109 , fTmx(tmx) | 143 , fTmx(tmx) |
110 , fTmy(tmy) { | 144 , fTmy(tmy) { |
111 } | 145 } |
112 | 146 |
113 SkPictureShader::~SkPictureShader() { | |
114 fPicture->unref(); | |
115 } | |
116 | |
117 SkPictureShader* SkPictureShader::Create(const SkPicture* picture, TileMode tmx, TileMode tmy, | 147 SkPictureShader* SkPictureShader::Create(const SkPicture* picture, TileMode tmx, TileMode tmy, |
118 const SkMatrix* localMatrix, const SkRe ct* tile) { | 148 const SkMatrix* localMatrix, const SkRe ct* tile) { |
119 if (!picture || picture->cullRect().isEmpty() || (tile && tile->isEmpty())) { | 149 if (!picture || picture->cullRect().isEmpty() || (tile && tile->isEmpty())) { |
120 return NULL; | 150 return NULL; |
121 } | 151 } |
122 return SkNEW_ARGS(SkPictureShader, (picture, tmx, tmy, localMatrix, tile)); | 152 return SkNEW_ARGS(SkPictureShader, (picture, tmx, tmy, localMatrix, tile)); |
123 } | 153 } |
124 | 154 |
125 SkFlattenable* SkPictureShader::CreateProc(SkReadBuffer& buffer) { | 155 SkFlattenable* SkPictureShader::CreateProc(SkReadBuffer& buffer) { |
126 SkMatrix lm; | 156 SkMatrix lm; |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
181 SkAutoTUnref<SkShader> tileShader; | 211 SkAutoTUnref<SkShader> tileShader; |
182 BitmapShaderKey key(fPicture->uniqueID(), | 212 BitmapShaderKey key(fPicture->uniqueID(), |
183 fTile, | 213 fTile, |
184 fTmx, | 214 fTmx, |
185 fTmy, | 215 fTmy, |
186 tileScale, | 216 tileScale, |
187 this->getLocalMatrix()); | 217 this->getLocalMatrix()); |
188 | 218 |
189 if (!SkResourceCache::Find(key, BitmapShaderRec::Visitor, &tileShader)) { | 219 if (!SkResourceCache::Find(key, BitmapShaderRec::Visitor, &tileShader)) { |
190 SkBitmap bm; | 220 SkBitmap bm; |
191 bm.setInfo(SkImageInfo::MakeN32Premul(tileSize)); | 221 if (!SkInstallDiscardablePixelRef(SkNEW_ARGS(PictureImageGenerator, |
192 if (!cache_try_alloc_pixels(&bm)) { | 222 (fPicture, fTile, tileSize) ), &bm)) { |
193 return NULL; | 223 return NULL; |
194 } | 224 } |
195 bm.eraseColor(SK_ColorTRANSPARENT); | |
196 | |
197 SkCanvas canvas(bm); | |
198 canvas.scale(tileScale.width(), tileScale.height()); | |
199 canvas.translate(-fTile.x(), -fTile.y()); | |
200 canvas.drawPicture(fPicture); | |
201 | 225 |
202 SkMatrix shaderMatrix = this->getLocalMatrix(); | 226 SkMatrix shaderMatrix = this->getLocalMatrix(); |
203 shaderMatrix.preScale(1 / tileScale.width(), 1 / tileScale.height()); | 227 shaderMatrix.preScale(1 / tileScale.width(), 1 / tileScale.height()); |
204 tileShader.reset(CreateBitmapShader(bm, fTmx, fTmy, &shaderMatrix)); | 228 tileShader.reset(CreateBitmapShader(bm, fTmx, fTmy, &shaderMatrix)); |
205 | 229 |
206 SkResourceCache::Add(SkNEW_ARGS(BitmapShaderRec, (key, tileShader.get(), bm.getSize()))); | 230 SkResourceCache::Add(SkNEW_ARGS(BitmapShaderRec, (key, tileShader.get(), bm.getSize()))); |
207 } | 231 } |
208 | 232 |
209 return tileShader.detach(); | 233 return tileShader.detach(); |
210 } | 234 } |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
271 fBitmapShaderContext->shadeSpan16(x, y, dstC, count); | 295 fBitmapShaderContext->shadeSpan16(x, y, dstC, count); |
272 } | 296 } |
273 | 297 |
274 #ifndef SK_IGNORE_TO_STRING | 298 #ifndef SK_IGNORE_TO_STRING |
275 void SkPictureShader::toString(SkString* str) const { | 299 void SkPictureShader::toString(SkString* str) const { |
276 static const char* gTileModeName[SkShader::kTileModeCount] = { | 300 static const char* gTileModeName[SkShader::kTileModeCount] = { |
277 "clamp", "repeat", "mirror" | 301 "clamp", "repeat", "mirror" |
278 }; | 302 }; |
279 | 303 |
280 str->appendf("PictureShader: [%f:%f:%f:%f] ", | 304 str->appendf("PictureShader: [%f:%f:%f:%f] ", |
281 fPicture ? fPicture->cullRect().fLeft : 0, | 305 fPicture->cullRect().fLeft, |
282 fPicture ? fPicture->cullRect().fTop : 0, | 306 fPicture->cullRect().fTop, |
283 fPicture ? fPicture->cullRect().fRight : 0, | 307 fPicture->cullRect().fRight, |
284 fPicture ? fPicture->cullRect().fBottom : 0); | 308 fPicture->cullRect().fBottom); |
285 | 309 |
286 str->appendf("(%s, %s)", gTileModeName[fTmx], gTileModeName[fTmy]); | 310 str->appendf("(%s, %s)", gTileModeName[fTmx], gTileModeName[fTmy]); |
287 | 311 |
288 this->INHERITED::toString(str); | 312 this->INHERITED::toString(str); |
289 } | 313 } |
290 #endif | 314 #endif |
291 | 315 |
292 #if SK_SUPPORT_GPU | 316 #if SK_SUPPORT_GPU |
293 bool SkPictureShader::asFragmentProcessor(GrContext* context, const SkPaint& pai nt, | 317 bool SkPictureShader::asFragmentProcessor(GrContext* context, const SkPaint& pai nt, |
294 const SkMatrix& viewM, const SkMatrix* localMatrix, | 318 const SkMatrix& viewM, const SkMatrix* localMatrix, |
295 GrColor* paintColor, | 319 GrColor* paintColor, |
296 GrFragmentProcessor** fp) const { | 320 GrFragmentProcessor** fp) const { |
297 SkAutoTUnref<SkShader> bitmapShader(this->refBitmapShader(viewM, localMatrix )); | 321 SkAutoTUnref<SkShader> bitmapShader(this->refBitmapShader(viewM, localMatrix )); |
298 if (!bitmapShader) { | 322 if (!bitmapShader) { |
299 return false; | 323 return false; |
300 } | 324 } |
301 return bitmapShader->asFragmentProcessor(context, paint, viewM, NULL, paintC olor, fp); | 325 return bitmapShader->asFragmentProcessor(context, paint, viewM, NULL, paintC olor, fp); |
302 } | 326 } |
303 #else | 327 #else |
304 bool SkPictureShader::asFragmentProcessor(GrContext*, const SkPaint&, const SkMa trix&, | 328 bool SkPictureShader::asFragmentProcessor(GrContext*, const SkPaint&, const SkMa trix&, |
305 const SkMatrix*, GrColor*, | 329 const SkMatrix*, GrColor*, |
306 GrFragmentProcessor**) const { | 330 GrFragmentProcessor**) const { |
307 SkDEBUGFAIL("Should not call in GPU-less build"); | 331 SkDEBUGFAIL("Should not call in GPU-less build"); |
308 return false; | 332 return false; |
309 } | 333 } |
310 #endif | 334 #endif |
OLD | NEW |