blob: fb2ebdd53fcbbf70c1ed93568f14ed3526b7bce8 [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
krajcevski9a3cdbb2014-06-05 07:03:39 -0700247 else if (
248 // We do not support scratch ETC1 textures, hence they should all be at least
249 // trying to go to the cache.
250 cache
251 // Make sure that the underlying device supports ETC1 textures before we go ahead
252 // and check the data.
253 && ctx->getGpu()->caps()->isConfigTexturable(kETC1_GrPixelConfig)
254 // If the bitmap had compressed data and was then uncompressed, it'll still return
255 // compressed data on 'refEncodedData' and upload it. Probably not good, since if
256 // the bitmap has available pixels, then they might not be what the decompressed
257 // data is.
258 && !(bitmap->readyToDraw())) {
krajcevski9c0e6292014-06-02 07:38:14 -0700259 GrTexture *texture = load_etc1_texture(ctx, params, *bitmap, desc);
260 if (NULL != texture) {
261 return texture;
262 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000263 }
krajcevski8c111f72014-06-02 13:51:34 -0700264#endif // SK_IGNORE_ETC1_SUPPORT
reed@google.comac10a2d2010-12-22 21:39:39 +0000265
bsalomon@google.com7f4ad5a2013-05-07 19:36:43 +0000266 SkAutoLockPixels alp(*bitmap);
267 if (!bitmap->readyToDraw()) {
268 return NULL;
269 }
bsalomon@google.com0797c2c2012-12-20 15:13:01 +0000270 if (cache) {
robertphillips@google.com9c2ea842012-08-13 17:47:59 +0000271 // This texture is likely to be used again so leave it in the cache
bsalomon@google.com0797c2c2012-12-20 15:13:01 +0000272 GrCacheID cacheID;
273 generate_bitmap_cache_id(origBitmap, &cacheID);
commit-bot@chromium.org50a30432013-10-24 17:44:27 +0000274
275 GrResourceKey key;
276 GrTexture* result = ctx->createTexture(params, desc, cacheID,
277 bitmap->getPixels(), bitmap->rowBytes(), &key);
commit-bot@chromium.org3843f3f2013-10-31 20:22:47 +0000278 if (NULL != result) {
279 add_genID_listener(key, origBitmap.pixelRef());
280 }
commit-bot@chromium.org50a30432013-10-24 17:44:27 +0000281 return result;
282 } else {
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000283 // This texture is unlikely to be used again (in its present form) so
284 // just use a scratch texture. This will remove the texture from the
285 // cache so no one else can find it. Additionally, once unlocked, the
286 // scratch texture will go to the end of the list for purging so will
robertphillips@google.com9c2ea842012-08-13 17:47:59 +0000287 // likely be available for this volatile bitmap the next time around.
bsalomon@google.com95ed55a2013-01-24 14:46:47 +0000288 GrTexture* result = ctx->lockAndRefScratchTexture(desc, GrContext::kExact_ScratchTexMatch);
robertphillips@google.com1f47f4f2012-08-16 14:49:16 +0000289 result->writePixels(0, 0,
290 bitmap->width(), bitmap->height(),
291 desc.fConfig,
292 bitmap->getPixels(),
293 bitmap->rowBytes());
294 return result;
junov@google.com4ee7ae52011-06-30 17:30:49 +0000295 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000296}
297
bsalomon@google.com0797c2c2012-12-20 15:13:01 +0000298bool GrIsBitmapInCache(const GrContext* ctx,
299 const SkBitmap& bitmap,
300 const GrTextureParams* params) {
301 GrCacheID cacheID;
302 generate_bitmap_cache_id(bitmap, &cacheID);
303
304 GrTextureDesc desc;
305 generate_bitmap_texture_desc(bitmap, &desc);
306 return ctx->isTextureInCache(desc, cacheID, params);
307}
reed@google.comac10a2d2010-12-22 21:39:39 +0000308
bsalomon@google.com95ed55a2013-01-24 14:46:47 +0000309GrTexture* GrLockAndRefCachedBitmapTexture(GrContext* ctx,
310 const SkBitmap& bitmap,
311 const GrTextureParams* params) {
robertphillips@google.com1f47f4f2012-08-16 14:49:16 +0000312 GrTexture* result = NULL;
rileya@google.com24f3ad12012-07-18 21:47:40 +0000313
bsalomon@google.com0797c2c2012-12-20 15:13:01 +0000314 bool cache = !bitmap.isVolatile();
315
316 if (cache) {
317 // If the bitmap isn't changing try to find a cached copy first.
318
319 GrCacheID cacheID;
320 generate_bitmap_cache_id(bitmap, &cacheID);
rileya@google.com24f3ad12012-07-18 21:47:40 +0000321
322 GrTextureDesc desc;
bsalomon@google.com0797c2c2012-12-20 15:13:01 +0000323 generate_bitmap_texture_desc(bitmap, &desc);
rileya@google.com24f3ad12012-07-18 21:47:40 +0000324
bsalomon@google.com95ed55a2013-01-24 14:46:47 +0000325 result = ctx->findAndRefTexture(desc, cacheID, params);
bsalomon@google.com0797c2c2012-12-20 15:13:01 +0000326 }
327 if (NULL == result) {
328 result = sk_gr_create_bitmap_texture(ctx, cache, params, bitmap);
rileya@google.com24f3ad12012-07-18 21:47:40 +0000329 }
robertphillips@google.com1f47f4f2012-08-16 14:49:16 +0000330 if (NULL == result) {
rileya@google.com24f3ad12012-07-18 21:47:40 +0000331 GrPrintf("---- failed to create texture for cache [%d %d]\n",
332 bitmap.width(), bitmap.height());
333 }
robertphillips@google.com1f47f4f2012-08-16 14:49:16 +0000334 return result;
rileya@google.com24f3ad12012-07-18 21:47:40 +0000335}
336
bsalomon@google.com95ed55a2013-01-24 14:46:47 +0000337void GrUnlockAndUnrefCachedBitmapTexture(GrTexture* texture) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000338 SkASSERT(NULL != texture->getContext());
robertphillips@google.com1f47f4f2012-08-16 14:49:16 +0000339
robertphillips@google.com9fbcad02012-09-09 14:44:15 +0000340 texture->getContext()->unlockScratchTexture(texture);
bsalomon@google.com95ed55a2013-01-24 14:46:47 +0000341 texture->unref();
rileya@google.com24f3ad12012-07-18 21:47:40 +0000342}
343
344///////////////////////////////////////////////////////////////////////////////
345
rileya@google.com24f3ad12012-07-18 21:47:40 +0000346GrPixelConfig SkBitmapConfig2GrPixelConfig(SkBitmap::Config config) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000347 switch (config) {
348 case SkBitmap::kA8_Config:
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000349 return kAlpha_8_GrPixelConfig;
reed@google.comac10a2d2010-12-22 21:39:39 +0000350 case SkBitmap::kIndex8_Config:
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000351 return kIndex_8_GrPixelConfig;
reed@google.comac10a2d2010-12-22 21:39:39 +0000352 case SkBitmap::kRGB_565_Config:
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000353 return kRGB_565_GrPixelConfig;
reed@google.comac10a2d2010-12-22 21:39:39 +0000354 case SkBitmap::kARGB_4444_Config:
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000355 return kRGBA_4444_GrPixelConfig;
reed@google.comac10a2d2010-12-22 21:39:39 +0000356 case SkBitmap::kARGB_8888_Config:
bsalomon@google.comfec0bc32013-02-07 14:43:04 +0000357 return kSkia8888_GrPixelConfig;
reed@google.comac10a2d2010-12-22 21:39:39 +0000358 default:
reed@google.com2cb14802013-06-26 14:35:02 +0000359 // kNo_Config, kA1_Config missing
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000360 return kUnknown_GrPixelConfig;
reed@google.comac10a2d2010-12-22 21:39:39 +0000361 }
362}
reed@google.combf790232013-12-13 19:45:58 +0000363
commit-bot@chromium.org15a14052014-02-16 00:59:25 +0000364// alphatype is ignore for now, but if GrPixelConfig is expanded to encompass
365// alpha info, that will be considered.
366GrPixelConfig SkImageInfo2GrPixelConfig(SkColorType ct, SkAlphaType) {
367 switch (ct) {
368 case kUnknown_SkColorType:
369 return kUnknown_GrPixelConfig;
370 case kAlpha_8_SkColorType:
371 return kAlpha_8_GrPixelConfig;
372 case kRGB_565_SkColorType:
373 return kRGB_565_GrPixelConfig;
374 case kARGB_4444_SkColorType:
375 return kRGBA_4444_GrPixelConfig;
376 case kRGBA_8888_SkColorType:
377 return kRGBA_8888_GrPixelConfig;
378 case kBGRA_8888_SkColorType:
379 return kBGRA_8888_GrPixelConfig;
380 case kIndex_8_SkColorType:
381 return kIndex_8_GrPixelConfig;
382 }
383 SkASSERT(0); // shouldn't get here
384 return kUnknown_GrPixelConfig;
385}
386
reed@google.combf790232013-12-13 19:45:58 +0000387bool GrPixelConfig2ColorType(GrPixelConfig config, SkColorType* ctOut) {
388 SkColorType ct;
389 switch (config) {
390 case kAlpha_8_GrPixelConfig:
391 ct = kAlpha_8_SkColorType;
392 break;
393 case kIndex_8_GrPixelConfig:
394 ct = kIndex_8_SkColorType;
395 break;
396 case kRGB_565_GrPixelConfig:
397 ct = kRGB_565_SkColorType;
398 break;
399 case kRGBA_4444_GrPixelConfig:
400 ct = kARGB_4444_SkColorType;
401 break;
402 case kRGBA_8888_GrPixelConfig:
403 ct = kRGBA_8888_SkColorType;
404 break;
405 case kBGRA_8888_GrPixelConfig:
406 ct = kBGRA_8888_SkColorType;
407 break;
408 default:
409 return false;
410 }
411 if (ctOut) {
412 *ctOut = ct;
413 }
414 return true;
415}
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000416
417///////////////////////////////////////////////////////////////////////////////
418
commit-bot@chromium.org3595f882014-05-19 19:35:57 +0000419void SkPaint2GrPaintNoShader(GrContext* context, const SkPaint& skPaint, bool justAlpha,
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000420 bool constantColor, GrPaint* grPaint) {
421
422 grPaint->setDither(skPaint.isDither());
423 grPaint->setAntiAlias(skPaint.isAntiAlias());
424
425 SkXfermode::Coeff sm;
426 SkXfermode::Coeff dm;
427
428 SkXfermode* mode = skPaint.getXfermode();
429 GrEffectRef* xferEffect = NULL;
430 if (SkXfermode::AsNewEffectOrCoeff(mode, &xferEffect, &sm, &dm)) {
431 if (NULL != xferEffect) {
432 grPaint->addColorEffect(xferEffect)->unref();
433 sm = SkXfermode::kOne_Coeff;
434 dm = SkXfermode::kZero_Coeff;
435 }
436 } else {
437 //SkDEBUGCODE(SkDebugf("Unsupported xfer mode.\n");)
438 // Fall back to src-over
439 sm = SkXfermode::kOne_Coeff;
440 dm = SkXfermode::kISA_Coeff;
441 }
442 grPaint->setBlendFunc(sk_blend_to_grblend(sm), sk_blend_to_grblend(dm));
443
444 if (justAlpha) {
445 uint8_t alpha = skPaint.getAlpha();
446 grPaint->setColor(GrColorPackRGBA(alpha, alpha, alpha, alpha));
447 // justAlpha is currently set to true only if there is a texture,
448 // so constantColor should not also be true.
449 SkASSERT(!constantColor);
450 } else {
451 grPaint->setColor(SkColor2GrColor(skPaint.getColor()));
452 }
453
454 SkColorFilter* colorFilter = skPaint.getColorFilter();
455 if (NULL != colorFilter) {
456 // if the source color is a constant then apply the filter here once rather than per pixel
457 // in a shader.
458 if (constantColor) {
459 SkColor filtered = colorFilter->filterColor(skPaint.getColor());
460 grPaint->setColor(SkColor2GrColor(filtered));
461 } else {
commit-bot@chromium.org3595f882014-05-19 19:35:57 +0000462 SkAutoTUnref<GrEffectRef> effect(colorFilter->asNewEffect(context));
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000463 if (NULL != effect.get()) {
464 grPaint->addColorEffect(effect);
465 }
466 }
467 }
468}
469
commit-bot@chromium.org9e967ad2014-05-20 15:06:29 +0000470/**
471 * Unlike GrContext::AutoMatrix, this doesn't require setting a new matrix. GrContext::AutoMatrix
472 * likes to set the new matrix in its constructor because it is usually necessary to simulataneously
473 * update a GrPaint. This AutoMatrix is used while initially setting up GrPaint, however.
474 */
475class AutoMatrix {
476public:
477 AutoMatrix(GrContext* context) {
478 fMatrix = context->getMatrix();
479 fContext = context;
480 }
481 ~AutoMatrix() {
482 SkASSERT(NULL != fContext);
483 fContext->setMatrix(fMatrix);
484 }
485private:
486 GrContext* fContext;
487 SkMatrix fMatrix;
488};
489
commit-bot@chromium.org3595f882014-05-19 19:35:57 +0000490void SkPaint2GrPaintShader(GrContext* context, const SkPaint& skPaint,
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000491 bool constantColor, GrPaint* grPaint) {
492 SkShader* shader = skPaint.getShader();
493 if (NULL == shader) {
commit-bot@chromium.org3595f882014-05-19 19:35:57 +0000494 SkPaint2GrPaintNoShader(context, skPaint, false, constantColor, grPaint);
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000495 return;
496 }
497
commit-bot@chromium.org9e967ad2014-05-20 15:06:29 +0000498 // SkShader::asNewEffect() may do offscreen rendering. Save off the current RT, clip, and
499 // matrix. We don't reset the matrix on the context because SkShader::asNewEffect may use
500 // GrContext::getMatrix() to know the transformation from local coords to device space.
501 GrContext::AutoRenderTarget art(context, NULL);
502 GrContext::AutoClip ac(context, GrContext::AutoClip::kWideOpen_InitialClip);
503 AutoMatrix am(context);
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000504
505 // setup the shader as the first color effect on the paint
commit-bot@chromium.org3595f882014-05-19 19:35:57 +0000506 SkAutoTUnref<GrEffectRef> effect(shader->asNewEffect(context, skPaint, NULL));
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000507 if (NULL != effect.get()) {
508 grPaint->addColorEffect(effect);
509 // Now setup the rest of the paint.
commit-bot@chromium.org3595f882014-05-19 19:35:57 +0000510 SkPaint2GrPaintNoShader(context, skPaint, true, false, grPaint);
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000511 } else {
512 // We still don't have SkColorShader::asNewEffect() implemented.
513 SkShader::GradientInfo info;
514 SkColor color;
515
516 info.fColors = &color;
517 info.fColorOffsets = NULL;
518 info.fColorCount = 1;
519 if (SkShader::kColor_GradientType == shader->asAGradient(&info)) {
520 SkPaint copy(skPaint);
521 copy.setShader(NULL);
522 // modulate the paint alpha by the shader's solid color alpha
523 U8CPU newA = SkMulDiv255Round(SkColorGetA(color), copy.getAlpha());
524 copy.setColor(SkColorSetA(color, newA));
commit-bot@chromium.org3595f882014-05-19 19:35:57 +0000525 SkPaint2GrPaintNoShader(context, copy, false, constantColor, grPaint);
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000526 } else {
commit-bot@chromium.org3595f882014-05-19 19:35:57 +0000527 SkPaint2GrPaintNoShader(context, skPaint, false, constantColor, grPaint);
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000528 }
529 }
530}