blob: d8444968da6ea2e788b16900fc80af3e314a1243 [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
reedb5d32632015-09-29 13:36:50 -07008#include "GrTextureMaker.h"
9
reed@google.comac10a2d2010-12-22 21:39:39 +000010#include "SkGr.h"
egdaniel378092f2014-12-03 10:40:13 -080011
bsalomon76228632015-05-29 08:02:10 -070012#include "GrCaps.h"
bsalomonf276ac52015-10-09 13:36:42 -070013#include "GrContext.h"
robertphillipsea461502015-05-26 11:38:03 -070014#include "GrDrawContext.h"
egdaniel378092f2014-12-03 10:40:13 -080015#include "GrXferProcessor.h"
reed43fe6182015-09-08 08:37:36 -070016#include "GrYUVProvider.h"
17
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +000018#include "SkColorFilter.h"
commit-bot@chromium.orgea476e12013-10-14 18:29:23 +000019#include "SkConfig8888.h"
bsalomonb4d40ef2015-07-15 10:12:16 -070020#include "SkCanvas.h"
krajcevski9c0e6292014-06-02 07:38:14 -070021#include "SkData.h"
joshualitt5f5a8d72015-02-25 14:09:45 -080022#include "SkErrorInternals.h"
reed8b26b992015-05-07 15:36:17 -070023#include "SkGrPixelRef.h"
commit-bot@chromium.org50a30432013-10-24 17:44:27 +000024#include "SkMessageBus.h"
25#include "SkPixelRef.h"
sugoi692135f2015-01-19 10:10:27 -080026#include "SkResourceCache.h"
krajcevski40a1e112014-08-05 14:13:36 -070027#include "SkTextureCompressor.h"
sugoi692135f2015-01-19 10:10:27 -080028#include "SkYUVPlanesCache.h"
joshualitt9bc39542015-08-12 12:57:54 -070029#include "effects/GrBicubicEffect.h"
bsalomonf1b7a1d2015-09-28 06:26:28 -070030#include "effects/GrConstColorProcessor.h"
krajcevskif461a8f2014-06-19 14:14:06 -070031#include "effects/GrDitherEffect.h"
egdaniel378092f2014-12-03 10:40:13 -080032#include "effects/GrPorterDuffXferProcessor.h"
bsalomonf1b7a1d2015-09-28 06:26:28 -070033#include "effects/GrXfermodeFragmentProcessor.h"
sugoi518d83d2014-07-21 11:37:39 -070034#include "effects/GrYUVtoRGBEffect.h"
krajcevski9c0e6292014-06-02 07:38:14 -070035
krajcevski8c111f72014-06-02 13:51:34 -070036#ifndef SK_IGNORE_ETC1_SUPPORT
krajcevski99ffe242014-06-03 13:04:35 -070037# include "ktx.h"
krajcevski9c0e6292014-06-02 07:38:14 -070038# include "etc1.h"
39#endif
reed@google.comac10a2d2010-12-22 21:39:39 +000040
bsalomon466c2c42015-10-16 12:01:18 -070041GrSurfaceDesc GrImageInfoToSurfaceDesc(const SkImageInfo& info) {
42 GrSurfaceDesc desc;
43 desc.fFlags = kNone_GrSurfaceFlags;
44 desc.fWidth = info.width();
45 desc.fHeight = info.height();
46 desc.fConfig = SkImageInfo2GrPixelConfig(info);
47 desc.fSampleCnt = 0;
48 return desc;
49}
50
51static void get_stretch(const GrCaps& caps, int width, int height,
52 const GrTextureParams& params, SkGrStretch* stretch) {
53 stretch->fType = SkGrStretch::kNone_Type;
54 bool doStretch = false;
55 if (params.isTiled() && !caps.npotTextureTileSupport() &&
56 (!SkIsPow2(width) || !SkIsPow2(height))) {
57 doStretch = true;
58 stretch->fWidth = GrNextPow2(SkTMax(width, caps.minTextureSize()));
59 stretch->fHeight = GrNextPow2(SkTMax(height, caps.minTextureSize()));
60 } else if (width < caps.minTextureSize() || height < caps.minTextureSize()) {
61 // The small texture issues appear to be with tiling. Hence it seems ok to scale them
62 // up using the GPU. If issues persist we may need to CPU-stretch.
63 doStretch = true;
64 stretch->fWidth = SkTMax(width, caps.minTextureSize());
65 stretch->fHeight = SkTMax(height, caps.minTextureSize());
66 }
67 if (doStretch) {
68 switch (params.filterMode()) {
69 case GrTextureParams::kNone_FilterMode:
70 stretch->fType = SkGrStretch::kNearest_Type;
71 break;
72 case GrTextureParams::kBilerp_FilterMode:
73 case GrTextureParams::kMipMap_FilterMode:
74 stretch->fType = SkGrStretch::kBilerp_Type;
75 break;
76 }
77 } else {
78 stretch->fWidth = -1;
79 stretch->fHeight = -1;
80 stretch->fType = SkGrStretch::kNone_Type;
81 }
82}
83
84static void make_unstretched_key(GrUniqueKey* key, uint32_t imageID, const SkIRect& subset) {
85 SkASSERT(SkIsU16(subset.width()));
86 SkASSERT(SkIsU16(subset.height()));
87
88 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
89 GrUniqueKey::Builder builder(key, kDomain, 4);
90 builder[0] = imageID;
91 builder[1] = subset.x();
92 builder[2] = subset.y();
93 builder[3] = subset.width() | (subset.height() << 16);
94}
95
96void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& subset,
97 const GrCaps& caps, const GrTextureParams& params) {
98 SkGrStretch stretch;
99 get_stretch(caps, subset.width(), subset.height(), params, &stretch);
100 if (SkGrStretch::kNone_Type != stretch.fType) {
101 GrUniqueKey tmpKey;
102 make_unstretched_key(&tmpKey, imageID, subset);
103 if (!GrMakeStretchedKey(tmpKey, stretch, key)) {
104 *key = tmpKey;
105 }
106 } else {
107 make_unstretched_key(key, imageID, subset);
108 }
109}
110
111GrPixelConfig GrIsCompressedTextureDataSupported(GrContext* ctx, SkData* data,
112 int expectedW, int expectedH,
113 const void** outStartOfDataToUpload) {
114 *outStartOfDataToUpload = nullptr;
115#ifndef SK_IGNORE_ETC1_SUPPORT
116 if (!ctx->caps()->isConfigTexturable(kETC1_GrPixelConfig)) {
117 return kUnknown_GrPixelConfig;
118 }
119
120 const uint8_t* bytes = data->bytes();
121 if (data->size() > ETC_PKM_HEADER_SIZE && etc1_pkm_is_valid(bytes)) {
122 // Does the data match the dimensions of the bitmap? If not,
123 // then we don't know how to scale the image to match it...
124 if (etc1_pkm_get_width(bytes) != (unsigned)expectedW ||
125 etc1_pkm_get_height(bytes) != (unsigned)expectedH)
126 {
127 return kUnknown_GrPixelConfig;
128 }
129
130 *outStartOfDataToUpload = bytes + ETC_PKM_HEADER_SIZE;
131 return kETC1_GrPixelConfig;
132 } else if (SkKTXFile::is_ktx(bytes)) {
133 SkKTXFile ktx(data);
134
135 // Is it actually an ETC1 texture?
136 if (!ktx.isCompressedFormat(SkTextureCompressor::kETC1_Format)) {
137 return kUnknown_GrPixelConfig;
138 }
139
140 // Does the data match the dimensions of the bitmap? If not,
141 // then we don't know how to scale the image to match it...
142 if (ktx.width() != expectedW || ktx.height() != expectedH) {
143 return kUnknown_GrPixelConfig;
144 }
145
146 *outStartOfDataToUpload = ktx.pixelData();
147 return kETC1_GrPixelConfig;
148 }
149#endif
150 return kUnknown_GrPixelConfig;
151}
152
reed@google.comac10a2d2010-12-22 21:39:39 +0000153/* Fill out buffer with the compressed format Ganesh expects from a colortable
154 based bitmap. [palette (colortable) + indices].
bsalomon@google.com5782d712011-01-21 21:03:59 +0000155
156 At the moment Ganesh only supports 8bit version. If Ganesh allowed we others
reed@google.comac10a2d2010-12-22 21:39:39 +0000157 we could detect that the colortable.count is <= 16, and then repack the
158 indices as nibbles to save RAM, but it would take more time (i.e. a lot
159 slower than memcpy), so skipping that for now.
bsalomon@google.com5782d712011-01-21 21:03:59 +0000160
reed@google.comac10a2d2010-12-22 21:39:39 +0000161 Ganesh wants a full 256 palette entry, even though Skia's ctable is only as big
162 as the colortable.count says it is.
163 */
bsalomone79a2da2014-10-24 12:42:51 -0700164static void build_index8_data(void* buffer, const SkBitmap& bitmap) {
reed0689d7b2014-06-14 05:30:20 -0700165 SkASSERT(kIndex_8_SkColorType == bitmap.colorType());
bsalomon@google.com5782d712011-01-21 21:03:59 +0000166
bsalomon@google.com7f4ad5a2013-05-07 19:36:43 +0000167 SkAutoLockPixels alp(bitmap);
reed@google.comac10a2d2010-12-22 21:39:39 +0000168 if (!bitmap.readyToDraw()) {
tomhudson@google.com0c00f212011-12-28 14:59:50 +0000169 SkDEBUGFAIL("bitmap not ready to draw!");
reed@google.comac10a2d2010-12-22 21:39:39 +0000170 return;
171 }
172
173 SkColorTable* ctable = bitmap.getColorTable();
174 char* dst = (char*)buffer;
bsalomon@google.com5782d712011-01-21 21:03:59 +0000175
reed@google.com7111d462014-03-25 16:20:24 +0000176 const int count = ctable->count();
177
178 SkDstPixelInfo dstPI;
179 dstPI.fColorType = kRGBA_8888_SkColorType;
180 dstPI.fAlphaType = kPremul_SkAlphaType;
181 dstPI.fPixels = buffer;
182 dstPI.fRowBytes = count * sizeof(SkPMColor);
183
184 SkSrcPixelInfo srcPI;
commit-bot@chromium.org28fcae22014-04-11 17:15:40 +0000185 srcPI.fColorType = kN32_SkColorType;
reed@google.com7111d462014-03-25 16:20:24 +0000186 srcPI.fAlphaType = kPremul_SkAlphaType;
mtklein775b8192014-12-02 09:11:25 -0800187 srcPI.fPixels = ctable->readColors();
reed@google.com7111d462014-03-25 16:20:24 +0000188 srcPI.fRowBytes = count * sizeof(SkPMColor);
189
190 srcPI.convertPixelsTo(&dstPI, count, 1);
191
reed@google.comac10a2d2010-12-22 21:39:39 +0000192 // always skip a full 256 number of entries, even if we memcpy'd fewer
bsalomond4cb9222014-08-11 14:19:09 -0700193 dst += 256 * sizeof(GrColor);
reed@google.comac10a2d2010-12-22 21:39:39 +0000194
scroggo@google.com0ba4bf42013-02-25 16:02:36 +0000195 if ((unsigned)bitmap.width() == bitmap.rowBytes()) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000196 memcpy(dst, bitmap.getPixels(), bitmap.getSize());
197 } else {
198 // need to trim off the extra bytes per row
199 size_t width = bitmap.width();
200 size_t rowBytes = bitmap.rowBytes();
201 const char* src = (const char*)bitmap.getPixels();
202 for (int y = 0; y < bitmap.height(); y++) {
203 memcpy(dst, src, width);
204 src += rowBytes;
205 dst += width;
206 }
207 }
208}
209
210////////////////////////////////////////////////////////////////////////////////
211
bsalomon37f9a262015-02-02 13:00:10 -0800212
reed856e9d92015-09-30 12:21:45 -0700213bool GrMakeStretchedKey(const GrUniqueKey& origKey, const SkGrStretch& stretch,
214 GrUniqueKey* stretchedKey) {
reedb5d32632015-09-29 13:36:50 -0700215 if (origKey.isValid() && SkGrStretch::kNone_Type != stretch.fType) {
bsalomonc59a1df2015-06-01 07:13:42 -0700216 uint32_t width = SkToU16(stretch.fWidth);
217 uint32_t height = SkToU16(stretch.fHeight);
bsalomon8718aaf2015-02-19 07:24:21 -0800218 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
reed8f343722015-08-13 13:32:39 -0700219 GrUniqueKey::Builder builder(stretchedKey, origKey, kDomain, 2);
bsalomonc59a1df2015-06-01 07:13:42 -0700220 builder[0] = stretch.fType;
221 builder[1] = width | (height << 16);
bsalomon37f9a262015-02-02 13:00:10 -0800222 builder.finish();
223 return true;
224 }
bsalomon23e619c2015-02-06 11:54:28 -0800225 SkASSERT(!stretchedKey->isValid());
bsalomon37f9a262015-02-02 13:00:10 -0800226 return false;
227}
228
commit-bot@chromium.org50a30432013-10-24 17:44:27 +0000229namespace {
230
231// When the SkPixelRef genID changes, invalidate a corresponding GrResource described by key.
bsalomon23e619c2015-02-06 11:54:28 -0800232class BitmapInvalidator : public SkPixelRef::GenIDChangeListener {
commit-bot@chromium.org50a30432013-10-24 17:44:27 +0000233public:
bsalomon8718aaf2015-02-19 07:24:21 -0800234 explicit BitmapInvalidator(const GrUniqueKey& key) : fMsg(key) {}
commit-bot@chromium.org50a30432013-10-24 17:44:27 +0000235private:
bsalomon8718aaf2015-02-19 07:24:21 -0800236 GrUniqueKeyInvalidatedMessage fMsg;
commit-bot@chromium.org50a30432013-10-24 17:44:27 +0000237
mtklein36352bf2015-03-25 18:17:31 -0700238 void onChange() override {
bsalomon8718aaf2015-02-19 07:24:21 -0800239 SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(fMsg);
commit-bot@chromium.org50a30432013-10-24 17:44:27 +0000240 }
241};
242
243} // namespace
244
commit-bot@chromium.org50a30432013-10-24 17:44:27 +0000245
reed43fe6182015-09-08 08:37:36 -0700246GrTexture* GrCreateTextureForPixels(GrContext* ctx,
247 const GrUniqueKey& optionalKey,
248 GrSurfaceDesc desc,
249 SkPixelRef* pixelRefForInvalidationNotification,
250 const void* pixels,
251 size_t rowBytes) {
bsalomond309e7a2015-04-30 14:18:54 -0700252 GrTexture* result = ctx->textureProvider()->createTexture(desc, true, pixels, rowBytes);
bsalomond0423582015-02-06 08:49:24 -0800253 if (result && optionalKey.isValid()) {
reed43fe6182015-09-08 08:37:36 -0700254 if (pixelRefForInvalidationNotification) {
255 BitmapInvalidator* listener = new BitmapInvalidator(optionalKey);
256 pixelRefForInvalidationNotification->addGenIDChangeListener(listener);
257 }
bsalomond309e7a2015-04-30 14:18:54 -0700258 ctx->textureProvider()->assignUniqueKeyToTexture(optionalKey, result);
sugoi0249ec22014-09-09 08:12:34 -0700259 }
260 return result;
261}
262
bsalomonc59a1df2015-06-01 07:13:42 -0700263// creates a new texture that is the input texture scaled up. If optionalKey is valid it will be
264// set on the new texture. stretch controls whether the scaling is done using nearest or bilerp
265// filtering and the size to stretch the texture to.
reedb5d32632015-09-29 13:36:50 -0700266GrTexture* stretch_texture(GrTexture* inputTexture, const SkGrStretch& stretch,
bsalomonc59a1df2015-06-01 07:13:42 -0700267 SkPixelRef* pixelRef,
268 const GrUniqueKey& optionalKey) {
reedb5d32632015-09-29 13:36:50 -0700269 SkASSERT(SkGrStretch::kNone_Type != stretch.fType);
bsalomon37f9a262015-02-02 13:00:10 -0800270
271 GrContext* context = inputTexture->getContext();
272 SkASSERT(context);
bsalomon76228632015-05-29 08:02:10 -0700273 const GrCaps* caps = context->caps();
bsalomon37f9a262015-02-02 13:00:10 -0800274
275 // Either it's a cache miss or the original wasn't cached to begin with.
276 GrSurfaceDesc rtDesc = inputTexture->desc();
bsalomon6bc1b5f2015-02-23 09:06:38 -0800277 rtDesc.fFlags = rtDesc.fFlags | kRenderTarget_GrSurfaceFlag;
bsalomonc59a1df2015-06-01 07:13:42 -0700278 rtDesc.fWidth = stretch.fWidth;
279 rtDesc.fHeight = stretch.fHeight;
bsalomon37f9a262015-02-02 13:00:10 -0800280 rtDesc.fConfig = GrMakePixelConfigUncompressed(rtDesc.fConfig);
281
282 // If the config isn't renderable try converting to either A8 or an 32 bit config. Otherwise,
283 // fail.
bsalomon76228632015-05-29 08:02:10 -0700284 if (!caps->isConfigRenderable(rtDesc.fConfig, false)) {
bsalomon37f9a262015-02-02 13:00:10 -0800285 if (GrPixelConfigIsAlphaOnly(rtDesc.fConfig)) {
bsalomon76228632015-05-29 08:02:10 -0700286 if (caps->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) {
bsalomon37f9a262015-02-02 13:00:10 -0800287 rtDesc.fConfig = kAlpha_8_GrPixelConfig;
bsalomon76228632015-05-29 08:02:10 -0700288 } else if (caps->isConfigRenderable(kSkia8888_GrPixelConfig, false)) {
bsalomon37f9a262015-02-02 13:00:10 -0800289 rtDesc.fConfig = kSkia8888_GrPixelConfig;
290 } else {
halcanary96fcdcc2015-08-27 07:41:13 -0700291 return nullptr;
bsalomon37f9a262015-02-02 13:00:10 -0800292 }
293 } else if (kRGB_GrColorComponentFlags ==
294 (kRGB_GrColorComponentFlags & GrPixelConfigComponentMask(rtDesc.fConfig))) {
bsalomon76228632015-05-29 08:02:10 -0700295 if (caps->isConfigRenderable(kSkia8888_GrPixelConfig, false)) {
bsalomon37f9a262015-02-02 13:00:10 -0800296 rtDesc.fConfig = kSkia8888_GrPixelConfig;
297 } else {
halcanary96fcdcc2015-08-27 07:41:13 -0700298 return nullptr;
bsalomon37f9a262015-02-02 13:00:10 -0800299 }
300 } else {
halcanary96fcdcc2015-08-27 07:41:13 -0700301 return nullptr;
bsalomon37f9a262015-02-02 13:00:10 -0800302 }
303 }
304
reed43fe6182015-09-08 08:37:36 -0700305 SkAutoTUnref<GrTexture> stretched(GrCreateTextureForPixels(context, optionalKey, rtDesc,
306 pixelRef, nullptr,0));
bsalomon23e619c2015-02-06 11:54:28 -0800307 if (!stretched) {
halcanary96fcdcc2015-08-27 07:41:13 -0700308 return nullptr;
bsalomon37f9a262015-02-02 13:00:10 -0800309 }
310 GrPaint paint;
311
312 // If filtering is not desired then we want to ensure all texels in the resampled image are
313 // copies of texels from the original.
314 GrTextureParams params(SkShader::kClamp_TileMode,
reedb5d32632015-09-29 13:36:50 -0700315 SkGrStretch::kBilerp_Type == stretch.fType ?
bsalomonc59a1df2015-06-01 07:13:42 -0700316 GrTextureParams::kBilerp_FilterMode :
317 GrTextureParams::kNone_FilterMode);
bsalomon37f9a262015-02-02 13:00:10 -0800318 paint.addColorTextureProcessor(inputTexture, SkMatrix::I(), params);
319
320 SkRect rect = SkRect::MakeWH(SkIntToScalar(rtDesc.fWidth), SkIntToScalar(rtDesc.fHeight));
321 SkRect localRect = SkRect::MakeWH(1.f, 1.f);
322
robertphillips2e1e51f2015-10-15 08:01:48 -0700323 SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(stretched->asRenderTarget()));
robertphillipsea461502015-05-26 11:38:03 -0700324 if (!drawContext) {
halcanary96fcdcc2015-08-27 07:41:13 -0700325 return nullptr;
robertphillipsea461502015-05-26 11:38:03 -0700326 }
327
robertphillips2e1e51f2015-10-15 08:01:48 -0700328 drawContext->drawNonAARectToRect(GrClip::WideOpen(), paint, SkMatrix::I(), rect, localRect);
bsalomon37f9a262015-02-02 13:00:10 -0800329
reed43fe6182015-09-08 08:37:36 -0700330 return stretched.detach();
bsalomon37f9a262015-02-02 13:00:10 -0800331}
332
reed43fe6182015-09-08 08:37:36 -0700333/*
334 * Once we have made SkImages handle all lazy/deferred/generated content, the YUV apis will
335 * be gone from SkPixelRef, and we can remove this subclass entirely.
336 */
337class PixelRef_GrYUVProvider : public GrYUVProvider {
338 SkPixelRef* fPR;
339
340public:
341 PixelRef_GrYUVProvider(SkPixelRef* pr) : fPR(pr) {}
342
343 uint32_t onGetID() override { return fPR->getGenerationID(); }
344 bool onGetYUVSizes(SkISize sizes[3]) override {
345 return fPR->getYUV8Planes(sizes, nullptr, nullptr, nullptr);
346 }
347 bool onGetYUVPlanes(SkISize sizes[3], void* planes[3], size_t rowBytes[3],
348 SkYUVColorSpace* space) override {
349 return fPR->getYUV8Planes(sizes, planes, rowBytes, space);
350 }
351};
krajcevski9c0e6292014-06-02 07:38:14 -0700352
bsalomon8718aaf2015-02-19 07:24:21 -0800353static GrTexture* load_yuv_texture(GrContext* ctx, const GrUniqueKey& optionalKey,
bsalomonf2703d82014-10-28 14:33:06 -0700354 const SkBitmap& bm, const GrSurfaceDesc& desc) {
sugoiff58e462014-10-16 05:19:31 -0700355 // Subsets are not supported, the whole pixelRef is loaded when using YUV decoding
sugoi518d83d2014-07-21 11:37:39 -0700356 SkPixelRef* pixelRef = bm.pixelRef();
reed43fe6182015-09-08 08:37:36 -0700357 if ((nullptr == pixelRef) ||
sugoi692135f2015-01-19 10:10:27 -0800358 (pixelRef->info().width() != bm.info().width()) ||
359 (pixelRef->info().height() != bm.info().height())) {
halcanary96fcdcc2015-08-27 07:41:13 -0700360 return nullptr;
sugoi518d83d2014-07-21 11:37:39 -0700361 }
362
sugoiba18f912015-02-04 10:53:03 -0800363 const bool useCache = optionalKey.isValid();
reed43fe6182015-09-08 08:37:36 -0700364 PixelRef_GrYUVProvider provider(pixelRef);
365 GrTexture* texture = provider.refAsTexture(ctx, desc, useCache);
366 if (!texture) {
367 return nullptr;
368 }
369
sugoiba18f912015-02-04 10:53:03 -0800370 if (useCache) {
reed43fe6182015-09-08 08:37:36 -0700371 BitmapInvalidator* listener = new BitmapInvalidator(optionalKey);
372 pixelRef->addGenIDChangeListener(listener);
373 ctx->textureProvider()->assignUniqueKeyToTexture(optionalKey, texture);
sugoiba18f912015-02-04 10:53:03 -0800374 }
reed43fe6182015-09-08 08:37:36 -0700375 return texture;
sugoi518d83d2014-07-21 11:37:39 -0700376}
377
bsalomon466c2c42015-10-16 12:01:18 -0700378static GrTexture* load_etc1_texture(GrContext* ctx, const GrUniqueKey& optionalKey,
379 const SkBitmap &bm, GrSurfaceDesc desc) {
380 SkAutoTUnref<SkData> data(bm.pixelRef()->refEncodedData());
381 if (!data) {
382 return nullptr;
383 }
384
385 const void* startOfTexData;
386 desc.fConfig = GrIsCompressedTextureDataSupported(ctx, data, bm.width(), bm.height(),
387 &startOfTexData);
388 if (kUnknown_GrPixelConfig == desc.fConfig) {
389 return nullptr;
390 }
391
392 return GrCreateTextureForPixels(ctx, optionalKey, desc, bm.pixelRef(), startOfTexData, 0);
393}
394
bsalomon37f9a262015-02-02 13:00:10 -0800395static GrTexture* create_unstretched_bitmap_texture(GrContext* ctx,
396 const SkBitmap& origBitmap,
bsalomon8718aaf2015-02-19 07:24:21 -0800397 const GrUniqueKey& optionalKey) {
bsalomonb4d40ef2015-07-15 10:12:16 -0700398 if (origBitmap.width() < ctx->caps()->minTextureSize() ||
399 origBitmap.height() < ctx->caps()->minTextureSize()) {
halcanary96fcdcc2015-08-27 07:41:13 -0700400 return nullptr;
bsalomonb4d40ef2015-07-15 10:12:16 -0700401 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000402 SkBitmap tmpBitmap;
403
404 const SkBitmap* bitmap = &origBitmap;
bsalomon@google.com5782d712011-01-21 21:03:59 +0000405
reed3322a812015-09-16 10:09:24 -0700406 GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(bitmap->info());
bsalomon76228632015-05-29 08:02:10 -0700407 const GrCaps* caps = ctx->caps();
bsalomon@google.com5782d712011-01-21 21:03:59 +0000408
reed0689d7b2014-06-14 05:30:20 -0700409 if (kIndex_8_SkColorType == bitmap->colorType()) {
bsalomon76228632015-05-29 08:02:10 -0700410 if (caps->isConfigTexturable(kIndex_8_GrPixelConfig)) {
bsalomond4cb9222014-08-11 14:19:09 -0700411 size_t imageSize = GrCompressedFormatDataSize(kIndex_8_GrPixelConfig,
412 bitmap->width(), bitmap->height());
413 SkAutoMalloc storage(imageSize);
bsalomone79a2da2014-10-24 12:42:51 -0700414 build_index8_data(storage.get(), origBitmap);
reed@google.comac10a2d2010-12-22 21:39:39 +0000415
416 // our compressed data will be trimmed, so pass width() for its
417 // "rowBytes", since they are the same now.
reed43fe6182015-09-08 08:37:36 -0700418 return GrCreateTextureForPixels(ctx, optionalKey, desc, origBitmap.pixelRef(),
419 storage.get(), bitmap->width());
reed@google.comac10a2d2010-12-22 21:39:39 +0000420 } else {
commit-bot@chromium.org28fcae22014-04-11 17:15:40 +0000421 origBitmap.copyTo(&tmpBitmap, kN32_SkColorType);
reed@google.comac10a2d2010-12-22 21:39:39 +0000422 // now bitmap points to our temp, which has been promoted to 32bits
423 bitmap = &tmpBitmap;
commit-bot@chromium.org3adcc342014-04-23 19:18:09 +0000424 desc.fConfig = SkImageInfo2GrPixelConfig(bitmap->info());
reed@google.comac10a2d2010-12-22 21:39:39 +0000425 }
reed43fe6182015-09-08 08:37:36 -0700426 } else if (!bitmap->readyToDraw()) {
427 // If the bitmap had compressed data and was then uncompressed, it'll still return
428 // compressed data on 'refEncodedData' and upload it. Probably not good, since if
429 // the bitmap has available pixels, then they might not be what the decompressed
430 // data is.
bsalomon37f9a262015-02-02 13:00:10 -0800431 GrTexture *texture = load_etc1_texture(ctx, optionalKey, *bitmap, desc);
bsalomon49f085d2014-09-05 13:34:00 -0700432 if (texture) {
krajcevski9c0e6292014-06-02 07:38:14 -0700433 return texture;
434 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000435 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000436
bsalomond2a6f4e2015-02-04 10:55:54 -0800437 GrTexture *texture = load_yuv_texture(ctx, optionalKey, *bitmap, desc);
438 if (texture) {
439 return texture;
sugoi518d83d2014-07-21 11:37:39 -0700440 }
bsalomond2a6f4e2015-02-04 10:55:54 -0800441
bsalomon@google.com7f4ad5a2013-05-07 19:36:43 +0000442 SkAutoLockPixels alp(*bitmap);
443 if (!bitmap->readyToDraw()) {
halcanary96fcdcc2015-08-27 07:41:13 -0700444 return nullptr;
bsalomon@google.com7f4ad5a2013-05-07 19:36:43 +0000445 }
commit-bot@chromium.org50a30432013-10-24 17:44:27 +0000446
reed43fe6182015-09-08 08:37:36 -0700447 return GrCreateTextureForPixels(ctx, optionalKey, desc, origBitmap.pixelRef(),
448 bitmap->getPixels(), bitmap->rowBytes());
bsalomon37f9a262015-02-02 13:00:10 -0800449}
450
reedb5d32632015-09-29 13:36:50 -0700451static SkBitmap stretch_on_cpu(const SkBitmap& bmp, const SkGrStretch& stretch) {
bsalomonb4d40ef2015-07-15 10:12:16 -0700452 SkBitmap stretched;
453 stretched.allocN32Pixels(stretch.fWidth, stretch.fHeight);
454 SkCanvas canvas(stretched);
455 SkPaint paint;
456 switch (stretch.fType) {
reedb5d32632015-09-29 13:36:50 -0700457 case SkGrStretch::kNearest_Type:
bsalomonb4d40ef2015-07-15 10:12:16 -0700458 paint.setFilterQuality(kNone_SkFilterQuality);
459 break;
reedb5d32632015-09-29 13:36:50 -0700460 case SkGrStretch::kBilerp_Type:
bsalomonb4d40ef2015-07-15 10:12:16 -0700461 paint.setFilterQuality(kLow_SkFilterQuality);
462 break;
reedb5d32632015-09-29 13:36:50 -0700463 case SkGrStretch::kNone_Type:
bsalomonb4d40ef2015-07-15 10:12:16 -0700464 SkDEBUGFAIL("Shouldn't get here.");
465 break;
466 }
467 SkRect dstRect = SkRect::MakeWH(SkIntToScalar(stretch.fWidth), SkIntToScalar(stretch.fHeight));
reed84984ef2015-07-17 07:09:43 -0700468 canvas.drawBitmapRect(bmp, dstRect, &paint);
bsalomonb4d40ef2015-07-15 10:12:16 -0700469 return stretched;
470}
471
reedb5d32632015-09-29 13:36:50 -0700472class Bitmap_GrTextureMaker : public GrTextureMaker {
473public:
474 Bitmap_GrTextureMaker(const SkBitmap& bitmap)
475 : INHERITED(bitmap.width(), bitmap.height())
476 , fBitmap(bitmap)
477 {}
rileya@google.com24f3ad12012-07-18 21:47:40 +0000478
reedb5d32632015-09-29 13:36:50 -0700479protected:
480 GrTexture* onRefUnstretchedTexture(GrContext* ctx) override {
481 GrTexture* tex = fBitmap.getTexture();
482 if (tex) {
483 return SkRef(tex);
bsalomon88425562015-02-04 09:12:46 -0800484 }
bsalomon88425562015-02-04 09:12:46 -0800485
reedb5d32632015-09-29 13:36:50 -0700486 GrUniqueKey unstretchedKey;
487 make_unstretched_key(&unstretchedKey, fBitmap.getGenerationID(), fBitmap.getSubset());
bsalomon@google.com0797c2c2012-12-20 15:13:01 +0000488
reedb5d32632015-09-29 13:36:50 -0700489 GrTexture* result = ctx->textureProvider()->findAndRefTextureByUniqueKey(unstretchedKey);
bsalomon37f9a262015-02-02 13:00:10 -0800490 if (result) {
491 return result;
492 }
reedb5d32632015-09-29 13:36:50 -0700493 return create_unstretched_bitmap_texture(ctx, fBitmap, unstretchedKey);
bsalomon37f9a262015-02-02 13:00:10 -0800494 }
bsalomone137db82015-01-31 20:10:56 -0800495
reedb5d32632015-09-29 13:36:50 -0700496 bool onMakeStretchedKey(const SkGrStretch& stretch, GrUniqueKey* stretchedKey) override {
497 if (fBitmap.isVolatile()) {
498 return false;
499 }
500
501 GrUniqueKey unstretchedKey;
502 make_unstretched_key(&unstretchedKey, fBitmap.getGenerationID(), fBitmap.getSubset());
reed856e9d92015-09-30 12:21:45 -0700503 return GrMakeStretchedKey(unstretchedKey, stretch, stretchedKey);
bsalomon37f9a262015-02-02 13:00:10 -0800504 }
bsalomone137db82015-01-31 20:10:56 -0800505
reedb5d32632015-09-29 13:36:50 -0700506 void onNotifyStretchCached(const GrUniqueKey& stretchedKey) override {
507 fBitmap.pixelRef()->addGenIDChangeListener(new BitmapInvalidator(stretchedKey));
508 }
bsalomon37f9a262015-02-02 13:00:10 -0800509
reedb5d32632015-09-29 13:36:50 -0700510 bool onGetROBitmap(SkBitmap* bitmap) override {
511 *bitmap = fBitmap;
512 return true;
513 }
514
515private:
516 const SkBitmap fBitmap;
517
518 typedef GrTextureMaker INHERITED;
519};
520
521GrTexture* GrRefCachedBitmapTexture(GrContext* ctx, const SkBitmap& bitmap,
bsalomonafa95e22015-10-12 10:39:46 -0700522 const GrTextureParams& params) {
reedb5d32632015-09-29 13:36:50 -0700523 return Bitmap_GrTextureMaker(bitmap).refCachedTexture(ctx, params);
rileya@google.com24f3ad12012-07-18 21:47:40 +0000524}
reed8f343722015-08-13 13:32:39 -0700525
rileya@google.com24f3ad12012-07-18 21:47:40 +0000526///////////////////////////////////////////////////////////////////////////////
527
commit-bot@chromium.org15a14052014-02-16 00:59:25 +0000528// alphatype is ignore for now, but if GrPixelConfig is expanded to encompass
529// alpha info, that will be considered.
jvanverthfa1e8a72014-12-22 08:31:49 -0800530GrPixelConfig SkImageInfo2GrPixelConfig(SkColorType ct, SkAlphaType, SkColorProfileType pt) {
commit-bot@chromium.org15a14052014-02-16 00:59:25 +0000531 switch (ct) {
532 case kUnknown_SkColorType:
533 return kUnknown_GrPixelConfig;
534 case kAlpha_8_SkColorType:
535 return kAlpha_8_GrPixelConfig;
536 case kRGB_565_SkColorType:
537 return kRGB_565_GrPixelConfig;
538 case kARGB_4444_SkColorType:
539 return kRGBA_4444_GrPixelConfig;
540 case kRGBA_8888_SkColorType:
jvanverth99babf22015-05-22 06:06:40 -0700541 //if (kSRGB_SkColorProfileType == pt) {
542 // return kSRGBA_8888_GrPixelConfig;
543 //}
commit-bot@chromium.org15a14052014-02-16 00:59:25 +0000544 return kRGBA_8888_GrPixelConfig;
545 case kBGRA_8888_SkColorType:
546 return kBGRA_8888_GrPixelConfig;
547 case kIndex_8_SkColorType:
548 return kIndex_8_GrPixelConfig;
reed0c9b1a82015-03-17 17:44:06 -0700549 case kGray_8_SkColorType:
550 return kAlpha_8_GrPixelConfig; // TODO: gray8 support on gpu
commit-bot@chromium.org15a14052014-02-16 00:59:25 +0000551 }
552 SkASSERT(0); // shouldn't get here
553 return kUnknown_GrPixelConfig;
554}
555
jvanverthfa1e8a72014-12-22 08:31:49 -0800556bool GrPixelConfig2ColorAndProfileType(GrPixelConfig config, SkColorType* ctOut,
557 SkColorProfileType* ptOut) {
reed@google.combf790232013-12-13 19:45:58 +0000558 SkColorType ct;
jvanverthfa1e8a72014-12-22 08:31:49 -0800559 SkColorProfileType pt = kLinear_SkColorProfileType;
reed@google.combf790232013-12-13 19:45:58 +0000560 switch (config) {
561 case kAlpha_8_GrPixelConfig:
562 ct = kAlpha_8_SkColorType;
563 break;
564 case kIndex_8_GrPixelConfig:
565 ct = kIndex_8_SkColorType;
566 break;
567 case kRGB_565_GrPixelConfig:
568 ct = kRGB_565_SkColorType;
569 break;
570 case kRGBA_4444_GrPixelConfig:
571 ct = kARGB_4444_SkColorType;
572 break;
573 case kRGBA_8888_GrPixelConfig:
574 ct = kRGBA_8888_SkColorType;
575 break;
576 case kBGRA_8888_GrPixelConfig:
577 ct = kBGRA_8888_SkColorType;
578 break;
jvanverthfa1e8a72014-12-22 08:31:49 -0800579 case kSRGBA_8888_GrPixelConfig:
580 ct = kRGBA_8888_SkColorType;
581 pt = kSRGB_SkColorProfileType;
582 break;
reed@google.combf790232013-12-13 19:45:58 +0000583 default:
584 return false;
585 }
586 if (ctOut) {
587 *ctOut = ct;
588 }
jvanverthfa1e8a72014-12-22 08:31:49 -0800589 if (ptOut) {
590 *ptOut = pt;
591 }
reed@google.combf790232013-12-13 19:45:58 +0000592 return true;
593}
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000594
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000595
bsalomonf1b7a1d2015-09-28 06:26:28 -0700596////////////////////////////////////////////////////////////////////////////////////////////////
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000597
bsalomonaa48d362015-10-01 08:34:17 -0700598static inline bool blend_requires_shader(const SkXfermode::Mode mode, bool primitiveIsSrc) {
599 if (primitiveIsSrc) {
600 return SkXfermode::kSrc_Mode != mode;
601 } else {
602 return SkXfermode::kDst_Mode != mode;
603 }
604}
605
bsalomonf1b7a1d2015-09-28 06:26:28 -0700606static inline bool skpaint_to_grpaint_impl(GrContext* context,
607 const SkPaint& skPaint,
608 const SkMatrix& viewM,
609 const GrFragmentProcessor** shaderProcessor,
610 SkXfermode::Mode* primColorMode,
611 bool primitiveIsSrc,
612 GrPaint* grPaint) {
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000613 grPaint->setAntiAlias(skPaint.isAntiAlias());
614
bsalomonf1b7a1d2015-09-28 06:26:28 -0700615 // Setup the initial color considering the shader, the SkPaint color, and the presence or not
616 // of per-vertex colors.
617 SkAutoTUnref<const GrFragmentProcessor> aufp;
bsalomonaa48d362015-10-01 08:34:17 -0700618 const GrFragmentProcessor* shaderFP = nullptr;
619 if (!primColorMode || blend_requires_shader(*primColorMode, primitiveIsSrc)) {
620 if (shaderProcessor) {
621 shaderFP = *shaderProcessor;
622 } else if (const SkShader* shader = skPaint.getShader()) {
623 aufp.reset(shader->asFragmentProcessor(context, viewM, nullptr,
bsalomon4a339522015-10-06 08:40:50 -0700624 skPaint.getFilterQuality()));
bsalomonaa48d362015-10-01 08:34:17 -0700625 shaderFP = aufp;
626 if (!shaderFP) {
627 return false;
628 }
bsalomonf1b7a1d2015-09-28 06:26:28 -0700629 }
630 }
631
632 // Set this in below cases if the output of the shader/paint-color/paint-alpha/primXfermode is
633 // a known constant value. In that case we can simply apply a color filter during this
634 // conversion without converting the color filter to a GrFragmentProcessor.
635 bool applyColorFilterToPaintColor = false;
636 if (shaderFP) {
637 if (primColorMode) {
638 // There is a blend between the primitive color and the shader color. The shader sees
639 // the opaque paint color. The shader's output is blended using the provided mode by
640 // the primitive color. The blended color is then modulated by the paint's alpha.
641
642 // The geometry processor will insert the primitive color to start the color chain, so
643 // the GrPaint color will be ignored.
644
645 GrColor shaderInput = SkColorToOpaqueGrColor(skPaint.getColor());
646
647 shaderFP = GrFragmentProcessor::OverrideInput(shaderFP, shaderInput);
648 aufp.reset(shaderFP);
649
650 if (primitiveIsSrc) {
651 shaderFP = GrXfermodeFragmentProcessor::CreateFromDstProcessor(shaderFP,
652 *primColorMode);
653 } else {
654 shaderFP = GrXfermodeFragmentProcessor::CreateFromSrcProcessor(shaderFP,
655 *primColorMode);
656 }
657 aufp.reset(shaderFP);
658 // The above may return null if compose results in a pass through of the prim color.
659 if (shaderFP) {
660 grPaint->addColorFragmentProcessor(shaderFP);
661 }
662
663 GrColor paintAlpha = SkColorAlphaToGrColor(skPaint.getColor());
664 if (GrColor_WHITE != paintAlpha) {
665 grPaint->addColorFragmentProcessor(GrConstColorProcessor::Create(
666 paintAlpha, GrConstColorProcessor::kModulateRGBA_InputMode))->unref();
667 }
668 } else {
669 // The shader's FP sees the paint unpremul color
670 grPaint->setColor(SkColorToUnpremulGrColor(skPaint.getColor()));
671 grPaint->addColorFragmentProcessor(shaderFP);
672 }
673 } else {
674 if (primColorMode) {
675 // There is a blend between the primitive color and the paint color. The blend considers
676 // the opaque paint color. The paint's alpha is applied to the post-blended color.
677 SkAutoTUnref<const GrFragmentProcessor> processor(
678 GrConstColorProcessor::Create(SkColorToOpaqueGrColor(skPaint.getColor()),
679 GrConstColorProcessor::kIgnore_InputMode));
680 if (primitiveIsSrc) {
681 processor.reset(GrXfermodeFragmentProcessor::CreateFromDstProcessor(processor,
682 *primColorMode));
683 } else {
684 processor.reset(GrXfermodeFragmentProcessor::CreateFromSrcProcessor(processor,
685 *primColorMode));
686
687 }
688 if (processor) {
689 grPaint->addColorFragmentProcessor(processor);
690 }
691
bsalomonaa48d362015-10-01 08:34:17 -0700692 grPaint->setColor(SkColorToOpaqueGrColor(skPaint.getColor()));
bsalomonf1b7a1d2015-09-28 06:26:28 -0700693
694 GrColor paintAlpha = SkColorAlphaToGrColor(skPaint.getColor());
bsalomonaa48d362015-10-01 08:34:17 -0700695 if (GrColor_WHITE != paintAlpha) {
696 grPaint->addColorFragmentProcessor(GrConstColorProcessor::Create(
697 paintAlpha, GrConstColorProcessor::kModulateRGBA_InputMode))->unref();
698 }
bsalomonf1b7a1d2015-09-28 06:26:28 -0700699 } else {
700 // No shader, no primitive color.
701 grPaint->setColor(SkColorToPremulGrColor(skPaint.getColor()));
702 applyColorFilterToPaintColor = true;
703 }
704 }
705
706 SkColorFilter* colorFilter = skPaint.getColorFilter();
707 if (colorFilter) {
708 if (applyColorFilterToPaintColor) {
709 grPaint->setColor(SkColorToPremulGrColor(colorFilter->filterColor(skPaint.getColor())));
710 } else {
bsalomone25eea42015-09-29 06:38:55 -0700711 SkAutoTUnref<const GrFragmentProcessor> cfFP(
bsalomon4a339522015-10-06 08:40:50 -0700712 colorFilter->asFragmentProcessor(context));
bsalomone25eea42015-09-29 06:38:55 -0700713 if (cfFP) {
714 grPaint->addColorFragmentProcessor(cfFP);
bsalomonf1b7a1d2015-09-28 06:26:28 -0700715 } else {
716 return false;
717 }
718 }
719 }
720
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000721 SkXfermode* mode = skPaint.getXfermode();
halcanary96fcdcc2015-08-27 07:41:13 -0700722 GrXPFactory* xpFactory = nullptr;
egdaniel58136162015-01-20 10:19:22 -0800723 if (!SkXfermode::AsXPFactory(mode, &xpFactory)) {
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000724 // Fall back to src-over
bsalomonbed83a62015-04-15 14:18:34 -0700725 // return false here?
egdanielc016fb82014-12-03 11:41:54 -0800726 xpFactory = GrPorterDuffXPFactory::Create(SkXfermode::kSrcOver_Mode);
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000727 }
egdaniel378092f2014-12-03 10:40:13 -0800728 SkASSERT(xpFactory);
729 grPaint->setXPFactory(xpFactory)->unref();
mtklein775b8192014-12-02 09:11:25 -0800730
krajcevskif461a8f2014-06-19 14:14:06 -0700731#ifndef SK_IGNORE_GPU_DITHER
bsalomonac856c92015-08-27 06:30:17 -0700732 if (skPaint.isDither() && grPaint->numColorFragmentProcessors() > 0) {
bsalomonaca31fe2015-09-22 11:38:46 -0700733 grPaint->addColorFragmentProcessor(GrDitherEffect::Create())->unref();
krajcevskif461a8f2014-06-19 14:14:06 -0700734 }
735#endif
bsalomonbed83a62015-04-15 14:18:34 -0700736 return true;
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000737}
738
bsalomonf1b7a1d2015-09-28 06:26:28 -0700739bool SkPaintToGrPaint(GrContext* context, const SkPaint& skPaint, const SkMatrix& viewM,
740 GrPaint* grPaint) {
741 return skpaint_to_grpaint_impl(context, skPaint, viewM, nullptr, nullptr, false, grPaint);
742}
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000743
bsalomonf1b7a1d2015-09-28 06:26:28 -0700744/** Replaces the SkShader (if any) on skPaint with the passed in GrFragmentProcessor. */
745bool SkPaintToGrPaintReplaceShader(GrContext* context,
746 const SkPaint& skPaint,
747 const GrFragmentProcessor* shaderFP,
748 GrPaint* grPaint) {
749 if (!shaderFP) {
bsalomonc21b09e2015-08-28 18:46:56 -0700750 return false;
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000751 }
bsalomonf1b7a1d2015-09-28 06:26:28 -0700752 return skpaint_to_grpaint_impl(context, skPaint, SkMatrix::I(), &shaderFP, nullptr, false,
753 grPaint);
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000754}
reed8b26b992015-05-07 15:36:17 -0700755
bsalomonf1b7a1d2015-09-28 06:26:28 -0700756/** Ignores the SkShader (if any) on skPaint. */
757bool SkPaintToGrPaintNoShader(GrContext* context,
758 const SkPaint& skPaint,
759 GrPaint* grPaint) {
760 // Use a ptr to a nullptr to to indicate that the SkShader is ignored and not replaced.
761 static const GrFragmentProcessor* kNullShaderFP = nullptr;
762 static const GrFragmentProcessor** kIgnoreShader = &kNullShaderFP;
763 return skpaint_to_grpaint_impl(context, skPaint, SkMatrix::I(), kIgnoreShader, nullptr, false,
764 grPaint);
765}
766
767/** Blends the SkPaint's shader (or color if no shader) with a per-primitive color which must
768be setup as a vertex attribute using the specified SkXfermode::Mode. */
769bool SkPaintToGrPaintWithXfermode(GrContext* context,
770 const SkPaint& skPaint,
771 const SkMatrix& viewM,
772 SkXfermode::Mode primColorMode,
773 bool primitiveIsSrc,
774 GrPaint* grPaint) {
775 return skpaint_to_grpaint_impl(context, skPaint, viewM, nullptr, &primColorMode, primitiveIsSrc,
776 grPaint);
777}
778
779
780////////////////////////////////////////////////////////////////////////////////////////////////
781
reed8b26b992015-05-07 15:36:17 -0700782SkImageInfo GrMakeInfoFromTexture(GrTexture* tex, int w, int h, bool isOpaque) {
783#ifdef SK_DEBUG
784 const GrSurfaceDesc& desc = tex->desc();
785 SkASSERT(w <= desc.fWidth);
786 SkASSERT(h <= desc.fHeight);
787#endif
788 const GrPixelConfig config = tex->config();
789 SkColorType ct;
790 SkAlphaType at = isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
halcanary96fcdcc2015-08-27 07:41:13 -0700791 if (!GrPixelConfig2ColorAndProfileType(config, &ct, nullptr)) {
reed8b26b992015-05-07 15:36:17 -0700792 ct = kUnknown_SkColorType;
793 }
794 return SkImageInfo::Make(w, h, ct, at);
795}
796
797
798void GrWrapTextureInBitmap(GrTexture* src, int w, int h, bool isOpaque, SkBitmap* dst) {
799 const SkImageInfo info = GrMakeInfoFromTexture(src, w, h, isOpaque);
800 dst->setInfo(info);
halcanary385fe4d2015-08-26 13:07:48 -0700801 dst->setPixelRef(new SkGrPixelRef(info, src))->unref();
reed8b26b992015-05-07 15:36:17 -0700802}
joshualitt9bc39542015-08-12 12:57:54 -0700803
804GrTextureParams::FilterMode GrSkFilterQualityToGrFilterMode(SkFilterQuality paintFilterQuality,
805 const SkMatrix& viewM,
806 const SkMatrix& localM,
807 bool* doBicubic) {
808 *doBicubic = false;
809 GrTextureParams::FilterMode textureFilterMode;
810 switch (paintFilterQuality) {
811 case kNone_SkFilterQuality:
812 textureFilterMode = GrTextureParams::kNone_FilterMode;
813 break;
814 case kLow_SkFilterQuality:
815 textureFilterMode = GrTextureParams::kBilerp_FilterMode;
816 break;
817 case kMedium_SkFilterQuality: {
818 SkMatrix matrix;
819 matrix.setConcat(viewM, localM);
820 if (matrix.getMinScale() < SK_Scalar1) {
821 textureFilterMode = GrTextureParams::kMipMap_FilterMode;
822 } else {
823 // Don't trigger MIP level generation unnecessarily.
824 textureFilterMode = GrTextureParams::kBilerp_FilterMode;
825 }
826 break;
827 }
828 case kHigh_SkFilterQuality: {
829 SkMatrix matrix;
830 matrix.setConcat(viewM, localM);
831 *doBicubic = GrBicubicEffect::ShouldUseBicubic(matrix, &textureFilterMode);
832 break;
833 }
834 default:
835 SkErrorInternals::SetError( kInvalidPaint_SkError,
836 "Sorry, I don't understand the filtering "
837 "mode you asked for. Falling back to "
838 "MIPMaps.");
839 textureFilterMode = GrTextureParams::kMipMap_FilterMode;
840 break;
841
842 }
843 return textureFilterMode;
844}
reedb5d32632015-09-29 13:36:50 -0700845
846////////////////////////////////////////////////////////////////////////////////////////////////
847
bsalomonafa95e22015-10-12 10:39:46 -0700848GrTexture* GrTextureMaker::refCachedTexture(GrContext* ctx, const GrTextureParams& params) {
reedb5d32632015-09-29 13:36:50 -0700849 SkGrStretch stretch;
bsalomonafa95e22015-10-12 10:39:46 -0700850 get_stretch(*ctx->caps(), this->width(), this->height(), params, &stretch);
reedb5d32632015-09-29 13:36:50 -0700851
852 if (SkGrStretch::kNone_Type == stretch.fType) {
853 return this->onRefUnstretchedTexture(ctx);
854 }
855
856 GrUniqueKey stretchedKey;
857 if (this->onMakeStretchedKey(stretch, &stretchedKey)) {
858 GrTexture* result = ctx->textureProvider()->findAndRefTextureByUniqueKey(stretchedKey);
859 if (result) {
860 return result;
861 }
862 }
863
864 GrTexture* result = this->onGenerateStretchedTexture(ctx, stretch);
865 if (!result) {
866 return nullptr;
867 }
868
869 if (stretchedKey.isValid()) {
870 ctx->textureProvider()->assignUniqueKeyToTexture(stretchedKey, result);
871 this->onNotifyStretchCached(stretchedKey);
872 }
873 return result;
874}
875
876GrTexture* GrTextureMaker::onGenerateStretchedTexture(GrContext* ctx, const SkGrStretch& stretch) {
877 if (this->width() < ctx->caps()->minTextureSize() ||
878 this->height() < ctx->caps()->minTextureSize())
879 {
880 // we can't trust our ability to use HW to perform the stretch, so we request
881 // a raster instead, and perform the stretch on the CPU.
882 SkBitmap bitmap;
883 if (!this->onGetROBitmap(&bitmap)) {
884 return nullptr;
885 }
886 SkBitmap stretchedBmp = stretch_on_cpu(bitmap, stretch);
887 return create_unstretched_bitmap_texture(ctx, stretchedBmp, GrUniqueKey());
888 } else {
889 SkAutoTUnref<GrTexture> unstretched(this->onRefUnstretchedTexture(ctx));
890 if (!unstretched) {
891 return nullptr;
892 }
893 return stretch_texture(unstretched, stretch, nullptr, GrUniqueKey());
894 }
895}