blob: 18b27534bceca3550929900504004eb73d12cfb1 [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"
egdaniel378092f2014-12-03 10:40:13 -08009
10#include "GrDrawTargetCaps.h"
11#include "GrGpu.h"
12#include "GrXferProcessor.h"
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +000013#include "SkColorFilter.h"
commit-bot@chromium.orgea476e12013-10-14 18:29:23 +000014#include "SkConfig8888.h"
krajcevski9c0e6292014-06-02 07:38:14 -070015#include "SkData.h"
commit-bot@chromium.org50a30432013-10-24 17:44:27 +000016#include "SkMessageBus.h"
17#include "SkPixelRef.h"
sugoi692135f2015-01-19 10:10:27 -080018#include "SkResourceCache.h"
krajcevski40a1e112014-08-05 14:13:36 -070019#include "SkTextureCompressor.h"
sugoi692135f2015-01-19 10:10:27 -080020#include "SkYUVPlanesCache.h"
krajcevskif461a8f2014-06-19 14:14:06 -070021#include "effects/GrDitherEffect.h"
egdaniel378092f2014-12-03 10:40:13 -080022#include "effects/GrPorterDuffXferProcessor.h"
sugoi518d83d2014-07-21 11:37:39 -070023#include "effects/GrYUVtoRGBEffect.h"
krajcevski9c0e6292014-06-02 07:38:14 -070024
krajcevski8c111f72014-06-02 13:51:34 -070025#ifndef SK_IGNORE_ETC1_SUPPORT
krajcevski99ffe242014-06-03 13:04:35 -070026# include "ktx.h"
krajcevski9c0e6292014-06-02 07:38:14 -070027# include "etc1.h"
28#endif
reed@google.comac10a2d2010-12-22 21:39:39 +000029
30/* Fill out buffer with the compressed format Ganesh expects from a colortable
31 based bitmap. [palette (colortable) + indices].
bsalomon@google.com5782d712011-01-21 21:03:59 +000032
33 At the moment Ganesh only supports 8bit version. If Ganesh allowed we others
reed@google.comac10a2d2010-12-22 21:39:39 +000034 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.
bsalomon@google.com5782d712011-01-21 21:03:59 +000037
reed@google.comac10a2d2010-12-22 21:39:39 +000038 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 */
bsalomone79a2da2014-10-24 12:42:51 -070041static void build_index8_data(void* buffer, const SkBitmap& bitmap) {
reed0689d7b2014-06-14 05:30:20 -070042 SkASSERT(kIndex_8_SkColorType == bitmap.colorType());
bsalomon@google.com5782d712011-01-21 21:03:59 +000043
bsalomon@google.com7f4ad5a2013-05-07 19:36:43 +000044 SkAutoLockPixels alp(bitmap);
reed@google.comac10a2d2010-12-22 21:39:39 +000045 if (!bitmap.readyToDraw()) {
tomhudson@google.com0c00f212011-12-28 14:59:50 +000046 SkDEBUGFAIL("bitmap not ready to draw!");
reed@google.comac10a2d2010-12-22 21:39:39 +000047 return;
48 }
49
50 SkColorTable* ctable = bitmap.getColorTable();
51 char* dst = (char*)buffer;
bsalomon@google.com5782d712011-01-21 21:03:59 +000052
reed@google.com7111d462014-03-25 16:20:24 +000053 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;
commit-bot@chromium.org28fcae22014-04-11 17:15:40 +000062 srcPI.fColorType = kN32_SkColorType;
reed@google.com7111d462014-03-25 16:20:24 +000063 srcPI.fAlphaType = kPremul_SkAlphaType;
mtklein775b8192014-12-02 09:11:25 -080064 srcPI.fPixels = ctable->readColors();
reed@google.com7111d462014-03-25 16:20:24 +000065 srcPI.fRowBytes = count * sizeof(SkPMColor);
66
67 srcPI.convertPixelsTo(&dstPI, count, 1);
68
reed@google.comac10a2d2010-12-22 21:39:39 +000069 // always skip a full 256 number of entries, even if we memcpy'd fewer
bsalomond4cb9222014-08-11 14:19:09 -070070 dst += 256 * sizeof(GrColor);
reed@google.comac10a2d2010-12-22 21:39:39 +000071
scroggo@google.com0ba4bf42013-02-25 16:02:36 +000072 if ((unsigned)bitmap.width() == bitmap.rowBytes()) {
reed@google.comac10a2d2010-12-22 21:39:39 +000073 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
bsalomon@google.com0797c2c2012-12-20 15:13:01 +000089static void generate_bitmap_cache_id(const SkBitmap& bitmap, GrCacheID* id) {
90 // Our id includes the offset, width, and height so that bitmaps created by extractSubset()
91 // are unique.
92 uint32_t genID = bitmap.getGenerationID();
reed@google.com672588b2014-01-08 15:42:01 +000093 SkIPoint origin = bitmap.pixelRefOrigin();
94 int16_t width = SkToS16(bitmap.width());
95 int16_t height = SkToS16(bitmap.height());
bsalomon@google.com0797c2c2012-12-20 15:13:01 +000096
skia.committer@gmail.com2859eb72012-12-21 02:01:28 +000097 GrCacheID::Key key;
reed@google.com672588b2014-01-08 15:42:01 +000098 memcpy(key.fData8 + 0, &genID, 4);
99 memcpy(key.fData8 + 4, &origin.fX, 4);
100 memcpy(key.fData8 + 8, &origin.fY, 4);
101 memcpy(key.fData8 + 12, &width, 2);
102 memcpy(key.fData8 + 14, &height, 2);
103 static const size_t kKeyDataSize = 16;
bsalomon@google.com10a9fb82013-01-02 19:29:57 +0000104 memset(key.fData8 + kKeyDataSize, 0, sizeof(key) - kKeyDataSize);
reed@google.com672588b2014-01-08 15:42:01 +0000105 GR_STATIC_ASSERT(sizeof(key) >= kKeyDataSize);
bsalomon@google.com0797c2c2012-12-20 15:13:01 +0000106 static const GrCacheID::Domain gBitmapTextureDomain = GrCacheID::GenerateDomain();
107 id->reset(gBitmapTextureDomain, key);
108}
109
bsalomonf2703d82014-10-28 14:33:06 -0700110static void generate_bitmap_texture_desc(const SkBitmap& bitmap, GrSurfaceDesc* desc) {
111 desc->fFlags = kNone_GrSurfaceFlags;
bsalomon@google.com0797c2c2012-12-20 15:13:01 +0000112 desc->fWidth = bitmap.width();
113 desc->fHeight = bitmap.height();
commit-bot@chromium.org3adcc342014-04-23 19:18:09 +0000114 desc->fConfig = SkImageInfo2GrPixelConfig(bitmap.info());
bsalomon@google.com0797c2c2012-12-20 15:13:01 +0000115 desc->fSampleCnt = 0;
116}
117
commit-bot@chromium.org50a30432013-10-24 17:44:27 +0000118namespace {
119
120// When the SkPixelRef genID changes, invalidate a corresponding GrResource described by key.
121class GrResourceInvalidator : public SkPixelRef::GenIDChangeListener {
122public:
123 explicit GrResourceInvalidator(GrResourceKey key) : fKey(key) {}
124private:
125 GrResourceKey fKey;
126
mtklein72c9faa2015-01-09 10:06:39 -0800127 void onChange() SK_OVERRIDE {
commit-bot@chromium.org50a30432013-10-24 17:44:27 +0000128 const GrResourceInvalidatedMessage message = { fKey };
129 SkMessageBus<GrResourceInvalidatedMessage>::Post(message);
130 }
131};
132
133} // namespace
134
135static void add_genID_listener(GrResourceKey key, SkPixelRef* pixelRef) {
bsalomon49f085d2014-09-05 13:34:00 -0700136 SkASSERT(pixelRef);
commit-bot@chromium.org50a30432013-10-24 17:44:27 +0000137 pixelRef->addGenIDChangeListener(SkNEW_ARGS(GrResourceInvalidator, (key)));
138}
139
sugoi0249ec22014-09-09 08:12:34 -0700140static GrTexture* sk_gr_allocate_texture(GrContext* ctx,
141 bool cache,
142 const GrTextureParams* params,
143 const SkBitmap& bm,
bsalomonf2703d82014-10-28 14:33:06 -0700144 GrSurfaceDesc desc,
sugoi0249ec22014-09-09 08:12:34 -0700145 const void* pixels,
146 size_t rowBytes) {
147 GrTexture* result;
148 if (cache) {
149 // This texture is likely to be used again so leave it in the cache
150 GrCacheID cacheID;
151 generate_bitmap_cache_id(bm, &cacheID);
152
153 GrResourceKey key;
154 result = ctx->createTexture(params, desc, cacheID, pixels, rowBytes, &key);
155 if (result) {
156 add_genID_listener(key, bm.pixelRef());
157 }
158 } else {
159 // This texture is unlikely to be used again (in its present form) so
160 // just use a scratch texture. This will remove the texture from the
161 // cache so no one else can find it. Additionally, once unlocked, the
162 // scratch texture will go to the end of the list for purging so will
163 // likely be available for this volatile bitmap the next time around.
bsalomone3059732014-10-14 11:47:22 -0700164 result = ctx->refScratchTexture(desc, GrContext::kExact_ScratchTexMatch);
sugoi0249ec22014-09-09 08:12:34 -0700165 if (pixels) {
166 result->writePixels(0, 0, bm.width(), bm.height(), desc.fConfig, pixels, rowBytes);
167 }
168 }
169 return result;
170}
171
krajcevski8c111f72014-06-02 13:51:34 -0700172#ifndef SK_IGNORE_ETC1_SUPPORT
sugoi0249ec22014-09-09 08:12:34 -0700173static GrTexture *load_etc1_texture(GrContext* ctx, bool cache,
krajcevski9c0e6292014-06-02 07:38:14 -0700174 const GrTextureParams* params,
bsalomonf2703d82014-10-28 14:33:06 -0700175 const SkBitmap &bm, GrSurfaceDesc desc) {
krajcevski99ffe242014-06-03 13:04:35 -0700176 SkAutoTUnref<SkData> data(bm.pixelRef()->refEncodedData());
krajcevski9c0e6292014-06-02 07:38:14 -0700177
178 // Is this even encoded data?
179 if (NULL == data) {
180 return NULL;
181 }
182
183 // Is this a valid PKM encoded data?
184 const uint8_t *bytes = data->bytes();
krajcevski99ffe242014-06-03 13:04:35 -0700185 if (etc1_pkm_is_valid(bytes)) {
186 uint32_t encodedWidth = etc1_pkm_get_width(bytes);
187 uint32_t encodedHeight = etc1_pkm_get_height(bytes);
188
189 // Does the data match the dimensions of the bitmap? If not,
190 // then we don't know how to scale the image to match it...
191 if (encodedWidth != static_cast<uint32_t>(bm.width()) ||
192 encodedHeight != static_cast<uint32_t>(bm.height())) {
193 return NULL;
194 }
195
196 // Everything seems good... skip ahead to the data.
197 bytes += ETC_PKM_HEADER_SIZE;
198 desc.fConfig = kETC1_GrPixelConfig;
199 } else if (SkKTXFile::is_ktx(bytes)) {
200 SkKTXFile ktx(data);
201
202 // Is it actually an ETC1 texture?
krajcevski40a1e112014-08-05 14:13:36 -0700203 if (!ktx.isCompressedFormat(SkTextureCompressor::kETC1_Format)) {
krajcevski99ffe242014-06-03 13:04:35 -0700204 return NULL;
205 }
206
207 // Does the data match the dimensions of the bitmap? If not,
208 // then we don't know how to scale the image to match it...
209 if (ktx.width() != bm.width() || ktx.height() != bm.height()) {
210 return NULL;
mtklein775b8192014-12-02 09:11:25 -0800211 }
krajcevski99ffe242014-06-03 13:04:35 -0700212
213 bytes = ktx.pixelData();
214 desc.fConfig = kETC1_GrPixelConfig;
215 } else {
krajcevski9c0e6292014-06-02 07:38:14 -0700216 return NULL;
217 }
218
sugoi0249ec22014-09-09 08:12:34 -0700219 return sk_gr_allocate_texture(ctx, cache, params, bm, desc, bytes, 0);
krajcevski9c0e6292014-06-02 07:38:14 -0700220}
krajcevski8c111f72014-06-02 13:51:34 -0700221#endif // SK_IGNORE_ETC1_SUPPORT
krajcevski9c0e6292014-06-02 07:38:14 -0700222
sugoi0249ec22014-09-09 08:12:34 -0700223static GrTexture *load_yuv_texture(GrContext* ctx, bool cache, const GrTextureParams* params,
bsalomonf2703d82014-10-28 14:33:06 -0700224 const SkBitmap& bm, const GrSurfaceDesc& desc) {
sugoiff58e462014-10-16 05:19:31 -0700225 // Subsets are not supported, the whole pixelRef is loaded when using YUV decoding
sugoi518d83d2014-07-21 11:37:39 -0700226 SkPixelRef* pixelRef = bm.pixelRef();
sugoi692135f2015-01-19 10:10:27 -0800227 if ((NULL == pixelRef) ||
228 (pixelRef->info().width() != bm.info().width()) ||
229 (pixelRef->info().height() != bm.info().height())) {
sugoi518d83d2014-07-21 11:37:39 -0700230 return NULL;
231 }
232
sugoi692135f2015-01-19 10:10:27 -0800233 SkYUVPlanesCache::Info yuvInfo;
234 SkAutoTUnref<SkCachedData> cachedData(
235 SkYUVPlanesCache::FindAndRef(pixelRef->getGenerationID(), &yuvInfo));
236
sugoi518d83d2014-07-21 11:37:39 -0700237 void* planes[3];
sugoi692135f2015-01-19 10:10:27 -0800238 if (cachedData->data()) {
239 planes[0] = (void*)cachedData->data();
240 planes[1] = (uint8_t*)planes[0] + yuvInfo.fSizeInMemory[0];
241 planes[2] = (uint8_t*)planes[1] + yuvInfo.fSizeInMemory[1];
242 } else {
243 // Fetch yuv plane sizes for memory allocation. Here, width and height can be
244 // rounded up to JPEG block size and be larger than the image's width and height.
245 if (!pixelRef->getYUV8Planes(yuvInfo.fSize, NULL, NULL, NULL)) {
246 return NULL;
247 }
sugoi518d83d2014-07-21 11:37:39 -0700248
sugoi692135f2015-01-19 10:10:27 -0800249 // Allocate the memory for YUV
250 size_t totalSize(0);
251 for (int i = 0; i < 3; ++i) {
252 yuvInfo.fRowBytes[i] = yuvInfo.fSize[i].fWidth;
253 yuvInfo.fSizeInMemory[i] = yuvInfo.fRowBytes[i] * yuvInfo.fSize[i].fHeight;
254 totalSize += yuvInfo.fSizeInMemory[i];
255 }
256 cachedData.reset(SkResourceCache::NewCachedData(totalSize));
257 planes[0] = cachedData->writable_data();
258 planes[1] = (uint8_t*)planes[0] + yuvInfo.fSizeInMemory[0];
259 planes[2] = (uint8_t*)planes[1] + yuvInfo.fSizeInMemory[1];
rileyaabaef862014-09-12 17:45:58 -0700260
sugoi692135f2015-01-19 10:10:27 -0800261 // Get the YUV planes and update plane sizes to actual image size
262 if (!pixelRef->getYUV8Planes(yuvInfo.fSize, planes, yuvInfo.fRowBytes,
263 &yuvInfo.fColorSpace)) {
264 return NULL;
265 }
266
267 // Decoding is done, cache the resulting YUV planes
268 SkYUVPlanesCache::Add(pixelRef->getGenerationID(), cachedData, &yuvInfo);
sugoi518d83d2014-07-21 11:37:39 -0700269 }
270
bsalomonf2703d82014-10-28 14:33:06 -0700271 GrSurfaceDesc yuvDesc;
sugoi518d83d2014-07-21 11:37:39 -0700272 yuvDesc.fConfig = kAlpha_8_GrPixelConfig;
bsalomone3059732014-10-14 11:47:22 -0700273 SkAutoTUnref<GrTexture> yuvTextures[3];
sugoi518d83d2014-07-21 11:37:39 -0700274 for (int i = 0; i < 3; ++i) {
sugoi692135f2015-01-19 10:10:27 -0800275 yuvDesc.fWidth = yuvInfo.fSize[i].fWidth;
276 yuvDesc.fHeight = yuvInfo.fSize[i].fHeight;
bsalomone3059732014-10-14 11:47:22 -0700277 yuvTextures[i].reset(
278 ctx->refScratchTexture(yuvDesc, GrContext::kApprox_ScratchTexMatch));
279 if (!yuvTextures[i] ||
280 !yuvTextures[i]->writePixels(0, 0, yuvDesc.fWidth, yuvDesc.fHeight,
sugoi692135f2015-01-19 10:10:27 -0800281 yuvDesc.fConfig, planes[i], yuvInfo.fRowBytes[i])) {
sugoi518d83d2014-07-21 11:37:39 -0700282 return NULL;
283 }
284 }
285
bsalomonf2703d82014-10-28 14:33:06 -0700286 GrSurfaceDesc rtDesc = desc;
sugoi518d83d2014-07-21 11:37:39 -0700287 rtDesc.fFlags = rtDesc.fFlags |
bsalomonf2703d82014-10-28 14:33:06 -0700288 kRenderTarget_GrSurfaceFlag |
289 kNoStencil_GrSurfaceFlag;
sugoi518d83d2014-07-21 11:37:39 -0700290
sugoi0249ec22014-09-09 08:12:34 -0700291 GrTexture* result = sk_gr_allocate_texture(ctx, cache, params, bm, rtDesc, NULL, 0);
sugoi518d83d2014-07-21 11:37:39 -0700292
sugoi518d83d2014-07-21 11:37:39 -0700293 GrRenderTarget* renderTarget = result ? result->asRenderTarget() : NULL;
bsalomon49f085d2014-09-05 13:34:00 -0700294 if (renderTarget) {
sugoi692135f2015-01-19 10:10:27 -0800295 SkAutoTUnref<GrFragmentProcessor> yuvToRgbProcessor(GrYUVtoRGBEffect::Create(
296 yuvTextures[0], yuvTextures[1], yuvTextures[2], yuvInfo.fColorSpace));
sugoi518d83d2014-07-21 11:37:39 -0700297 GrPaint paint;
joshualittb0a8a372014-09-23 09:50:21 -0700298 paint.addColorProcessor(yuvToRgbProcessor);
sugoi692135f2015-01-19 10:10:27 -0800299 SkRect r = SkRect::MakeWH(SkIntToScalar(yuvInfo.fSize[0].fWidth),
300 SkIntToScalar(yuvInfo.fSize[0].fHeight));
sugoi518d83d2014-07-21 11:37:39 -0700301 GrContext::AutoRenderTarget autoRT(ctx, renderTarget);
sugoi518d83d2014-07-21 11:37:39 -0700302 GrContext::AutoClip ac(ctx, GrContext::AutoClip::kWideOpen_InitialClip);
joshualitt5531d512014-12-17 15:50:11 -0800303 ctx->drawRect(paint, SkMatrix::I(), r);
sugoi518d83d2014-07-21 11:37:39 -0700304 } else {
305 SkSafeSetNull(result);
306 }
307
308 return result;
309}
310
robertphillips@google.com1f47f4f2012-08-16 14:49:16 +0000311static GrTexture* sk_gr_create_bitmap_texture(GrContext* ctx,
bsalomon@google.com0797c2c2012-12-20 15:13:01 +0000312 bool cache,
robertphillips@google.com1f47f4f2012-08-16 14:49:16 +0000313 const GrTextureParams* params,
314 const SkBitmap& origBitmap) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000315 SkBitmap tmpBitmap;
316
317 const SkBitmap* bitmap = &origBitmap;
bsalomon@google.com5782d712011-01-21 21:03:59 +0000318
bsalomonf2703d82014-10-28 14:33:06 -0700319 GrSurfaceDesc desc;
bsalomon@google.com0797c2c2012-12-20 15:13:01 +0000320 generate_bitmap_texture_desc(*bitmap, &desc);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000321
reed0689d7b2014-06-14 05:30:20 -0700322 if (kIndex_8_SkColorType == bitmap->colorType()) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000323 // build_compressed_data doesn't do npot->pot expansion
324 // and paletted textures can't be sub-updated
bsalomone79a2da2014-10-24 12:42:51 -0700325 if (cache && ctx->supportsIndex8PixelConfig(params, bitmap->width(), bitmap->height())) {
bsalomond4cb9222014-08-11 14:19:09 -0700326 size_t imageSize = GrCompressedFormatDataSize(kIndex_8_GrPixelConfig,
327 bitmap->width(), bitmap->height());
328 SkAutoMalloc storage(imageSize);
bsalomone79a2da2014-10-24 12:42:51 -0700329 build_index8_data(storage.get(), origBitmap);
reed@google.comac10a2d2010-12-22 21:39:39 +0000330
331 // our compressed data will be trimmed, so pass width() for its
332 // "rowBytes", since they are the same now.
sugoi0249ec22014-09-09 08:12:34 -0700333 return sk_gr_allocate_texture(ctx, cache, params, origBitmap,
334 desc, storage.get(), bitmap->width());
reed@google.comac10a2d2010-12-22 21:39:39 +0000335 } else {
commit-bot@chromium.org28fcae22014-04-11 17:15:40 +0000336 origBitmap.copyTo(&tmpBitmap, kN32_SkColorType);
reed@google.comac10a2d2010-12-22 21:39:39 +0000337 // now bitmap points to our temp, which has been promoted to 32bits
338 bitmap = &tmpBitmap;
commit-bot@chromium.org3adcc342014-04-23 19:18:09 +0000339 desc.fConfig = SkImageInfo2GrPixelConfig(bitmap->info());
reed@google.comac10a2d2010-12-22 21:39:39 +0000340 }
krajcevski309e8692014-06-02 08:02:45 -0700341 }
krajcevski9c0e6292014-06-02 07:38:14 -0700342
343 // Is this an ETC1 encoded texture?
krajcevski8c111f72014-06-02 13:51:34 -0700344#ifndef SK_IGNORE_ETC1_SUPPORT
krajcevski9a3cdbb2014-06-05 07:03:39 -0700345 else if (
bungeman77cd8b02014-09-10 14:59:59 -0700346 // We do not support scratch ETC1 textures, hence they should all be at least
347 // trying to go to the cache.
348 cache
krajcevski9a3cdbb2014-06-05 07:03:39 -0700349 // Make sure that the underlying device supports ETC1 textures before we go ahead
350 // and check the data.
bungeman77cd8b02014-09-10 14:59:59 -0700351 && ctx->getGpu()->caps()->isConfigTexturable(kETC1_GrPixelConfig)
krajcevski9a3cdbb2014-06-05 07:03:39 -0700352 // If the bitmap had compressed data and was then uncompressed, it'll still return
353 // compressed data on 'refEncodedData' and upload it. Probably not good, since if
354 // the bitmap has available pixels, then they might not be what the decompressed
355 // data is.
356 && !(bitmap->readyToDraw())) {
sugoi0249ec22014-09-09 08:12:34 -0700357 GrTexture *texture = load_etc1_texture(ctx, cache, params, *bitmap, desc);
bsalomon49f085d2014-09-05 13:34:00 -0700358 if (texture) {
krajcevski9c0e6292014-06-02 07:38:14 -0700359 return texture;
360 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000361 }
krajcevski8c111f72014-06-02 13:51:34 -0700362#endif // SK_IGNORE_ETC1_SUPPORT
reed@google.comac10a2d2010-12-22 21:39:39 +0000363
sugoi518d83d2014-07-21 11:37:39 -0700364 else {
sugoi0249ec22014-09-09 08:12:34 -0700365 GrTexture *texture = load_yuv_texture(ctx, cache, params, *bitmap, desc);
bsalomon49f085d2014-09-05 13:34:00 -0700366 if (texture) {
sugoi518d83d2014-07-21 11:37:39 -0700367 return texture;
368 }
369 }
bsalomon@google.com7f4ad5a2013-05-07 19:36:43 +0000370 SkAutoLockPixels alp(*bitmap);
371 if (!bitmap->readyToDraw()) {
372 return NULL;
373 }
commit-bot@chromium.org50a30432013-10-24 17:44:27 +0000374
sugoi0249ec22014-09-09 08:12:34 -0700375 return sk_gr_allocate_texture(ctx, cache, params, origBitmap, desc,
376 bitmap->getPixels(), bitmap->rowBytes());
reed@google.comac10a2d2010-12-22 21:39:39 +0000377}
378
bsalomon9ed7f572014-12-19 12:26:37 -0800379static GrTexture* get_texture_backing_bmp(const SkBitmap& bitmap, const GrContext* context,
380 const GrTextureParams* params) {
381 if (GrTexture* texture = bitmap.getTexture()) {
382 // Our texture-resizing-for-tiling used to upscale NPOT textures for tiling only works with
383 // content-key cached resources. Rather than invest in that legacy code path, we'll just
384 // take the horribly slow route of causing a cache miss which will cause the pixels to be
385 // read and reuploaded to a texture with a content key.
386 if (params && !context->getGpu()->caps()->npotTextureTileSupport() &&
387 (params->isTiled() || GrTextureParams::kMipMap_FilterMode == params->filterMode())) {
388 return NULL;
389 }
390 return texture;
391 }
392 return NULL;
393}
394
bsalomon@google.com0797c2c2012-12-20 15:13:01 +0000395bool GrIsBitmapInCache(const GrContext* ctx,
396 const SkBitmap& bitmap,
397 const GrTextureParams* params) {
bsalomon9ed7f572014-12-19 12:26:37 -0800398 if (get_texture_backing_bmp(bitmap, ctx, params)) {
399 return true;
400 }
401
bsalomon@google.com0797c2c2012-12-20 15:13:01 +0000402 GrCacheID cacheID;
403 generate_bitmap_cache_id(bitmap, &cacheID);
404
bsalomonf2703d82014-10-28 14:33:06 -0700405 GrSurfaceDesc desc;
bsalomon@google.com0797c2c2012-12-20 15:13:01 +0000406 generate_bitmap_texture_desc(bitmap, &desc);
407 return ctx->isTextureInCache(desc, cacheID, params);
408}
reed@google.comac10a2d2010-12-22 21:39:39 +0000409
bsalomonbcf0a522014-10-08 08:40:09 -0700410GrTexture* GrRefCachedBitmapTexture(GrContext* ctx,
411 const SkBitmap& bitmap,
412 const GrTextureParams* params) {
bsalomon9ed7f572014-12-19 12:26:37 -0800413 GrTexture* result = get_texture_backing_bmp(bitmap, ctx, params);
414 if (result) {
415 return SkRef(result);
416 }
rileya@google.com24f3ad12012-07-18 21:47:40 +0000417
bsalomon@google.com0797c2c2012-12-20 15:13:01 +0000418 bool cache = !bitmap.isVolatile();
419
420 if (cache) {
421 // If the bitmap isn't changing try to find a cached copy first.
422
423 GrCacheID cacheID;
424 generate_bitmap_cache_id(bitmap, &cacheID);
rileya@google.com24f3ad12012-07-18 21:47:40 +0000425
bsalomonf2703d82014-10-28 14:33:06 -0700426 GrSurfaceDesc desc;
bsalomon@google.com0797c2c2012-12-20 15:13:01 +0000427 generate_bitmap_texture_desc(bitmap, &desc);
rileya@google.com24f3ad12012-07-18 21:47:40 +0000428
bsalomon@google.com95ed55a2013-01-24 14:46:47 +0000429 result = ctx->findAndRefTexture(desc, cacheID, params);
bsalomon@google.com0797c2c2012-12-20 15:13:01 +0000430 }
431 if (NULL == result) {
432 result = sk_gr_create_bitmap_texture(ctx, cache, params, bitmap);
rileya@google.com24f3ad12012-07-18 21:47:40 +0000433 }
robertphillips@google.com1f47f4f2012-08-16 14:49:16 +0000434 if (NULL == result) {
tfarina38406c82014-10-31 07:11:12 -0700435 SkDebugf("---- failed to create texture for cache [%d %d]\n",
436 bitmap.width(), bitmap.height());
rileya@google.com24f3ad12012-07-18 21:47:40 +0000437 }
robertphillips@google.com1f47f4f2012-08-16 14:49:16 +0000438 return result;
rileya@google.com24f3ad12012-07-18 21:47:40 +0000439}
440
rileya@google.com24f3ad12012-07-18 21:47:40 +0000441///////////////////////////////////////////////////////////////////////////////
442
commit-bot@chromium.org15a14052014-02-16 00:59:25 +0000443// alphatype is ignore for now, but if GrPixelConfig is expanded to encompass
444// alpha info, that will be considered.
jvanverthfa1e8a72014-12-22 08:31:49 -0800445GrPixelConfig SkImageInfo2GrPixelConfig(SkColorType ct, SkAlphaType, SkColorProfileType pt) {
commit-bot@chromium.org15a14052014-02-16 00:59:25 +0000446 switch (ct) {
447 case kUnknown_SkColorType:
448 return kUnknown_GrPixelConfig;
449 case kAlpha_8_SkColorType:
450 return kAlpha_8_GrPixelConfig;
451 case kRGB_565_SkColorType:
452 return kRGB_565_GrPixelConfig;
453 case kARGB_4444_SkColorType:
454 return kRGBA_4444_GrPixelConfig;
455 case kRGBA_8888_SkColorType:
jvanverthfe43c402014-12-22 10:29:30 -0800456// if (kSRGB_SkColorProfileType == pt) {
457// return kSRGBA_8888_GrPixelConfig;
458// }
commit-bot@chromium.org15a14052014-02-16 00:59:25 +0000459 return kRGBA_8888_GrPixelConfig;
460 case kBGRA_8888_SkColorType:
461 return kBGRA_8888_GrPixelConfig;
462 case kIndex_8_SkColorType:
463 return kIndex_8_GrPixelConfig;
464 }
465 SkASSERT(0); // shouldn't get here
466 return kUnknown_GrPixelConfig;
467}
468
jvanverthfa1e8a72014-12-22 08:31:49 -0800469bool GrPixelConfig2ColorAndProfileType(GrPixelConfig config, SkColorType* ctOut,
470 SkColorProfileType* ptOut) {
reed@google.combf790232013-12-13 19:45:58 +0000471 SkColorType ct;
jvanverthfa1e8a72014-12-22 08:31:49 -0800472 SkColorProfileType pt = kLinear_SkColorProfileType;
reed@google.combf790232013-12-13 19:45:58 +0000473 switch (config) {
474 case kAlpha_8_GrPixelConfig:
475 ct = kAlpha_8_SkColorType;
476 break;
477 case kIndex_8_GrPixelConfig:
478 ct = kIndex_8_SkColorType;
479 break;
480 case kRGB_565_GrPixelConfig:
481 ct = kRGB_565_SkColorType;
482 break;
483 case kRGBA_4444_GrPixelConfig:
484 ct = kARGB_4444_SkColorType;
485 break;
486 case kRGBA_8888_GrPixelConfig:
487 ct = kRGBA_8888_SkColorType;
488 break;
489 case kBGRA_8888_GrPixelConfig:
490 ct = kBGRA_8888_SkColorType;
491 break;
jvanverthfa1e8a72014-12-22 08:31:49 -0800492 case kSRGBA_8888_GrPixelConfig:
493 ct = kRGBA_8888_SkColorType;
494 pt = kSRGB_SkColorProfileType;
495 break;
reed@google.combf790232013-12-13 19:45:58 +0000496 default:
497 return false;
498 }
499 if (ctOut) {
500 *ctOut = ct;
501 }
jvanverthfa1e8a72014-12-22 08:31:49 -0800502 if (ptOut) {
503 *ptOut = pt;
504 }
reed@google.combf790232013-12-13 19:45:58 +0000505 return true;
506}
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000507
508///////////////////////////////////////////////////////////////////////////////
509
bsalomon83d081a2014-07-08 09:56:10 -0700510void SkPaint2GrPaintNoShader(GrContext* context, const SkPaint& skPaint, GrColor paintColor,
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000511 bool constantColor, GrPaint* grPaint) {
512
513 grPaint->setDither(skPaint.isDither());
514 grPaint->setAntiAlias(skPaint.isAntiAlias());
515
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000516 SkXfermode* mode = skPaint.getXfermode();
egdaniel378092f2014-12-03 10:40:13 -0800517 GrFragmentProcessor* fragmentProcessor = NULL;
518 GrXPFactory* xpFactory = NULL;
egdaniel95131432014-12-09 11:15:43 -0800519 if (SkXfermode::AsFragmentProcessorOrXPFactory(mode, &fragmentProcessor, &xpFactory)) {
egdaniel378092f2014-12-03 10:40:13 -0800520 if (fragmentProcessor) {
521 SkASSERT(NULL == xpFactory);
522 grPaint->addColorProcessor(fragmentProcessor)->unref();
egdanielc016fb82014-12-03 11:41:54 -0800523 xpFactory = GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode);
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000524 }
525 } else {
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000526 // Fall back to src-over
egdanielc016fb82014-12-03 11:41:54 -0800527 xpFactory = GrPorterDuffXPFactory::Create(SkXfermode::kSrcOver_Mode);
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000528 }
egdaniel378092f2014-12-03 10:40:13 -0800529 SkASSERT(xpFactory);
530 grPaint->setXPFactory(xpFactory)->unref();
mtklein775b8192014-12-02 09:11:25 -0800531
dandov9de5b512014-06-10 14:38:28 -0700532 //set the color of the paint to the one of the parameter
bsalomon83d081a2014-07-08 09:56:10 -0700533 grPaint->setColor(paintColor);
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000534
535 SkColorFilter* colorFilter = skPaint.getColorFilter();
bsalomon49f085d2014-09-05 13:34:00 -0700536 if (colorFilter) {
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000537 // if the source color is a constant then apply the filter here once rather than per pixel
538 // in a shader.
539 if (constantColor) {
540 SkColor filtered = colorFilter->filterColor(skPaint.getColor());
541 grPaint->setColor(SkColor2GrColor(filtered));
542 } else {
joshualittb0a8a372014-09-23 09:50:21 -0700543 SkAutoTUnref<GrFragmentProcessor> fp(colorFilter->asFragmentProcessor(context));
544 if (fp.get()) {
545 grPaint->addColorProcessor(fp);
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000546 }
547 }
548 }
krajcevskif461a8f2014-06-19 14:14:06 -0700549
550#ifndef SK_IGNORE_GPU_DITHER
551 // If the dither flag is set, then we need to see if the underlying context
552 // supports it. If not, then install a dither effect.
553 if (skPaint.isDither() && grPaint->numColorStages() > 0) {
554 // What are we rendering into?
555 const GrRenderTarget *target = context->getRenderTarget();
bsalomon49f085d2014-09-05 13:34:00 -0700556 SkASSERT(target);
krajcevskif461a8f2014-06-19 14:14:06 -0700557
558 // Suspect the dithering flag has no effect on these configs, otherwise
559 // fall back on setting the appropriate state.
560 if (target->config() == kRGBA_8888_GrPixelConfig ||
561 target->config() == kBGRA_8888_GrPixelConfig) {
562 // The dither flag is set and the target is likely
563 // not going to be dithered by the GPU.
joshualittb0a8a372014-09-23 09:50:21 -0700564 SkAutoTUnref<GrFragmentProcessor> fp(GrDitherEffect::Create());
565 if (fp.get()) {
566 grPaint->addColorProcessor(fp);
krajcevskif461a8f2014-06-19 14:14:06 -0700567 grPaint->setDither(false);
568 }
569 }
570 }
571#endif
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000572}
573
joshualitt5531d512014-12-17 15:50:11 -0800574void SkPaint2GrPaintShader(GrContext* context, const SkPaint& skPaint, const SkMatrix& viewM,
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000575 bool constantColor, GrPaint* grPaint) {
576 SkShader* shader = skPaint.getShader();
577 if (NULL == shader) {
dandov9de5b512014-06-10 14:38:28 -0700578 SkPaint2GrPaintNoShader(context, skPaint, SkColor2GrColor(skPaint.getColor()),
579 constantColor, grPaint);
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000580 return;
581 }
582
bsalomon83d081a2014-07-08 09:56:10 -0700583 GrColor paintColor = SkColor2GrColor(skPaint.getColor());
krajcevskif461a8f2014-06-19 14:14:06 -0700584
585 // Start a new block here in order to preserve our context state after calling
joshualittb0a8a372014-09-23 09:50:21 -0700586 // asFragmentProcessor(). Since these calls get passed back to the client, we don't really
krajcevskif461a8f2014-06-19 14:14:06 -0700587 // want them messing around with the context.
588 {
joshualittb0a8a372014-09-23 09:50:21 -0700589 // SkShader::asFragmentProcessor() may do offscreen rendering. Save off the current RT,
joshualitt5531d512014-12-17 15:50:11 -0800590 // and clip
krajcevskif461a8f2014-06-19 14:14:06 -0700591 GrContext::AutoRenderTarget art(context, NULL);
592 GrContext::AutoClip ac(context, GrContext::AutoClip::kWideOpen_InitialClip);
krajcevskif461a8f2014-06-19 14:14:06 -0700593
bsalomon83d081a2014-07-08 09:56:10 -0700594 // Allow the shader to modify paintColor and also create an effect to be installed as
595 // the first color effect on the GrPaint.
joshualittb0a8a372014-09-23 09:50:21 -0700596 GrFragmentProcessor* fp = NULL;
joshualitt5531d512014-12-17 15:50:11 -0800597 if (shader->asFragmentProcessor(context, skPaint, viewM, NULL, &paintColor, &fp) && fp) {
joshualittb0a8a372014-09-23 09:50:21 -0700598 grPaint->addColorProcessor(fp)->unref();
krajcevskif461a8f2014-06-19 14:14:06 -0700599 constantColor = false;
600 }
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000601 }
krajcevskif461a8f2014-06-19 14:14:06 -0700602
joshualittb0a8a372014-09-23 09:50:21 -0700603 // The grcolor is automatically set when calling asFragmentProcessor.
dandov9de5b512014-06-10 14:38:28 -0700604 // If the shader can be seen as an effect it returns true and adds its effect to the grpaint.
bsalomon83d081a2014-07-08 09:56:10 -0700605 SkPaint2GrPaintNoShader(context, skPaint, paintColor, constantColor, grPaint);
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000606}