OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2010 Google Inc. | 2 * Copyright 2010 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 "GrTextureMaker.h" |
| 9 |
8 #include "SkGr.h" | 10 #include "SkGr.h" |
9 | 11 |
10 #include "GrCaps.h" | 12 #include "GrCaps.h" |
11 #include "GrDrawContext.h" | 13 #include "GrDrawContext.h" |
12 #include "GrXferProcessor.h" | 14 #include "GrXferProcessor.h" |
13 #include "GrYUVProvider.h" | 15 #include "GrYUVProvider.h" |
14 | 16 |
15 #include "SkColorFilter.h" | 17 #include "SkColorFilter.h" |
16 #include "SkConfig8888.h" | 18 #include "SkConfig8888.h" |
17 #include "SkCanvas.h" | 19 #include "SkCanvas.h" |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 for (int y = 0; y < bitmap.height(); y++) { | 89 for (int y = 0; y < bitmap.height(); y++) { |
88 memcpy(dst, src, width); | 90 memcpy(dst, src, width); |
89 src += rowBytes; | 91 src += rowBytes; |
90 dst += width; | 92 dst += width; |
91 } | 93 } |
92 } | 94 } |
93 } | 95 } |
94 | 96 |
95 //////////////////////////////////////////////////////////////////////////////// | 97 //////////////////////////////////////////////////////////////////////////////// |
96 | 98 |
97 struct Stretch { | |
98 enum Type { | |
99 kNone_Type, | |
100 kBilerp_Type, | |
101 kNearest_Type | |
102 } fType; | |
103 int fWidth; | |
104 int fHeight; | |
105 }; | |
106 | |
107 static void get_stretch(const GrContext* ctx, int width, int height, | 99 static void get_stretch(const GrContext* ctx, int width, int height, |
108 const GrTextureParams* params, Stretch* stretch) { | 100 const GrTextureParams* params, SkGrStretch* stretch) { |
109 stretch->fType = Stretch::kNone_Type; | 101 stretch->fType = SkGrStretch::kNone_Type; |
110 bool doStretch = false; | 102 bool doStretch = false; |
111 if (params && params->isTiled() && !ctx->caps()->npotTextureTileSupport() && | 103 if (params && params->isTiled() && !ctx->caps()->npotTextureTileSupport() && |
112 (!SkIsPow2(width) || !SkIsPow2(height))) { | 104 (!SkIsPow2(width) || !SkIsPow2(height))) { |
113 doStretch = true; | 105 doStretch = true; |
114 stretch->fWidth = GrNextPow2(SkTMax(width, ctx->caps()->minTextureSize(
))); | 106 stretch->fWidth = GrNextPow2(SkTMax(width, ctx->caps()->minTextureSize(
))); |
115 stretch->fHeight = GrNextPow2(SkTMax(height, ctx->caps()->minTextureSize
())); | 107 stretch->fHeight = GrNextPow2(SkTMax(height, ctx->caps()->minTextureSize
())); |
116 } else if (width < ctx->caps()->minTextureSize() || height < ctx->caps()->mi
nTextureSize()) { | 108 } else if (width < ctx->caps()->minTextureSize() || height < ctx->caps()->mi
nTextureSize()) { |
117 // The small texture issues appear to be with tiling. Hence it seems ok
to scale them | 109 // The small texture issues appear to be with tiling. Hence it seems ok
to scale them |
118 // up using the GPU. If issues persist we may need to CPU-stretch. | 110 // up using the GPU. If issues persist we may need to CPU-stretch. |
119 doStretch = true; | 111 doStretch = true; |
120 stretch->fWidth = SkTMax(width, ctx->caps()->minTextureSize()); | 112 stretch->fWidth = SkTMax(width, ctx->caps()->minTextureSize()); |
121 stretch->fHeight = SkTMax(height, ctx->caps()->minTextureSize()); | 113 stretch->fHeight = SkTMax(height, ctx->caps()->minTextureSize()); |
122 } | 114 } |
123 if (doStretch) { | 115 if (doStretch) { |
124 if (params) { | 116 if (params) { |
125 switch(params->filterMode()) { | 117 switch(params->filterMode()) { |
126 case GrTextureParams::kNone_FilterMode: | 118 case GrTextureParams::kNone_FilterMode: |
127 stretch->fType = Stretch::kNearest_Type; | 119 stretch->fType = SkGrStretch::kNearest_Type; |
128 break; | 120 break; |
129 case GrTextureParams::kBilerp_FilterMode: | 121 case GrTextureParams::kBilerp_FilterMode: |
130 case GrTextureParams::kMipMap_FilterMode: | 122 case GrTextureParams::kMipMap_FilterMode: |
131 stretch->fType = Stretch::kBilerp_Type; | 123 stretch->fType = SkGrStretch::kBilerp_Type; |
132 break; | 124 break; |
133 } | 125 } |
134 } else { | 126 } else { |
135 stretch->fType = Stretch::kBilerp_Type; | 127 stretch->fType = SkGrStretch::kBilerp_Type; |
136 } | 128 } |
137 } else { | 129 } else { |
138 stretch->fWidth = -1; | 130 stretch->fWidth = -1; |
139 stretch->fHeight = -1; | 131 stretch->fHeight = -1; |
140 stretch->fType = Stretch::kNone_Type; | 132 stretch->fType = SkGrStretch::kNone_Type; |
141 } | 133 } |
142 } | 134 } |
143 | 135 |
144 static bool make_stretched_key(const GrUniqueKey& origKey, const Stretch& stretc
h, | 136 static bool make_stretched_key(const GrUniqueKey& origKey, const SkGrStretch& st
retch, |
145 GrUniqueKey* stretchedKey) { | 137 GrUniqueKey* stretchedKey) { |
146 if (origKey.isValid() && Stretch::kNone_Type != stretch.fType) { | 138 if (origKey.isValid() && SkGrStretch::kNone_Type != stretch.fType) { |
147 uint32_t width = SkToU16(stretch.fWidth); | 139 uint32_t width = SkToU16(stretch.fWidth); |
148 uint32_t height = SkToU16(stretch.fHeight); | 140 uint32_t height = SkToU16(stretch.fHeight); |
149 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain()
; | 141 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain()
; |
150 GrUniqueKey::Builder builder(stretchedKey, origKey, kDomain, 2); | 142 GrUniqueKey::Builder builder(stretchedKey, origKey, kDomain, 2); |
151 builder[0] = stretch.fType; | 143 builder[0] = stretch.fType; |
152 builder[1] = width | (height << 16); | 144 builder[1] = width | (height << 16); |
153 builder.finish(); | 145 builder.finish(); |
154 return true; | 146 return true; |
155 } | 147 } |
156 SkASSERT(!stretchedKey->isValid()); | 148 SkASSERT(!stretchedKey->isValid()); |
157 return false; | 149 return false; |
158 } | 150 } |
159 | 151 |
160 static void make_unstretched_key(GrUniqueKey* key, uint32_t imageID, const SkIRe
ct& subset) { | 152 static void make_unstretched_key(GrUniqueKey* key, uint32_t imageID, const SkIRe
ct& subset) { |
161 SkASSERT(SkIsU16(subset.width())); | 153 SkASSERT(SkIsU16(subset.width())); |
162 SkASSERT(SkIsU16(subset.height())); | 154 SkASSERT(SkIsU16(subset.height())); |
163 | 155 |
164 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); | 156 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); |
165 GrUniqueKey::Builder builder(key, kDomain, 4); | 157 GrUniqueKey::Builder builder(key, kDomain, 4); |
166 builder[0] = imageID; | 158 builder[0] = imageID; |
167 builder[1] = subset.x(); | 159 builder[1] = subset.x(); |
168 builder[2] = subset.y(); | 160 builder[2] = subset.y(); |
169 builder[3] = subset.width() | (subset.height() << 16); | 161 builder[3] = subset.width() | (subset.height() << 16); |
170 } | 162 } |
171 | 163 |
172 void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& sub
set, | 164 void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& sub
set, |
173 const GrCaps& caps, SkImageUsageType usage) { | 165 const GrCaps& caps, SkImageUsageType usage) { |
174 const Stretch::Type stretches[] = { | 166 const SkGrStretch::Type stretches[] = { |
175 Stretch::kNone_Type, // kUntiled_SkImageUsageType | 167 SkGrStretch::kNone_Type, // kUntiled_SkImageUsageType |
176 Stretch::kNearest_Type, // kTiled_Unfiltered_SkImageUsageType | 168 SkGrStretch::kNearest_Type, // kTiled_Unfiltered_SkImageUsageType |
177 Stretch::kBilerp_Type, // kTiled_Filtered_SkImageUsageType | 169 SkGrStretch::kBilerp_Type, // kTiled_Filtered_SkImageUsageType |
178 }; | 170 }; |
179 | 171 |
180 const bool isPow2 = SkIsPow2(subset.width()) && SkIsPow2(subset.height()); | 172 const bool isPow2 = SkIsPow2(subset.width()) && SkIsPow2(subset.height()); |
181 const bool needToStretch = !isPow2 && | 173 const bool needToStretch = !isPow2 && |
182 usage != kUntiled_SkImageUsageType && | 174 usage != kUntiled_SkImageUsageType && |
183 !caps.npotTextureTileSupport(); | 175 !caps.npotTextureTileSupport(); |
184 | 176 |
185 if (needToStretch) { | 177 if (needToStretch) { |
186 GrUniqueKey tmpKey; | 178 GrUniqueKey tmpKey; |
187 make_unstretched_key(&tmpKey, imageID, subset); | 179 make_unstretched_key(&tmpKey, imageID, subset); |
188 | 180 |
189 Stretch stretch; | 181 SkGrStretch stretch; |
190 stretch.fType = stretches[usage]; | 182 stretch.fType = stretches[usage]; |
191 stretch.fWidth = SkNextPow2(subset.width()); | 183 stretch.fWidth = SkNextPow2(subset.width()); |
192 stretch.fHeight = SkNextPow2(subset.height()); | 184 stretch.fHeight = SkNextPow2(subset.height()); |
193 if (!make_stretched_key(tmpKey, stretch, key)) { | 185 if (!make_stretched_key(tmpKey, stretch, key)) { |
194 goto UNSTRETCHED; | 186 goto UNSTRETCHED; |
195 } | 187 } |
196 } else { | 188 } else { |
197 UNSTRETCHED: | 189 UNSTRETCHED: |
198 make_unstretched_key(key, imageID, subset); | 190 make_unstretched_key(key, imageID, subset); |
199 } | 191 } |
200 } | 192 } |
201 | 193 |
202 static void make_image_keys(uint32_t imageID, const SkIRect& subset, const Stret
ch& stretch, | 194 static void make_image_keys(uint32_t imageID, const SkIRect& subset, const SkGrS
tretch& stretch, |
203 GrUniqueKey* key, GrUniqueKey* stretchedKey) { | 195 GrUniqueKey* key, GrUniqueKey* stretchedKey) { |
204 make_unstretched_key(key, imageID, subset); | 196 make_unstretched_key(key, imageID, subset); |
205 if (Stretch::kNone_Type != stretch.fType) { | 197 if (SkGrStretch::kNone_Type != stretch.fType) { |
206 make_stretched_key(*key, stretch, stretchedKey); | 198 make_stretched_key(*key, stretch, stretchedKey); |
207 } | 199 } |
208 } | 200 } |
209 | 201 |
210 GrSurfaceDesc GrImageInfoToSurfaceDesc(const SkImageInfo& info) { | 202 GrSurfaceDesc GrImageInfoToSurfaceDesc(const SkImageInfo& info) { |
211 GrSurfaceDesc desc; | 203 GrSurfaceDesc desc; |
212 desc.fFlags = kNone_GrSurfaceFlags; | 204 desc.fFlags = kNone_GrSurfaceFlags; |
213 desc.fWidth = info.width(); | 205 desc.fWidth = info.width(); |
214 desc.fHeight = info.height(); | 206 desc.fHeight = info.height(); |
215 desc.fConfig = SkImageInfo2GrPixelConfig(info); | 207 desc.fConfig = SkImageInfo2GrPixelConfig(info); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
247 pixelRefForInvalidationNotification->addGenIDChangeListener(listener
); | 239 pixelRefForInvalidationNotification->addGenIDChangeListener(listener
); |
248 } | 240 } |
249 ctx->textureProvider()->assignUniqueKeyToTexture(optionalKey, result); | 241 ctx->textureProvider()->assignUniqueKeyToTexture(optionalKey, result); |
250 } | 242 } |
251 return result; | 243 return result; |
252 } | 244 } |
253 | 245 |
254 // creates a new texture that is the input texture scaled up. If optionalKey is
valid it will be | 246 // creates a new texture that is the input texture scaled up. If optionalKey is
valid it will be |
255 // set on the new texture. stretch controls whether the scaling is done using ne
arest or bilerp | 247 // set on the new texture. stretch controls whether the scaling is done using ne
arest or bilerp |
256 // filtering and the size to stretch the texture to. | 248 // filtering and the size to stretch the texture to. |
257 GrTexture* stretch_texture(GrTexture* inputTexture, const Stretch& stretch, | 249 GrTexture* stretch_texture(GrTexture* inputTexture, const SkGrStretch& stretch, |
258 SkPixelRef* pixelRef, | 250 SkPixelRef* pixelRef, |
259 const GrUniqueKey& optionalKey) { | 251 const GrUniqueKey& optionalKey) { |
260 SkASSERT(Stretch::kNone_Type != stretch.fType); | 252 SkASSERT(SkGrStretch::kNone_Type != stretch.fType); |
261 | 253 |
262 GrContext* context = inputTexture->getContext(); | 254 GrContext* context = inputTexture->getContext(); |
263 SkASSERT(context); | 255 SkASSERT(context); |
264 const GrCaps* caps = context->caps(); | 256 const GrCaps* caps = context->caps(); |
265 | 257 |
266 // Either it's a cache miss or the original wasn't cached to begin with. | 258 // Either it's a cache miss or the original wasn't cached to begin with. |
267 GrSurfaceDesc rtDesc = inputTexture->desc(); | 259 GrSurfaceDesc rtDesc = inputTexture->desc(); |
268 rtDesc.fFlags = rtDesc.fFlags | kRenderTarget_GrSurfaceFlag; | 260 rtDesc.fFlags = rtDesc.fFlags | kRenderTarget_GrSurfaceFlag; |
269 rtDesc.fWidth = stretch.fWidth; | 261 rtDesc.fWidth = stretch.fWidth; |
270 rtDesc.fHeight = stretch.fHeight; | 262 rtDesc.fHeight = stretch.fHeight; |
(...skipping 25 matching lines...) Expand all Loading... |
296 SkAutoTUnref<GrTexture> stretched(GrCreateTextureForPixels(context, optional
Key, rtDesc, | 288 SkAutoTUnref<GrTexture> stretched(GrCreateTextureForPixels(context, optional
Key, rtDesc, |
297 pixelRef, nullptr
,0)); | 289 pixelRef, nullptr
,0)); |
298 if (!stretched) { | 290 if (!stretched) { |
299 return nullptr; | 291 return nullptr; |
300 } | 292 } |
301 GrPaint paint; | 293 GrPaint paint; |
302 | 294 |
303 // If filtering is not desired then we want to ensure all texels in the resa
mpled image are | 295 // If filtering is not desired then we want to ensure all texels in the resa
mpled image are |
304 // copies of texels from the original. | 296 // copies of texels from the original. |
305 GrTextureParams params(SkShader::kClamp_TileMode, | 297 GrTextureParams params(SkShader::kClamp_TileMode, |
306 Stretch::kBilerp_Type == stretch.fType ? | 298 SkGrStretch::kBilerp_Type == stretch.fType ? |
307 GrTextureParams::kBilerp_FilterMode : | 299 GrTextureParams::kBilerp_FilterMode : |
308 GrTextureParams::kNone_FilterMode); | 300 GrTextureParams::kNone_FilterMode); |
309 paint.addColorTextureProcessor(inputTexture, SkMatrix::I(), params); | 301 paint.addColorTextureProcessor(inputTexture, SkMatrix::I(), params); |
310 | 302 |
311 SkRect rect = SkRect::MakeWH(SkIntToScalar(rtDesc.fWidth), SkIntToScalar(rtD
esc.fHeight)); | 303 SkRect rect = SkRect::MakeWH(SkIntToScalar(rtDesc.fWidth), SkIntToScalar(rtD
esc.fHeight)); |
312 SkRect localRect = SkRect::MakeWH(1.f, 1.f); | 304 SkRect localRect = SkRect::MakeWH(1.f, 1.f); |
313 | 305 |
314 SkAutoTUnref<GrDrawContext> drawContext(context->drawContext()); | 306 SkAutoTUnref<GrDrawContext> drawContext(context->drawContext()); |
315 if (!drawContext) { | 307 if (!drawContext) { |
316 return nullptr; | 308 return nullptr; |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
475 | 467 |
476 SkAutoLockPixels alp(*bitmap); | 468 SkAutoLockPixels alp(*bitmap); |
477 if (!bitmap->readyToDraw()) { | 469 if (!bitmap->readyToDraw()) { |
478 return nullptr; | 470 return nullptr; |
479 } | 471 } |
480 | 472 |
481 return GrCreateTextureForPixels(ctx, optionalKey, desc, origBitmap.pixelRef(
), | 473 return GrCreateTextureForPixels(ctx, optionalKey, desc, origBitmap.pixelRef(
), |
482 bitmap->getPixels(), bitmap->rowBytes()); | 474 bitmap->getPixels(), bitmap->rowBytes()); |
483 } | 475 } |
484 | 476 |
485 static SkBitmap stretch_on_cpu(const SkBitmap& bmp, const Stretch& stretch) { | 477 static SkBitmap stretch_on_cpu(const SkBitmap& bmp, const SkGrStretch& stretch)
{ |
486 SkBitmap stretched; | 478 SkBitmap stretched; |
487 stretched.allocN32Pixels(stretch.fWidth, stretch.fHeight); | 479 stretched.allocN32Pixels(stretch.fWidth, stretch.fHeight); |
488 SkCanvas canvas(stretched); | 480 SkCanvas canvas(stretched); |
489 SkPaint paint; | 481 SkPaint paint; |
490 switch (stretch.fType) { | 482 switch (stretch.fType) { |
491 case Stretch::kNearest_Type: | 483 case SkGrStretch::kNearest_Type: |
492 paint.setFilterQuality(kNone_SkFilterQuality); | 484 paint.setFilterQuality(kNone_SkFilterQuality); |
493 break; | 485 break; |
494 case Stretch::kBilerp_Type: | 486 case SkGrStretch::kBilerp_Type: |
495 paint.setFilterQuality(kLow_SkFilterQuality); | 487 paint.setFilterQuality(kLow_SkFilterQuality); |
496 break; | 488 break; |
497 case Stretch::kNone_Type: | 489 case SkGrStretch::kNone_Type: |
498 SkDEBUGFAIL("Shouldn't get here."); | 490 SkDEBUGFAIL("Shouldn't get here."); |
499 break; | 491 break; |
500 } | 492 } |
501 SkRect dstRect = SkRect::MakeWH(SkIntToScalar(stretch.fWidth), SkIntToScalar
(stretch.fHeight)); | 493 SkRect dstRect = SkRect::MakeWH(SkIntToScalar(stretch.fWidth), SkIntToScalar
(stretch.fHeight)); |
502 canvas.drawBitmapRect(bmp, dstRect, &paint); | 494 canvas.drawBitmapRect(bmp, dstRect, &paint); |
503 return stretched; | 495 return stretched; |
504 } | 496 } |
505 | 497 |
506 static GrTexture* create_bitmap_texture(GrContext* ctx, | |
507 const SkBitmap& bmp, | |
508 const Stretch& stretch, | |
509 const GrUniqueKey& unstretchedKey, | |
510 const GrUniqueKey& stretchedKey) { | |
511 if (Stretch::kNone_Type != stretch.fType) { | |
512 SkAutoTUnref<GrTexture> unstretched; | |
513 // Check if we have the unstretched version in the cache, if not create
it. | |
514 if (unstretchedKey.isValid()) { | |
515 unstretched.reset(ctx->textureProvider()->findAndRefTextureByUniqueK
ey(unstretchedKey)); | |
516 } | |
517 if (!unstretched) { | |
518 unstretched.reset(create_unstretched_bitmap_texture(ctx, bmp, unstre
tchedKey)); | |
519 if (!unstretched) { | |
520 // We might not have been able to create a unstrecthed texture b
ecause it is smaller | |
521 // than the min texture size. In that case do cpu stretching. | |
522 SkBitmap stretchedBmp = stretch_on_cpu(bmp, stretch); | |
523 return create_unstretched_bitmap_texture(ctx, stretchedBmp, stre
tchedKey); | |
524 } | |
525 } | |
526 return stretch_texture(unstretched, stretch, bmp.pixelRef(), stretchedKe
y); | |
527 } | |
528 return create_unstretched_bitmap_texture(ctx, bmp, unstretchedKey); | |
529 } | |
530 | |
531 bool GrIsImageInCache(const GrContext* ctx, uint32_t imageID, const SkIRect& sub
set, | 498 bool GrIsImageInCache(const GrContext* ctx, uint32_t imageID, const SkIRect& sub
set, |
532 GrTexture* nativeTexture, const GrTextureParams* params) { | 499 GrTexture* nativeTexture, const GrTextureParams* params) { |
533 Stretch stretch; | 500 SkGrStretch stretch; |
534 get_stretch(ctx, subset.width(), subset.height(), params, &stretch); | 501 get_stretch(ctx, subset.width(), subset.height(), params, &stretch); |
535 | 502 |
536 // Handle the case where the bitmap/image is explicitly texture backed. | 503 // Handle the case where the bitmap/image is explicitly texture backed. |
537 if (nativeTexture) { | 504 if (nativeTexture) { |
538 if (Stretch::kNone_Type == stretch.fType) { | 505 if (SkGrStretch::kNone_Type == stretch.fType) { |
539 return true; | 506 return true; |
540 } | 507 } |
541 const GrUniqueKey& key = nativeTexture->getUniqueKey(); | 508 const GrUniqueKey& key = nativeTexture->getUniqueKey(); |
542 if (!key.isValid()) { | 509 if (!key.isValid()) { |
543 return false; | 510 return false; |
544 } | 511 } |
545 GrUniqueKey stretchedKey; | 512 GrUniqueKey stretchedKey; |
546 make_stretched_key(key, stretch, &stretchedKey); | 513 make_stretched_key(key, stretch, &stretchedKey); |
547 return ctx->textureProvider()->existsTextureWithUniqueKey(stretchedKey); | 514 return ctx->textureProvider()->existsTextureWithUniqueKey(stretchedKey); |
548 } | 515 } |
549 | 516 |
550 GrUniqueKey key, stretchedKey; | 517 GrUniqueKey key, stretchedKey; |
551 make_image_keys(imageID, subset, stretch, &key, &stretchedKey); | 518 make_image_keys(imageID, subset, stretch, &key, &stretchedKey); |
552 return ctx->textureProvider()->existsTextureWithUniqueKey( | 519 return ctx->textureProvider()->existsTextureWithUniqueKey( |
553 (Stretch::kNone_Type == stretch.fType) ? key : stretchedKey); | 520 (SkGrStretch::kNone_Type == stretch.fType) ? key : stretchedKey); |
554 } | 521 } |
555 | 522 |
556 bool GrIsBitmapInCache(const GrContext* ctx, const SkBitmap& bitmap, | 523 bool GrIsBitmapInCache(const GrContext* ctx, const SkBitmap& bitmap, |
557 const GrTextureParams* params) { | 524 const GrTextureParams* params) { |
558 if (bitmap.isVolatile()) { | 525 if (bitmap.isVolatile()) { |
559 return false; // we don't cache volatile bitmaps. | 526 return false; // we don't cache volatile bitmaps. |
560 } | 527 } |
561 return GrIsImageInCache(ctx, bitmap.getGenerationID(), bitmap.getSubset(), b
itmap.getTexture(), | 528 return GrIsImageInCache(ctx, bitmap.getGenerationID(), bitmap.getSubset(), b
itmap.getTexture(), |
562 params); | 529 params); |
563 } | 530 } |
564 | 531 |
565 GrTexture* GrRefCachedBitmapTexture(GrContext* ctx, | 532 class Bitmap_GrTextureMaker : public GrTextureMaker { |
566 const SkBitmap& bitmap, | 533 public: |
567 const GrTextureParams* params) { | 534 Bitmap_GrTextureMaker(const SkBitmap& bitmap) |
| 535 : INHERITED(bitmap.width(), bitmap.height()) |
| 536 , fBitmap(bitmap) |
| 537 {} |
568 | 538 |
569 Stretch stretch; | 539 protected: |
570 get_stretch(ctx, bitmap.width(), bitmap.height(), params, &stretch); | 540 GrTexture* onRefUnstretchedTexture(GrContext* ctx) override { |
| 541 GrTexture* tex = fBitmap.getTexture(); |
| 542 if (tex) { |
| 543 return SkRef(tex); |
| 544 } |
571 | 545 |
572 GrTexture* result = bitmap.getTexture(); | 546 GrUniqueKey unstretchedKey; |
573 if (result) { | 547 make_unstretched_key(&unstretchedKey, fBitmap.getGenerationID(), fBitmap
.getSubset()); |
574 if (Stretch::kNone_Type == stretch.fType) { | |
575 return SkRef(result); | |
576 } | |
577 GrUniqueKey stretchedKey; | |
578 // Don't create a key for the resized version if the bmp is volatile. | |
579 if (!bitmap.isVolatile()) { | |
580 const GrUniqueKey& key = result->getUniqueKey(); | |
581 if (key.isValid()) { | |
582 make_stretched_key(key, stretch, &stretchedKey); | |
583 GrTexture* stretched = | |
584 ctx->textureProvider()->findAndRefTextureByUniqueKey(stretch
edKey); | |
585 if (stretched) { | |
586 return stretched; | |
587 } | |
588 } | |
589 } | |
590 return stretch_texture(result, stretch, bitmap.pixelRef(), stretchedKey)
; | |
591 } | |
592 | 548 |
593 GrUniqueKey key, resizedKey; | 549 GrTexture* result = ctx->textureProvider()->findAndRefTextureByUniqueKey
(unstretchedKey); |
594 | |
595 if (!bitmap.isVolatile()) { | |
596 // If the bitmap isn't changing try to find a cached copy first. | |
597 make_image_keys(bitmap.getGenerationID(), bitmap.getSubset(), stretch, &
key, &resizedKey); | |
598 | |
599 result = ctx->textureProvider()->findAndRefTextureByUniqueKey( | |
600 resizedKey.isValid() ? resizedKey : key); | |
601 if (result) { | 550 if (result) { |
602 return result; | 551 return result; |
603 } | 552 } |
| 553 return create_unstretched_bitmap_texture(ctx, fBitmap, unstretchedKey); |
604 } | 554 } |
605 | 555 |
606 result = create_bitmap_texture(ctx, bitmap, stretch, key, resizedKey); | 556 bool onMakeStretchedKey(const SkGrStretch& stretch, GrUniqueKey* stretchedKe
y) override { |
607 if (result) { | 557 if (fBitmap.isVolatile()) { |
608 return result; | 558 return false; |
| 559 } |
| 560 |
| 561 GrUniqueKey unstretchedKey; |
| 562 make_unstretched_key(&unstretchedKey, fBitmap.getGenerationID(), fBitmap
.getSubset()); |
| 563 return make_stretched_key(unstretchedKey, stretch, stretchedKey); |
609 } | 564 } |
610 | 565 |
611 SkErrorInternals::SetError( kInternalError_SkError, | 566 void onNotifyStretchCached(const GrUniqueKey& stretchedKey) override { |
612 "---- failed to create texture for cache [%d %d]
\n", | 567 fBitmap.pixelRef()->addGenIDChangeListener(new BitmapInvalidator(stretch
edKey)); |
613 bitmap.width(), bitmap.height()); | 568 } |
614 | 569 |
615 return nullptr; | 570 bool onGetROBitmap(SkBitmap* bitmap) override { |
| 571 *bitmap = fBitmap; |
| 572 return true; |
| 573 } |
| 574 |
| 575 private: |
| 576 const SkBitmap fBitmap; |
| 577 |
| 578 typedef GrTextureMaker INHERITED; |
| 579 }; |
| 580 |
| 581 GrTexture* GrRefCachedBitmapTexture(GrContext* ctx, const SkBitmap& bitmap, |
| 582 const GrTextureParams* params) { |
| 583 return Bitmap_GrTextureMaker(bitmap).refCachedTexture(ctx, params); |
616 } | 584 } |
617 | 585 |
618 // TODO: make this be the canonical signature, and turn the version that takes G
rTextureParams* | 586 // TODO: make this be the canonical signature, and turn the version that takes G
rTextureParams* |
619 // into a wrapper that contains the inverse of these tables. | 587 // into a wrapper that contains the inverse of these tables. |
620 GrTexture* GrRefCachedBitmapTexture(GrContext* ctx, | 588 GrTexture* GrRefCachedBitmapTexture(GrContext* ctx, |
621 const SkBitmap& bitmap, | 589 const SkBitmap& bitmap, |
622 SkImageUsageType usage) { | 590 SkImageUsageType usage) { |
623 // Just need a params that will trigger the correct cache key / etc, since t
he usage doesn't | 591 // Just need a params that will trigger the correct cache key / etc, since t
he usage doesn't |
624 // tell us the specifics about filter level or specific tiling. | 592 // tell us the specifics about filter level or specific tiling. |
625 | 593 |
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
941 SkErrorInternals::SetError( kInvalidPaint_SkError, | 909 SkErrorInternals::SetError( kInvalidPaint_SkError, |
942 "Sorry, I don't understand the filtering
" | 910 "Sorry, I don't understand the filtering
" |
943 "mode you asked for. Falling back to " | 911 "mode you asked for. Falling back to " |
944 "MIPMaps."); | 912 "MIPMaps."); |
945 textureFilterMode = GrTextureParams::kMipMap_FilterMode; | 913 textureFilterMode = GrTextureParams::kMipMap_FilterMode; |
946 break; | 914 break; |
947 | 915 |
948 } | 916 } |
949 return textureFilterMode; | 917 return textureFilterMode; |
950 } | 918 } |
| 919 |
| 920 ////////////////////////////////////////////////////////////////////////////////
//////////////// |
| 921 |
| 922 GrTexture* GrTextureMaker::refCachedTexture(GrContext* ctx, const GrTextureParam
s* params) { |
| 923 SkGrStretch stretch; |
| 924 get_stretch(ctx, this->width(), this->height(), params, &stretch); |
| 925 |
| 926 if (SkGrStretch::kNone_Type == stretch.fType) { |
| 927 return this->onRefUnstretchedTexture(ctx); |
| 928 } |
| 929 |
| 930 GrUniqueKey stretchedKey; |
| 931 if (this->onMakeStretchedKey(stretch, &stretchedKey)) { |
| 932 GrTexture* result = ctx->textureProvider()->findAndRefTextureByUniqueKey
(stretchedKey); |
| 933 if (result) { |
| 934 return result; |
| 935 } |
| 936 } |
| 937 |
| 938 GrTexture* result = this->onGenerateStretchedTexture(ctx, stretch); |
| 939 if (!result) { |
| 940 return nullptr; |
| 941 } |
| 942 |
| 943 if (stretchedKey.isValid()) { |
| 944 ctx->textureProvider()->assignUniqueKeyToTexture(stretchedKey, result); |
| 945 this->onNotifyStretchCached(stretchedKey); |
| 946 } |
| 947 return result; |
| 948 } |
| 949 |
| 950 GrTexture* GrTextureMaker::onGenerateStretchedTexture(GrContext* ctx, const SkGr
Stretch& stretch) { |
| 951 if (this->width() < ctx->caps()->minTextureSize() || |
| 952 this->height() < ctx->caps()->minTextureSize()) |
| 953 { |
| 954 // we can't trust our ability to use HW to perform the stretch, so we re
quest |
| 955 // a raster instead, and perform the stretch on the CPU. |
| 956 SkBitmap bitmap; |
| 957 if (!this->onGetROBitmap(&bitmap)) { |
| 958 return nullptr; |
| 959 } |
| 960 SkBitmap stretchedBmp = stretch_on_cpu(bitmap, stretch); |
| 961 return create_unstretched_bitmap_texture(ctx, stretchedBmp, GrUniqueKey(
)); |
| 962 } else { |
| 963 SkAutoTUnref<GrTexture> unstretched(this->onRefUnstretchedTexture(ctx)); |
| 964 if (!unstretched) { |
| 965 return nullptr; |
| 966 } |
| 967 return stretch_texture(unstretched, stretch, nullptr, GrUniqueKey()); |
| 968 } |
| 969 } |
OLD | NEW |