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