1 /*
2  * Copyright 2010 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "SkGr.h"
9 
10 #include "GrXferProcessor.h"
11 #include "SkColorFilter.h"
12 #include "SkConfig8888.h"
13 #include "SkData.h"
14 #include "SkErrorInternals.h"
15 #include "SkGrPixelRef.h"
16 #include "SkMessageBus.h"
17 #include "SkPixelRef.h"
18 #include "SkResourceCache.h"
19 #include "SkTextureCompressor.h"
20 #include "SkYUVPlanesCache.h"
21 #include "effects/GrDitherEffect.h"
22 #include "effects/GrPorterDuffXferProcessor.h"
23 #include "effects/GrYUVtoRGBEffect.h"
24 
25 #ifndef SK_IGNORE_ETC1_SUPPORT
26 #  include "ktx.h"
27 #  include "etc1.h"
28 #endif
29 
30 /*  Fill out buffer with the compressed format Ganesh expects from a colortable
31  based bitmap. [palette (colortable) + indices].
32 
33  At the moment Ganesh only supports 8bit version. If Ganesh allowed we others
34  we could detect that the colortable.count is <= 16, and then repack the
35  indices as nibbles to save RAM, but it would take more time (i.e. a lot
36  slower than memcpy), so skipping that for now.
37 
38  Ganesh wants a full 256 palette entry, even though Skia's ctable is only as big
39  as the colortable.count says it is.
40  */
build_index8_data(void * buffer,const SkBitmap & bitmap)41 static void build_index8_data(void* buffer, const SkBitmap& bitmap) {
42     SkASSERT(kIndex_8_SkColorType == bitmap.colorType());
43 
44     SkAutoLockPixels alp(bitmap);
45     if (!bitmap.readyToDraw()) {
46         SkDEBUGFAIL("bitmap not ready to draw!");
47         return;
48     }
49 
50     SkColorTable* ctable = bitmap.getColorTable();
51     char* dst = (char*)buffer;
52 
53     const int count = ctable->count();
54 
55     SkDstPixelInfo dstPI;
56     dstPI.fColorType = kRGBA_8888_SkColorType;
57     dstPI.fAlphaType = kPremul_SkAlphaType;
58     dstPI.fPixels = buffer;
59     dstPI.fRowBytes = count * sizeof(SkPMColor);
60 
61     SkSrcPixelInfo srcPI;
62     srcPI.fColorType = kN32_SkColorType;
63     srcPI.fAlphaType = kPremul_SkAlphaType;
64     srcPI.fPixels = ctable->readColors();
65     srcPI.fRowBytes = count * sizeof(SkPMColor);
66 
67     srcPI.convertPixelsTo(&dstPI, count, 1);
68 
69     // always skip a full 256 number of entries, even if we memcpy'd fewer
70     dst += 256 * sizeof(GrColor);
71 
72     if ((unsigned)bitmap.width() == bitmap.rowBytes()) {
73         memcpy(dst, bitmap.getPixels(), bitmap.getSize());
74     } else {
75         // need to trim off the extra bytes per row
76         size_t width = bitmap.width();
77         size_t rowBytes = bitmap.rowBytes();
78         const char* src = (const char*)bitmap.getPixels();
79         for (int y = 0; y < bitmap.height(); y++) {
80             memcpy(dst, src, width);
81             src += rowBytes;
82             dst += width;
83         }
84     }
85 }
86 
87 ////////////////////////////////////////////////////////////////////////////////
88 
89 enum Stretch {
90     kNo_Stretch,
91     kBilerp_Stretch,
92     kNearest_Stretch
93 };
94 
get_stretch_type(const GrContext * ctx,int width,int height,const GrTextureParams * params)95 static Stretch get_stretch_type(const GrContext* ctx, int width, int height,
96                                 const GrTextureParams* params) {
97     if (params && params->isTiled()) {
98         if (!ctx->npotTextureTileSupport() && (!SkIsPow2(width) || !SkIsPow2(height))) {
99             switch(params->filterMode()) {
100                 case GrTextureParams::kNone_FilterMode:
101                     return kNearest_Stretch;
102                 case GrTextureParams::kBilerp_FilterMode:
103                 case GrTextureParams::kMipMap_FilterMode:
104                     return kBilerp_Stretch;
105             }
106         }
107     }
108     return kNo_Stretch;
109 }
110 
make_stretched_key(const GrUniqueKey & origKey,Stretch stretch,GrUniqueKey * stretchedKey)111 static bool make_stretched_key(const GrUniqueKey& origKey, Stretch stretch,
112                                GrUniqueKey* stretchedKey) {
113     if (origKey.isValid() && kNo_Stretch != stretch) {
114         static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
115         GrUniqueKey::Builder builder(stretchedKey, origKey, kDomain, 1);
116         builder[0] = stretch;
117         builder.finish();
118         return true;
119     }
120     SkASSERT(!stretchedKey->isValid());
121     return false;
122 }
123 
make_unstretched_key(const SkBitmap & bitmap,GrUniqueKey * key)124 static void make_unstretched_key(const SkBitmap& bitmap, GrUniqueKey* key) {
125     // Our id includes the offset, width, and height so that bitmaps created by extractSubset()
126     // are unique.
127     uint32_t genID = bitmap.getGenerationID();
128     SkIPoint origin = bitmap.pixelRefOrigin();
129     uint32_t width = SkToU16(bitmap.width());
130     uint32_t height = SkToU16(bitmap.height());
131 
132     static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
133     GrUniqueKey::Builder builder(key, kDomain, 4);
134     builder[0] = genID;
135     builder[1] = origin.fX;
136     builder[2] = origin.fY;
137     builder[3] = width | (height << 16);
138 }
139 
make_bitmap_keys(const SkBitmap & bitmap,Stretch stretch,GrUniqueKey * key,GrUniqueKey * stretchedKey)140 static void make_bitmap_keys(const SkBitmap& bitmap,
141                              Stretch stretch,
142                              GrUniqueKey* key,
143                              GrUniqueKey* stretchedKey) {
144     make_unstretched_key(bitmap, key);
145     if (kNo_Stretch != stretch) {
146         make_stretched_key(*key, stretch, stretchedKey);
147     }
148 }
149 
generate_bitmap_texture_desc(const SkBitmap & bitmap,GrSurfaceDesc * desc)150 static void generate_bitmap_texture_desc(const SkBitmap& bitmap, GrSurfaceDesc* desc) {
151     desc->fFlags = kNone_GrSurfaceFlags;
152     desc->fWidth = bitmap.width();
153     desc->fHeight = bitmap.height();
154     desc->fConfig = SkImageInfo2GrPixelConfig(bitmap.info());
155     desc->fSampleCnt = 0;
156 }
157 
158 namespace {
159 
160 // When the SkPixelRef genID changes, invalidate a corresponding GrResource described by key.
161 class BitmapInvalidator : public SkPixelRef::GenIDChangeListener {
162 public:
BitmapInvalidator(const GrUniqueKey & key)163     explicit BitmapInvalidator(const GrUniqueKey& key) : fMsg(key) {}
164 private:
165     GrUniqueKeyInvalidatedMessage fMsg;
166 
onChange()167     void onChange() override {
168         SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(fMsg);
169     }
170 };
171 
172 }  // namespace
173 
174 
create_texture_for_bmp(GrContext * ctx,const GrUniqueKey & optionalKey,GrSurfaceDesc desc,SkPixelRef * pixelRefForInvalidationNotification,const void * pixels,size_t rowBytes)175 static GrTexture* create_texture_for_bmp(GrContext* ctx,
176                                          const GrUniqueKey& optionalKey,
177                                          GrSurfaceDesc desc,
178                                          SkPixelRef* pixelRefForInvalidationNotification,
179                                          const void* pixels,
180                                          size_t rowBytes) {
181     GrTexture* result = ctx->textureProvider()->createTexture(desc, true, pixels, rowBytes);
182     if (result && optionalKey.isValid()) {
183         BitmapInvalidator* listener = SkNEW_ARGS(BitmapInvalidator, (optionalKey));
184         pixelRefForInvalidationNotification->addGenIDChangeListener(listener);
185         ctx->textureProvider()->assignUniqueKeyToTexture(optionalKey, result);
186     }
187     return result;
188 }
189 
190 // creates a new texture that is the input texture scaled up to the next power of two in
191 // width or height. If optionalKey is valid it will be set on the new texture. stretch
192 // controls whether the scaling is done using nearest or bilerp filtering.
stretch_texture_to_next_pot(GrTexture * inputTexture,Stretch stretch,SkPixelRef * pixelRef,const GrUniqueKey & optionalKey)193 GrTexture* stretch_texture_to_next_pot(GrTexture* inputTexture, Stretch stretch,
194                                        SkPixelRef* pixelRef,
195                                        const GrUniqueKey& optionalKey) {
196     SkASSERT(kNo_Stretch != stretch);
197 
198     GrContext* context = inputTexture->getContext();
199     SkASSERT(context);
200 
201     // Either it's a cache miss or the original wasn't cached to begin with.
202     GrSurfaceDesc rtDesc = inputTexture->desc();
203     rtDesc.fFlags =  rtDesc.fFlags | kRenderTarget_GrSurfaceFlag;
204     rtDesc.fWidth  = GrNextPow2(rtDesc.fWidth);
205     rtDesc.fHeight = GrNextPow2(rtDesc.fHeight);
206     rtDesc.fConfig = GrMakePixelConfigUncompressed(rtDesc.fConfig);
207 
208     // If the config isn't renderable try converting to either A8 or an 32 bit config. Otherwise,
209     // fail.
210     if (!context->isConfigRenderable(rtDesc.fConfig, false)) {
211         if (GrPixelConfigIsAlphaOnly(rtDesc.fConfig)) {
212             if (context->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) {
213                 rtDesc.fConfig = kAlpha_8_GrPixelConfig;
214             } else if (context->isConfigRenderable(kSkia8888_GrPixelConfig, false)) {
215                 rtDesc.fConfig = kSkia8888_GrPixelConfig;
216             } else {
217                 return NULL;
218             }
219         } else if (kRGB_GrColorComponentFlags ==
220                    (kRGB_GrColorComponentFlags & GrPixelConfigComponentMask(rtDesc.fConfig))) {
221             if (context->isConfigRenderable(kSkia8888_GrPixelConfig, false)) {
222                 rtDesc.fConfig = kSkia8888_GrPixelConfig;
223             } else {
224                 return NULL;
225             }
226         } else {
227             return NULL;
228         }
229     }
230 
231     GrTexture* stretched = create_texture_for_bmp(context, optionalKey, rtDesc, pixelRef, NULL, 0);
232 
233     if (!stretched) {
234         return NULL;
235     }
236     GrPaint paint;
237 
238     // If filtering is not desired then we want to ensure all texels in the resampled image are
239     // copies of texels from the original.
240     GrTextureParams params(SkShader::kClamp_TileMode,
241                            kBilerp_Stretch == stretch ? GrTextureParams::kBilerp_FilterMode :
242                                                         GrTextureParams::kNone_FilterMode);
243     paint.addColorTextureProcessor(inputTexture, SkMatrix::I(), params);
244 
245     SkRect rect = SkRect::MakeWH(SkIntToScalar(rtDesc.fWidth), SkIntToScalar(rtDesc.fHeight));
246     SkRect localRect = SkRect::MakeWH(1.f, 1.f);
247 
248     context->drawNonAARectToRect(stretched->asRenderTarget(), GrClip::WideOpen(), paint,
249                                  SkMatrix::I(), rect, localRect);
250 
251     return stretched;
252 }
253 
254 #ifndef SK_IGNORE_ETC1_SUPPORT
load_etc1_texture(GrContext * ctx,const GrUniqueKey & optionalKey,const SkBitmap & bm,GrSurfaceDesc desc)255 static GrTexture *load_etc1_texture(GrContext* ctx, const GrUniqueKey& optionalKey,
256                                     const SkBitmap &bm, GrSurfaceDesc desc) {
257     SkAutoTUnref<SkData> data(bm.pixelRef()->refEncodedData());
258 
259     // Is this even encoded data?
260     if (NULL == data) {
261         return NULL;
262     }
263 
264     // Is this a valid PKM encoded data?
265     const uint8_t *bytes = data->bytes();
266     if (etc1_pkm_is_valid(bytes)) {
267         uint32_t encodedWidth = etc1_pkm_get_width(bytes);
268         uint32_t encodedHeight = etc1_pkm_get_height(bytes);
269 
270         // Does the data match the dimensions of the bitmap? If not,
271         // then we don't know how to scale the image to match it...
272         if (encodedWidth != static_cast<uint32_t>(bm.width()) ||
273             encodedHeight != static_cast<uint32_t>(bm.height())) {
274             return NULL;
275         }
276 
277         // Everything seems good... skip ahead to the data.
278         bytes += ETC_PKM_HEADER_SIZE;
279         desc.fConfig = kETC1_GrPixelConfig;
280     } else if (SkKTXFile::is_ktx(bytes)) {
281         SkKTXFile ktx(data);
282 
283         // Is it actually an ETC1 texture?
284         if (!ktx.isCompressedFormat(SkTextureCompressor::kETC1_Format)) {
285             return NULL;
286         }
287 
288         // Does the data match the dimensions of the bitmap? If not,
289         // then we don't know how to scale the image to match it...
290         if (ktx.width() != bm.width() || ktx.height() != bm.height()) {
291             return NULL;
292         }
293 
294         bytes = ktx.pixelData();
295         desc.fConfig = kETC1_GrPixelConfig;
296     } else {
297         return NULL;
298     }
299 
300     return create_texture_for_bmp(ctx, optionalKey, desc, bm.pixelRef(), bytes, 0);
301 }
302 #endif   // SK_IGNORE_ETC1_SUPPORT
303 
load_yuv_texture(GrContext * ctx,const GrUniqueKey & optionalKey,const SkBitmap & bm,const GrSurfaceDesc & desc)304 static GrTexture* load_yuv_texture(GrContext* ctx, const GrUniqueKey& optionalKey,
305                                    const SkBitmap& bm, const GrSurfaceDesc& desc) {
306     // Subsets are not supported, the whole pixelRef is loaded when using YUV decoding
307     SkPixelRef* pixelRef = bm.pixelRef();
308     if ((NULL == pixelRef) ||
309         (pixelRef->info().width()  != bm.info().width()) ||
310         (pixelRef->info().height() != bm.info().height())) {
311         return NULL;
312     }
313 
314     const bool useCache = optionalKey.isValid();
315     SkYUVPlanesCache::Info yuvInfo;
316     SkAutoTUnref<SkCachedData> cachedData;
317     SkAutoMalloc storage;
318     if (useCache) {
319         cachedData.reset(SkYUVPlanesCache::FindAndRef(pixelRef->getGenerationID(), &yuvInfo));
320     }
321 
322     void* planes[3];
323     if (cachedData.get()) {
324         planes[0] = (void*)cachedData->data();
325         planes[1] = (uint8_t*)planes[0] + yuvInfo.fSizeInMemory[0];
326         planes[2] = (uint8_t*)planes[1] + yuvInfo.fSizeInMemory[1];
327     } else {
328         // Fetch yuv plane sizes for memory allocation. Here, width and height can be
329         // rounded up to JPEG block size and be larger than the image's width and height.
330         if (!pixelRef->getYUV8Planes(yuvInfo.fSize, NULL, NULL, NULL)) {
331             return NULL;
332         }
333 
334         // Allocate the memory for YUV
335         size_t totalSize(0);
336         for (int i = 0; i < 3; ++i) {
337             yuvInfo.fRowBytes[i] = yuvInfo.fSize[i].fWidth;
338             yuvInfo.fSizeInMemory[i] = yuvInfo.fRowBytes[i] * yuvInfo.fSize[i].fHeight;
339             totalSize += yuvInfo.fSizeInMemory[i];
340         }
341         if (useCache) {
342             cachedData.reset(SkResourceCache::NewCachedData(totalSize));
343             planes[0] = cachedData->writable_data();
344         } else {
345             storage.reset(totalSize);
346             planes[0] = storage.get();
347         }
348         planes[1] = (uint8_t*)planes[0] + yuvInfo.fSizeInMemory[0];
349         planes[2] = (uint8_t*)planes[1] + yuvInfo.fSizeInMemory[1];
350 
351         // Get the YUV planes and update plane sizes to actual image size
352         if (!pixelRef->getYUV8Planes(yuvInfo.fSize, planes, yuvInfo.fRowBytes,
353                                      &yuvInfo.fColorSpace)) {
354             return NULL;
355         }
356 
357         if (useCache) {
358             // Decoding is done, cache the resulting YUV planes
359             SkYUVPlanesCache::Add(pixelRef->getGenerationID(), cachedData, &yuvInfo);
360         }
361     }
362 
363     GrSurfaceDesc yuvDesc;
364     yuvDesc.fConfig = kAlpha_8_GrPixelConfig;
365     SkAutoTUnref<GrTexture> yuvTextures[3];
366     for (int i = 0; i < 3; ++i) {
367         yuvDesc.fWidth  = yuvInfo.fSize[i].fWidth;
368         yuvDesc.fHeight = yuvInfo.fSize[i].fHeight;
369         bool needsExactTexture =
370             (yuvDesc.fWidth  != yuvInfo.fSize[0].fWidth) ||
371             (yuvDesc.fHeight != yuvInfo.fSize[0].fHeight);
372         yuvTextures[i].reset(ctx->textureProvider()->refScratchTexture(yuvDesc,
373             needsExactTexture ? GrTextureProvider::kExact_ScratchTexMatch :
374                                 GrTextureProvider::kApprox_ScratchTexMatch));
375         if (!yuvTextures[i] ||
376             !yuvTextures[i]->writePixels(0, 0, yuvDesc.fWidth, yuvDesc.fHeight,
377                                          yuvDesc.fConfig, planes[i], yuvInfo.fRowBytes[i])) {
378             return NULL;
379         }
380     }
381 
382     GrSurfaceDesc rtDesc = desc;
383     rtDesc.fFlags = rtDesc.fFlags | kRenderTarget_GrSurfaceFlag;
384 
385     GrTexture* result = create_texture_for_bmp(ctx, optionalKey, rtDesc, pixelRef, NULL, 0);
386     if (!result) {
387         return NULL;
388     }
389 
390     GrRenderTarget* renderTarget = result->asRenderTarget();
391     SkASSERT(renderTarget);
392 
393     SkAutoTUnref<GrFragmentProcessor>
394         yuvToRgbProcessor(GrYUVtoRGBEffect::Create(yuvTextures[0], yuvTextures[1], yuvTextures[2],
395                                                    yuvInfo.fSize, yuvInfo.fColorSpace));
396     GrPaint paint;
397     paint.addColorProcessor(yuvToRgbProcessor);
398     SkRect r = SkRect::MakeWH(SkIntToScalar(yuvInfo.fSize[0].fWidth),
399                               SkIntToScalar(yuvInfo.fSize[0].fHeight));
400 
401     ctx->drawRect(renderTarget, GrClip::WideOpen(), paint, SkMatrix::I(), r);
402 
403     return result;
404 }
405 
create_unstretched_bitmap_texture(GrContext * ctx,const SkBitmap & origBitmap,const GrUniqueKey & optionalKey)406 static GrTexture* create_unstretched_bitmap_texture(GrContext* ctx,
407                                                     const SkBitmap& origBitmap,
408                                                     const GrUniqueKey& optionalKey) {
409     SkBitmap tmpBitmap;
410 
411     const SkBitmap* bitmap = &origBitmap;
412 
413     GrSurfaceDesc desc;
414     generate_bitmap_texture_desc(*bitmap, &desc);
415 
416     if (kIndex_8_SkColorType == bitmap->colorType()) {
417         if (ctx->isConfigTexturable(kIndex_8_GrPixelConfig)) {
418             size_t imageSize = GrCompressedFormatDataSize(kIndex_8_GrPixelConfig,
419                                                           bitmap->width(), bitmap->height());
420             SkAutoMalloc storage(imageSize);
421             build_index8_data(storage.get(), origBitmap);
422 
423             // our compressed data will be trimmed, so pass width() for its
424             // "rowBytes", since they are the same now.
425             return create_texture_for_bmp(ctx, optionalKey, desc, origBitmap.pixelRef(),
426                                           storage.get(), bitmap->width());
427         } else {
428             origBitmap.copyTo(&tmpBitmap, kN32_SkColorType);
429             // now bitmap points to our temp, which has been promoted to 32bits
430             bitmap = &tmpBitmap;
431             desc.fConfig = SkImageInfo2GrPixelConfig(bitmap->info());
432         }
433     }
434 
435     // Is this an ETC1 encoded texture?
436 #ifndef SK_IGNORE_ETC1_SUPPORT
437     // Make sure that the underlying device supports ETC1 textures before we go ahead
438     // and check the data.
439     else if (ctx->isConfigTexturable(kETC1_GrPixelConfig)
440             // If the bitmap had compressed data and was then uncompressed, it'll still return
441             // compressed data on 'refEncodedData' and upload it. Probably not good, since if
442             // the bitmap has available pixels, then they might not be what the decompressed
443             // data is.
444             && !(bitmap->readyToDraw())) {
445         GrTexture *texture = load_etc1_texture(ctx, optionalKey, *bitmap, desc);
446         if (texture) {
447             return texture;
448         }
449     }
450 #endif   // SK_IGNORE_ETC1_SUPPORT
451 
452     GrTexture *texture = load_yuv_texture(ctx, optionalKey, *bitmap, desc);
453     if (texture) {
454         return texture;
455     }
456 
457     SkAutoLockPixels alp(*bitmap);
458     if (!bitmap->readyToDraw()) {
459         return NULL;
460     }
461 
462     return create_texture_for_bmp(ctx, optionalKey, desc, origBitmap.pixelRef(),
463                                   bitmap->getPixels(), bitmap->rowBytes());
464 }
465 
create_bitmap_texture(GrContext * ctx,const SkBitmap & bmp,Stretch stretch,const GrUniqueKey & unstretchedKey,const GrUniqueKey & stretchedKey)466 static GrTexture* create_bitmap_texture(GrContext* ctx,
467                                         const SkBitmap& bmp,
468                                         Stretch stretch,
469                                         const GrUniqueKey& unstretchedKey,
470                                         const GrUniqueKey& stretchedKey) {
471     if (kNo_Stretch != stretch) {
472         SkAutoTUnref<GrTexture> unstretched;
473         // Check if we have the unstretched version in the cache, if not create it.
474         if (unstretchedKey.isValid()) {
475             unstretched.reset(ctx->textureProvider()->findAndRefTextureByUniqueKey(unstretchedKey));
476         }
477         if (!unstretched) {
478             unstretched.reset(create_unstretched_bitmap_texture(ctx, bmp, unstretchedKey));
479             if (!unstretched) {
480                 return NULL;
481             }
482         }
483         GrTexture* stretched = stretch_texture_to_next_pot(unstretched, stretch, bmp.pixelRef(),
484                                                            stretchedKey);
485         return stretched;
486     }
487 
488     return create_unstretched_bitmap_texture(ctx, bmp, unstretchedKey);
489 
490 }
491 
GrIsBitmapInCache(const GrContext * ctx,const SkBitmap & bitmap,const GrTextureParams * params)492 bool GrIsBitmapInCache(const GrContext* ctx,
493                        const SkBitmap& bitmap,
494                        const GrTextureParams* params) {
495     Stretch stretch = get_stretch_type(ctx, bitmap.width(), bitmap.height(), params);
496 
497     // Handle the case where the bitmap is explicitly texture backed.
498     GrTexture* texture = bitmap.getTexture();
499     if (texture) {
500         if (kNo_Stretch == stretch) {
501             return true;
502         }
503         // No keys for volatile bitmaps.
504         if (bitmap.isVolatile()) {
505             return false;
506         }
507         const GrUniqueKey& key = texture->getUniqueKey();
508         if (!key.isValid()) {
509             return false;
510         }
511         GrUniqueKey stretchedKey;
512         make_stretched_key(key, stretch, &stretchedKey);
513         return ctx->textureProvider()->existsTextureWithUniqueKey(stretchedKey);
514     }
515 
516     // We don't cache volatile bitmaps
517     if (bitmap.isVolatile()) {
518         return false;
519     }
520 
521     GrUniqueKey key, stretchedKey;
522     make_bitmap_keys(bitmap, stretch, &key, &stretchedKey);
523     return ctx->textureProvider()->existsTextureWithUniqueKey(
524         (kNo_Stretch == stretch) ? key : stretchedKey);
525 }
526 
GrRefCachedBitmapTexture(GrContext * ctx,const SkBitmap & bitmap,const GrTextureParams * params)527 GrTexture* GrRefCachedBitmapTexture(GrContext* ctx,
528                                     const SkBitmap& bitmap,
529                                     const GrTextureParams* params) {
530 
531     Stretch stretch = get_stretch_type(ctx, bitmap.width(), bitmap.height(), params);
532 
533     GrTexture* result = bitmap.getTexture();
534     if (result) {
535         if (kNo_Stretch == stretch) {
536             return SkRef(result);
537         }
538         GrUniqueKey stretchedKey;
539         // Don't create a key for the resized version if the bmp is volatile.
540         if (!bitmap.isVolatile()) {
541             const GrUniqueKey& key = result->getUniqueKey();
542             if (key.isValid()) {
543                 make_stretched_key(key, stretch, &stretchedKey);
544                 GrTexture* stretched =
545                     ctx->textureProvider()->findAndRefTextureByUniqueKey(stretchedKey);
546                 if (stretched) {
547                     return stretched;
548                 }
549             }
550         }
551         return stretch_texture_to_next_pot(result, stretch, bitmap.pixelRef(), stretchedKey);
552     }
553 
554     GrUniqueKey key, resizedKey;
555 
556     if (!bitmap.isVolatile()) {
557         // If the bitmap isn't changing try to find a cached copy first.
558         make_bitmap_keys(bitmap, stretch, &key, &resizedKey);
559 
560         result = ctx->textureProvider()->findAndRefTextureByUniqueKey(
561             resizedKey.isValid() ? resizedKey : key);
562         if (result) {
563             return result;
564         }
565     }
566 
567     result = create_bitmap_texture(ctx, bitmap, stretch, key, resizedKey);
568     if (result) {
569         return result;
570     }
571 
572     SkErrorInternals::SetError( kInternalError_SkError,
573                                 "---- failed to create texture for cache [%d %d]\n",
574                                 bitmap.width(), bitmap.height());
575 
576     return NULL;
577 }
578 ///////////////////////////////////////////////////////////////////////////////
579 
580 // alphatype is ignore for now, but if GrPixelConfig is expanded to encompass
581 // alpha info, that will be considered.
SkImageInfo2GrPixelConfig(SkColorType ct,SkAlphaType,SkColorProfileType pt)582 GrPixelConfig SkImageInfo2GrPixelConfig(SkColorType ct, SkAlphaType, SkColorProfileType pt) {
583     switch (ct) {
584         case kUnknown_SkColorType:
585             return kUnknown_GrPixelConfig;
586         case kAlpha_8_SkColorType:
587             return kAlpha_8_GrPixelConfig;
588         case kRGB_565_SkColorType:
589             return kRGB_565_GrPixelConfig;
590         case kARGB_4444_SkColorType:
591             return kRGBA_4444_GrPixelConfig;
592         case kRGBA_8888_SkColorType:
593 //            if (kSRGB_SkColorProfileType == pt) {
594 //                return kSRGBA_8888_GrPixelConfig;
595 //            }
596             return kRGBA_8888_GrPixelConfig;
597         case kBGRA_8888_SkColorType:
598             return kBGRA_8888_GrPixelConfig;
599         case kIndex_8_SkColorType:
600             return kIndex_8_GrPixelConfig;
601         case kGray_8_SkColorType:
602             return kAlpha_8_GrPixelConfig; // TODO: gray8 support on gpu
603     }
604     SkASSERT(0);    // shouldn't get here
605     return kUnknown_GrPixelConfig;
606 }
607 
GrPixelConfig2ColorAndProfileType(GrPixelConfig config,SkColorType * ctOut,SkColorProfileType * ptOut)608 bool GrPixelConfig2ColorAndProfileType(GrPixelConfig config, SkColorType* ctOut,
609                                        SkColorProfileType* ptOut) {
610     SkColorType ct;
611     SkColorProfileType pt = kLinear_SkColorProfileType;
612     switch (config) {
613         case kAlpha_8_GrPixelConfig:
614             ct = kAlpha_8_SkColorType;
615             break;
616         case kIndex_8_GrPixelConfig:
617             ct = kIndex_8_SkColorType;
618             break;
619         case kRGB_565_GrPixelConfig:
620             ct = kRGB_565_SkColorType;
621             break;
622         case kRGBA_4444_GrPixelConfig:
623             ct = kARGB_4444_SkColorType;
624             break;
625         case kRGBA_8888_GrPixelConfig:
626             ct = kRGBA_8888_SkColorType;
627             break;
628         case kBGRA_8888_GrPixelConfig:
629             ct = kBGRA_8888_SkColorType;
630             break;
631         case kSRGBA_8888_GrPixelConfig:
632             ct = kRGBA_8888_SkColorType;
633             pt = kSRGB_SkColorProfileType;
634             break;
635         default:
636             return false;
637     }
638     if (ctOut) {
639         *ctOut = ct;
640     }
641     if (ptOut) {
642         *ptOut = pt;
643     }
644     return true;
645 }
646 
647 ///////////////////////////////////////////////////////////////////////////////
648 
SkPaint2GrPaintNoShader(GrContext * context,GrRenderTarget * rt,const SkPaint & skPaint,GrColor paintColor,bool constantColor,GrPaint * grPaint)649 bool SkPaint2GrPaintNoShader(GrContext* context, GrRenderTarget* rt, const SkPaint& skPaint,
650                              GrColor paintColor, bool constantColor, GrPaint* grPaint) {
651 
652     grPaint->setDither(skPaint.isDither());
653     grPaint->setAntiAlias(skPaint.isAntiAlias());
654 
655     SkXfermode* mode = skPaint.getXfermode();
656     GrXPFactory* xpFactory = NULL;
657     if (!SkXfermode::AsXPFactory(mode, &xpFactory)) {
658         // Fall back to src-over
659         // return false here?
660         xpFactory = GrPorterDuffXPFactory::Create(SkXfermode::kSrcOver_Mode);
661     }
662     SkASSERT(xpFactory);
663     grPaint->setXPFactory(xpFactory)->unref();
664 
665     //set the color of the paint to the one of the parameter
666     grPaint->setColor(paintColor);
667 
668     SkColorFilter* colorFilter = skPaint.getColorFilter();
669     if (colorFilter) {
670         // if the source color is a constant then apply the filter here once rather than per pixel
671         // in a shader.
672         if (constantColor) {
673             SkColor filtered = colorFilter->filterColor(skPaint.getColor());
674             grPaint->setColor(SkColor2GrColor(filtered));
675         } else {
676             SkTDArray<GrFragmentProcessor*> array;
677             // return false if failed?
678             if (colorFilter->asFragmentProcessors(context, &array)) {
679                 for (int i = 0; i < array.count(); ++i) {
680                     grPaint->addColorProcessor(array[i]);
681                     array[i]->unref();
682                 }
683             }
684         }
685     }
686 
687 #ifndef SK_IGNORE_GPU_DITHER
688     // If the dither flag is set, then we need to see if the underlying context
689     // supports it. If not, then install a dither effect.
690     if (skPaint.isDither() && grPaint->numColorStages() > 0) {
691         // What are we rendering into?
692         SkASSERT(rt);
693 
694         // Suspect the dithering flag has no effect on these configs, otherwise
695         // fall back on setting the appropriate state.
696         if (GrPixelConfigIs8888(rt->config()) ||
697             GrPixelConfigIs8888(rt->config())) {
698             // The dither flag is set and the target is likely
699             // not going to be dithered by the GPU.
700             SkAutoTUnref<GrFragmentProcessor> fp(GrDitherEffect::Create());
701             if (fp.get()) {
702                 grPaint->addColorProcessor(fp);
703                 grPaint->setDither(false);
704             }
705         }
706     }
707 #endif
708     return true;
709 }
710 
SkPaint2GrPaint(GrContext * context,GrRenderTarget * rt,const SkPaint & skPaint,const SkMatrix & viewM,bool constantColor,GrPaint * grPaint)711 bool SkPaint2GrPaint(GrContext* context, GrRenderTarget* rt, const SkPaint& skPaint,
712                      const SkMatrix& viewM, bool constantColor, GrPaint* grPaint) {
713     SkShader* shader = skPaint.getShader();
714     if (NULL == shader) {
715         return SkPaint2GrPaintNoShader(context, rt, skPaint, SkColor2GrColor(skPaint.getColor()),
716                                        constantColor, grPaint);
717     }
718 
719     GrColor paintColor = SkColor2GrColor(skPaint.getColor());
720 
721     // Start a new block here in order to preserve our context state after calling
722     // asFragmentProcessor(). Since these calls get passed back to the client, we don't really
723     // want them messing around with the context.
724     {
725         // Allow the shader to modify paintColor and also create an effect to be installed as
726         // the first color effect on the GrPaint.
727         GrFragmentProcessor* fp = NULL;
728         if (!shader->asFragmentProcessor(context, skPaint, viewM, NULL, &paintColor, &fp)) {
729             return false;
730         }
731         if (fp) {
732             grPaint->addColorProcessor(fp)->unref();
733             constantColor = false;
734         }
735     }
736 
737     // The grcolor is automatically set when calling asFragmentProcessor.
738     // If the shader can be seen as an effect it returns true and adds its effect to the grpaint.
739     return SkPaint2GrPaintNoShader(context, rt, skPaint, paintColor, constantColor, grPaint);
740 }
741 
GrMakeInfoFromTexture(GrTexture * tex,int w,int h,bool isOpaque)742 SkImageInfo GrMakeInfoFromTexture(GrTexture* tex, int w, int h, bool isOpaque) {
743 #ifdef SK_DEBUG
744     const GrSurfaceDesc& desc = tex->desc();
745     SkASSERT(w <= desc.fWidth);
746     SkASSERT(h <= desc.fHeight);
747 #endif
748     const GrPixelConfig config = tex->config();
749     SkColorType ct;
750     SkAlphaType at = isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
751     if (!GrPixelConfig2ColorAndProfileType(config, &ct, NULL)) {
752         ct = kUnknown_SkColorType;
753     }
754     return SkImageInfo::Make(w, h, ct, at);
755 }
756 
757 
GrWrapTextureInBitmap(GrTexture * src,int w,int h,bool isOpaque,SkBitmap * dst)758 void GrWrapTextureInBitmap(GrTexture* src, int w, int h, bool isOpaque, SkBitmap* dst) {
759     const SkImageInfo info = GrMakeInfoFromTexture(src, w, h, isOpaque);
760     dst->setInfo(info);
761     dst->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, src)))->unref();
762 }
763