blob: 58d16ae881e11d287dc50b705535061fb4619208 [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
Brian Osman3b66ab62016-11-28 09:26:31 -050010#include "GrBitmapTextureMaker.h"
bsalomon76228632015-05-29 08:02:10 -070011#include "GrCaps.h"
bsalomonf276ac52015-10-09 13:36:42 -070012#include "GrContext.h"
bsalomon045802d2015-10-20 07:58:01 -070013#include "GrGpuResourcePriv.h"
Brian Osman3b66ab62016-11-28 09:26:31 -050014#include "GrRenderTargetContext.h"
Brian Osman32342f02017-03-04 08:12:46 -050015#include "GrResourceProvider.h"
Hal Canary6f6961e2017-01-31 13:50:44 -050016#include "GrTextureProxy.h"
cblume55f2d2d2016-02-26 13:20:48 -080017#include "GrTypes.h"
egdaniel378092f2014-12-03 10:40:13 -080018#include "GrXferProcessor.h"
reed43fe6182015-09-08 08:37:36 -070019
Hal Canary95e3c052017-01-11 12:44:43 -050020#include "SkAutoMalloc.h"
reed374772b2016-10-05 17:33:02 -070021#include "SkBlendModePriv.h"
Hal Canary95e3c052017-01-11 12:44:43 -050022#include "SkCanvas.h"
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +000023#include "SkColorFilter.h"
Matt Sarett485c4992017-02-14 14:18:27 -050024#include "SkConvertPixels.h"
krajcevski9c0e6292014-06-02 07:38:14 -070025#include "SkData.h"
Brian Osman4075ec82017-01-17 16:41:03 +000026#include "SkImageInfoPriv.h"
Robert Phillipsa29a9562016-10-20 09:40:55 -040027#include "SkMaskFilter.h"
commit-bot@chromium.org50a30432013-10-24 17:44:27 +000028#include "SkMessageBus.h"
cblume55f2d2d2016-02-26 13:20:48 -080029#include "SkMipMap.h"
Kevin Lubickc456b732017-01-11 17:21:57 +000030#include "SkPM4fPriv.h"
Hal Canary95e3c052017-01-11 12:44:43 -050031#include "SkPixelRef.h"
sugoi692135f2015-01-19 10:10:27 -080032#include "SkResourceCache.h"
cblume55f2d2d2016-02-26 13:20:48 -080033#include "SkTemplates.h"
joshualitt9bc39542015-08-12 12:57:54 -070034#include "effects/GrBicubicEffect.h"
bsalomonf1b7a1d2015-09-28 06:26:28 -070035#include "effects/GrConstColorProcessor.h"
krajcevskif461a8f2014-06-19 14:14:06 -070036#include "effects/GrDitherEffect.h"
egdaniel378092f2014-12-03 10:40:13 -080037#include "effects/GrPorterDuffXferProcessor.h"
bsalomonf1b7a1d2015-09-28 06:26:28 -070038#include "effects/GrXfermodeFragmentProcessor.h"
krajcevski9c0e6292014-06-02 07:38:14 -070039
krajcevski8c111f72014-06-02 13:51:34 -070040#ifndef SK_IGNORE_ETC1_SUPPORT
krajcevski9c0e6292014-06-02 07:38:14 -070041# include "etc1.h"
42#endif
reed@google.comac10a2d2010-12-22 21:39:39 +000043
brianosmana6359362016-03-21 06:55:37 -070044GrSurfaceDesc GrImageInfoToSurfaceDesc(const SkImageInfo& info, const GrCaps& caps) {
bsalomon466c2c42015-10-16 12:01:18 -070045 GrSurfaceDesc desc;
46 desc.fFlags = kNone_GrSurfaceFlags;
47 desc.fWidth = info.width();
48 desc.fHeight = info.height();
brianosmana6359362016-03-21 06:55:37 -070049 desc.fConfig = SkImageInfo2GrPixelConfig(info, caps);
bsalomon466c2c42015-10-16 12:01:18 -070050 desc.fSampleCnt = 0;
51 return desc;
52}
53
bsalomon045802d2015-10-20 07:58:01 -070054void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& imageBounds) {
55 SkASSERT(key);
56 SkASSERT(imageID);
57 SkASSERT(!imageBounds.isEmpty());
58 static const GrUniqueKey::Domain kImageIDDomain = GrUniqueKey::GenerateDomain();
59 GrUniqueKey::Builder builder(key, kImageIDDomain, 5);
bsalomon466c2c42015-10-16 12:01:18 -070060 builder[0] = imageID;
bsalomon045802d2015-10-20 07:58:01 -070061 builder[1] = imageBounds.fLeft;
62 builder[2] = imageBounds.fTop;
63 builder[3] = imageBounds.fRight;
64 builder[4] = imageBounds.fBottom;
bsalomon466c2c42015-10-16 12:01:18 -070065}
66
67GrPixelConfig GrIsCompressedTextureDataSupported(GrContext* ctx, SkData* data,
68 int expectedW, int expectedH,
69 const void** outStartOfDataToUpload) {
70 *outStartOfDataToUpload = nullptr;
71#ifndef SK_IGNORE_ETC1_SUPPORT
72 if (!ctx->caps()->isConfigTexturable(kETC1_GrPixelConfig)) {
73 return kUnknown_GrPixelConfig;
74 }
75
76 const uint8_t* bytes = data->bytes();
77 if (data->size() > ETC_PKM_HEADER_SIZE && etc1_pkm_is_valid(bytes)) {
78 // Does the data match the dimensions of the bitmap? If not,
79 // then we don't know how to scale the image to match it...
80 if (etc1_pkm_get_width(bytes) != (unsigned)expectedW ||
81 etc1_pkm_get_height(bytes) != (unsigned)expectedH)
82 {
83 return kUnknown_GrPixelConfig;
84 }
85
86 *outStartOfDataToUpload = bytes + ETC_PKM_HEADER_SIZE;
87 return kETC1_GrPixelConfig;
bsalomon466c2c42015-10-16 12:01:18 -070088 }
89#endif
90 return kUnknown_GrPixelConfig;
91}
92
bsalomon045802d2015-10-20 07:58:01 -070093//////////////////////////////////////////////////////////////////////////////
bsalomon@google.com5782d712011-01-21 21:03:59 +000094
bsalomon0d996862016-03-09 18:44:43 -080095GrTexture* GrUploadBitmapToTexture(GrContext* ctx, const SkBitmap& bitmap) {
bsalomon0d996862016-03-09 18:44:43 -080096 SkAutoLockPixels alp(bitmap);
97 if (!bitmap.readyToDraw()) {
98 return nullptr;
99 }
100 SkPixmap pixmap;
101 if (!bitmap.peekPixels(&pixmap)) {
102 return nullptr;
103 }
ericrk8bea8902016-03-18 11:52:20 -0700104 return GrUploadPixmapToTexture(ctx, pixmap, SkBudgeted::kYes);
bsalomon0d996862016-03-09 18:44:43 -0800105}
106
bsalomon@google.com5782d712011-01-21 21:03:59 +0000107
Robert Phillips26c90e02017-03-14 14:39:29 -0400108sk_sp<GrTextureProxy> GrUploadBitmapToTextureProxy(GrResourceProvider* resourceProvider,
109 const SkBitmap& bitmap) {
Robert Phillipsd3749482017-03-14 09:17:43 -0400110 SkAutoLockPixels alp(bitmap);
111 if (!bitmap.readyToDraw()) {
Brian Osman4075ec82017-01-17 16:41:03 +0000112 return nullptr;
113 }
Robert Phillipsd3749482017-03-14 09:17:43 -0400114 SkPixmap pixmap;
115 if (!bitmap.peekPixels(&pixmap)) {
116 return nullptr;
117 }
Robert Phillips26c90e02017-03-14 14:39:29 -0400118 return GrUploadPixmapToTextureProxy(resourceProvider, pixmap, SkBudgeted::kYes);
Robert Phillipsd3749482017-03-14 09:17:43 -0400119}
Brian Osman4075ec82017-01-17 16:41:03 +0000120
Robert Phillipsd3749482017-03-14 09:17:43 -0400121static const SkPixmap* compute_desc(const GrCaps& caps, const SkPixmap& pixmap,
122 GrSurfaceDesc* desc,
123 SkBitmap* tmpBitmap, SkPixmap* tmpPixmap) {
124 const SkPixmap* pmap = &pixmap;
125
126 *desc = GrImageInfoToSurfaceDesc(pixmap.info(), caps);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000127
Brian Osmand0be1ef2017-01-11 16:57:15 -0500128 // TODO: We're checking for srgbSupport, but we can then end up picking sBGRA as our pixel
129 // config (which may not be supported). We need better fallback management here.
Brian Osman47299142017-03-07 13:22:22 -0500130 SkColorSpace* colorSpace = pixmap.colorSpace();
Brian Osmand0be1ef2017-01-11 16:57:15 -0500131
Robert Phillipsd3749482017-03-14 09:17:43 -0400132 if (caps.srgbSupport() &&
Brian Osman47299142017-03-07 13:22:22 -0500133 colorSpace && colorSpace->gammaCloseToSRGB() && !as_CSB(colorSpace)->nonLinearBlending() &&
Robert Phillipsd3749482017-03-14 09:17:43 -0400134 !GrPixelConfigIsSRGB(desc->fConfig)) {
brianosmanb109b8c2016-06-16 13:03:24 -0700135 // We were supplied an sRGB-like color space, but we don't have a suitable pixel config.
brianosmana6359362016-03-21 06:55:37 -0700136 // Convert to 8888 sRGB so we can handle the data correctly. The raster backend doesn't
137 // handle sRGB Index8 -> sRGB 8888 correctly (yet), so lie about both the source and
138 // destination (claim they're linear):
139 SkImageInfo linSrcInfo = SkImageInfo::Make(pixmap.width(), pixmap.height(),
140 pixmap.colorType(), pixmap.alphaType());
141 SkPixmap linSrcPixmap(linSrcInfo, pixmap.addr(), pixmap.rowBytes(), pixmap.ctable());
142
brianosmanb109b8c2016-06-16 13:03:24 -0700143 SkImageInfo dstInfo = SkImageInfo::Make(pixmap.width(), pixmap.height(),
144 kN32_SkColorType, kPremul_SkAlphaType,
Robert Phillips70b49fd2017-01-13 11:21:36 -0500145 pixmap.info().refColorSpace());
brianosmanb109b8c2016-06-16 13:03:24 -0700146
Robert Phillipsd3749482017-03-14 09:17:43 -0400147 tmpBitmap->allocPixels(dstInfo);
brianosmana6359362016-03-21 06:55:37 -0700148
149 SkImageInfo linDstInfo = SkImageInfo::MakeN32Premul(pixmap.width(), pixmap.height());
Robert Phillipsd3749482017-03-14 09:17:43 -0400150 if (!linSrcPixmap.readPixels(linDstInfo, tmpBitmap->getPixels(), tmpBitmap->rowBytes())) {
brianosmana6359362016-03-21 06:55:37 -0700151 return nullptr;
152 }
Robert Phillipsd3749482017-03-14 09:17:43 -0400153 if (!tmpBitmap->peekPixels(tmpPixmap)) {
brianosmana6359362016-03-21 06:55:37 -0700154 return nullptr;
155 }
Robert Phillipsd3749482017-03-14 09:17:43 -0400156 pmap = tmpPixmap;
brianosmana6359362016-03-21 06:55:37 -0700157 // must rebuild desc, since we've forced the info to be N32
Robert Phillipsd3749482017-03-14 09:17:43 -0400158 *desc = GrImageInfoToSurfaceDesc(pmap->info(), caps);
brianosmana6359362016-03-21 06:55:37 -0700159 } else if (kIndex_8_SkColorType == pixmap.colorType()) {
Brian Osmand0be1ef2017-01-11 16:57:15 -0500160 SkImageInfo info = SkImageInfo::MakeN32Premul(pixmap.width(), pixmap.height());
Robert Phillipsd3749482017-03-14 09:17:43 -0400161 tmpBitmap->allocPixels(info);
162 if (!pixmap.readPixels(info, tmpBitmap->getPixels(), tmpBitmap->rowBytes())) {
Brian Osmand0be1ef2017-01-11 16:57:15 -0500163 return nullptr;
krajcevski9c0e6292014-06-02 07:38:14 -0700164 }
Robert Phillipsd3749482017-03-14 09:17:43 -0400165 if (!tmpBitmap->peekPixels(tmpPixmap)) {
Brian Osmand0be1ef2017-01-11 16:57:15 -0500166 return nullptr;
167 }
Robert Phillipsd3749482017-03-14 09:17:43 -0400168 pmap = tmpPixmap;
Brian Osmand0be1ef2017-01-11 16:57:15 -0500169 // must rebuild desc, since we've forced the info to be N32
Robert Phillipsd3749482017-03-14 09:17:43 -0400170 *desc = GrImageInfoToSurfaceDesc(pmap->info(), caps);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000171 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000172
Robert Phillipsd3749482017-03-14 09:17:43 -0400173 return pmap;
bsalomon37f9a262015-02-02 13:00:10 -0800174}
175
Robert Phillipsd3749482017-03-14 09:17:43 -0400176GrTexture* GrUploadPixmapToTexture(GrContext* ctx, const SkPixmap& pixmap, SkBudgeted budgeted) {
177 if (!SkImageInfoIsValid(pixmap.info())) {
178 return nullptr;
179 }
180
181 SkBitmap tmpBitmap;
182 SkPixmap tmpPixmap;
183 GrSurfaceDesc desc;
184
185 if (const SkPixmap* pmap = compute_desc(*ctx->caps(), pixmap, &desc, &tmpBitmap, &tmpPixmap)) {
186 return ctx->resourceProvider()->createTexture(desc, budgeted, pmap->addr(),
187 pmap->rowBytes());
188 }
189
190 return nullptr;
191}
192
Robert Phillips26c90e02017-03-14 14:39:29 -0400193sk_sp<GrTextureProxy> GrUploadPixmapToTextureProxy(GrResourceProvider* resourceProvider,
Robert Phillipsd3749482017-03-14 09:17:43 -0400194 const SkPixmap& pixmap,
195 SkBudgeted budgeted) {
196 if (!SkImageInfoIsValid(pixmap.info())) {
197 return nullptr;
198 }
199
200 SkBitmap tmpBitmap;
201 SkPixmap tmpPixmap;
202 GrSurfaceDesc desc;
203
Robert Phillips26c90e02017-03-14 14:39:29 -0400204 if (const SkPixmap* pmap = compute_desc(*resourceProvider->caps(), pixmap, &desc,
205 &tmpBitmap, &tmpPixmap)) {
206 return GrSurfaceProxy::MakeDeferred(resourceProvider, desc,
Robert Phillipsd3749482017-03-14 09:17:43 -0400207 budgeted, pmap->addr(), pmap->rowBytes());
208 }
209
210 return nullptr;
211}
bsalomonb4d40ef2015-07-15 10:12:16 -0700212
bsalomon045802d2015-10-20 07:58:01 -0700213////////////////////////////////////////////////////////////////////////////////
214
bsalomonc55271f2015-11-09 11:55:57 -0800215void GrInstallBitmapUniqueKeyInvalidator(const GrUniqueKey& key, SkPixelRef* pixelRef) {
bsalomon89fe56b2015-10-29 10:49:28 -0700216 class Invalidator : public SkPixelRef::GenIDChangeListener {
217 public:
218 explicit Invalidator(const GrUniqueKey& key) : fMsg(key) {}
219 private:
220 GrUniqueKeyInvalidatedMessage fMsg;
221
222 void onChange() override { SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(fMsg); }
223 };
224
225 pixelRef->addGenIDChangeListener(new Invalidator(key));
226}
227
brianosman982eb7f2016-06-06 13:10:58 -0700228GrTexture* GrGenerateMipMapsAndUploadToTexture(GrContext* ctx, const SkBitmap& bitmap,
Brian Osman61624f02016-12-09 14:51:59 -0500229 SkColorSpace* dstColorSpace)
cblume55f2d2d2016-02-26 13:20:48 -0800230{
Brian Osman61624f02016-12-09 14:51:59 -0500231 SkDestinationSurfaceColorMode colorMode = dstColorSpace
232 ? SkDestinationSurfaceColorMode::kGammaAndColorSpaceAware
233 : SkDestinationSurfaceColorMode::kLegacy;
234
Brian Osman4075ec82017-01-17 16:41:03 +0000235 if (!SkImageInfoIsValid(bitmap.info())) {
236 return nullptr;
237 }
238
brianosmana6359362016-03-21 06:55:37 -0700239 GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(bitmap.info(), *ctx->caps());
cblume55f2d2d2016-02-26 13:20:48 -0800240
cblume55f2d2d2016-02-26 13:20:48 -0800241 SkAutoPixmapUnlock srcUnlocker;
242 if (!bitmap.requestLock(&srcUnlocker)) {
243 return nullptr;
244 }
245 const SkPixmap& pixmap = srcUnlocker.pixmap();
246 // Try to catch where we might have returned nullptr for src crbug.com/492818
247 if (nullptr == pixmap.addr()) {
248 sk_throw();
249 }
250
Brian Osman7b8400d2016-11-08 17:08:54 -0500251 std::unique_ptr<SkMipMap> mipmaps(SkMipMap::Build(pixmap, colorMode, nullptr));
cblume55f2d2d2016-02-26 13:20:48 -0800252 if (!mipmaps) {
253 return nullptr;
254 }
255
256 const int mipLevelCount = mipmaps->countLevels() + 1;
257 if (mipLevelCount < 1) {
258 return nullptr;
259 }
260
261 const bool isMipMapped = mipLevelCount > 1;
262 desc.fIsMipMapped = isMipMapped;
263
Ben Wagner7ecc5962016-11-02 17:07:33 -0400264 std::unique_ptr<GrMipLevel[]> texels(new GrMipLevel[mipLevelCount]);
cblume55f2d2d2016-02-26 13:20:48 -0800265
266 texels[0].fPixels = pixmap.addr();
267 texels[0].fRowBytes = pixmap.rowBytes();
268
269 for (int i = 1; i < mipLevelCount; ++i) {
270 SkMipMap::Level generatedMipLevel;
271 mipmaps->getLevel(i - 1, &generatedMipLevel);
272 texels[i].fPixels = generatedMipLevel.fPixmap.addr();
273 texels[i].fRowBytes = generatedMipLevel.fPixmap.rowBytes();
274 }
275
Robert Phillipsa4c41b32017-03-15 13:02:45 -0400276 return ctx->resourceProvider()->createMipMappedTexture(desc,
277 SkBudgeted::kYes,
278 texels.get(),
279 mipLevelCount,
280 0, colorMode);
cblume55f2d2d2016-02-26 13:20:48 -0800281}
282
Robert Phillips0c984a02017-03-16 07:51:56 -0400283sk_sp<GrTextureProxy> GrGenerateMipMapsAndUploadToTextureProxy(GrContext* ctx,
284 const SkBitmap& bitmap,
285 SkColorSpace* dstColorSpace) {
286 sk_sp<GrTexture> tex(GrGenerateMipMapsAndUploadToTexture(ctx, bitmap, dstColorSpace));
287
288 return GrSurfaceProxy::MakeWrapped(std::move(tex));
289}
290
cblume186d2d42016-06-03 11:17:42 -0700291GrTexture* GrUploadMipMapToTexture(GrContext* ctx, const SkImageInfo& info,
Robert Phillipsa4c41b32017-03-15 13:02:45 -0400292 const GrMipLevel* texels, int mipLevelCount,
293 SkDestinationSurfaceColorMode colorMode) {
Brian Osman4075ec82017-01-17 16:41:03 +0000294 if (!SkImageInfoIsValid(info)) {
295 return nullptr;
296 }
297
cblume186d2d42016-06-03 11:17:42 -0700298 const GrCaps* caps = ctx->caps();
Brian Osman32342f02017-03-04 08:12:46 -0500299 return ctx->resourceProvider()->createMipMappedTexture(GrImageInfoToSurfaceDesc(info, *caps),
300 SkBudgeted::kYes, texels,
Robert Phillipsa4c41b32017-03-15 13:02:45 -0400301 mipLevelCount, 0, colorMode);
cblume186d2d42016-06-03 11:17:42 -0700302}
303
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400304sk_sp<GrTextureProxy> GrUploadMipMapToTextureProxy(GrContext* ctx, const SkImageInfo& info,
305 const GrMipLevel* texels,
306 int mipLevelCount,
307 SkDestinationSurfaceColorMode colorMode) {
308 sk_sp<GrTexture> tex(GrUploadMipMapToTexture(ctx, info, texels, mipLevelCount, colorMode));
309
310 return GrSurfaceProxy::MakeWrapped(std::move(tex));
311}
312
reedb5d32632015-09-29 13:36:50 -0700313GrTexture* GrRefCachedBitmapTexture(GrContext* ctx, const SkBitmap& bitmap,
Robert Phillips67c18d62017-01-20 12:44:06 -0500314 const GrSamplerParams& params, SkScalar scaleAdjust[2]) {
Brian Osman7992da32016-11-18 11:28:24 -0500315 // Caller doesn't care about the texture's color space (they can always get it from the bitmap)
Robert Phillips67c18d62017-01-20 12:44:06 -0500316 return GrBitmapTextureMaker(ctx, bitmap).refTextureForParams(params, nullptr,
317 nullptr, scaleAdjust);
rileya@google.com24f3ad12012-07-18 21:47:40 +0000318}
reed8f343722015-08-13 13:32:39 -0700319
Robert Phillipsbbd7a3b2017-03-21 08:48:40 -0400320sk_sp<GrTextureProxy> GrRefCachedBitmapTextureProxy(GrContext* ctx,
321 const SkBitmap& bitmap,
322 const GrSamplerParams& params,
323 SkScalar scaleAdjust[2]) {
324 // Caller doesn't care about the texture's color space (they can always get it from the bitmap)
325 sk_sp<GrTexture> tex(GrBitmapTextureMaker(ctx, bitmap).refTextureForParams(params, nullptr,
326 nullptr,
327 scaleAdjust));
328 return GrSurfaceProxy::MakeWrapped(std::move(tex));
329}
330
Robert Phillips26c90e02017-03-14 14:39:29 -0400331sk_sp<GrTextureProxy> GrMakeCachedBitmapProxy(GrResourceProvider* resourceProvider,
332 const SkBitmap& bitmap) {
Robert Phillipse14d3052017-02-15 13:18:21 -0500333 GrUniqueKey originalKey;
334
335 if (!bitmap.isVolatile()) {
336 SkIPoint origin = bitmap.pixelRefOrigin();
337 SkIRect subset = SkIRect::MakeXYWH(origin.fX, origin.fY, bitmap.width(), bitmap.height());
338 GrMakeKeyFromImageID(&originalKey, bitmap.pixelRef()->getGenerationID(), subset);
339 }
340
Robert Phillipsd3749482017-03-14 09:17:43 -0400341 sk_sp<GrTextureProxy> proxy;
Robert Phillipse14d3052017-02-15 13:18:21 -0500342
343 if (originalKey.isValid()) {
Robert Phillips26c90e02017-03-14 14:39:29 -0400344 proxy = resourceProvider->findProxyByUniqueKey(originalKey);
Robert Phillipse14d3052017-02-15 13:18:21 -0500345 }
Robert Phillipsd3749482017-03-14 09:17:43 -0400346 if (!proxy) {
Robert Phillips26c90e02017-03-14 14:39:29 -0400347 proxy = GrUploadBitmapToTextureProxy(resourceProvider, bitmap);
Robert Phillipsd3749482017-03-14 09:17:43 -0400348 if (proxy && originalKey.isValid()) {
Robert Phillips26c90e02017-03-14 14:39:29 -0400349 resourceProvider->assignUniqueKeyToProxy(originalKey, proxy.get());
Robert Phillipsd3749482017-03-14 09:17:43 -0400350 // MDB TODO (caching): this has to play nice with the GrSurfaceProxy's caching
Robert Phillipse14d3052017-02-15 13:18:21 -0500351 GrInstallBitmapUniqueKeyInvalidator(originalKey, bitmap.pixelRef());
352 }
353 }
354
Robert Phillipsd3749482017-03-14 09:17:43 -0400355 return proxy;
Robert Phillipse14d3052017-02-15 13:18:21 -0500356}
357
reedc7ec7c92016-07-25 08:29:10 -0700358sk_sp<GrTexture> GrMakeCachedBitmapTexture(GrContext* ctx, const SkBitmap& bitmap,
Robert Phillips67c18d62017-01-20 12:44:06 -0500359 const GrSamplerParams& params, SkScalar scaleAdjust[2]) {
Brian Osman7992da32016-11-18 11:28:24 -0500360 // Caller doesn't care about the texture's color space (they can always get it from the bitmap)
Brian Osman61624f02016-12-09 14:51:59 -0500361 GrTexture* tex = GrBitmapTextureMaker(ctx, bitmap).refTextureForParams(params, nullptr,
Robert Phillips67c18d62017-01-20 12:44:06 -0500362 nullptr, scaleAdjust);
reedc7ec7c92016-07-25 08:29:10 -0700363 return sk_sp<GrTexture>(tex);
364}
365
rileya@google.com24f3ad12012-07-18 21:47:40 +0000366///////////////////////////////////////////////////////////////////////////////
367
Brian Osman72ae4312016-10-20 16:53:45 -0400368GrColor4f SkColorToPremulGrColor4f(SkColor c, SkColorSpace* dstColorSpace) {
369 // We want to premultiply after linearizing, so this is easy:
370 return SkColorToUnpremulGrColor4f(c, dstColorSpace).premul();
371}
372
373GrColor4f SkColorToUnpremulGrColor4f(SkColor c, SkColorSpace* dstColorSpace) {
374 if (dstColorSpace) {
Matt Sarett77a7a1b2017-02-07 13:56:11 -0500375 auto srgbColorSpace = SkColorSpace::MakeSRGB();
Brian Osman72ae4312016-10-20 16:53:45 -0400376 auto gamutXform = GrColorSpaceXform::Make(srgbColorSpace.get(), dstColorSpace);
Brian Osman47299142017-03-07 13:22:22 -0500377 return SkColorToUnpremulGrColor4f(c, dstColorSpace, gamutXform.get());
Brian Osman72ae4312016-10-20 16:53:45 -0400378 } else {
Brian Osman47299142017-03-07 13:22:22 -0500379 return SkColorToUnpremulGrColor4f(c, nullptr, nullptr);
Brian Osman72ae4312016-10-20 16:53:45 -0400380 }
381}
382
Brian Osman47299142017-03-07 13:22:22 -0500383GrColor4f SkColorToPremulGrColor4f(SkColor c, SkColorSpace* dstColorSpace,
384 GrColorSpaceXform* gamutXform) {
Brian Osmanc68d4aa2016-09-30 11:41:59 -0400385 // We want to premultiply after linearizing, so this is easy:
Brian Osman47299142017-03-07 13:22:22 -0500386 return SkColorToUnpremulGrColor4f(c, dstColorSpace, gamutXform).premul();
Brian Osmanc68d4aa2016-09-30 11:41:59 -0400387}
388
Brian Osman47299142017-03-07 13:22:22 -0500389GrColor4f SkColorToUnpremulGrColor4f(SkColor c, SkColorSpace* dstColorSpace,
390 GrColorSpaceXform* gamutXform) {
Brian Osmanc68d4aa2016-09-30 11:41:59 -0400391 // You can't be color-space aware in legacy mode
Brian Osman47299142017-03-07 13:22:22 -0500392 SkASSERT(dstColorSpace || !gamutXform);
Brian Osmanc68d4aa2016-09-30 11:41:59 -0400393
394 GrColor4f color;
Brian Osman47299142017-03-07 13:22:22 -0500395 if (dstColorSpace) {
Brian Osmanc68d4aa2016-09-30 11:41:59 -0400396 // SkColor4f::FromColor does sRGB -> Linear
397 color = GrColor4f::FromSkColor4f(SkColor4f::FromColor(c));
398 } else {
399 // GrColor4f::FromGrColor just multiplies by 1/255
400 color = GrColor4f::FromGrColor(SkColorToUnpremulGrColor(c));
401 }
402
403 if (gamutXform) {
404 color = gamutXform->apply(color);
405 }
406
407 return color;
408}
409
410///////////////////////////////////////////////////////////////////////////////
411
Brian Osman0c2997b2017-01-11 16:58:42 -0500412GrPixelConfig SkImageInfo2GrPixelConfig(const SkImageInfo& info, const GrCaps& caps) {
brianosmana6359362016-03-21 06:55:37 -0700413 // We intentionally ignore profile type for non-8888 formats. Anything we can't support
414 // in hardware will be expanded to sRGB 8888 in GrUploadPixmapToTexture.
Brian Osman0c2997b2017-01-11 16:58:42 -0500415 SkColorSpace* cs = info.colorSpace();
416 switch (info.colorType()) {
brianosmanc571c002016-03-17 13:01:26 -0700417 case kUnknown_SkColorType:
418 return kUnknown_GrPixelConfig;
419 case kAlpha_8_SkColorType:
420 return kAlpha_8_GrPixelConfig;
421 case kRGB_565_SkColorType:
422 return kRGB_565_GrPixelConfig;
423 case kARGB_4444_SkColorType:
424 return kRGBA_4444_GrPixelConfig;
425 case kRGBA_8888_SkColorType:
Brian Osman47299142017-03-07 13:22:22 -0500426 return (caps.srgbSupport() && cs && cs->gammaCloseToSRGB() &&
427 !as_CSB(cs)->nonLinearBlending())
brianosmana6359362016-03-21 06:55:37 -0700428 ? kSRGBA_8888_GrPixelConfig : kRGBA_8888_GrPixelConfig;
brianosmanc571c002016-03-17 13:01:26 -0700429 case kBGRA_8888_SkColorType:
Brian Osman47299142017-03-07 13:22:22 -0500430 return (caps.srgbSupport() && cs && cs->gammaCloseToSRGB() &&
431 !as_CSB(cs)->nonLinearBlending())
brianosmana6359362016-03-21 06:55:37 -0700432 ? kSBGRA_8888_GrPixelConfig : kBGRA_8888_GrPixelConfig;
brianosmanc571c002016-03-17 13:01:26 -0700433 case kIndex_8_SkColorType:
Brian Osmand0be1ef2017-01-11 16:57:15 -0500434 return kSkia8888_GrPixelConfig;
brianosmanc571c002016-03-17 13:01:26 -0700435 case kGray_8_SkColorType:
Brian Osman986563b2017-01-10 14:20:02 -0500436 return kGray_8_GrPixelConfig;
brianosmanc571c002016-03-17 13:01:26 -0700437 case kRGBA_F16_SkColorType:
438 return kRGBA_half_GrPixelConfig;
commit-bot@chromium.org15a14052014-02-16 00:59:25 +0000439 }
440 SkASSERT(0); // shouldn't get here
441 return kUnknown_GrPixelConfig;
442}
443
brianosman396fcdb2016-07-22 06:26:11 -0700444bool GrPixelConfigToColorType(GrPixelConfig config, SkColorType* ctOut) {
reed@google.combf790232013-12-13 19:45:58 +0000445 SkColorType ct;
446 switch (config) {
447 case kAlpha_8_GrPixelConfig:
448 ct = kAlpha_8_SkColorType;
449 break;
Brian Osman986563b2017-01-10 14:20:02 -0500450 case kGray_8_GrPixelConfig:
451 ct = kGray_8_SkColorType;
452 break;
reed@google.combf790232013-12-13 19:45:58 +0000453 case kRGB_565_GrPixelConfig:
454 ct = kRGB_565_SkColorType;
455 break;
456 case kRGBA_4444_GrPixelConfig:
457 ct = kARGB_4444_SkColorType;
458 break;
459 case kRGBA_8888_GrPixelConfig:
460 ct = kRGBA_8888_SkColorType;
461 break;
462 case kBGRA_8888_GrPixelConfig:
463 ct = kBGRA_8888_SkColorType;
464 break;
jvanverthfa1e8a72014-12-22 08:31:49 -0800465 case kSRGBA_8888_GrPixelConfig:
466 ct = kRGBA_8888_SkColorType;
jvanverthfa1e8a72014-12-22 08:31:49 -0800467 break;
brianosmana6359362016-03-21 06:55:37 -0700468 case kSBGRA_8888_GrPixelConfig:
469 ct = kBGRA_8888_SkColorType;
brianosmana6359362016-03-21 06:55:37 -0700470 break;
brianosman9ac5b912016-04-12 13:49:53 -0700471 case kRGBA_half_GrPixelConfig:
472 ct = kRGBA_F16_SkColorType;
473 break;
reed@google.combf790232013-12-13 19:45:58 +0000474 default:
475 return false;
476 }
477 if (ctOut) {
478 *ctOut = ct;
479 }
480 return true;
481}
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000482
brianosman27a3aa52016-09-23 07:11:34 -0700483GrPixelConfig GrRenderableConfigForColorSpace(const SkColorSpace* colorSpace) {
Brian Osman47299142017-03-07 13:22:22 -0500484 if (!colorSpace || as_CSB(colorSpace)->nonLinearBlending()) {
brianosman2695eaa2016-09-21 06:45:09 -0700485 return kRGBA_8888_GrPixelConfig;
486 } else if (colorSpace->gammaIsLinear()) {
487 return kRGBA_half_GrPixelConfig;
488 } else if (colorSpace->gammaCloseToSRGB()) {
489 return kSRGBA_8888_GrPixelConfig;
490 } else {
491 SkDEBUGFAIL("No renderable config exists for color space with strange gamma");
492 return kUnknown_GrPixelConfig;
493 }
494}
495
bsalomonf1b7a1d2015-09-28 06:26:28 -0700496////////////////////////////////////////////////////////////////////////////////////////////////
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000497
Mike Reed7d954ad2016-10-28 15:42:34 -0400498static inline bool blend_requires_shader(const SkBlendMode mode, bool primitiveIsSrc) {
bsalomonaa48d362015-10-01 08:34:17 -0700499 if (primitiveIsSrc) {
Mike Reed7d954ad2016-10-28 15:42:34 -0400500 return SkBlendMode::kSrc != mode;
bsalomonaa48d362015-10-01 08:34:17 -0700501 } else {
Mike Reed7d954ad2016-10-28 15:42:34 -0400502 return SkBlendMode::kDst != mode;
bsalomonaa48d362015-10-01 08:34:17 -0700503 }
504}
505
bsalomonf1b7a1d2015-09-28 06:26:28 -0700506static inline bool skpaint_to_grpaint_impl(GrContext* context,
Brian Osman11052242016-10-27 14:47:55 -0400507 GrRenderTargetContext* rtc,
bsalomonf1b7a1d2015-09-28 06:26:28 -0700508 const SkPaint& skPaint,
509 const SkMatrix& viewM,
bungeman06ca8ec2016-06-09 08:01:03 -0700510 sk_sp<GrFragmentProcessor>* shaderProcessor,
Mike Reed7d954ad2016-10-28 15:42:34 -0400511 SkBlendMode* primColorMode,
bsalomonf1b7a1d2015-09-28 06:26:28 -0700512 bool primitiveIsSrc,
513 GrPaint* grPaint) {
Brian Osman11052242016-10-27 14:47:55 -0400514 grPaint->setAllowSRGBInputs(rtc->isGammaCorrect());
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000515
Brian Osmanc68d4aa2016-09-30 11:41:59 -0400516 // Convert SkPaint color to 4f format, including optional linearizing and gamut conversion.
Brian Osman47299142017-03-07 13:22:22 -0500517 GrColor4f origColor = SkColorToUnpremulGrColor4f(skPaint.getColor(), rtc->getColorSpace(),
Brian Osman11052242016-10-27 14:47:55 -0400518 rtc->getColorXformFromSRGB());
brianosmana4535a32016-06-24 12:50:19 -0700519
bsalomonf1b7a1d2015-09-28 06:26:28 -0700520 // Setup the initial color considering the shader, the SkPaint color, and the presence or not
521 // of per-vertex colors.
bungeman06ca8ec2016-06-09 08:01:03 -0700522 sk_sp<GrFragmentProcessor> shaderFP;
bsalomonaa48d362015-10-01 08:34:17 -0700523 if (!primColorMode || blend_requires_shader(*primColorMode, primitiveIsSrc)) {
524 if (shaderProcessor) {
525 shaderFP = *shaderProcessor;
526 } else if (const SkShader* shader = skPaint.getShader()) {
brianosman839345d2016-07-22 11:04:53 -0700527 shaderFP = shader->asFragmentProcessor(SkShader::AsFPArgs(context, &viewM, nullptr,
528 skPaint.getFilterQuality(),
Brian Osman61624f02016-12-09 14:51:59 -0500529 rtc->getColorSpace()));
bsalomonaa48d362015-10-01 08:34:17 -0700530 if (!shaderFP) {
531 return false;
532 }
bsalomonf1b7a1d2015-09-28 06:26:28 -0700533 }
534 }
535
536 // Set this in below cases if the output of the shader/paint-color/paint-alpha/primXfermode is
537 // a known constant value. In that case we can simply apply a color filter during this
538 // conversion without converting the color filter to a GrFragmentProcessor.
539 bool applyColorFilterToPaintColor = false;
540 if (shaderFP) {
541 if (primColorMode) {
542 // There is a blend between the primitive color and the shader color. The shader sees
543 // the opaque paint color. The shader's output is blended using the provided mode by
544 // the primitive color. The blended color is then modulated by the paint's alpha.
545
546 // The geometry processor will insert the primitive color to start the color chain, so
547 // the GrPaint color will be ignored.
548
brianosman4cea3b92016-09-08 09:33:50 -0700549 GrColor4f shaderInput = origColor.opaque();
bsalomonf1b7a1d2015-09-28 06:26:28 -0700550 shaderFP = GrFragmentProcessor::OverrideInput(shaderFP, shaderInput);
bsalomonf1b7a1d2015-09-28 06:26:28 -0700551 if (primitiveIsSrc) {
bungeman06ca8ec2016-06-09 08:01:03 -0700552 shaderFP = GrXfermodeFragmentProcessor::MakeFromDstProcessor(std::move(shaderFP),
553 *primColorMode);
bsalomonf1b7a1d2015-09-28 06:26:28 -0700554 } else {
bungeman06ca8ec2016-06-09 08:01:03 -0700555 shaderFP = GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(shaderFP),
556 *primColorMode);
bsalomonf1b7a1d2015-09-28 06:26:28 -0700557 }
bsalomonf1b7a1d2015-09-28 06:26:28 -0700558 // The above may return null if compose results in a pass through of the prim color.
559 if (shaderFP) {
560 grPaint->addColorFragmentProcessor(shaderFP);
561 }
562
brianosmana4535a32016-06-24 12:50:19 -0700563 // We can ignore origColor here - alpha is unchanged by gamma
bsalomonf1b7a1d2015-09-28 06:26:28 -0700564 GrColor paintAlpha = SkColorAlphaToGrColor(skPaint.getColor());
565 if (GrColor_WHITE != paintAlpha) {
Brian Osman618d3042016-10-25 10:51:28 -0400566 // No gamut conversion - paintAlpha is a (linear) alpha value, splatted to all
567 // color channels. It's value should be treated as the same in ANY color space.
bungeman06ca8ec2016-06-09 08:01:03 -0700568 grPaint->addColorFragmentProcessor(GrConstColorProcessor::Make(
Brian Osman618d3042016-10-25 10:51:28 -0400569 GrColor4f::FromGrColor(paintAlpha),
570 GrConstColorProcessor::kModulateRGBA_InputMode));
bsalomonf1b7a1d2015-09-28 06:26:28 -0700571 }
572 } else {
573 // The shader's FP sees the paint unpremul color
brianosmana4535a32016-06-24 12:50:19 -0700574 grPaint->setColor4f(origColor);
bungeman06ca8ec2016-06-09 08:01:03 -0700575 grPaint->addColorFragmentProcessor(std::move(shaderFP));
bsalomonf1b7a1d2015-09-28 06:26:28 -0700576 }
577 } else {
578 if (primColorMode) {
579 // There is a blend between the primitive color and the paint color. The blend considers
580 // the opaque paint color. The paint's alpha is applied to the post-blended color.
bungeman06ca8ec2016-06-09 08:01:03 -0700581 sk_sp<GrFragmentProcessor> processor(
Brian Osman618d3042016-10-25 10:51:28 -0400582 GrConstColorProcessor::Make(origColor.opaque(),
583 GrConstColorProcessor::kIgnore_InputMode));
bsalomonf1b7a1d2015-09-28 06:26:28 -0700584 if (primitiveIsSrc) {
bungeman06ca8ec2016-06-09 08:01:03 -0700585 processor = GrXfermodeFragmentProcessor::MakeFromDstProcessor(std::move(processor),
586 *primColorMode);
bsalomonf1b7a1d2015-09-28 06:26:28 -0700587 } else {
bungeman06ca8ec2016-06-09 08:01:03 -0700588 processor = GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(processor),
589 *primColorMode);
bsalomonf1b7a1d2015-09-28 06:26:28 -0700590 }
591 if (processor) {
bungeman06ca8ec2016-06-09 08:01:03 -0700592 grPaint->addColorFragmentProcessor(std::move(processor));
bsalomonf1b7a1d2015-09-28 06:26:28 -0700593 }
594
brianosmana4535a32016-06-24 12:50:19 -0700595 grPaint->setColor4f(origColor.opaque());
bsalomonf1b7a1d2015-09-28 06:26:28 -0700596
brianosmana4535a32016-06-24 12:50:19 -0700597 // We can ignore origColor here - alpha is unchanged by gamma
bsalomonf1b7a1d2015-09-28 06:26:28 -0700598 GrColor paintAlpha = SkColorAlphaToGrColor(skPaint.getColor());
bsalomonaa48d362015-10-01 08:34:17 -0700599 if (GrColor_WHITE != paintAlpha) {
Brian Osman618d3042016-10-25 10:51:28 -0400600 // No gamut conversion - paintAlpha is a (linear) alpha value, splatted to all
601 // color channels. It's value should be treated as the same in ANY color space.
bungeman06ca8ec2016-06-09 08:01:03 -0700602 grPaint->addColorFragmentProcessor(GrConstColorProcessor::Make(
Brian Osman618d3042016-10-25 10:51:28 -0400603 GrColor4f::FromGrColor(paintAlpha),
604 GrConstColorProcessor::kModulateRGBA_InputMode));
bsalomonaa48d362015-10-01 08:34:17 -0700605 }
bsalomonf1b7a1d2015-09-28 06:26:28 -0700606 } else {
607 // No shader, no primitive color.
brianosmana4535a32016-06-24 12:50:19 -0700608 grPaint->setColor4f(origColor.premul());
bsalomonf1b7a1d2015-09-28 06:26:28 -0700609 applyColorFilterToPaintColor = true;
610 }
611 }
612
613 SkColorFilter* colorFilter = skPaint.getColorFilter();
614 if (colorFilter) {
615 if (applyColorFilterToPaintColor) {
Brian Osman8bf4e672016-10-17 16:54:49 -0400616 // If we're in legacy mode, we *must* avoid using the 4f version of the color filter,
617 // because that will combine with the linearized version of the stored color.
Brian Osman11052242016-10-27 14:47:55 -0400618 if (rtc->isGammaCorrect()) {
Brian Osman8bf4e672016-10-17 16:54:49 -0400619 grPaint->setColor4f(GrColor4f::FromSkColor4f(
620 colorFilter->filterColor4f(origColor.toSkColor4f())).premul());
621 } else {
622 grPaint->setColor4f(SkColorToPremulGrColor4f(
Brian Osman47299142017-03-07 13:22:22 -0500623 colorFilter->filterColor(skPaint.getColor()), nullptr, nullptr));
Brian Osman8bf4e672016-10-17 16:54:49 -0400624 }
bsalomonf1b7a1d2015-09-28 06:26:28 -0700625 } else {
Brian Osman618d3042016-10-25 10:51:28 -0400626 sk_sp<GrFragmentProcessor> cfFP(colorFilter->asFragmentProcessor(context,
Brian Osman11052242016-10-27 14:47:55 -0400627 rtc->getColorSpace()));
bsalomone25eea42015-09-29 06:38:55 -0700628 if (cfFP) {
bungeman06ca8ec2016-06-09 08:01:03 -0700629 grPaint->addColorFragmentProcessor(std::move(cfFP));
bsalomonf1b7a1d2015-09-28 06:26:28 -0700630 } else {
631 return false;
632 }
633 }
634 }
635
Robert Phillipsa29a9562016-10-20 09:40:55 -0400636 SkMaskFilter* maskFilter = skPaint.getMaskFilter();
637 if (maskFilter) {
638 GrFragmentProcessor* mfFP;
639 if (maskFilter->asFragmentProcessor(&mfFP, nullptr, viewM)) {
640 grPaint->addCoverageFragmentProcessor(sk_sp<GrFragmentProcessor>(mfFP));
641 }
642 }
643
robertphillips4f037942016-02-09 05:09:27 -0800644 // When the xfermode is null on the SkPaint (meaning kSrcOver) we need the XPFactory field on
645 // the GrPaint to also be null (also kSrcOver).
646 SkASSERT(!grPaint->getXPFactory());
reed374772b2016-10-05 17:33:02 -0700647 if (!skPaint.isSrcOver()) {
648 grPaint->setXPFactory(SkBlendMode_AsXPFactory(skPaint.getBlendMode()));
robertphillips4f037942016-02-09 05:09:27 -0800649 }
mtklein775b8192014-12-02 09:11:25 -0800650
krajcevskif461a8f2014-06-19 14:14:06 -0700651#ifndef SK_IGNORE_GPU_DITHER
Brian Osman11052242016-10-27 14:47:55 -0400652 if (skPaint.isDither() && grPaint->numColorFragmentProcessors() > 0 && !rtc->isGammaCorrect()) {
bungeman06ca8ec2016-06-09 08:01:03 -0700653 grPaint->addColorFragmentProcessor(GrDitherEffect::Make());
krajcevskif461a8f2014-06-19 14:14:06 -0700654 }
655#endif
bsalomonbed83a62015-04-15 14:18:34 -0700656 return true;
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000657}
658
Brian Osman11052242016-10-27 14:47:55 -0400659bool SkPaintToGrPaint(GrContext* context, GrRenderTargetContext* rtc, const SkPaint& skPaint,
brianosman8fe485b2016-07-25 12:31:51 -0700660 const SkMatrix& viewM, GrPaint* grPaint) {
Brian Osman11052242016-10-27 14:47:55 -0400661 return skpaint_to_grpaint_impl(context, rtc, skPaint, viewM, nullptr, nullptr, false, grPaint);
bsalomonf1b7a1d2015-09-28 06:26:28 -0700662}
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000663
bsalomonf1b7a1d2015-09-28 06:26:28 -0700664/** Replaces the SkShader (if any) on skPaint with the passed in GrFragmentProcessor. */
665bool SkPaintToGrPaintReplaceShader(GrContext* context,
Brian Osman11052242016-10-27 14:47:55 -0400666 GrRenderTargetContext* rtc,
bsalomonf1b7a1d2015-09-28 06:26:28 -0700667 const SkPaint& skPaint,
bungeman06ca8ec2016-06-09 08:01:03 -0700668 sk_sp<GrFragmentProcessor> shaderFP,
bsalomonf1b7a1d2015-09-28 06:26:28 -0700669 GrPaint* grPaint) {
670 if (!shaderFP) {
bsalomonc21b09e2015-08-28 18:46:56 -0700671 return false;
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000672 }
Brian Osman11052242016-10-27 14:47:55 -0400673 return skpaint_to_grpaint_impl(context, rtc, skPaint, SkMatrix::I(), &shaderFP, nullptr, false,
brianosman8fe485b2016-07-25 12:31:51 -0700674 grPaint);
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000675}
reed8b26b992015-05-07 15:36:17 -0700676
bsalomonf1b7a1d2015-09-28 06:26:28 -0700677/** Ignores the SkShader (if any) on skPaint. */
678bool SkPaintToGrPaintNoShader(GrContext* context,
Brian Osman11052242016-10-27 14:47:55 -0400679 GrRenderTargetContext* rtc,
bsalomonf1b7a1d2015-09-28 06:26:28 -0700680 const SkPaint& skPaint,
681 GrPaint* grPaint) {
682 // Use a ptr to a nullptr to to indicate that the SkShader is ignored and not replaced.
bungeman06ca8ec2016-06-09 08:01:03 -0700683 static sk_sp<GrFragmentProcessor> kNullShaderFP(nullptr);
684 static sk_sp<GrFragmentProcessor>* kIgnoreShader = &kNullShaderFP;
Brian Osman11052242016-10-27 14:47:55 -0400685 return skpaint_to_grpaint_impl(context, rtc, skPaint, SkMatrix::I(), kIgnoreShader, nullptr,
brianosman8fe485b2016-07-25 12:31:51 -0700686 false, grPaint);
bsalomonf1b7a1d2015-09-28 06:26:28 -0700687}
688
689/** Blends the SkPaint's shader (or color if no shader) with a per-primitive color which must
Mike Reed7d954ad2016-10-28 15:42:34 -0400690be setup as a vertex attribute using the specified SkBlendMode. */
bsalomonf1b7a1d2015-09-28 06:26:28 -0700691bool SkPaintToGrPaintWithXfermode(GrContext* context,
Brian Osman11052242016-10-27 14:47:55 -0400692 GrRenderTargetContext* rtc,
bsalomonf1b7a1d2015-09-28 06:26:28 -0700693 const SkPaint& skPaint,
694 const SkMatrix& viewM,
Mike Reed7d954ad2016-10-28 15:42:34 -0400695 SkBlendMode primColorMode,
bsalomonf1b7a1d2015-09-28 06:26:28 -0700696 bool primitiveIsSrc,
697 GrPaint* grPaint) {
Brian Osman11052242016-10-27 14:47:55 -0400698 return skpaint_to_grpaint_impl(context, rtc, skPaint, viewM, nullptr, &primColorMode,
brianosman8fe485b2016-07-25 12:31:51 -0700699 primitiveIsSrc, grPaint);
bsalomonf1b7a1d2015-09-28 06:26:28 -0700700}
701
joshualitt33a5fce2015-11-18 13:28:51 -0800702bool SkPaintToGrPaintWithTexture(GrContext* context,
Brian Osman11052242016-10-27 14:47:55 -0400703 GrRenderTargetContext* rtc,
joshualitt33a5fce2015-11-18 13:28:51 -0800704 const SkPaint& paint,
705 const SkMatrix& viewM,
bungeman06ca8ec2016-06-09 08:01:03 -0700706 sk_sp<GrFragmentProcessor> fp,
joshualitt33a5fce2015-11-18 13:28:51 -0800707 bool textureIsAlphaOnly,
708 GrPaint* grPaint) {
bungeman06ca8ec2016-06-09 08:01:03 -0700709 sk_sp<GrFragmentProcessor> shaderFP;
joshualitt33a5fce2015-11-18 13:28:51 -0800710 if (textureIsAlphaOnly) {
711 if (const SkShader* shader = paint.getShader()) {
brianosman839345d2016-07-22 11:04:53 -0700712 shaderFP = shader->asFragmentProcessor(SkShader::AsFPArgs(context,
713 &viewM,
714 nullptr,
715 paint.getFilterQuality(),
Brian Osman61624f02016-12-09 14:51:59 -0500716 rtc->getColorSpace()));
joshualitt33a5fce2015-11-18 13:28:51 -0800717 if (!shaderFP) {
718 return false;
719 }
bungeman06ca8ec2016-06-09 08:01:03 -0700720 sk_sp<GrFragmentProcessor> fpSeries[] = { std::move(shaderFP), std::move(fp) };
721 shaderFP = GrFragmentProcessor::RunInSeries(fpSeries, 2);
joshualitt33a5fce2015-11-18 13:28:51 -0800722 } else {
Brian Salomon22af73f2017-01-26 11:25:12 -0500723 shaderFP = GrFragmentProcessor::MakeInputPremulAndMulByOutput(fp);
joshualitt33a5fce2015-11-18 13:28:51 -0800724 }
725 } else {
bungeman06ca8ec2016-06-09 08:01:03 -0700726 shaderFP = GrFragmentProcessor::MulOutputByInputAlpha(fp);
joshualitt33a5fce2015-11-18 13:28:51 -0800727 }
728
Brian Osman11052242016-10-27 14:47:55 -0400729 return SkPaintToGrPaintReplaceShader(context, rtc, paint, std::move(shaderFP), grPaint);
joshualitt33a5fce2015-11-18 13:28:51 -0800730}
731
bsalomonf1b7a1d2015-09-28 06:26:28 -0700732
733////////////////////////////////////////////////////////////////////////////////////////////////
734
Brian Salomon514baff2016-11-17 15:17:07 -0500735GrSamplerParams::FilterMode GrSkFilterQualityToGrFilterMode(SkFilterQuality paintFilterQuality,
joshualitt9bc39542015-08-12 12:57:54 -0700736 const SkMatrix& viewM,
737 const SkMatrix& localM,
738 bool* doBicubic) {
739 *doBicubic = false;
Brian Salomon514baff2016-11-17 15:17:07 -0500740 GrSamplerParams::FilterMode textureFilterMode;
joshualitt9bc39542015-08-12 12:57:54 -0700741 switch (paintFilterQuality) {
742 case kNone_SkFilterQuality:
Brian Salomon514baff2016-11-17 15:17:07 -0500743 textureFilterMode = GrSamplerParams::kNone_FilterMode;
joshualitt9bc39542015-08-12 12:57:54 -0700744 break;
745 case kLow_SkFilterQuality:
Brian Salomon514baff2016-11-17 15:17:07 -0500746 textureFilterMode = GrSamplerParams::kBilerp_FilterMode;
joshualitt9bc39542015-08-12 12:57:54 -0700747 break;
748 case kMedium_SkFilterQuality: {
749 SkMatrix matrix;
750 matrix.setConcat(viewM, localM);
751 if (matrix.getMinScale() < SK_Scalar1) {
Brian Salomon514baff2016-11-17 15:17:07 -0500752 textureFilterMode = GrSamplerParams::kMipMap_FilterMode;
joshualitt9bc39542015-08-12 12:57:54 -0700753 } else {
754 // Don't trigger MIP level generation unnecessarily.
Brian Salomon514baff2016-11-17 15:17:07 -0500755 textureFilterMode = GrSamplerParams::kBilerp_FilterMode;
joshualitt9bc39542015-08-12 12:57:54 -0700756 }
757 break;
758 }
759 case kHigh_SkFilterQuality: {
760 SkMatrix matrix;
761 matrix.setConcat(viewM, localM);
762 *doBicubic = GrBicubicEffect::ShouldUseBicubic(matrix, &textureFilterMode);
763 break;
764 }
765 default:
Mike Kleine54c75f2016-10-13 14:18:09 -0400766 // Should be unreachable. If not, fall back to mipmaps.
Brian Salomon514baff2016-11-17 15:17:07 -0500767 textureFilterMode = GrSamplerParams::kMipMap_FilterMode;
joshualitt9bc39542015-08-12 12:57:54 -0700768 break;
769
770 }
771 return textureFilterMode;
772}