blob: 31372cd02a1816cf378ecae4f71070465983955d [file] [log] [blame]
reed@google.comac10a2d2010-12-22 21:39:39 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * 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.
reed@google.comac10a2d2010-12-22 21:39:39 +00006 */
7
reed@google.comac10a2d2010-12-22 21:39:39 +00008#include "SkGr.h"
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +00009#include "SkColorFilter.h"
commit-bot@chromium.orgea476e12013-10-14 18:29:23 +000010#include "SkConfig8888.h"
krajcevski9c0e6292014-06-02 07:38:14 -070011#include "SkData.h"
commit-bot@chromium.org50a30432013-10-24 17:44:27 +000012#include "SkMessageBus.h"
13#include "SkPixelRef.h"
14#include "GrResourceCache.h"
krajcevski9c0e6292014-06-02 07:38:14 -070015#include "GrGpu.h"
16#include "GrDrawTargetCaps.h"
17
krajcevski8c111f72014-06-02 13:51:34 -070018#ifndef SK_IGNORE_ETC1_SUPPORT
krajcevski99ffe242014-06-03 13:04:35 -070019# include "ktx.h"
krajcevski9c0e6292014-06-02 07:38:14 -070020# include "etc1.h"
21#endif
reed@google.comac10a2d2010-12-22 21:39:39 +000022
23/* Fill out buffer with the compressed format Ganesh expects from a colortable
24 based bitmap. [palette (colortable) + indices].
bsalomon@google.com5782d712011-01-21 21:03:59 +000025
26 At the moment Ganesh only supports 8bit version. If Ganesh allowed we others
reed@google.comac10a2d2010-12-22 21:39:39 +000027 we could detect that the colortable.count is <= 16, and then repack the
28 indices as nibbles to save RAM, but it would take more time (i.e. a lot
29 slower than memcpy), so skipping that for now.
bsalomon@google.com5782d712011-01-21 21:03:59 +000030
reed@google.comac10a2d2010-12-22 21:39:39 +000031 Ganesh wants a full 256 palette entry, even though Skia's ctable is only as big
32 as the colortable.count says it is.
33 */
34static void build_compressed_data(void* buffer, const SkBitmap& bitmap) {
35 SkASSERT(SkBitmap::kIndex8_Config == bitmap.config());
bsalomon@google.com5782d712011-01-21 21:03:59 +000036
bsalomon@google.com7f4ad5a2013-05-07 19:36:43 +000037 SkAutoLockPixels alp(bitmap);
reed@google.comac10a2d2010-12-22 21:39:39 +000038 if (!bitmap.readyToDraw()) {
tomhudson@google.com0c00f212011-12-28 14:59:50 +000039 SkDEBUGFAIL("bitmap not ready to draw!");
reed@google.comac10a2d2010-12-22 21:39:39 +000040 return;
41 }
42
43 SkColorTable* ctable = bitmap.getColorTable();
44 char* dst = (char*)buffer;
bsalomon@google.com5782d712011-01-21 21:03:59 +000045
reed@google.com7111d462014-03-25 16:20:24 +000046 const int count = ctable->count();
47
48 SkDstPixelInfo dstPI;
49 dstPI.fColorType = kRGBA_8888_SkColorType;
50 dstPI.fAlphaType = kPremul_SkAlphaType;
51 dstPI.fPixels = buffer;
52 dstPI.fRowBytes = count * sizeof(SkPMColor);
53
54 SkSrcPixelInfo srcPI;
commit-bot@chromium.org28fcae22014-04-11 17:15:40 +000055 srcPI.fColorType = kN32_SkColorType;
reed@google.com7111d462014-03-25 16:20:24 +000056 srcPI.fAlphaType = kPremul_SkAlphaType;
57 srcPI.fPixels = ctable->lockColors();
58 srcPI.fRowBytes = count * sizeof(SkPMColor);
59
60 srcPI.convertPixelsTo(&dstPI, count, 1);
61
reed@google.com0a6151d2013-10-10 14:44:56 +000062 ctable->unlockColors();
bsalomon@google.com5782d712011-01-21 21:03:59 +000063
reed@google.comac10a2d2010-12-22 21:39:39 +000064 // always skip a full 256 number of entries, even if we memcpy'd fewer
bsalomon@google.comfea37b52011-04-25 15:51:06 +000065 dst += kGrColorTableSize;
reed@google.comac10a2d2010-12-22 21:39:39 +000066
scroggo@google.com0ba4bf42013-02-25 16:02:36 +000067 if ((unsigned)bitmap.width() == bitmap.rowBytes()) {
reed@google.comac10a2d2010-12-22 21:39:39 +000068 memcpy(dst, bitmap.getPixels(), bitmap.getSize());
69 } else {
70 // need to trim off the extra bytes per row
71 size_t width = bitmap.width();
72 size_t rowBytes = bitmap.rowBytes();
73 const char* src = (const char*)bitmap.getPixels();
74 for (int y = 0; y < bitmap.height(); y++) {
75 memcpy(dst, src, width);
76 src += rowBytes;
77 dst += width;
78 }
79 }
80}
81
82////////////////////////////////////////////////////////////////////////////////
83
bsalomon@google.com0797c2c2012-12-20 15:13:01 +000084static void generate_bitmap_cache_id(const SkBitmap& bitmap, GrCacheID* id) {
85 // Our id includes the offset, width, and height so that bitmaps created by extractSubset()
86 // are unique.
87 uint32_t genID = bitmap.getGenerationID();
reed@google.com672588b2014-01-08 15:42:01 +000088 SkIPoint origin = bitmap.pixelRefOrigin();
89 int16_t width = SkToS16(bitmap.width());
90 int16_t height = SkToS16(bitmap.height());
bsalomon@google.com0797c2c2012-12-20 15:13:01 +000091
skia.committer@gmail.com2859eb72012-12-21 02:01:28 +000092 GrCacheID::Key key;
reed@google.com672588b2014-01-08 15:42:01 +000093 memcpy(key.fData8 + 0, &genID, 4);
94 memcpy(key.fData8 + 4, &origin.fX, 4);
95 memcpy(key.fData8 + 8, &origin.fY, 4);
96 memcpy(key.fData8 + 12, &width, 2);
97 memcpy(key.fData8 + 14, &height, 2);
98 static const size_t kKeyDataSize = 16;
bsalomon@google.com10a9fb82013-01-02 19:29:57 +000099 memset(key.fData8 + kKeyDataSize, 0, sizeof(key) - kKeyDataSize);
reed@google.com672588b2014-01-08 15:42:01 +0000100 GR_STATIC_ASSERT(sizeof(key) >= kKeyDataSize);
bsalomon@google.com0797c2c2012-12-20 15:13:01 +0000101 static const GrCacheID::Domain gBitmapTextureDomain = GrCacheID::GenerateDomain();
102 id->reset(gBitmapTextureDomain, key);
103}
104
105static void generate_bitmap_texture_desc(const SkBitmap& bitmap, GrTextureDesc* desc) {
106 desc->fFlags = kNone_GrTextureFlags;
107 desc->fWidth = bitmap.width();
108 desc->fHeight = bitmap.height();
commit-bot@chromium.org3adcc342014-04-23 19:18:09 +0000109 desc->fConfig = SkImageInfo2GrPixelConfig(bitmap.info());
bsalomon@google.com0797c2c2012-12-20 15:13:01 +0000110 desc->fSampleCnt = 0;
111}
112
commit-bot@chromium.org50a30432013-10-24 17:44:27 +0000113namespace {
114
115// When the SkPixelRef genID changes, invalidate a corresponding GrResource described by key.
116class GrResourceInvalidator : public SkPixelRef::GenIDChangeListener {
117public:
118 explicit GrResourceInvalidator(GrResourceKey key) : fKey(key) {}
119private:
120 GrResourceKey fKey;
121
122 virtual void onChange() SK_OVERRIDE {
123 const GrResourceInvalidatedMessage message = { fKey };
124 SkMessageBus<GrResourceInvalidatedMessage>::Post(message);
125 }
126};
127
128} // namespace
129
130static void add_genID_listener(GrResourceKey key, SkPixelRef* pixelRef) {
131 SkASSERT(NULL != pixelRef);
132 pixelRef->addGenIDChangeListener(SkNEW_ARGS(GrResourceInvalidator, (key)));
133}
134
krajcevski8c111f72014-06-02 13:51:34 -0700135#ifndef SK_IGNORE_ETC1_SUPPORT
krajcevski9c0e6292014-06-02 07:38:14 -0700136static GrTexture *load_etc1_texture(GrContext* ctx,
137 const GrTextureParams* params,
138 const SkBitmap &bm, GrTextureDesc desc) {
krajcevski99ffe242014-06-03 13:04:35 -0700139 SkAutoTUnref<SkData> data(bm.pixelRef()->refEncodedData());
krajcevski9c0e6292014-06-02 07:38:14 -0700140
141 // Is this even encoded data?
142 if (NULL == data) {
143 return NULL;
144 }
145
146 // Is this a valid PKM encoded data?
147 const uint8_t *bytes = data->bytes();
krajcevski99ffe242014-06-03 13:04:35 -0700148 if (etc1_pkm_is_valid(bytes)) {
149 uint32_t encodedWidth = etc1_pkm_get_width(bytes);
150 uint32_t encodedHeight = etc1_pkm_get_height(bytes);
151
152 // Does the data match the dimensions of the bitmap? If not,
153 // then we don't know how to scale the image to match it...
154 if (encodedWidth != static_cast<uint32_t>(bm.width()) ||
155 encodedHeight != static_cast<uint32_t>(bm.height())) {
156 return NULL;
157 }
158
159 // Everything seems good... skip ahead to the data.
160 bytes += ETC_PKM_HEADER_SIZE;
161 desc.fConfig = kETC1_GrPixelConfig;
162 } else if (SkKTXFile::is_ktx(bytes)) {
163 SkKTXFile ktx(data);
164
165 // Is it actually an ETC1 texture?
166 if (!ktx.isETC1()) {
167 return NULL;
168 }
169
170 // Does the data match the dimensions of the bitmap? If not,
171 // then we don't know how to scale the image to match it...
172 if (ktx.width() != bm.width() || ktx.height() != bm.height()) {
173 return NULL;
174 }
175
176 bytes = ktx.pixelData();
177 desc.fConfig = kETC1_GrPixelConfig;
178 } else {
krajcevski9c0e6292014-06-02 07:38:14 -0700179 return NULL;
180 }
181
krajcevski9c0e6292014-06-02 07:38:14 -0700182 // This texture is likely to be used again so leave it in the cache
183 GrCacheID cacheID;
184 generate_bitmap_cache_id(bm, &cacheID);
185
186 GrResourceKey key;
187 GrTexture* result = ctx->createTexture(params, desc, cacheID, bytes, 0, &key);
188 if (NULL != result) {
189 add_genID_listener(key, bm.pixelRef());
190 }
191 return result;
192}
krajcevski8c111f72014-06-02 13:51:34 -0700193#endif // SK_IGNORE_ETC1_SUPPORT
krajcevski9c0e6292014-06-02 07:38:14 -0700194
robertphillips@google.com1f47f4f2012-08-16 14:49:16 +0000195static GrTexture* sk_gr_create_bitmap_texture(GrContext* ctx,
bsalomon@google.com0797c2c2012-12-20 15:13:01 +0000196 bool cache,
robertphillips@google.com1f47f4f2012-08-16 14:49:16 +0000197 const GrTextureParams* params,
198 const SkBitmap& origBitmap) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000199 SkBitmap tmpBitmap;
200
201 const SkBitmap* bitmap = &origBitmap;
bsalomon@google.com5782d712011-01-21 21:03:59 +0000202
robertphillips@google.com75b3c962012-06-07 12:08:45 +0000203 GrTextureDesc desc;
bsalomon@google.com0797c2c2012-12-20 15:13:01 +0000204 generate_bitmap_texture_desc(*bitmap, &desc);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000205
reed@google.comac10a2d2010-12-22 21:39:39 +0000206 if (SkBitmap::kIndex8_Config == bitmap->config()) {
207 // build_compressed_data doesn't do npot->pot expansion
208 // and paletted textures can't be sub-updated
bsalomon@google.com7f4ad5a2013-05-07 19:36:43 +0000209 if (ctx->supportsIndex8PixelConfig(params, bitmap->width(), bitmap->height())) {
210 size_t imagesize = bitmap->width() * bitmap->height() + kGrColorTableSize;
reed@google.comac10a2d2010-12-22 21:39:39 +0000211 SkAutoMalloc storage(imagesize);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000212
reed@google.comac10a2d2010-12-22 21:39:39 +0000213 build_compressed_data(storage.get(), origBitmap);
214
215 // our compressed data will be trimmed, so pass width() for its
216 // "rowBytes", since they are the same now.
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000217
bsalomon@google.com0797c2c2012-12-20 15:13:01 +0000218 if (cache) {
219 GrCacheID cacheID;
220 generate_bitmap_cache_id(origBitmap, &cacheID);
commit-bot@chromium.org50a30432013-10-24 17:44:27 +0000221
222 GrResourceKey key;
223 GrTexture* result = ctx->createTexture(params, desc, cacheID,
224 storage.get(), bitmap->width(), &key);
commit-bot@chromium.org3843f3f2013-10-31 20:22:47 +0000225 if (NULL != result) {
226 add_genID_listener(key, origBitmap.pixelRef());
227 }
commit-bot@chromium.org50a30432013-10-24 17:44:27 +0000228 return result;
junov@google.com4ee7ae52011-06-30 17:30:49 +0000229 } else {
bsalomon@google.com95ed55a2013-01-24 14:46:47 +0000230 GrTexture* result = ctx->lockAndRefScratchTexture(desc,
bsalomon@google.com0797c2c2012-12-20 15:13:01 +0000231 GrContext::kExact_ScratchTexMatch);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000232 result->writePixels(0, 0, bitmap->width(),
robertphillips@google.com1f47f4f2012-08-16 14:49:16 +0000233 bitmap->height(), desc.fConfig,
bsalomon@google.com0342a852012-08-20 19:22:38 +0000234 storage.get());
robertphillips@google.com1f47f4f2012-08-16 14:49:16 +0000235 return result;
junov@google.com4ee7ae52011-06-30 17:30:49 +0000236 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000237 } else {
commit-bot@chromium.org28fcae22014-04-11 17:15:40 +0000238 origBitmap.copyTo(&tmpBitmap, kN32_SkColorType);
reed@google.comac10a2d2010-12-22 21:39:39 +0000239 // now bitmap points to our temp, which has been promoted to 32bits
240 bitmap = &tmpBitmap;
commit-bot@chromium.org3adcc342014-04-23 19:18:09 +0000241 desc.fConfig = SkImageInfo2GrPixelConfig(bitmap->info());
reed@google.comac10a2d2010-12-22 21:39:39 +0000242 }
krajcevski309e8692014-06-02 08:02:45 -0700243 }
krajcevski9c0e6292014-06-02 07:38:14 -0700244
245 // Is this an ETC1 encoded texture?
krajcevski8c111f72014-06-02 13:51:34 -0700246#ifndef SK_IGNORE_ETC1_SUPPORT
krajcevski309e8692014-06-02 08:02:45 -0700247 else if (cache && ctx->getGpu()->caps()->isConfigTexturable(kETC1_GrPixelConfig)) {
krajcevski9c0e6292014-06-02 07:38:14 -0700248 GrTexture *texture = load_etc1_texture(ctx, params, *bitmap, desc);
249 if (NULL != texture) {
250 return texture;
251 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000252 }
krajcevski8c111f72014-06-02 13:51:34 -0700253#endif // SK_IGNORE_ETC1_SUPPORT
reed@google.comac10a2d2010-12-22 21:39:39 +0000254
bsalomon@google.com7f4ad5a2013-05-07 19:36:43 +0000255 SkAutoLockPixels alp(*bitmap);
256 if (!bitmap->readyToDraw()) {
257 return NULL;
258 }
bsalomon@google.com0797c2c2012-12-20 15:13:01 +0000259 if (cache) {
robertphillips@google.com9c2ea842012-08-13 17:47:59 +0000260 // This texture is likely to be used again so leave it in the cache
bsalomon@google.com0797c2c2012-12-20 15:13:01 +0000261 GrCacheID cacheID;
262 generate_bitmap_cache_id(origBitmap, &cacheID);
commit-bot@chromium.org50a30432013-10-24 17:44:27 +0000263
264 GrResourceKey key;
265 GrTexture* result = ctx->createTexture(params, desc, cacheID,
266 bitmap->getPixels(), bitmap->rowBytes(), &key);
commit-bot@chromium.org3843f3f2013-10-31 20:22:47 +0000267 if (NULL != result) {
268 add_genID_listener(key, origBitmap.pixelRef());
269 }
commit-bot@chromium.org50a30432013-10-24 17:44:27 +0000270 return result;
271 } else {
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000272 // This texture is unlikely to be used again (in its present form) so
273 // just use a scratch texture. This will remove the texture from the
274 // cache so no one else can find it. Additionally, once unlocked, the
275 // scratch texture will go to the end of the list for purging so will
robertphillips@google.com9c2ea842012-08-13 17:47:59 +0000276 // likely be available for this volatile bitmap the next time around.
bsalomon@google.com95ed55a2013-01-24 14:46:47 +0000277 GrTexture* result = ctx->lockAndRefScratchTexture(desc, GrContext::kExact_ScratchTexMatch);
robertphillips@google.com1f47f4f2012-08-16 14:49:16 +0000278 result->writePixels(0, 0,
279 bitmap->width(), bitmap->height(),
280 desc.fConfig,
281 bitmap->getPixels(),
282 bitmap->rowBytes());
283 return result;
junov@google.com4ee7ae52011-06-30 17:30:49 +0000284 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000285}
286
bsalomon@google.com0797c2c2012-12-20 15:13:01 +0000287bool GrIsBitmapInCache(const GrContext* ctx,
288 const SkBitmap& bitmap,
289 const GrTextureParams* params) {
290 GrCacheID cacheID;
291 generate_bitmap_cache_id(bitmap, &cacheID);
292
293 GrTextureDesc desc;
294 generate_bitmap_texture_desc(bitmap, &desc);
295 return ctx->isTextureInCache(desc, cacheID, params);
296}
reed@google.comac10a2d2010-12-22 21:39:39 +0000297
bsalomon@google.com95ed55a2013-01-24 14:46:47 +0000298GrTexture* GrLockAndRefCachedBitmapTexture(GrContext* ctx,
299 const SkBitmap& bitmap,
300 const GrTextureParams* params) {
robertphillips@google.com1f47f4f2012-08-16 14:49:16 +0000301 GrTexture* result = NULL;
rileya@google.com24f3ad12012-07-18 21:47:40 +0000302
bsalomon@google.com0797c2c2012-12-20 15:13:01 +0000303 bool cache = !bitmap.isVolatile();
304
305 if (cache) {
306 // If the bitmap isn't changing try to find a cached copy first.
307
308 GrCacheID cacheID;
309 generate_bitmap_cache_id(bitmap, &cacheID);
rileya@google.com24f3ad12012-07-18 21:47:40 +0000310
311 GrTextureDesc desc;
bsalomon@google.com0797c2c2012-12-20 15:13:01 +0000312 generate_bitmap_texture_desc(bitmap, &desc);
rileya@google.com24f3ad12012-07-18 21:47:40 +0000313
bsalomon@google.com95ed55a2013-01-24 14:46:47 +0000314 result = ctx->findAndRefTexture(desc, cacheID, params);
bsalomon@google.com0797c2c2012-12-20 15:13:01 +0000315 }
316 if (NULL == result) {
317 result = sk_gr_create_bitmap_texture(ctx, cache, params, bitmap);
rileya@google.com24f3ad12012-07-18 21:47:40 +0000318 }
robertphillips@google.com1f47f4f2012-08-16 14:49:16 +0000319 if (NULL == result) {
rileya@google.com24f3ad12012-07-18 21:47:40 +0000320 GrPrintf("---- failed to create texture for cache [%d %d]\n",
321 bitmap.width(), bitmap.height());
322 }
robertphillips@google.com1f47f4f2012-08-16 14:49:16 +0000323 return result;
rileya@google.com24f3ad12012-07-18 21:47:40 +0000324}
325
bsalomon@google.com95ed55a2013-01-24 14:46:47 +0000326void GrUnlockAndUnrefCachedBitmapTexture(GrTexture* texture) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000327 SkASSERT(NULL != texture->getContext());
robertphillips@google.com1f47f4f2012-08-16 14:49:16 +0000328
robertphillips@google.com9fbcad02012-09-09 14:44:15 +0000329 texture->getContext()->unlockScratchTexture(texture);
bsalomon@google.com95ed55a2013-01-24 14:46:47 +0000330 texture->unref();
rileya@google.com24f3ad12012-07-18 21:47:40 +0000331}
332
333///////////////////////////////////////////////////////////////////////////////
334
rileya@google.com24f3ad12012-07-18 21:47:40 +0000335GrPixelConfig SkBitmapConfig2GrPixelConfig(SkBitmap::Config config) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000336 switch (config) {
337 case SkBitmap::kA8_Config:
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000338 return kAlpha_8_GrPixelConfig;
reed@google.comac10a2d2010-12-22 21:39:39 +0000339 case SkBitmap::kIndex8_Config:
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000340 return kIndex_8_GrPixelConfig;
reed@google.comac10a2d2010-12-22 21:39:39 +0000341 case SkBitmap::kRGB_565_Config:
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000342 return kRGB_565_GrPixelConfig;
reed@google.comac10a2d2010-12-22 21:39:39 +0000343 case SkBitmap::kARGB_4444_Config:
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000344 return kRGBA_4444_GrPixelConfig;
reed@google.comac10a2d2010-12-22 21:39:39 +0000345 case SkBitmap::kARGB_8888_Config:
bsalomon@google.comfec0bc32013-02-07 14:43:04 +0000346 return kSkia8888_GrPixelConfig;
reed@google.comac10a2d2010-12-22 21:39:39 +0000347 default:
reed@google.com2cb14802013-06-26 14:35:02 +0000348 // kNo_Config, kA1_Config missing
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000349 return kUnknown_GrPixelConfig;
reed@google.comac10a2d2010-12-22 21:39:39 +0000350 }
351}
reed@google.combf790232013-12-13 19:45:58 +0000352
commit-bot@chromium.org15a14052014-02-16 00:59:25 +0000353// alphatype is ignore for now, but if GrPixelConfig is expanded to encompass
354// alpha info, that will be considered.
355GrPixelConfig SkImageInfo2GrPixelConfig(SkColorType ct, SkAlphaType) {
356 switch (ct) {
357 case kUnknown_SkColorType:
358 return kUnknown_GrPixelConfig;
359 case kAlpha_8_SkColorType:
360 return kAlpha_8_GrPixelConfig;
361 case kRGB_565_SkColorType:
362 return kRGB_565_GrPixelConfig;
363 case kARGB_4444_SkColorType:
364 return kRGBA_4444_GrPixelConfig;
365 case kRGBA_8888_SkColorType:
366 return kRGBA_8888_GrPixelConfig;
367 case kBGRA_8888_SkColorType:
368 return kBGRA_8888_GrPixelConfig;
369 case kIndex_8_SkColorType:
370 return kIndex_8_GrPixelConfig;
371 }
372 SkASSERT(0); // shouldn't get here
373 return kUnknown_GrPixelConfig;
374}
375
reed@google.combf790232013-12-13 19:45:58 +0000376bool GrPixelConfig2ColorType(GrPixelConfig config, SkColorType* ctOut) {
377 SkColorType ct;
378 switch (config) {
379 case kAlpha_8_GrPixelConfig:
380 ct = kAlpha_8_SkColorType;
381 break;
382 case kIndex_8_GrPixelConfig:
383 ct = kIndex_8_SkColorType;
384 break;
385 case kRGB_565_GrPixelConfig:
386 ct = kRGB_565_SkColorType;
387 break;
388 case kRGBA_4444_GrPixelConfig:
389 ct = kARGB_4444_SkColorType;
390 break;
391 case kRGBA_8888_GrPixelConfig:
392 ct = kRGBA_8888_SkColorType;
393 break;
394 case kBGRA_8888_GrPixelConfig:
395 ct = kBGRA_8888_SkColorType;
396 break;
397 default:
398 return false;
399 }
400 if (ctOut) {
401 *ctOut = ct;
402 }
403 return true;
404}
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000405
406///////////////////////////////////////////////////////////////////////////////
407
commit-bot@chromium.org3595f882014-05-19 19:35:57 +0000408void SkPaint2GrPaintNoShader(GrContext* context, const SkPaint& skPaint, bool justAlpha,
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000409 bool constantColor, GrPaint* grPaint) {
410
411 grPaint->setDither(skPaint.isDither());
412 grPaint->setAntiAlias(skPaint.isAntiAlias());
413
414 SkXfermode::Coeff sm;
415 SkXfermode::Coeff dm;
416
417 SkXfermode* mode = skPaint.getXfermode();
418 GrEffectRef* xferEffect = NULL;
419 if (SkXfermode::AsNewEffectOrCoeff(mode, &xferEffect, &sm, &dm)) {
420 if (NULL != xferEffect) {
421 grPaint->addColorEffect(xferEffect)->unref();
422 sm = SkXfermode::kOne_Coeff;
423 dm = SkXfermode::kZero_Coeff;
424 }
425 } else {
426 //SkDEBUGCODE(SkDebugf("Unsupported xfer mode.\n");)
427 // Fall back to src-over
428 sm = SkXfermode::kOne_Coeff;
429 dm = SkXfermode::kISA_Coeff;
430 }
431 grPaint->setBlendFunc(sk_blend_to_grblend(sm), sk_blend_to_grblend(dm));
432
433 if (justAlpha) {
434 uint8_t alpha = skPaint.getAlpha();
435 grPaint->setColor(GrColorPackRGBA(alpha, alpha, alpha, alpha));
436 // justAlpha is currently set to true only if there is a texture,
437 // so constantColor should not also be true.
438 SkASSERT(!constantColor);
439 } else {
440 grPaint->setColor(SkColor2GrColor(skPaint.getColor()));
441 }
442
443 SkColorFilter* colorFilter = skPaint.getColorFilter();
444 if (NULL != colorFilter) {
445 // if the source color is a constant then apply the filter here once rather than per pixel
446 // in a shader.
447 if (constantColor) {
448 SkColor filtered = colorFilter->filterColor(skPaint.getColor());
449 grPaint->setColor(SkColor2GrColor(filtered));
450 } else {
commit-bot@chromium.org3595f882014-05-19 19:35:57 +0000451 SkAutoTUnref<GrEffectRef> effect(colorFilter->asNewEffect(context));
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000452 if (NULL != effect.get()) {
453 grPaint->addColorEffect(effect);
454 }
455 }
456 }
457}
458
commit-bot@chromium.org9e967ad2014-05-20 15:06:29 +0000459/**
460 * Unlike GrContext::AutoMatrix, this doesn't require setting a new matrix. GrContext::AutoMatrix
461 * likes to set the new matrix in its constructor because it is usually necessary to simulataneously
462 * update a GrPaint. This AutoMatrix is used while initially setting up GrPaint, however.
463 */
464class AutoMatrix {
465public:
466 AutoMatrix(GrContext* context) {
467 fMatrix = context->getMatrix();
468 fContext = context;
469 }
470 ~AutoMatrix() {
471 SkASSERT(NULL != fContext);
472 fContext->setMatrix(fMatrix);
473 }
474private:
475 GrContext* fContext;
476 SkMatrix fMatrix;
477};
478
commit-bot@chromium.org3595f882014-05-19 19:35:57 +0000479void SkPaint2GrPaintShader(GrContext* context, const SkPaint& skPaint,
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000480 bool constantColor, GrPaint* grPaint) {
481 SkShader* shader = skPaint.getShader();
482 if (NULL == shader) {
commit-bot@chromium.org3595f882014-05-19 19:35:57 +0000483 SkPaint2GrPaintNoShader(context, skPaint, false, constantColor, grPaint);
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000484 return;
485 }
486
commit-bot@chromium.org9e967ad2014-05-20 15:06:29 +0000487 // SkShader::asNewEffect() may do offscreen rendering. Save off the current RT, clip, and
488 // matrix. We don't reset the matrix on the context because SkShader::asNewEffect may use
489 // GrContext::getMatrix() to know the transformation from local coords to device space.
490 GrContext::AutoRenderTarget art(context, NULL);
491 GrContext::AutoClip ac(context, GrContext::AutoClip::kWideOpen_InitialClip);
492 AutoMatrix am(context);
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000493
494 // setup the shader as the first color effect on the paint
commit-bot@chromium.org3595f882014-05-19 19:35:57 +0000495 SkAutoTUnref<GrEffectRef> effect(shader->asNewEffect(context, skPaint, NULL));
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000496 if (NULL != effect.get()) {
497 grPaint->addColorEffect(effect);
498 // Now setup the rest of the paint.
commit-bot@chromium.org3595f882014-05-19 19:35:57 +0000499 SkPaint2GrPaintNoShader(context, skPaint, true, false, grPaint);
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000500 } else {
501 // We still don't have SkColorShader::asNewEffect() implemented.
502 SkShader::GradientInfo info;
503 SkColor color;
504
505 info.fColors = &color;
506 info.fColorOffsets = NULL;
507 info.fColorCount = 1;
508 if (SkShader::kColor_GradientType == shader->asAGradient(&info)) {
509 SkPaint copy(skPaint);
510 copy.setShader(NULL);
511 // modulate the paint alpha by the shader's solid color alpha
512 U8CPU newA = SkMulDiv255Round(SkColorGetA(color), copy.getAlpha());
513 copy.setColor(SkColorSetA(color, newA));
commit-bot@chromium.org3595f882014-05-19 19:35:57 +0000514 SkPaint2GrPaintNoShader(context, copy, false, constantColor, grPaint);
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000515 } else {
commit-bot@chromium.org3595f882014-05-19 19:35:57 +0000516 SkPaint2GrPaintNoShader(context, skPaint, false, constantColor, grPaint);
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000517 }
518 }
519}