blob: 471a39305f5693defd7ba23ba054f516194fe2fa [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
reed@google.comac10a2d2010-12-22 21:39:39 +00009#include "SkGr.h"
bsalomon0d996862016-03-09 18:44:43 -080010#include "SkGrPriv.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"
Brian Osman11052242016-10-27 14:47:55 -040014#include "GrRenderTargetContext.h"
bsalomon045802d2015-10-20 07:58:01 -070015#include "GrGpuResourcePriv.h"
bsalomonc55271f2015-11-09 11:55:57 -080016#include "GrImageIDTextureAdjuster.h"
cblume55f2d2d2016-02-26 13:20:48 -080017#include "GrTextureParamsAdjuster.h"
brianosmanfe199872016-06-13 07:59:48 -070018#include "GrTexturePriv.h"
cblume55f2d2d2016-02-26 13:20:48 -080019#include "GrTypes.h"
egdaniel378092f2014-12-03 10:40:13 -080020#include "GrXferProcessor.h"
reed43fe6182015-09-08 08:37:36 -070021#include "GrYUVProvider.h"
22
reed374772b2016-10-05 17:33:02 -070023#include "SkBlendModePriv.h"
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +000024#include "SkColorFilter.h"
commit-bot@chromium.orgea476e12013-10-14 18:29:23 +000025#include "SkConfig8888.h"
bsalomonb4d40ef2015-07-15 10:12:16 -070026#include "SkCanvas.h"
krajcevski9c0e6292014-06-02 07:38:14 -070027#include "SkData.h"
Robert Phillipsa29a9562016-10-20 09:40:55 -040028#include "SkMaskFilter.h"
commit-bot@chromium.org50a30432013-10-24 17:44:27 +000029#include "SkMessageBus.h"
cblume55f2d2d2016-02-26 13:20:48 -080030#include "SkMipMap.h"
commit-bot@chromium.org50a30432013-10-24 17:44:27 +000031#include "SkPixelRef.h"
brianosmana4535a32016-06-24 12:50:19 -070032#include "SkPM4fPriv.h"
sugoi692135f2015-01-19 10:10:27 -080033#include "SkResourceCache.h"
cblume55f2d2d2016-02-26 13:20:48 -080034#include "SkTemplates.h"
sugoi692135f2015-01-19 10:10:27 -080035#include "SkYUVPlanesCache.h"
joshualitt9bc39542015-08-12 12:57:54 -070036#include "effects/GrBicubicEffect.h"
bsalomonf1b7a1d2015-09-28 06:26:28 -070037#include "effects/GrConstColorProcessor.h"
krajcevskif461a8f2014-06-19 14:14:06 -070038#include "effects/GrDitherEffect.h"
egdaniel378092f2014-12-03 10:40:13 -080039#include "effects/GrPorterDuffXferProcessor.h"
bsalomonf1b7a1d2015-09-28 06:26:28 -070040#include "effects/GrXfermodeFragmentProcessor.h"
bsalomonf267c1e2016-02-01 13:16:14 -080041#include "effects/GrYUVEffect.h"
krajcevski9c0e6292014-06-02 07:38:14 -070042
krajcevski8c111f72014-06-02 13:51:34 -070043#ifndef SK_IGNORE_ETC1_SUPPORT
krajcevski99ffe242014-06-03 13:04:35 -070044# include "ktx.h"
krajcevski9c0e6292014-06-02 07:38:14 -070045# include "etc1.h"
46#endif
reed@google.comac10a2d2010-12-22 21:39:39 +000047
brianosmana6359362016-03-21 06:55:37 -070048GrSurfaceDesc GrImageInfoToSurfaceDesc(const SkImageInfo& info, const GrCaps& caps) {
bsalomon466c2c42015-10-16 12:01:18 -070049 GrSurfaceDesc desc;
50 desc.fFlags = kNone_GrSurfaceFlags;
51 desc.fWidth = info.width();
52 desc.fHeight = info.height();
brianosmana6359362016-03-21 06:55:37 -070053 desc.fConfig = SkImageInfo2GrPixelConfig(info, caps);
bsalomon466c2c42015-10-16 12:01:18 -070054 desc.fSampleCnt = 0;
55 return desc;
56}
57
bsalomon045802d2015-10-20 07:58:01 -070058void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& imageBounds) {
59 SkASSERT(key);
60 SkASSERT(imageID);
61 SkASSERT(!imageBounds.isEmpty());
62 static const GrUniqueKey::Domain kImageIDDomain = GrUniqueKey::GenerateDomain();
63 GrUniqueKey::Builder builder(key, kImageIDDomain, 5);
bsalomon466c2c42015-10-16 12:01:18 -070064 builder[0] = imageID;
bsalomon045802d2015-10-20 07:58:01 -070065 builder[1] = imageBounds.fLeft;
66 builder[2] = imageBounds.fTop;
67 builder[3] = imageBounds.fRight;
68 builder[4] = imageBounds.fBottom;
bsalomon466c2c42015-10-16 12:01:18 -070069}
70
71GrPixelConfig GrIsCompressedTextureDataSupported(GrContext* ctx, SkData* data,
72 int expectedW, int expectedH,
73 const void** outStartOfDataToUpload) {
74 *outStartOfDataToUpload = nullptr;
75#ifndef SK_IGNORE_ETC1_SUPPORT
76 if (!ctx->caps()->isConfigTexturable(kETC1_GrPixelConfig)) {
77 return kUnknown_GrPixelConfig;
78 }
79
80 const uint8_t* bytes = data->bytes();
81 if (data->size() > ETC_PKM_HEADER_SIZE && etc1_pkm_is_valid(bytes)) {
82 // Does the data match the dimensions of the bitmap? If not,
83 // then we don't know how to scale the image to match it...
84 if (etc1_pkm_get_width(bytes) != (unsigned)expectedW ||
85 etc1_pkm_get_height(bytes) != (unsigned)expectedH)
86 {
87 return kUnknown_GrPixelConfig;
88 }
89
90 *outStartOfDataToUpload = bytes + ETC_PKM_HEADER_SIZE;
91 return kETC1_GrPixelConfig;
scroggob8e09602016-04-12 07:41:22 -070092 } else if (SkKTXFile::is_ktx(bytes, data->size())) {
bsalomon466c2c42015-10-16 12:01:18 -070093 SkKTXFile ktx(data);
94
95 // Is it actually an ETC1 texture?
96 if (!ktx.isCompressedFormat(SkTextureCompressor::kETC1_Format)) {
97 return kUnknown_GrPixelConfig;
98 }
99
100 // Does the data match the dimensions of the bitmap? If not,
101 // then we don't know how to scale the image to match it...
102 if (ktx.width() != expectedW || ktx.height() != expectedH) {
103 return kUnknown_GrPixelConfig;
104 }
105
106 *outStartOfDataToUpload = ktx.pixelData();
107 return kETC1_GrPixelConfig;
108 }
109#endif
110 return kUnknown_GrPixelConfig;
111}
112
bsalomon045802d2015-10-20 07:58:01 -0700113//////////////////////////////////////////////////////////////////////////////
bsalomon@google.com5782d712011-01-21 21:03:59 +0000114
bsalomon045802d2015-10-20 07:58:01 -0700115/**
116 * Fill out buffer with the compressed format Ganesh expects from a colortable
117 * based bitmap. [palette (colortable) + indices].
118 *
119 * At the moment Ganesh only supports 8bit version. If Ganesh allowed we others
120 * we could detect that the colortable.count is <= 16, and then repack the
121 * indices as nibbles to save RAM, but it would take more time (i.e. a lot
122 * slower than memcpy), so skipping that for now.
123 *
124 * Ganesh wants a full 256 palette entry, even though Skia's ctable is only as big
125 * as the colortable.count says it is.
reed@google.comac10a2d2010-12-22 21:39:39 +0000126 */
bsalomon0d996862016-03-09 18:44:43 -0800127static void build_index8_data(void* buffer, const SkPixmap& pixmap) {
128 SkASSERT(kIndex_8_SkColorType == pixmap.colorType());
bsalomon@google.com5782d712011-01-21 21:03:59 +0000129
bsalomon0d996862016-03-09 18:44:43 -0800130 const SkColorTable* ctable = pixmap.ctable();
reed@google.comac10a2d2010-12-22 21:39:39 +0000131 char* dst = (char*)buffer;
bsalomon@google.com5782d712011-01-21 21:03:59 +0000132
reed@google.com7111d462014-03-25 16:20:24 +0000133 const int count = ctable->count();
134
135 SkDstPixelInfo dstPI;
136 dstPI.fColorType = kRGBA_8888_SkColorType;
137 dstPI.fAlphaType = kPremul_SkAlphaType;
138 dstPI.fPixels = buffer;
139 dstPI.fRowBytes = count * sizeof(SkPMColor);
140
141 SkSrcPixelInfo srcPI;
commit-bot@chromium.org28fcae22014-04-11 17:15:40 +0000142 srcPI.fColorType = kN32_SkColorType;
reed@google.com7111d462014-03-25 16:20:24 +0000143 srcPI.fAlphaType = kPremul_SkAlphaType;
mtklein775b8192014-12-02 09:11:25 -0800144 srcPI.fPixels = ctable->readColors();
reed@google.com7111d462014-03-25 16:20:24 +0000145 srcPI.fRowBytes = count * sizeof(SkPMColor);
146
147 srcPI.convertPixelsTo(&dstPI, count, 1);
148
reed@google.comac10a2d2010-12-22 21:39:39 +0000149 // always skip a full 256 number of entries, even if we memcpy'd fewer
bsalomond4cb9222014-08-11 14:19:09 -0700150 dst += 256 * sizeof(GrColor);
reed@google.comac10a2d2010-12-22 21:39:39 +0000151
bsalomon0d996862016-03-09 18:44:43 -0800152 if ((unsigned)pixmap.width() == pixmap.rowBytes()) {
153 memcpy(dst, pixmap.addr(), pixmap.getSafeSize());
reed@google.comac10a2d2010-12-22 21:39:39 +0000154 } else {
155 // need to trim off the extra bytes per row
bsalomon0d996862016-03-09 18:44:43 -0800156 size_t width = pixmap.width();
157 size_t rowBytes = pixmap.rowBytes();
158 const uint8_t* src = pixmap.addr8();
159 for (int y = 0; y < pixmap.height(); y++) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000160 memcpy(dst, src, width);
161 src += rowBytes;
162 dst += width;
163 }
164 }
165}
166
bsalomon045802d2015-10-20 07:58:01 -0700167/**
reed43fe6182015-09-08 08:37:36 -0700168 * Once we have made SkImages handle all lazy/deferred/generated content, the YUV apis will
169 * be gone from SkPixelRef, and we can remove this subclass entirely.
170 */
171class PixelRef_GrYUVProvider : public GrYUVProvider {
172 SkPixelRef* fPR;
173
174public:
175 PixelRef_GrYUVProvider(SkPixelRef* pr) : fPR(pr) {}
176
177 uint32_t onGetID() override { return fPR->getGenerationID(); }
msarett4984c3c2016-03-10 05:44:43 -0800178 bool onQueryYUV8(SkYUVSizeInfo* sizeInfo, SkYUVColorSpace* colorSpace) const override {
179 return fPR->queryYUV8(sizeInfo, colorSpace);
reed43fe6182015-09-08 08:37:36 -0700180 }
msarett4984c3c2016-03-10 05:44:43 -0800181 bool onGetYUV8Planes(const SkYUVSizeInfo& sizeInfo, void* planes[3]) override {
182 return fPR->getYUV8Planes(sizeInfo, planes);
reed43fe6182015-09-08 08:37:36 -0700183 }
184};
krajcevski9c0e6292014-06-02 07:38:14 -0700185
robertphillips677da9d2016-05-11 05:15:55 -0700186static sk_sp<GrTexture> create_texture_from_yuv(GrContext* ctx, const SkBitmap& bm,
187 const GrSurfaceDesc& desc) {
sugoiff58e462014-10-16 05:19:31 -0700188 // Subsets are not supported, the whole pixelRef is loaded when using YUV decoding
sugoi518d83d2014-07-21 11:37:39 -0700189 SkPixelRef* pixelRef = bm.pixelRef();
reed43fe6182015-09-08 08:37:36 -0700190 if ((nullptr == pixelRef) ||
bsalomon045802d2015-10-20 07:58:01 -0700191 (pixelRef->info().width() != bm.info().width()) ||
sugoi692135f2015-01-19 10:10:27 -0800192 (pixelRef->info().height() != bm.info().height())) {
halcanary96fcdcc2015-08-27 07:41:13 -0700193 return nullptr;
sugoi518d83d2014-07-21 11:37:39 -0700194 }
195
reed43fe6182015-09-08 08:37:36 -0700196 PixelRef_GrYUVProvider provider(pixelRef);
reed43fe6182015-09-08 08:37:36 -0700197
bsalomon045802d2015-10-20 07:58:01 -0700198 return provider.refAsTexture(ctx, desc, !bm.isVolatile());
sugoi518d83d2014-07-21 11:37:39 -0700199}
200
bsalomon045802d2015-10-20 07:58:01 -0700201static GrTexture* load_etc1_texture(GrContext* ctx, const SkBitmap &bm, GrSurfaceDesc desc) {
bungemanffae30d2016-08-03 13:32:32 -0700202 sk_sp<SkData> data(bm.pixelRef()->refEncodedData());
bsalomon466c2c42015-10-16 12:01:18 -0700203 if (!data) {
204 return nullptr;
205 }
206
207 const void* startOfTexData;
bungemanffae30d2016-08-03 13:32:32 -0700208 desc.fConfig = GrIsCompressedTextureDataSupported(ctx, data.get(), bm.width(), bm.height(),
bsalomon466c2c42015-10-16 12:01:18 -0700209 &startOfTexData);
210 if (kUnknown_GrPixelConfig == desc.fConfig) {
211 return nullptr;
212 }
213
bsalomon5ec26ae2016-02-25 08:33:02 -0800214 return ctx->textureProvider()->createTexture(desc, SkBudgeted::kYes, startOfTexData, 0);
bsalomon466c2c42015-10-16 12:01:18 -0700215}
216
bsalomon0d996862016-03-09 18:44:43 -0800217GrTexture* GrUploadBitmapToTexture(GrContext* ctx, const SkBitmap& bitmap) {
brianosmana6359362016-03-21 06:55:37 -0700218 GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(bitmap.info(), *ctx->caps());
bsalomon0d996862016-03-09 18:44:43 -0800219 if (GrTexture *texture = load_etc1_texture(ctx, bitmap, desc)) {
220 return texture;
221 }
bsalomon045802d2015-10-20 07:58:01 -0700222
robertphillips677da9d2016-05-11 05:15:55 -0700223 sk_sp<GrTexture> texture(create_texture_from_yuv(ctx, bitmap, desc));
224 if (texture) {
225 return texture.release();
bsalomon0d996862016-03-09 18:44:43 -0800226 }
227
228 SkAutoLockPixels alp(bitmap);
229 if (!bitmap.readyToDraw()) {
230 return nullptr;
231 }
232 SkPixmap pixmap;
233 if (!bitmap.peekPixels(&pixmap)) {
234 return nullptr;
235 }
ericrk8bea8902016-03-18 11:52:20 -0700236 return GrUploadPixmapToTexture(ctx, pixmap, SkBudgeted::kYes);
bsalomon0d996862016-03-09 18:44:43 -0800237}
238
ericrk8bea8902016-03-18 11:52:20 -0700239GrTexture* GrUploadPixmapToTexture(GrContext* ctx, const SkPixmap& pixmap, SkBudgeted budgeted) {
bsalomon0d996862016-03-09 18:44:43 -0800240 const SkPixmap* pmap = &pixmap;
241 SkPixmap tmpPixmap;
bsalomon045802d2015-10-20 07:58:01 -0700242 SkBitmap tmpBitmap;
bsalomon@google.com5782d712011-01-21 21:03:59 +0000243
bsalomon76228632015-05-29 08:02:10 -0700244 const GrCaps* caps = ctx->caps();
brianosmana6359362016-03-21 06:55:37 -0700245 GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(pixmap.info(), *caps);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000246
brianosmanefded512016-07-26 08:11:50 -0700247 if (caps->srgbSupport() &&
248 pixmap.info().colorSpace() && pixmap.info().colorSpace()->gammaCloseToSRGB() &&
249 !(GrPixelConfigIsSRGB(desc.fConfig) ||
250 kRGBA_half_GrPixelConfig == desc.fConfig ||
251 kRGBA_float_GrPixelConfig == desc.fConfig)) {
brianosmanb109b8c2016-06-16 13:03:24 -0700252 // We were supplied an sRGB-like color space, but we don't have a suitable pixel config.
brianosmana6359362016-03-21 06:55:37 -0700253 // Convert to 8888 sRGB so we can handle the data correctly. The raster backend doesn't
254 // handle sRGB Index8 -> sRGB 8888 correctly (yet), so lie about both the source and
255 // destination (claim they're linear):
256 SkImageInfo linSrcInfo = SkImageInfo::Make(pixmap.width(), pixmap.height(),
257 pixmap.colorType(), pixmap.alphaType());
258 SkPixmap linSrcPixmap(linSrcInfo, pixmap.addr(), pixmap.rowBytes(), pixmap.ctable());
259
brianosmanb109b8c2016-06-16 13:03:24 -0700260 SkImageInfo dstInfo = SkImageInfo::Make(pixmap.width(), pixmap.height(),
261 kN32_SkColorType, kPremul_SkAlphaType,
262 sk_ref_sp(pixmap.info().colorSpace()));
263
brianosmana6359362016-03-21 06:55:37 -0700264 tmpBitmap.allocPixels(dstInfo);
265
266 SkImageInfo linDstInfo = SkImageInfo::MakeN32Premul(pixmap.width(), pixmap.height());
267 if (!linSrcPixmap.readPixels(linDstInfo, tmpBitmap.getPixels(), tmpBitmap.rowBytes())) {
268 return nullptr;
269 }
270 if (!tmpBitmap.peekPixels(&tmpPixmap)) {
271 return nullptr;
272 }
273 pmap = &tmpPixmap;
274 // must rebuild desc, since we've forced the info to be N32
275 desc = GrImageInfoToSurfaceDesc(pmap->info(), *caps);
brianosman85f92692016-03-24 06:56:32 -0700276 } else if (kGray_8_SkColorType == pixmap.colorType()) {
277 // We don't have Gray8 support as a pixel config, so expand to 8888
278
279 // We should have converted sRGB Gray8 above (if we have sRGB support):
brianosmanb109b8c2016-06-16 13:03:24 -0700280 SkASSERT(!caps->srgbSupport() || !pixmap.info().colorSpace() ||
281 !pixmap.info().colorSpace()->gammaCloseToSRGB());
brianosman85f92692016-03-24 06:56:32 -0700282
283 SkImageInfo info = SkImageInfo::MakeN32(pixmap.width(), pixmap.height(),
284 kOpaque_SkAlphaType);
285 tmpBitmap.allocPixels(info);
286 if (!pixmap.readPixels(info, tmpBitmap.getPixels(), tmpBitmap.rowBytes())) {
287 return nullptr;
288 }
289 if (!tmpBitmap.peekPixels(&tmpPixmap)) {
290 return nullptr;
291 }
292 pmap = &tmpPixmap;
293 // must rebuild desc, since we've forced the info to be N32
294 desc = GrImageInfoToSurfaceDesc(pmap->info(), *caps);
brianosmana6359362016-03-21 06:55:37 -0700295 } else if (kIndex_8_SkColorType == pixmap.colorType()) {
bsalomon76228632015-05-29 08:02:10 -0700296 if (caps->isConfigTexturable(kIndex_8_GrPixelConfig)) {
bsalomond4cb9222014-08-11 14:19:09 -0700297 size_t imageSize = GrCompressedFormatDataSize(kIndex_8_GrPixelConfig,
bsalomon0d996862016-03-09 18:44:43 -0800298 pixmap.width(), pixmap.height());
bsalomond4cb9222014-08-11 14:19:09 -0700299 SkAutoMalloc storage(imageSize);
bsalomon0d996862016-03-09 18:44:43 -0800300 build_index8_data(storage.get(), pixmap);
reed@google.comac10a2d2010-12-22 21:39:39 +0000301
302 // our compressed data will be trimmed, so pass width() for its
303 // "rowBytes", since they are the same now.
ericrk8bea8902016-03-18 11:52:20 -0700304 return ctx->textureProvider()->createTexture(desc, budgeted, storage.get(),
bsalomon0d996862016-03-09 18:44:43 -0800305 pixmap.width());
reed@google.comac10a2d2010-12-22 21:39:39 +0000306 } else {
bsalomon0d996862016-03-09 18:44:43 -0800307 SkImageInfo info = SkImageInfo::MakeN32Premul(pixmap.width(), pixmap.height());
308 tmpBitmap.allocPixels(info);
309 if (!pixmap.readPixels(info, tmpBitmap.getPixels(), tmpBitmap.rowBytes())) {
310 return nullptr;
311 }
312 if (!tmpBitmap.peekPixels(&tmpPixmap)) {
313 return nullptr;
314 }
315 pmap = &tmpPixmap;
316 // must rebuild desc, since we've forced the info to be N32
brianosmana6359362016-03-21 06:55:37 -0700317 desc = GrImageInfoToSurfaceDesc(pmap->info(), *caps);
krajcevski9c0e6292014-06-02 07:38:14 -0700318 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000319 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000320
ericrk8bea8902016-03-18 11:52:20 -0700321 return ctx->textureProvider()->createTexture(desc, budgeted, pmap->addr(),
bsalomon0d996862016-03-09 18:44:43 -0800322 pmap->rowBytes());
bsalomon37f9a262015-02-02 13:00:10 -0800323}
324
bsalomonb4d40ef2015-07-15 10:12:16 -0700325
bsalomon045802d2015-10-20 07:58:01 -0700326////////////////////////////////////////////////////////////////////////////////
327
bsalomonc55271f2015-11-09 11:55:57 -0800328void GrInstallBitmapUniqueKeyInvalidator(const GrUniqueKey& key, SkPixelRef* pixelRef) {
bsalomon89fe56b2015-10-29 10:49:28 -0700329 class Invalidator : public SkPixelRef::GenIDChangeListener {
330 public:
331 explicit Invalidator(const GrUniqueKey& key) : fMsg(key) {}
332 private:
333 GrUniqueKeyInvalidatedMessage fMsg;
334
335 void onChange() override { SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(fMsg); }
336 };
337
338 pixelRef->addGenIDChangeListener(new Invalidator(key));
339}
340
brianosman982eb7f2016-06-06 13:10:58 -0700341GrTexture* GrGenerateMipMapsAndUploadToTexture(GrContext* ctx, const SkBitmap& bitmap,
Brian Osman7b8400d2016-11-08 17:08:54 -0500342 SkDestinationSurfaceColorMode colorMode)
cblume55f2d2d2016-02-26 13:20:48 -0800343{
brianosmana6359362016-03-21 06:55:37 -0700344 GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(bitmap.info(), *ctx->caps());
cblume55f2d2d2016-02-26 13:20:48 -0800345 if (kIndex_8_SkColorType != bitmap.colorType() && !bitmap.readyToDraw()) {
346 GrTexture* texture = load_etc1_texture(ctx, bitmap, desc);
347 if (texture) {
348 return texture;
349 }
350 }
351
robertphillips677da9d2016-05-11 05:15:55 -0700352 sk_sp<GrTexture> texture(create_texture_from_yuv(ctx, bitmap, desc));
cblume55f2d2d2016-02-26 13:20:48 -0800353 if (texture) {
robertphillips677da9d2016-05-11 05:15:55 -0700354 return texture.release();
cblume55f2d2d2016-02-26 13:20:48 -0800355 }
356
brianosman7e5e5942016-06-21 12:08:24 -0700357 // We don't support Gray8 directly in the GL backend, so fail-over to GrUploadBitmapToTexture.
358 // That will transform the Gray8 to 8888, then use the driver/GPU to build mipmaps. If we build
359 // the mips on the CPU here, they'll all be Gray8, which isn't useful. (They get treated as A8).
360 // TODO: A better option might be to transform the initial bitmap here to 8888, then run the
361 // CPU mip-mapper on that data before uploading. This is much less code for a rare case though:
362 if (kGray_8_SkColorType == bitmap.colorType()) {
363 return nullptr;
364 }
365
cblume55f2d2d2016-02-26 13:20:48 -0800366 SkASSERT(sizeof(int) <= sizeof(uint32_t));
367 if (bitmap.width() < 0 || bitmap.height() < 0) {
368 return nullptr;
369 }
370
371 SkAutoPixmapUnlock srcUnlocker;
372 if (!bitmap.requestLock(&srcUnlocker)) {
373 return nullptr;
374 }
375 const SkPixmap& pixmap = srcUnlocker.pixmap();
376 // Try to catch where we might have returned nullptr for src crbug.com/492818
377 if (nullptr == pixmap.addr()) {
378 sk_throw();
379 }
380
Brian Osman7b8400d2016-11-08 17:08:54 -0500381 std::unique_ptr<SkMipMap> mipmaps(SkMipMap::Build(pixmap, colorMode, nullptr));
cblume55f2d2d2016-02-26 13:20:48 -0800382 if (!mipmaps) {
383 return nullptr;
384 }
385
386 const int mipLevelCount = mipmaps->countLevels() + 1;
387 if (mipLevelCount < 1) {
388 return nullptr;
389 }
390
391 const bool isMipMapped = mipLevelCount > 1;
392 desc.fIsMipMapped = isMipMapped;
393
Ben Wagner7ecc5962016-11-02 17:07:33 -0400394 std::unique_ptr<GrMipLevel[]> texels(new GrMipLevel[mipLevelCount]);
cblume55f2d2d2016-02-26 13:20:48 -0800395
396 texels[0].fPixels = pixmap.addr();
397 texels[0].fRowBytes = pixmap.rowBytes();
398
399 for (int i = 1; i < mipLevelCount; ++i) {
400 SkMipMap::Level generatedMipLevel;
401 mipmaps->getLevel(i - 1, &generatedMipLevel);
402 texels[i].fPixels = generatedMipLevel.fPixmap.addr();
403 texels[i].fRowBytes = generatedMipLevel.fPixmap.rowBytes();
404 }
405
brianosmanfe199872016-06-13 07:59:48 -0700406 {
407 GrTexture* texture = ctx->textureProvider()->createMipMappedTexture(desc,
408 SkBudgeted::kYes,
409 texels.get(),
410 mipLevelCount);
brianosman7d2f6072016-06-17 07:03:45 -0700411 if (texture) {
Brian Osman7b8400d2016-11-08 17:08:54 -0500412 texture->texturePriv().setMipColorMode(colorMode);
brianosman7d2f6072016-06-17 07:03:45 -0700413 }
brianosmanfe199872016-06-13 07:59:48 -0700414 return texture;
415 }
cblume55f2d2d2016-02-26 13:20:48 -0800416}
417
cblume186d2d42016-06-03 11:17:42 -0700418GrTexture* GrUploadMipMapToTexture(GrContext* ctx, const SkImageInfo& info,
419 const GrMipLevel* texels, int mipLevelCount) {
420 const GrCaps* caps = ctx->caps();
421 return ctx->textureProvider()->createMipMappedTexture(GrImageInfoToSurfaceDesc(info, *caps),
422 SkBudgeted::kYes, texels,
423 mipLevelCount);
424}
425
reedb5d32632015-09-29 13:36:50 -0700426GrTexture* GrRefCachedBitmapTexture(GrContext* ctx, const SkBitmap& bitmap,
Brian Salomon514baff2016-11-17 15:17:07 -0500427 const GrSamplerParams& params,
Brian Osman7b8400d2016-11-08 17:08:54 -0500428 SkDestinationSurfaceColorMode colorMode) {
Brian Osman7992da32016-11-18 11:28:24 -0500429 // Caller doesn't care about the texture's color space (they can always get it from the bitmap)
430 return GrBitmapTextureMaker(ctx, bitmap).refTextureForParams(params, colorMode, nullptr);
rileya@google.com24f3ad12012-07-18 21:47:40 +0000431}
reed8f343722015-08-13 13:32:39 -0700432
reedc7ec7c92016-07-25 08:29:10 -0700433sk_sp<GrTexture> GrMakeCachedBitmapTexture(GrContext* ctx, const SkBitmap& bitmap,
Brian Salomon514baff2016-11-17 15:17:07 -0500434 const GrSamplerParams& params,
Brian Osman7b8400d2016-11-08 17:08:54 -0500435 SkDestinationSurfaceColorMode colorMode) {
Brian Osman7992da32016-11-18 11:28:24 -0500436 // Caller doesn't care about the texture's color space (they can always get it from the bitmap)
437 GrTexture* tex = GrBitmapTextureMaker(ctx, bitmap).refTextureForParams(params, colorMode,
438 nullptr);
reedc7ec7c92016-07-25 08:29:10 -0700439 return sk_sp<GrTexture>(tex);
440}
441
rileya@google.com24f3ad12012-07-18 21:47:40 +0000442///////////////////////////////////////////////////////////////////////////////
443
Brian Osman72ae4312016-10-20 16:53:45 -0400444GrColor4f SkColorToPremulGrColor4f(SkColor c, SkColorSpace* dstColorSpace) {
445 // We want to premultiply after linearizing, so this is easy:
446 return SkColorToUnpremulGrColor4f(c, dstColorSpace).premul();
447}
448
449GrColor4f SkColorToUnpremulGrColor4f(SkColor c, SkColorSpace* dstColorSpace) {
450 if (dstColorSpace) {
Brian Osman526972e2016-10-24 09:24:02 -0400451 auto srgbColorSpace = SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named);
Brian Osman72ae4312016-10-20 16:53:45 -0400452 auto gamutXform = GrColorSpaceXform::Make(srgbColorSpace.get(), dstColorSpace);
453 return SkColorToUnpremulGrColor4f(c, true, gamutXform.get());
454 } else {
455 return SkColorToUnpremulGrColor4f(c, false, nullptr);
456 }
457}
458
Brian Osmanc68d4aa2016-09-30 11:41:59 -0400459GrColor4f SkColorToPremulGrColor4f(SkColor c, bool gammaCorrect, GrColorSpaceXform* gamutXform) {
460 // We want to premultiply after linearizing, so this is easy:
461 return SkColorToUnpremulGrColor4f(c, gammaCorrect, gamutXform).premul();
462}
463
464GrColor4f SkColorToUnpremulGrColor4f(SkColor c, bool gammaCorrect, GrColorSpaceXform* gamutXform) {
465 // You can't be color-space aware in legacy mode
466 SkASSERT(gammaCorrect || !gamutXform);
467
468 GrColor4f color;
469 if (gammaCorrect) {
470 // SkColor4f::FromColor does sRGB -> Linear
471 color = GrColor4f::FromSkColor4f(SkColor4f::FromColor(c));
472 } else {
473 // GrColor4f::FromGrColor just multiplies by 1/255
474 color = GrColor4f::FromGrColor(SkColorToUnpremulGrColor(c));
475 }
476
477 if (gamutXform) {
478 color = gamutXform->apply(color);
479 }
480
481 return color;
482}
483
484///////////////////////////////////////////////////////////////////////////////
485
commit-bot@chromium.org15a14052014-02-16 00:59:25 +0000486// alphatype is ignore for now, but if GrPixelConfig is expanded to encompass
487// alpha info, that will be considered.
brianosmanb109b8c2016-06-16 13:03:24 -0700488GrPixelConfig SkImageInfo2GrPixelConfig(SkColorType ct, SkAlphaType, const SkColorSpace* cs,
brianosmana6359362016-03-21 06:55:37 -0700489 const GrCaps& caps) {
490 // We intentionally ignore profile type for non-8888 formats. Anything we can't support
491 // in hardware will be expanded to sRGB 8888 in GrUploadPixmapToTexture.
brianosmanc571c002016-03-17 13:01:26 -0700492 switch (ct) {
493 case kUnknown_SkColorType:
494 return kUnknown_GrPixelConfig;
495 case kAlpha_8_SkColorType:
496 return kAlpha_8_GrPixelConfig;
497 case kRGB_565_SkColorType:
498 return kRGB_565_GrPixelConfig;
499 case kARGB_4444_SkColorType:
500 return kRGBA_4444_GrPixelConfig;
501 case kRGBA_8888_SkColorType:
brianosmanb109b8c2016-06-16 13:03:24 -0700502 return (caps.srgbSupport() && cs && cs->gammaCloseToSRGB())
brianosmana6359362016-03-21 06:55:37 -0700503 ? kSRGBA_8888_GrPixelConfig : kRGBA_8888_GrPixelConfig;
brianosmanc571c002016-03-17 13:01:26 -0700504 case kBGRA_8888_SkColorType:
brianosmanb109b8c2016-06-16 13:03:24 -0700505 return (caps.srgbSupport() && cs && cs->gammaCloseToSRGB())
brianosmana6359362016-03-21 06:55:37 -0700506 ? kSBGRA_8888_GrPixelConfig : kBGRA_8888_GrPixelConfig;
brianosmanc571c002016-03-17 13:01:26 -0700507 case kIndex_8_SkColorType:
508 return kIndex_8_GrPixelConfig;
509 case kGray_8_SkColorType:
510 return kAlpha_8_GrPixelConfig; // TODO: gray8 support on gpu
511 case kRGBA_F16_SkColorType:
512 return kRGBA_half_GrPixelConfig;
commit-bot@chromium.org15a14052014-02-16 00:59:25 +0000513 }
514 SkASSERT(0); // shouldn't get here
515 return kUnknown_GrPixelConfig;
516}
517
brianosman396fcdb2016-07-22 06:26:11 -0700518bool GrPixelConfigToColorType(GrPixelConfig config, SkColorType* ctOut) {
reed@google.combf790232013-12-13 19:45:58 +0000519 SkColorType ct;
520 switch (config) {
521 case kAlpha_8_GrPixelConfig:
522 ct = kAlpha_8_SkColorType;
523 break;
524 case kIndex_8_GrPixelConfig:
525 ct = kIndex_8_SkColorType;
526 break;
527 case kRGB_565_GrPixelConfig:
528 ct = kRGB_565_SkColorType;
529 break;
530 case kRGBA_4444_GrPixelConfig:
531 ct = kARGB_4444_SkColorType;
532 break;
533 case kRGBA_8888_GrPixelConfig:
534 ct = kRGBA_8888_SkColorType;
535 break;
536 case kBGRA_8888_GrPixelConfig:
537 ct = kBGRA_8888_SkColorType;
538 break;
jvanverthfa1e8a72014-12-22 08:31:49 -0800539 case kSRGBA_8888_GrPixelConfig:
540 ct = kRGBA_8888_SkColorType;
jvanverthfa1e8a72014-12-22 08:31:49 -0800541 break;
brianosmana6359362016-03-21 06:55:37 -0700542 case kSBGRA_8888_GrPixelConfig:
543 ct = kBGRA_8888_SkColorType;
brianosmana6359362016-03-21 06:55:37 -0700544 break;
brianosman9ac5b912016-04-12 13:49:53 -0700545 case kRGBA_half_GrPixelConfig:
546 ct = kRGBA_F16_SkColorType;
547 break;
reed@google.combf790232013-12-13 19:45:58 +0000548 default:
549 return false;
550 }
551 if (ctOut) {
552 *ctOut = ct;
553 }
554 return true;
555}
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000556
brianosman27a3aa52016-09-23 07:11:34 -0700557GrPixelConfig GrRenderableConfigForColorSpace(const SkColorSpace* colorSpace) {
brianosman2695eaa2016-09-21 06:45:09 -0700558 if (!colorSpace) {
559 return kRGBA_8888_GrPixelConfig;
560 } else if (colorSpace->gammaIsLinear()) {
561 return kRGBA_half_GrPixelConfig;
562 } else if (colorSpace->gammaCloseToSRGB()) {
563 return kSRGBA_8888_GrPixelConfig;
564 } else {
565 SkDEBUGFAIL("No renderable config exists for color space with strange gamma");
566 return kUnknown_GrPixelConfig;
567 }
568}
569
bsalomonf1b7a1d2015-09-28 06:26:28 -0700570////////////////////////////////////////////////////////////////////////////////////////////////
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000571
Mike Reed7d954ad2016-10-28 15:42:34 -0400572static inline bool blend_requires_shader(const SkBlendMode mode, bool primitiveIsSrc) {
bsalomonaa48d362015-10-01 08:34:17 -0700573 if (primitiveIsSrc) {
Mike Reed7d954ad2016-10-28 15:42:34 -0400574 return SkBlendMode::kSrc != mode;
bsalomonaa48d362015-10-01 08:34:17 -0700575 } else {
Mike Reed7d954ad2016-10-28 15:42:34 -0400576 return SkBlendMode::kDst != mode;
bsalomonaa48d362015-10-01 08:34:17 -0700577 }
578}
579
bsalomonf1b7a1d2015-09-28 06:26:28 -0700580static inline bool skpaint_to_grpaint_impl(GrContext* context,
Brian Osman11052242016-10-27 14:47:55 -0400581 GrRenderTargetContext* rtc,
bsalomonf1b7a1d2015-09-28 06:26:28 -0700582 const SkPaint& skPaint,
583 const SkMatrix& viewM,
bungeman06ca8ec2016-06-09 08:01:03 -0700584 sk_sp<GrFragmentProcessor>* shaderProcessor,
Mike Reed7d954ad2016-10-28 15:42:34 -0400585 SkBlendMode* primColorMode,
bsalomonf1b7a1d2015-09-28 06:26:28 -0700586 bool primitiveIsSrc,
587 GrPaint* grPaint) {
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000588 grPaint->setAntiAlias(skPaint.isAntiAlias());
Brian Osman11052242016-10-27 14:47:55 -0400589 grPaint->setAllowSRGBInputs(rtc->isGammaCorrect());
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000590
Brian Osmanc68d4aa2016-09-30 11:41:59 -0400591 // Convert SkPaint color to 4f format, including optional linearizing and gamut conversion.
Brian Osman11052242016-10-27 14:47:55 -0400592 GrColor4f origColor = SkColorToUnpremulGrColor4f(skPaint.getColor(), rtc->isGammaCorrect(),
593 rtc->getColorXformFromSRGB());
brianosmana4535a32016-06-24 12:50:19 -0700594
bsalomonf1b7a1d2015-09-28 06:26:28 -0700595 // Setup the initial color considering the shader, the SkPaint color, and the presence or not
596 // of per-vertex colors.
bungeman06ca8ec2016-06-09 08:01:03 -0700597 sk_sp<GrFragmentProcessor> shaderFP;
bsalomonaa48d362015-10-01 08:34:17 -0700598 if (!primColorMode || blend_requires_shader(*primColorMode, primitiveIsSrc)) {
599 if (shaderProcessor) {
600 shaderFP = *shaderProcessor;
601 } else if (const SkShader* shader = skPaint.getShader()) {
brianosman839345d2016-07-22 11:04:53 -0700602 shaderFP = shader->asFragmentProcessor(SkShader::AsFPArgs(context, &viewM, nullptr,
603 skPaint.getFilterQuality(),
Brian Osman11052242016-10-27 14:47:55 -0400604 rtc->getColorSpace(),
Brian Osman7b8400d2016-11-08 17:08:54 -0500605 rtc->colorMode()));
bsalomonaa48d362015-10-01 08:34:17 -0700606 if (!shaderFP) {
607 return false;
608 }
bsalomonf1b7a1d2015-09-28 06:26:28 -0700609 }
610 }
611
612 // Set this in below cases if the output of the shader/paint-color/paint-alpha/primXfermode is
613 // a known constant value. In that case we can simply apply a color filter during this
614 // conversion without converting the color filter to a GrFragmentProcessor.
615 bool applyColorFilterToPaintColor = false;
616 if (shaderFP) {
617 if (primColorMode) {
618 // There is a blend between the primitive color and the shader color. The shader sees
619 // the opaque paint color. The shader's output is blended using the provided mode by
620 // the primitive color. The blended color is then modulated by the paint's alpha.
621
622 // The geometry processor will insert the primitive color to start the color chain, so
623 // the GrPaint color will be ignored.
624
brianosman4cea3b92016-09-08 09:33:50 -0700625 GrColor4f shaderInput = origColor.opaque();
bsalomonf1b7a1d2015-09-28 06:26:28 -0700626 shaderFP = GrFragmentProcessor::OverrideInput(shaderFP, shaderInput);
bsalomonf1b7a1d2015-09-28 06:26:28 -0700627 if (primitiveIsSrc) {
bungeman06ca8ec2016-06-09 08:01:03 -0700628 shaderFP = GrXfermodeFragmentProcessor::MakeFromDstProcessor(std::move(shaderFP),
629 *primColorMode);
bsalomonf1b7a1d2015-09-28 06:26:28 -0700630 } else {
bungeman06ca8ec2016-06-09 08:01:03 -0700631 shaderFP = GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(shaderFP),
632 *primColorMode);
bsalomonf1b7a1d2015-09-28 06:26:28 -0700633 }
bsalomonf1b7a1d2015-09-28 06:26:28 -0700634 // The above may return null if compose results in a pass through of the prim color.
635 if (shaderFP) {
636 grPaint->addColorFragmentProcessor(shaderFP);
637 }
638
brianosmana4535a32016-06-24 12:50:19 -0700639 // We can ignore origColor here - alpha is unchanged by gamma
bsalomonf1b7a1d2015-09-28 06:26:28 -0700640 GrColor paintAlpha = SkColorAlphaToGrColor(skPaint.getColor());
641 if (GrColor_WHITE != paintAlpha) {
Brian Osman618d3042016-10-25 10:51:28 -0400642 // No gamut conversion - paintAlpha is a (linear) alpha value, splatted to all
643 // color channels. It's value should be treated as the same in ANY color space.
bungeman06ca8ec2016-06-09 08:01:03 -0700644 grPaint->addColorFragmentProcessor(GrConstColorProcessor::Make(
Brian Osman618d3042016-10-25 10:51:28 -0400645 GrColor4f::FromGrColor(paintAlpha),
646 GrConstColorProcessor::kModulateRGBA_InputMode));
bsalomonf1b7a1d2015-09-28 06:26:28 -0700647 }
648 } else {
649 // The shader's FP sees the paint unpremul color
brianosmana4535a32016-06-24 12:50:19 -0700650 grPaint->setColor4f(origColor);
bungeman06ca8ec2016-06-09 08:01:03 -0700651 grPaint->addColorFragmentProcessor(std::move(shaderFP));
bsalomonf1b7a1d2015-09-28 06:26:28 -0700652 }
653 } else {
654 if (primColorMode) {
655 // There is a blend between the primitive color and the paint color. The blend considers
656 // the opaque paint color. The paint's alpha is applied to the post-blended color.
bungeman06ca8ec2016-06-09 08:01:03 -0700657 sk_sp<GrFragmentProcessor> processor(
Brian Osman618d3042016-10-25 10:51:28 -0400658 GrConstColorProcessor::Make(origColor.opaque(),
659 GrConstColorProcessor::kIgnore_InputMode));
bsalomonf1b7a1d2015-09-28 06:26:28 -0700660 if (primitiveIsSrc) {
bungeman06ca8ec2016-06-09 08:01:03 -0700661 processor = GrXfermodeFragmentProcessor::MakeFromDstProcessor(std::move(processor),
662 *primColorMode);
bsalomonf1b7a1d2015-09-28 06:26:28 -0700663 } else {
bungeman06ca8ec2016-06-09 08:01:03 -0700664 processor = GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(processor),
665 *primColorMode);
bsalomonf1b7a1d2015-09-28 06:26:28 -0700666 }
667 if (processor) {
bungeman06ca8ec2016-06-09 08:01:03 -0700668 grPaint->addColorFragmentProcessor(std::move(processor));
bsalomonf1b7a1d2015-09-28 06:26:28 -0700669 }
670
brianosmana4535a32016-06-24 12:50:19 -0700671 grPaint->setColor4f(origColor.opaque());
bsalomonf1b7a1d2015-09-28 06:26:28 -0700672
brianosmana4535a32016-06-24 12:50:19 -0700673 // We can ignore origColor here - alpha is unchanged by gamma
bsalomonf1b7a1d2015-09-28 06:26:28 -0700674 GrColor paintAlpha = SkColorAlphaToGrColor(skPaint.getColor());
bsalomonaa48d362015-10-01 08:34:17 -0700675 if (GrColor_WHITE != paintAlpha) {
Brian Osman618d3042016-10-25 10:51:28 -0400676 // No gamut conversion - paintAlpha is a (linear) alpha value, splatted to all
677 // color channels. It's value should be treated as the same in ANY color space.
bungeman06ca8ec2016-06-09 08:01:03 -0700678 grPaint->addColorFragmentProcessor(GrConstColorProcessor::Make(
Brian Osman618d3042016-10-25 10:51:28 -0400679 GrColor4f::FromGrColor(paintAlpha),
680 GrConstColorProcessor::kModulateRGBA_InputMode));
bsalomonaa48d362015-10-01 08:34:17 -0700681 }
bsalomonf1b7a1d2015-09-28 06:26:28 -0700682 } else {
683 // No shader, no primitive color.
brianosmana4535a32016-06-24 12:50:19 -0700684 grPaint->setColor4f(origColor.premul());
bsalomonf1b7a1d2015-09-28 06:26:28 -0700685 applyColorFilterToPaintColor = true;
686 }
687 }
688
689 SkColorFilter* colorFilter = skPaint.getColorFilter();
690 if (colorFilter) {
691 if (applyColorFilterToPaintColor) {
Brian Osman8bf4e672016-10-17 16:54:49 -0400692 // If we're in legacy mode, we *must* avoid using the 4f version of the color filter,
693 // because that will combine with the linearized version of the stored color.
Brian Osman11052242016-10-27 14:47:55 -0400694 if (rtc->isGammaCorrect()) {
Brian Osman8bf4e672016-10-17 16:54:49 -0400695 grPaint->setColor4f(GrColor4f::FromSkColor4f(
696 colorFilter->filterColor4f(origColor.toSkColor4f())).premul());
697 } else {
698 grPaint->setColor4f(SkColorToPremulGrColor4f(
699 colorFilter->filterColor(skPaint.getColor()), false, nullptr));
700 }
bsalomonf1b7a1d2015-09-28 06:26:28 -0700701 } else {
Brian Osman618d3042016-10-25 10:51:28 -0400702 sk_sp<GrFragmentProcessor> cfFP(colorFilter->asFragmentProcessor(context,
Brian Osman11052242016-10-27 14:47:55 -0400703 rtc->getColorSpace()));
bsalomone25eea42015-09-29 06:38:55 -0700704 if (cfFP) {
bungeman06ca8ec2016-06-09 08:01:03 -0700705 grPaint->addColorFragmentProcessor(std::move(cfFP));
bsalomonf1b7a1d2015-09-28 06:26:28 -0700706 } else {
707 return false;
708 }
709 }
710 }
711
Robert Phillipsa29a9562016-10-20 09:40:55 -0400712 SkMaskFilter* maskFilter = skPaint.getMaskFilter();
713 if (maskFilter) {
714 GrFragmentProcessor* mfFP;
715 if (maskFilter->asFragmentProcessor(&mfFP, nullptr, viewM)) {
716 grPaint->addCoverageFragmentProcessor(sk_sp<GrFragmentProcessor>(mfFP));
717 }
718 }
719
robertphillips4f037942016-02-09 05:09:27 -0800720 // When the xfermode is null on the SkPaint (meaning kSrcOver) we need the XPFactory field on
721 // the GrPaint to also be null (also kSrcOver).
722 SkASSERT(!grPaint->getXPFactory());
reed374772b2016-10-05 17:33:02 -0700723 if (!skPaint.isSrcOver()) {
724 grPaint->setXPFactory(SkBlendMode_AsXPFactory(skPaint.getBlendMode()));
robertphillips4f037942016-02-09 05:09:27 -0800725 }
mtklein775b8192014-12-02 09:11:25 -0800726
krajcevskif461a8f2014-06-19 14:14:06 -0700727#ifndef SK_IGNORE_GPU_DITHER
Brian Osman11052242016-10-27 14:47:55 -0400728 if (skPaint.isDither() && grPaint->numColorFragmentProcessors() > 0 && !rtc->isGammaCorrect()) {
bungeman06ca8ec2016-06-09 08:01:03 -0700729 grPaint->addColorFragmentProcessor(GrDitherEffect::Make());
krajcevskif461a8f2014-06-19 14:14:06 -0700730 }
731#endif
bsalomonbed83a62015-04-15 14:18:34 -0700732 return true;
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000733}
734
Brian Osman11052242016-10-27 14:47:55 -0400735bool SkPaintToGrPaint(GrContext* context, GrRenderTargetContext* rtc, const SkPaint& skPaint,
brianosman8fe485b2016-07-25 12:31:51 -0700736 const SkMatrix& viewM, GrPaint* grPaint) {
Brian Osman11052242016-10-27 14:47:55 -0400737 return skpaint_to_grpaint_impl(context, rtc, skPaint, viewM, nullptr, nullptr, false, grPaint);
bsalomonf1b7a1d2015-09-28 06:26:28 -0700738}
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000739
bsalomonf1b7a1d2015-09-28 06:26:28 -0700740/** Replaces the SkShader (if any) on skPaint with the passed in GrFragmentProcessor. */
741bool SkPaintToGrPaintReplaceShader(GrContext* context,
Brian Osman11052242016-10-27 14:47:55 -0400742 GrRenderTargetContext* rtc,
bsalomonf1b7a1d2015-09-28 06:26:28 -0700743 const SkPaint& skPaint,
bungeman06ca8ec2016-06-09 08:01:03 -0700744 sk_sp<GrFragmentProcessor> shaderFP,
bsalomonf1b7a1d2015-09-28 06:26:28 -0700745 GrPaint* grPaint) {
746 if (!shaderFP) {
bsalomonc21b09e2015-08-28 18:46:56 -0700747 return false;
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000748 }
Brian Osman11052242016-10-27 14:47:55 -0400749 return skpaint_to_grpaint_impl(context, rtc, skPaint, SkMatrix::I(), &shaderFP, nullptr, false,
brianosman8fe485b2016-07-25 12:31:51 -0700750 grPaint);
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000751}
reed8b26b992015-05-07 15:36:17 -0700752
bsalomonf1b7a1d2015-09-28 06:26:28 -0700753/** Ignores the SkShader (if any) on skPaint. */
754bool SkPaintToGrPaintNoShader(GrContext* context,
Brian Osman11052242016-10-27 14:47:55 -0400755 GrRenderTargetContext* rtc,
bsalomonf1b7a1d2015-09-28 06:26:28 -0700756 const SkPaint& skPaint,
757 GrPaint* grPaint) {
758 // Use a ptr to a nullptr to to indicate that the SkShader is ignored and not replaced.
bungeman06ca8ec2016-06-09 08:01:03 -0700759 static sk_sp<GrFragmentProcessor> kNullShaderFP(nullptr);
760 static sk_sp<GrFragmentProcessor>* kIgnoreShader = &kNullShaderFP;
Brian Osman11052242016-10-27 14:47:55 -0400761 return skpaint_to_grpaint_impl(context, rtc, skPaint, SkMatrix::I(), kIgnoreShader, nullptr,
brianosman8fe485b2016-07-25 12:31:51 -0700762 false, grPaint);
bsalomonf1b7a1d2015-09-28 06:26:28 -0700763}
764
765/** Blends the SkPaint's shader (or color if no shader) with a per-primitive color which must
Mike Reed7d954ad2016-10-28 15:42:34 -0400766be setup as a vertex attribute using the specified SkBlendMode. */
bsalomonf1b7a1d2015-09-28 06:26:28 -0700767bool SkPaintToGrPaintWithXfermode(GrContext* context,
Brian Osman11052242016-10-27 14:47:55 -0400768 GrRenderTargetContext* rtc,
bsalomonf1b7a1d2015-09-28 06:26:28 -0700769 const SkPaint& skPaint,
770 const SkMatrix& viewM,
Mike Reed7d954ad2016-10-28 15:42:34 -0400771 SkBlendMode primColorMode,
bsalomonf1b7a1d2015-09-28 06:26:28 -0700772 bool primitiveIsSrc,
773 GrPaint* grPaint) {
Brian Osman11052242016-10-27 14:47:55 -0400774 return skpaint_to_grpaint_impl(context, rtc, skPaint, viewM, nullptr, &primColorMode,
brianosman8fe485b2016-07-25 12:31:51 -0700775 primitiveIsSrc, grPaint);
bsalomonf1b7a1d2015-09-28 06:26:28 -0700776}
777
joshualitt33a5fce2015-11-18 13:28:51 -0800778bool SkPaintToGrPaintWithTexture(GrContext* context,
Brian Osman11052242016-10-27 14:47:55 -0400779 GrRenderTargetContext* rtc,
joshualitt33a5fce2015-11-18 13:28:51 -0800780 const SkPaint& paint,
781 const SkMatrix& viewM,
bungeman06ca8ec2016-06-09 08:01:03 -0700782 sk_sp<GrFragmentProcessor> fp,
joshualitt33a5fce2015-11-18 13:28:51 -0800783 bool textureIsAlphaOnly,
784 GrPaint* grPaint) {
bungeman06ca8ec2016-06-09 08:01:03 -0700785 sk_sp<GrFragmentProcessor> shaderFP;
joshualitt33a5fce2015-11-18 13:28:51 -0800786 if (textureIsAlphaOnly) {
787 if (const SkShader* shader = paint.getShader()) {
brianosman839345d2016-07-22 11:04:53 -0700788 shaderFP = shader->asFragmentProcessor(SkShader::AsFPArgs(context,
789 &viewM,
790 nullptr,
791 paint.getFilterQuality(),
Brian Osman11052242016-10-27 14:47:55 -0400792 rtc->getColorSpace(),
Brian Osman7b8400d2016-11-08 17:08:54 -0500793 rtc->colorMode()));
joshualitt33a5fce2015-11-18 13:28:51 -0800794 if (!shaderFP) {
795 return false;
796 }
bungeman06ca8ec2016-06-09 08:01:03 -0700797 sk_sp<GrFragmentProcessor> fpSeries[] = { std::move(shaderFP), std::move(fp) };
798 shaderFP = GrFragmentProcessor::RunInSeries(fpSeries, 2);
joshualitt33a5fce2015-11-18 13:28:51 -0800799 } else {
bungeman06ca8ec2016-06-09 08:01:03 -0700800 shaderFP = GrFragmentProcessor::MulOutputByInputUnpremulColor(fp);
joshualitt33a5fce2015-11-18 13:28:51 -0800801 }
802 } else {
bungeman06ca8ec2016-06-09 08:01:03 -0700803 shaderFP = GrFragmentProcessor::MulOutputByInputAlpha(fp);
joshualitt33a5fce2015-11-18 13:28:51 -0800804 }
805
Brian Osman11052242016-10-27 14:47:55 -0400806 return SkPaintToGrPaintReplaceShader(context, rtc, paint, std::move(shaderFP), grPaint);
joshualitt33a5fce2015-11-18 13:28:51 -0800807}
808
bsalomonf1b7a1d2015-09-28 06:26:28 -0700809
810////////////////////////////////////////////////////////////////////////////////////////////////
811
Brian Salomon514baff2016-11-17 15:17:07 -0500812GrSamplerParams::FilterMode GrSkFilterQualityToGrFilterMode(SkFilterQuality paintFilterQuality,
joshualitt9bc39542015-08-12 12:57:54 -0700813 const SkMatrix& viewM,
814 const SkMatrix& localM,
815 bool* doBicubic) {
816 *doBicubic = false;
Brian Salomon514baff2016-11-17 15:17:07 -0500817 GrSamplerParams::FilterMode textureFilterMode;
joshualitt9bc39542015-08-12 12:57:54 -0700818 switch (paintFilterQuality) {
819 case kNone_SkFilterQuality:
Brian Salomon514baff2016-11-17 15:17:07 -0500820 textureFilterMode = GrSamplerParams::kNone_FilterMode;
joshualitt9bc39542015-08-12 12:57:54 -0700821 break;
822 case kLow_SkFilterQuality:
Brian Salomon514baff2016-11-17 15:17:07 -0500823 textureFilterMode = GrSamplerParams::kBilerp_FilterMode;
joshualitt9bc39542015-08-12 12:57:54 -0700824 break;
825 case kMedium_SkFilterQuality: {
826 SkMatrix matrix;
827 matrix.setConcat(viewM, localM);
828 if (matrix.getMinScale() < SK_Scalar1) {
Brian Salomon514baff2016-11-17 15:17:07 -0500829 textureFilterMode = GrSamplerParams::kMipMap_FilterMode;
joshualitt9bc39542015-08-12 12:57:54 -0700830 } else {
831 // Don't trigger MIP level generation unnecessarily.
Brian Salomon514baff2016-11-17 15:17:07 -0500832 textureFilterMode = GrSamplerParams::kBilerp_FilterMode;
joshualitt9bc39542015-08-12 12:57:54 -0700833 }
834 break;
835 }
836 case kHigh_SkFilterQuality: {
837 SkMatrix matrix;
838 matrix.setConcat(viewM, localM);
839 *doBicubic = GrBicubicEffect::ShouldUseBicubic(matrix, &textureFilterMode);
840 break;
841 }
842 default:
Mike Kleine54c75f2016-10-13 14:18:09 -0400843 // Should be unreachable. If not, fall back to mipmaps.
Brian Salomon514baff2016-11-17 15:17:07 -0500844 textureFilterMode = GrSamplerParams::kMipMap_FilterMode;
joshualitt9bc39542015-08-12 12:57:54 -0700845 break;
846
847 }
848 return textureFilterMode;
849}