blob: e26de49e363f3b7f2adc6d0c8ac553b75273764e [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"
Greg Daniel55afd6d2017-09-29 09:32:44 -040013#include "GrContextPriv.h"
bsalomon045802d2015-10-20 07:58:01 -070014#include "GrGpuResourcePriv.h"
Brian Osman3b66ab62016-11-28 09:26:31 -050015#include "GrRenderTargetContext.h"
Brian Osman32342f02017-03-04 08:12:46 -050016#include "GrResourceProvider.h"
Hal Canary6f6961e2017-01-31 13:50:44 -050017#include "GrTextureProxy.h"
cblume55f2d2d2016-02-26 13:20:48 -080018#include "GrTypes.h"
egdaniel378092f2014-12-03 10:40:13 -080019#include "GrXferProcessor.h"
reed43fe6182015-09-08 08:37:36 -070020
Hal Canary95e3c052017-01-11 12:44:43 -050021#include "SkAutoMalloc.h"
reed374772b2016-10-05 17:33:02 -070022#include "SkBlendModePriv.h"
Hal Canary95e3c052017-01-11 12:44:43 -050023#include "SkCanvas.h"
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +000024#include "SkColorFilter.h"
Matt Sarett485c4992017-02-14 14:18:27 -050025#include "SkConvertPixels.h"
krajcevski9c0e6292014-06-02 07:38:14 -070026#include "SkData.h"
Brian Osman4075ec82017-01-17 16:41:03 +000027#include "SkImageInfoPriv.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"
Kevin Lubickc456b732017-01-11 17:21:57 +000031#include "SkPM4fPriv.h"
Florin Malitad4a70ee2017-06-19 10:21:43 -040032#include "SkPaintPriv.h"
Hal Canary95e3c052017-01-11 12:44:43 -050033#include "SkPixelRef.h"
sugoi692135f2015-01-19 10:10:27 -080034#include "SkResourceCache.h"
Florin Malita4aed1382017-05-25 10:38:07 -040035#include "SkShaderBase.h"
cblume55f2d2d2016-02-26 13:20:48 -080036#include "SkTemplates.h"
Derek Sollenberger559f5342017-08-17 12:34:54 -040037#include "SkTraceEvent.h"
joshualitt9bc39542015-08-12 12:57:54 -070038#include "effects/GrBicubicEffect.h"
bsalomonf1b7a1d2015-09-28 06:26:28 -070039#include "effects/GrConstColorProcessor.h"
krajcevskif461a8f2014-06-19 14:14:06 -070040#include "effects/GrDitherEffect.h"
egdaniel378092f2014-12-03 10:40:13 -080041#include "effects/GrPorterDuffXferProcessor.h"
bsalomonf1b7a1d2015-09-28 06:26:28 -070042#include "effects/GrXfermodeFragmentProcessor.h"
krajcevski9c0e6292014-06-02 07:38:14 -070043
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;
Robert Phillips019ff272017-07-24 14:47:57 -040047 desc.fOrigin = kTopLeft_GrSurfaceOrigin;
bsalomon466c2c42015-10-16 12:01:18 -070048 desc.fWidth = info.width();
49 desc.fHeight = info.height();
brianosmana6359362016-03-21 06:55:37 -070050 desc.fConfig = SkImageInfo2GrPixelConfig(info, caps);
bsalomon466c2c42015-10-16 12:01:18 -070051 desc.fSampleCnt = 0;
52 return desc;
53}
54
bsalomon045802d2015-10-20 07:58:01 -070055void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& imageBounds) {
56 SkASSERT(key);
57 SkASSERT(imageID);
58 SkASSERT(!imageBounds.isEmpty());
59 static const GrUniqueKey::Domain kImageIDDomain = GrUniqueKey::GenerateDomain();
60 GrUniqueKey::Builder builder(key, kImageIDDomain, 5);
bsalomon466c2c42015-10-16 12:01:18 -070061 builder[0] = imageID;
bsalomon045802d2015-10-20 07:58:01 -070062 builder[1] = imageBounds.fLeft;
63 builder[2] = imageBounds.fTop;
64 builder[3] = imageBounds.fRight;
65 builder[4] = imageBounds.fBottom;
bsalomon466c2c42015-10-16 12:01:18 -070066}
67
bsalomon045802d2015-10-20 07:58:01 -070068//////////////////////////////////////////////////////////////////////////////
Robert Phillips26c90e02017-03-14 14:39:29 -040069sk_sp<GrTextureProxy> GrUploadBitmapToTextureProxy(GrResourceProvider* resourceProvider,
Matt Sarettdedac852017-05-12 10:56:49 -040070 const SkBitmap& bitmap,
71 SkColorSpace* dstColorSpace) {
Robert Phillipsd3749482017-03-14 09:17:43 -040072 if (!bitmap.readyToDraw()) {
Brian Osman4075ec82017-01-17 16:41:03 +000073 return nullptr;
74 }
Robert Phillipsd3749482017-03-14 09:17:43 -040075 SkPixmap pixmap;
76 if (!bitmap.peekPixels(&pixmap)) {
77 return nullptr;
78 }
Matt Sarettdedac852017-05-12 10:56:49 -040079 return GrUploadPixmapToTextureProxy(resourceProvider, pixmap, SkBudgeted::kYes, dstColorSpace);
Robert Phillipsd3749482017-03-14 09:17:43 -040080}
Brian Osman4075ec82017-01-17 16:41:03 +000081
Robert Phillipsd3749482017-03-14 09:17:43 -040082static const SkPixmap* compute_desc(const GrCaps& caps, const SkPixmap& pixmap,
83 GrSurfaceDesc* desc,
84 SkBitmap* tmpBitmap, SkPixmap* tmpPixmap) {
85 const SkPixmap* pmap = &pixmap;
86
87 *desc = GrImageInfoToSurfaceDesc(pixmap.info(), caps);
bsalomon@google.com5782d712011-01-21 21:03:59 +000088
Brian Osmand0be1ef2017-01-11 16:57:15 -050089 // TODO: We're checking for srgbSupport, but we can then end up picking sBGRA as our pixel
90 // config (which may not be supported). We need better fallback management here.
Brian Osman47299142017-03-07 13:22:22 -050091 SkColorSpace* colorSpace = pixmap.colorSpace();
Brian Osmand0be1ef2017-01-11 16:57:15 -050092
Robert Phillipsd3749482017-03-14 09:17:43 -040093 if (caps.srgbSupport() &&
Matt Sarettf3880932017-03-24 10:06:03 -040094 colorSpace && colorSpace->gammaCloseToSRGB() && !GrPixelConfigIsSRGB(desc->fConfig)) {
brianosmanb109b8c2016-06-16 13:03:24 -070095 // We were supplied an sRGB-like color space, but we don't have a suitable pixel config.
brianosmana6359362016-03-21 06:55:37 -070096 // Convert to 8888 sRGB so we can handle the data correctly. The raster backend doesn't
97 // handle sRGB Index8 -> sRGB 8888 correctly (yet), so lie about both the source and
98 // destination (claim they're linear):
99 SkImageInfo linSrcInfo = SkImageInfo::Make(pixmap.width(), pixmap.height(),
100 pixmap.colorType(), pixmap.alphaType());
Mike Reed086a4272017-07-18 10:53:11 -0400101 SkPixmap linSrcPixmap(linSrcInfo, pixmap.addr(), pixmap.rowBytes());
brianosmana6359362016-03-21 06:55:37 -0700102
brianosmanb109b8c2016-06-16 13:03:24 -0700103 SkImageInfo dstInfo = SkImageInfo::Make(pixmap.width(), pixmap.height(),
104 kN32_SkColorType, kPremul_SkAlphaType,
Robert Phillips70b49fd2017-01-13 11:21:36 -0500105 pixmap.info().refColorSpace());
brianosmanb109b8c2016-06-16 13:03:24 -0700106
Robert Phillipsd3749482017-03-14 09:17:43 -0400107 tmpBitmap->allocPixels(dstInfo);
brianosmana6359362016-03-21 06:55:37 -0700108
109 SkImageInfo linDstInfo = SkImageInfo::MakeN32Premul(pixmap.width(), pixmap.height());
Robert Phillipsd3749482017-03-14 09:17:43 -0400110 if (!linSrcPixmap.readPixels(linDstInfo, tmpBitmap->getPixels(), tmpBitmap->rowBytes())) {
brianosmana6359362016-03-21 06:55:37 -0700111 return nullptr;
112 }
Robert Phillipsd3749482017-03-14 09:17:43 -0400113 if (!tmpBitmap->peekPixels(tmpPixmap)) {
brianosmana6359362016-03-21 06:55:37 -0700114 return nullptr;
115 }
Robert Phillipsd3749482017-03-14 09:17:43 -0400116 pmap = tmpPixmap;
brianosmana6359362016-03-21 06:55:37 -0700117 // must rebuild desc, since we've forced the info to be N32
Robert Phillipsd3749482017-03-14 09:17:43 -0400118 *desc = GrImageInfoToSurfaceDesc(pmap->info(), caps);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000119 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000120
Robert Phillipsd3749482017-03-14 09:17:43 -0400121 return pmap;
bsalomon37f9a262015-02-02 13:00:10 -0800122}
123
Matt Sarettdedac852017-05-12 10:56:49 -0400124sk_sp<GrTextureProxy> GrUploadPixmapToTextureProxy(GrResourceProvider* resourceProvider,
125 const SkPixmap& pixmap,
126 SkBudgeted budgeted,
127 SkColorSpace* dstColorSpace) {
128 SkDestinationSurfaceColorMode colorMode = dstColorSpace
129 ? SkDestinationSurfaceColorMode::kGammaAndColorSpaceAware
130 : SkDestinationSurfaceColorMode::kLegacy;
131
132 if (!SkImageInfoIsValid(pixmap.info(), colorMode)) {
133 return nullptr;
134 }
135
Robert Phillipsd3749482017-03-14 09:17:43 -0400136 SkBitmap tmpBitmap;
137 SkPixmap tmpPixmap;
138 GrSurfaceDesc desc;
139
Derek Sollenberger559f5342017-08-17 12:34:54 -0400140 ATRACE_ANDROID_FRAMEWORK("Upload Texture [%ux%u]", pixmap.width(), pixmap.height());
Robert Phillips26c90e02017-03-14 14:39:29 -0400141 if (const SkPixmap* pmap = compute_desc(*resourceProvider->caps(), pixmap, &desc,
142 &tmpBitmap, &tmpPixmap)) {
143 return GrSurfaceProxy::MakeDeferred(resourceProvider, desc,
Robert Phillipsd3749482017-03-14 09:17:43 -0400144 budgeted, pmap->addr(), pmap->rowBytes());
145 }
146
147 return nullptr;
148}
bsalomonb4d40ef2015-07-15 10:12:16 -0700149
bsalomon045802d2015-10-20 07:58:01 -0700150////////////////////////////////////////////////////////////////////////////////
151
bsalomonc55271f2015-11-09 11:55:57 -0800152void GrInstallBitmapUniqueKeyInvalidator(const GrUniqueKey& key, SkPixelRef* pixelRef) {
bsalomon89fe56b2015-10-29 10:49:28 -0700153 class Invalidator : public SkPixelRef::GenIDChangeListener {
154 public:
155 explicit Invalidator(const GrUniqueKey& key) : fMsg(key) {}
156 private:
157 GrUniqueKeyInvalidatedMessage fMsg;
158
159 void onChange() override { SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(fMsg); }
160 };
161
162 pixelRef->addGenIDChangeListener(new Invalidator(key));
163}
164
Robert Phillips78075802017-03-23 11:11:59 -0400165sk_sp<GrTextureProxy> GrGenerateMipMapsAndUploadToTextureProxy(GrContext* ctx,
166 const SkBitmap& bitmap,
167 SkColorSpace* dstColorSpace) {
Brian Osman61624f02016-12-09 14:51:59 -0500168 SkDestinationSurfaceColorMode colorMode = dstColorSpace
169 ? SkDestinationSurfaceColorMode::kGammaAndColorSpaceAware
170 : SkDestinationSurfaceColorMode::kLegacy;
171
Matt Sarettdedac852017-05-12 10:56:49 -0400172 if (!SkImageInfoIsValid(bitmap.info(), colorMode)) {
Brian Osman4075ec82017-01-17 16:41:03 +0000173 return nullptr;
174 }
175
Mike Reed4edb5d22017-04-17 11:02:51 -0400176 SkPixmap pixmap;
177 if (!bitmap.peekPixels(&pixmap)) {
cblume55f2d2d2016-02-26 13:20:48 -0800178 return nullptr;
179 }
cblume55f2d2d2016-02-26 13:20:48 -0800180
Greg Danielfaa53292017-09-07 16:17:24 -0400181 SkBitmap tmpBitmap;
182 SkPixmap tmpPixmap;
183 GrSurfaceDesc desc;
184 const SkPixmap* pmap = compute_desc(*ctx->resourceProvider()->caps(), pixmap, &desc,
185 &tmpBitmap, &tmpPixmap);
186 if (!pmap) {
187 return nullptr;
188 }
189
190 ATRACE_ANDROID_FRAMEWORK("Upload MipMap Texture [%ux%u]", pmap->width(), pmap->height());
191 std::unique_ptr<SkMipMap> mipmaps(SkMipMap::Build(*pmap, colorMode, nullptr));
cblume55f2d2d2016-02-26 13:20:48 -0800192 if (!mipmaps) {
193 return nullptr;
194 }
195
196 const int mipLevelCount = mipmaps->countLevels() + 1;
197 if (mipLevelCount < 1) {
198 return nullptr;
199 }
200
Ben Wagner7ecc5962016-11-02 17:07:33 -0400201 std::unique_ptr<GrMipLevel[]> texels(new GrMipLevel[mipLevelCount]);
cblume55f2d2d2016-02-26 13:20:48 -0800202
Greg Danielfaa53292017-09-07 16:17:24 -0400203 texels[0].fPixels = pmap->addr();
204 texels[0].fRowBytes = pmap->rowBytes();
cblume55f2d2d2016-02-26 13:20:48 -0800205
206 for (int i = 1; i < mipLevelCount; ++i) {
207 SkMipMap::Level generatedMipLevel;
208 mipmaps->getLevel(i - 1, &generatedMipLevel);
209 texels[i].fPixels = generatedMipLevel.fPixmap.addr();
210 texels[i].fRowBytes = generatedMipLevel.fPixmap.rowBytes();
211 }
212
Robert Phillips8e8c7552017-07-10 12:06:05 -0400213 return GrSurfaceProxy::MakeDeferredMipMap(ctx->resourceProvider(),
214 desc,
215 SkBudgeted::kYes,
216 texels.get(),
217 mipLevelCount,
218 colorMode);
Robert Phillips0c984a02017-03-16 07:51:56 -0400219}
220
Greg Daniel55afd6d2017-09-29 09:32:44 -0400221sk_sp<GrTextureProxy> GrCopyBaseMipMapToTextureProxy(GrContext* ctx,
222 GrTextureProxy* baseProxy,
223 SkColorSpace* dstColorSpace) {
224 SkASSERT(baseProxy);
225
226 SkDestinationSurfaceColorMode colorMode = dstColorSpace
227 ? SkDestinationSurfaceColorMode::kGammaAndColorSpaceAware
228 : SkDestinationSurfaceColorMode::kLegacy;
229
230 // SkMipMap doesn't include the base level in the level count so we have to add 1
231 int mipLevelCount = SkMipMap::ComputeLevelCount(baseProxy->width(), baseProxy->height()) + 1;
232
233 std::unique_ptr<GrMipLevel[]> texels(new GrMipLevel[mipLevelCount]);
234
235 // We don't want to upload any texel data
236 for (int i = 0; i < mipLevelCount; i++) {
237 texels[i].fPixels = nullptr;
238 texels[i].fRowBytes = 0;
239 }
240
241 GrSurfaceDesc desc;
242 desc.fFlags = kNone_GrSurfaceFlags;
243 desc.fOrigin = baseProxy->origin();
244 desc.fWidth = baseProxy->width();
245 desc.fHeight = baseProxy->height();
246 desc.fConfig = baseProxy->config();
247 desc.fSampleCnt = 0;
248
249 sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferredMipMap(ctx->resourceProvider(),
250 desc,
251 SkBudgeted::kYes, texels.get(),
252 mipLevelCount, colorMode);
253 if (!proxy) {
254 return nullptr;
255 }
256
257 // Copy the base layer to our proxy
258 sk_sp<GrSurfaceContext> sContext = ctx->contextPriv().makeWrappedSurfaceContext(proxy, nullptr);
259 SkASSERT(sContext);
260 SkAssertResult(sContext->copy(baseProxy));
261
262 return proxy;
263}
264
265
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400266sk_sp<GrTextureProxy> GrUploadMipMapToTextureProxy(GrContext* ctx, const SkImageInfo& info,
Robert Phillips590533f2017-07-11 14:22:35 -0400267 const GrMipLevel texels[],
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400268 int mipLevelCount,
269 SkDestinationSurfaceColorMode colorMode) {
Matt Sarettdedac852017-05-12 10:56:49 -0400270 if (!SkImageInfoIsValid(info, colorMode)) {
Robert Phillips78075802017-03-23 11:11:59 -0400271 return nullptr;
272 }
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400273
Robert Phillips8e8c7552017-07-10 12:06:05 -0400274 return GrSurfaceProxy::MakeDeferredMipMap(ctx->resourceProvider(),
275 GrImageInfoToSurfaceDesc(info, *ctx->caps()),
276 SkBudgeted::kYes, texels,
277 mipLevelCount, colorMode);
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400278}
279
Robert Phillipsbbd7a3b2017-03-21 08:48:40 -0400280sk_sp<GrTextureProxy> GrRefCachedBitmapTextureProxy(GrContext* ctx,
281 const SkBitmap& bitmap,
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400282 const GrSamplerState& params,
Robert Phillipsbbd7a3b2017-03-21 08:48:40 -0400283 SkScalar scaleAdjust[2]) {
284 // Caller doesn't care about the texture's color space (they can always get it from the bitmap)
Robert Phillips3798c862017-03-27 11:08:16 -0400285 return GrBitmapTextureMaker(ctx, bitmap).refTextureProxyForParams(params, nullptr,
286 nullptr, scaleAdjust);
Robert Phillipsbbd7a3b2017-03-21 08:48:40 -0400287}
288
Robert Phillips26c90e02017-03-14 14:39:29 -0400289sk_sp<GrTextureProxy> GrMakeCachedBitmapProxy(GrResourceProvider* resourceProvider,
290 const SkBitmap& bitmap) {
Robert Phillipse14d3052017-02-15 13:18:21 -0500291 GrUniqueKey originalKey;
292
293 if (!bitmap.isVolatile()) {
294 SkIPoint origin = bitmap.pixelRefOrigin();
295 SkIRect subset = SkIRect::MakeXYWH(origin.fX, origin.fY, bitmap.width(), bitmap.height());
296 GrMakeKeyFromImageID(&originalKey, bitmap.pixelRef()->getGenerationID(), subset);
297 }
298
Robert Phillipsd3749482017-03-14 09:17:43 -0400299 sk_sp<GrTextureProxy> proxy;
Robert Phillipse14d3052017-02-15 13:18:21 -0500300
301 if (originalKey.isValid()) {
Greg Danielcd871402017-09-26 12:49:26 -0400302 proxy = resourceProvider->findOrCreateProxyByUniqueKey(originalKey,
303 kTopLeft_GrSurfaceOrigin);
Robert Phillipse14d3052017-02-15 13:18:21 -0500304 }
Robert Phillipsd3749482017-03-14 09:17:43 -0400305 if (!proxy) {
Matt Sarettdedac852017-05-12 10:56:49 -0400306 // Pass nullptr for |dstColorSpace|. This is lenient - we allow a wider range of
307 // color spaces in legacy mode. Unfortunately, we have to be lenient here, since
308 // we can't necessarily know the |dstColorSpace| at this time.
309 proxy = GrUploadBitmapToTextureProxy(resourceProvider, bitmap, nullptr);
Robert Phillipsd3749482017-03-14 09:17:43 -0400310 if (proxy && originalKey.isValid()) {
Robert Phillips019ff272017-07-24 14:47:57 -0400311 SkASSERT(proxy->origin() == kTopLeft_GrSurfaceOrigin);
Robert Phillips26c90e02017-03-14 14:39:29 -0400312 resourceProvider->assignUniqueKeyToProxy(originalKey, proxy.get());
Robert Phillipse14d3052017-02-15 13:18:21 -0500313 GrInstallBitmapUniqueKeyInvalidator(originalKey, bitmap.pixelRef());
314 }
315 }
316
Robert Phillipsd3749482017-03-14 09:17:43 -0400317 return proxy;
Robert Phillipse14d3052017-02-15 13:18:21 -0500318}
319
rileya@google.com24f3ad12012-07-18 21:47:40 +0000320///////////////////////////////////////////////////////////////////////////////
321
Brian Osman72ae4312016-10-20 16:53:45 -0400322GrColor4f SkColorToPremulGrColor4f(SkColor c, SkColorSpace* dstColorSpace) {
323 // We want to premultiply after linearizing, so this is easy:
324 return SkColorToUnpremulGrColor4f(c, dstColorSpace).premul();
325}
326
327GrColor4f SkColorToUnpremulGrColor4f(SkColor c, SkColorSpace* dstColorSpace) {
328 if (dstColorSpace) {
Matt Sarett77a7a1b2017-02-07 13:56:11 -0500329 auto srgbColorSpace = SkColorSpace::MakeSRGB();
Brian Osman72ae4312016-10-20 16:53:45 -0400330 auto gamutXform = GrColorSpaceXform::Make(srgbColorSpace.get(), dstColorSpace);
Brian Osman47299142017-03-07 13:22:22 -0500331 return SkColorToUnpremulGrColor4f(c, dstColorSpace, gamutXform.get());
Brian Osman72ae4312016-10-20 16:53:45 -0400332 } else {
Brian Osman47299142017-03-07 13:22:22 -0500333 return SkColorToUnpremulGrColor4f(c, nullptr, nullptr);
Brian Osman72ae4312016-10-20 16:53:45 -0400334 }
335}
336
Brian Osman47299142017-03-07 13:22:22 -0500337GrColor4f SkColorToPremulGrColor4f(SkColor c, SkColorSpace* dstColorSpace,
338 GrColorSpaceXform* gamutXform) {
Brian Osmanc68d4aa2016-09-30 11:41:59 -0400339 // We want to premultiply after linearizing, so this is easy:
Brian Osman47299142017-03-07 13:22:22 -0500340 return SkColorToUnpremulGrColor4f(c, dstColorSpace, gamutXform).premul();
Brian Osmanc68d4aa2016-09-30 11:41:59 -0400341}
342
Brian Osman47299142017-03-07 13:22:22 -0500343GrColor4f SkColorToUnpremulGrColor4f(SkColor c, SkColorSpace* dstColorSpace,
344 GrColorSpaceXform* gamutXform) {
Brian Osmanc68d4aa2016-09-30 11:41:59 -0400345 // You can't be color-space aware in legacy mode
Brian Osman47299142017-03-07 13:22:22 -0500346 SkASSERT(dstColorSpace || !gamutXform);
Brian Osmanc68d4aa2016-09-30 11:41:59 -0400347
348 GrColor4f color;
Brian Osman47299142017-03-07 13:22:22 -0500349 if (dstColorSpace) {
Brian Osmanc68d4aa2016-09-30 11:41:59 -0400350 // SkColor4f::FromColor does sRGB -> Linear
351 color = GrColor4f::FromSkColor4f(SkColor4f::FromColor(c));
352 } else {
353 // GrColor4f::FromGrColor just multiplies by 1/255
354 color = GrColor4f::FromGrColor(SkColorToUnpremulGrColor(c));
355 }
356
357 if (gamutXform) {
358 color = gamutXform->apply(color);
359 }
360
361 return color;
362}
363
364///////////////////////////////////////////////////////////////////////////////
365
Greg Daniel81e7bf82017-07-19 14:47:42 -0400366GrPixelConfig SkImageInfo2GrPixelConfig(const SkColorType type, SkColorSpace* cs,
367 const GrCaps& caps) {
brianosmana6359362016-03-21 06:55:37 -0700368 // We intentionally ignore profile type for non-8888 formats. Anything we can't support
369 // in hardware will be expanded to sRGB 8888 in GrUploadPixmapToTexture.
Greg Daniel81e7bf82017-07-19 14:47:42 -0400370 switch (type) {
brianosmanc571c002016-03-17 13:01:26 -0700371 case kUnknown_SkColorType:
372 return kUnknown_GrPixelConfig;
373 case kAlpha_8_SkColorType:
374 return kAlpha_8_GrPixelConfig;
375 case kRGB_565_SkColorType:
376 return kRGB_565_GrPixelConfig;
377 case kARGB_4444_SkColorType:
378 return kRGBA_4444_GrPixelConfig;
379 case kRGBA_8888_SkColorType:
Matt Sarettf3880932017-03-24 10:06:03 -0400380 return (caps.srgbSupport() && cs && cs->gammaCloseToSRGB())
brianosmana6359362016-03-21 06:55:37 -0700381 ? kSRGBA_8888_GrPixelConfig : kRGBA_8888_GrPixelConfig;
brianosmanc571c002016-03-17 13:01:26 -0700382 case kBGRA_8888_SkColorType:
Matt Sarettf3880932017-03-24 10:06:03 -0400383 return (caps.srgbSupport() && cs && cs->gammaCloseToSRGB())
brianosmana6359362016-03-21 06:55:37 -0700384 ? kSBGRA_8888_GrPixelConfig : kBGRA_8888_GrPixelConfig;
brianosmanc571c002016-03-17 13:01:26 -0700385 case kGray_8_SkColorType:
Brian Osman986563b2017-01-10 14:20:02 -0500386 return kGray_8_GrPixelConfig;
brianosmanc571c002016-03-17 13:01:26 -0700387 case kRGBA_F16_SkColorType:
388 return kRGBA_half_GrPixelConfig;
commit-bot@chromium.org15a14052014-02-16 00:59:25 +0000389 }
390 SkASSERT(0); // shouldn't get here
391 return kUnknown_GrPixelConfig;
392}
393
Greg Daniel81e7bf82017-07-19 14:47:42 -0400394GrPixelConfig SkImageInfo2GrPixelConfig(const SkImageInfo& info, const GrCaps& caps) {
395 return SkImageInfo2GrPixelConfig(info.colorType(), info.colorSpace(), caps);
396}
397
brianosman396fcdb2016-07-22 06:26:11 -0700398bool GrPixelConfigToColorType(GrPixelConfig config, SkColorType* ctOut) {
reed@google.combf790232013-12-13 19:45:58 +0000399 SkColorType ct;
400 switch (config) {
401 case kAlpha_8_GrPixelConfig:
402 ct = kAlpha_8_SkColorType;
403 break;
Brian Osman986563b2017-01-10 14:20:02 -0500404 case kGray_8_GrPixelConfig:
405 ct = kGray_8_SkColorType;
406 break;
reed@google.combf790232013-12-13 19:45:58 +0000407 case kRGB_565_GrPixelConfig:
408 ct = kRGB_565_SkColorType;
409 break;
410 case kRGBA_4444_GrPixelConfig:
411 ct = kARGB_4444_SkColorType;
412 break;
413 case kRGBA_8888_GrPixelConfig:
414 ct = kRGBA_8888_SkColorType;
415 break;
416 case kBGRA_8888_GrPixelConfig:
417 ct = kBGRA_8888_SkColorType;
418 break;
jvanverthfa1e8a72014-12-22 08:31:49 -0800419 case kSRGBA_8888_GrPixelConfig:
420 ct = kRGBA_8888_SkColorType;
jvanverthfa1e8a72014-12-22 08:31:49 -0800421 break;
brianosmana6359362016-03-21 06:55:37 -0700422 case kSBGRA_8888_GrPixelConfig:
423 ct = kBGRA_8888_SkColorType;
brianosmana6359362016-03-21 06:55:37 -0700424 break;
brianosman9ac5b912016-04-12 13:49:53 -0700425 case kRGBA_half_GrPixelConfig:
426 ct = kRGBA_F16_SkColorType;
427 break;
reed@google.combf790232013-12-13 19:45:58 +0000428 default:
429 return false;
430 }
431 if (ctOut) {
432 *ctOut = ct;
433 }
434 return true;
435}
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000436
brianosman27a3aa52016-09-23 07:11:34 -0700437GrPixelConfig GrRenderableConfigForColorSpace(const SkColorSpace* colorSpace) {
Matt Sarettf3880932017-03-24 10:06:03 -0400438 if (!colorSpace) {
brianosman2695eaa2016-09-21 06:45:09 -0700439 return kRGBA_8888_GrPixelConfig;
440 } else if (colorSpace->gammaIsLinear()) {
441 return kRGBA_half_GrPixelConfig;
442 } else if (colorSpace->gammaCloseToSRGB()) {
443 return kSRGBA_8888_GrPixelConfig;
444 } else {
445 SkDEBUGFAIL("No renderable config exists for color space with strange gamma");
446 return kUnknown_GrPixelConfig;
447 }
448}
449
bsalomonf1b7a1d2015-09-28 06:26:28 -0700450////////////////////////////////////////////////////////////////////////////////////////////////
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000451
Mike Reed185ba212017-04-28 12:31:05 -0400452static inline bool blend_requires_shader(const SkBlendMode mode) {
453 return SkBlendMode::kDst != mode;
bsalomonaa48d362015-10-01 08:34:17 -0700454}
455
bsalomonf1b7a1d2015-09-28 06:26:28 -0700456static inline bool skpaint_to_grpaint_impl(GrContext* context,
Brian Osman11052242016-10-27 14:47:55 -0400457 GrRenderTargetContext* rtc,
bsalomonf1b7a1d2015-09-28 06:26:28 -0700458 const SkPaint& skPaint,
459 const SkMatrix& viewM,
Brian Salomonaff329b2017-08-11 09:40:37 -0400460 std::unique_ptr<GrFragmentProcessor>* shaderProcessor,
Mike Reed7d954ad2016-10-28 15:42:34 -0400461 SkBlendMode* primColorMode,
bsalomonf1b7a1d2015-09-28 06:26:28 -0700462 GrPaint* grPaint) {
Brian Osman11052242016-10-27 14:47:55 -0400463 grPaint->setAllowSRGBInputs(rtc->isGammaCorrect());
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000464
Brian Osmanc68d4aa2016-09-30 11:41:59 -0400465 // Convert SkPaint color to 4f format, including optional linearizing and gamut conversion.
Brian Osman47299142017-03-07 13:22:22 -0500466 GrColor4f origColor = SkColorToUnpremulGrColor4f(skPaint.getColor(), rtc->getColorSpace(),
Brian Osman11052242016-10-27 14:47:55 -0400467 rtc->getColorXformFromSRGB());
brianosmana4535a32016-06-24 12:50:19 -0700468
bsalomonf1b7a1d2015-09-28 06:26:28 -0700469 // Setup the initial color considering the shader, the SkPaint color, and the presence or not
470 // of per-vertex colors.
Brian Salomonaff329b2017-08-11 09:40:37 -0400471 std::unique_ptr<GrFragmentProcessor> shaderFP;
Mike Reed185ba212017-04-28 12:31:05 -0400472 if (!primColorMode || blend_requires_shader(*primColorMode)) {
bsalomonaa48d362015-10-01 08:34:17 -0700473 if (shaderProcessor) {
Brian Salomonaff329b2017-08-11 09:40:37 -0400474 shaderFP = std::move(*shaderProcessor);
Florin Malita4aed1382017-05-25 10:38:07 -0400475 } else if (const auto* shader = as_SB(skPaint.getShader())) {
476 shaderFP = shader->asFragmentProcessor(
477 SkShaderBase::AsFPArgs(context, &viewM, nullptr, skPaint.getFilterQuality(),
478 rtc->getColorSpace()));
bsalomonaa48d362015-10-01 08:34:17 -0700479 if (!shaderFP) {
480 return false;
481 }
bsalomonf1b7a1d2015-09-28 06:26:28 -0700482 }
483 }
484
485 // Set this in below cases if the output of the shader/paint-color/paint-alpha/primXfermode is
486 // a known constant value. In that case we can simply apply a color filter during this
487 // conversion without converting the color filter to a GrFragmentProcessor.
488 bool applyColorFilterToPaintColor = false;
489 if (shaderFP) {
490 if (primColorMode) {
491 // There is a blend between the primitive color and the shader color. The shader sees
492 // the opaque paint color. The shader's output is blended using the provided mode by
493 // the primitive color. The blended color is then modulated by the paint's alpha.
494
495 // The geometry processor will insert the primitive color to start the color chain, so
496 // the GrPaint color will be ignored.
497
brianosman4cea3b92016-09-08 09:33:50 -0700498 GrColor4f shaderInput = origColor.opaque();
Brian Salomonaff329b2017-08-11 09:40:37 -0400499 shaderFP = GrFragmentProcessor::OverrideInput(std::move(shaderFP), shaderInput);
Mike Reed185ba212017-04-28 12:31:05 -0400500 shaderFP = GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(shaderFP),
501 *primColorMode);
502
bsalomonf1b7a1d2015-09-28 06:26:28 -0700503 // The above may return null if compose results in a pass through of the prim color.
504 if (shaderFP) {
Robert Phillips1c9686b2017-06-30 08:40:28 -0400505 grPaint->addColorFragmentProcessor(std::move(shaderFP));
bsalomonf1b7a1d2015-09-28 06:26:28 -0700506 }
507
brianosmana4535a32016-06-24 12:50:19 -0700508 // We can ignore origColor here - alpha is unchanged by gamma
bsalomonf1b7a1d2015-09-28 06:26:28 -0700509 GrColor paintAlpha = SkColorAlphaToGrColor(skPaint.getColor());
510 if (GrColor_WHITE != paintAlpha) {
Brian Osman618d3042016-10-25 10:51:28 -0400511 // No gamut conversion - paintAlpha is a (linear) alpha value, splatted to all
512 // color channels. It's value should be treated as the same in ANY color space.
bungeman06ca8ec2016-06-09 08:01:03 -0700513 grPaint->addColorFragmentProcessor(GrConstColorProcessor::Make(
Brian Osman618d3042016-10-25 10:51:28 -0400514 GrColor4f::FromGrColor(paintAlpha),
515 GrConstColorProcessor::kModulateRGBA_InputMode));
bsalomonf1b7a1d2015-09-28 06:26:28 -0700516 }
517 } else {
518 // The shader's FP sees the paint unpremul color
brianosmana4535a32016-06-24 12:50:19 -0700519 grPaint->setColor4f(origColor);
bungeman06ca8ec2016-06-09 08:01:03 -0700520 grPaint->addColorFragmentProcessor(std::move(shaderFP));
bsalomonf1b7a1d2015-09-28 06:26:28 -0700521 }
522 } else {
523 if (primColorMode) {
524 // There is a blend between the primitive color and the paint color. The blend considers
525 // the opaque paint color. The paint's alpha is applied to the post-blended color.
Brian Salomonaff329b2017-08-11 09:40:37 -0400526 auto processor = GrConstColorProcessor::Make(origColor.opaque(),
527 GrConstColorProcessor::kIgnore_InputMode);
Mike Reed185ba212017-04-28 12:31:05 -0400528 processor = GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(processor),
529 *primColorMode);
bsalomonf1b7a1d2015-09-28 06:26:28 -0700530 if (processor) {
bungeman06ca8ec2016-06-09 08:01:03 -0700531 grPaint->addColorFragmentProcessor(std::move(processor));
bsalomonf1b7a1d2015-09-28 06:26:28 -0700532 }
533
brianosmana4535a32016-06-24 12:50:19 -0700534 grPaint->setColor4f(origColor.opaque());
bsalomonf1b7a1d2015-09-28 06:26:28 -0700535
brianosmana4535a32016-06-24 12:50:19 -0700536 // We can ignore origColor here - alpha is unchanged by gamma
bsalomonf1b7a1d2015-09-28 06:26:28 -0700537 GrColor paintAlpha = SkColorAlphaToGrColor(skPaint.getColor());
bsalomonaa48d362015-10-01 08:34:17 -0700538 if (GrColor_WHITE != paintAlpha) {
Brian Osman618d3042016-10-25 10:51:28 -0400539 // No gamut conversion - paintAlpha is a (linear) alpha value, splatted to all
540 // color channels. It's value should be treated as the same in ANY color space.
bungeman06ca8ec2016-06-09 08:01:03 -0700541 grPaint->addColorFragmentProcessor(GrConstColorProcessor::Make(
Brian Osman618d3042016-10-25 10:51:28 -0400542 GrColor4f::FromGrColor(paintAlpha),
543 GrConstColorProcessor::kModulateRGBA_InputMode));
bsalomonaa48d362015-10-01 08:34:17 -0700544 }
bsalomonf1b7a1d2015-09-28 06:26:28 -0700545 } else {
546 // No shader, no primitive color.
brianosmana4535a32016-06-24 12:50:19 -0700547 grPaint->setColor4f(origColor.premul());
bsalomonf1b7a1d2015-09-28 06:26:28 -0700548 applyColorFilterToPaintColor = true;
549 }
550 }
551
552 SkColorFilter* colorFilter = skPaint.getColorFilter();
553 if (colorFilter) {
554 if (applyColorFilterToPaintColor) {
Brian Osman8bf4e672016-10-17 16:54:49 -0400555 // If we're in legacy mode, we *must* avoid using the 4f version of the color filter,
556 // because that will combine with the linearized version of the stored color.
Brian Osman11052242016-10-27 14:47:55 -0400557 if (rtc->isGammaCorrect()) {
Brian Osman8bf4e672016-10-17 16:54:49 -0400558 grPaint->setColor4f(GrColor4f::FromSkColor4f(
559 colorFilter->filterColor4f(origColor.toSkColor4f())).premul());
560 } else {
561 grPaint->setColor4f(SkColorToPremulGrColor4f(
Brian Osman47299142017-03-07 13:22:22 -0500562 colorFilter->filterColor(skPaint.getColor()), nullptr, nullptr));
Brian Osman8bf4e672016-10-17 16:54:49 -0400563 }
bsalomonf1b7a1d2015-09-28 06:26:28 -0700564 } else {
Brian Salomonaff329b2017-08-11 09:40:37 -0400565 auto cfFP = colorFilter->asFragmentProcessor(context, rtc->getColorSpace());
bsalomone25eea42015-09-29 06:38:55 -0700566 if (cfFP) {
bungeman06ca8ec2016-06-09 08:01:03 -0700567 grPaint->addColorFragmentProcessor(std::move(cfFP));
bsalomonf1b7a1d2015-09-28 06:26:28 -0700568 } else {
569 return false;
570 }
571 }
572 }
573
Robert Phillipsa29a9562016-10-20 09:40:55 -0400574 SkMaskFilter* maskFilter = skPaint.getMaskFilter();
575 if (maskFilter) {
576 GrFragmentProcessor* mfFP;
Robert Phillipsd9d84852017-06-09 10:48:29 -0400577 if (maskFilter->asFragmentProcessor(&mfFP)) {
Brian Salomonaff329b2017-08-11 09:40:37 -0400578 grPaint->addCoverageFragmentProcessor(std::unique_ptr<GrFragmentProcessor>(mfFP));
Robert Phillipsa29a9562016-10-20 09:40:55 -0400579 }
580 }
581
robertphillips4f037942016-02-09 05:09:27 -0800582 // When the xfermode is null on the SkPaint (meaning kSrcOver) we need the XPFactory field on
583 // the GrPaint to also be null (also kSrcOver).
584 SkASSERT(!grPaint->getXPFactory());
reed374772b2016-10-05 17:33:02 -0700585 if (!skPaint.isSrcOver()) {
586 grPaint->setXPFactory(SkBlendMode_AsXPFactory(skPaint.getBlendMode()));
robertphillips4f037942016-02-09 05:09:27 -0800587 }
mtklein775b8192014-12-02 09:11:25 -0800588
krajcevskif461a8f2014-06-19 14:14:06 -0700589#ifndef SK_IGNORE_GPU_DITHER
Florin Malitad4a70ee2017-06-19 10:21:43 -0400590 // Conservative default, in case GrPixelConfigToColorType() fails.
591 SkColorType ct = SkColorType::kRGB_565_SkColorType;
592 GrPixelConfigToColorType(rtc->config(), &ct);
593 if (SkPaintPriv::ShouldDither(skPaint, ct) && grPaint->numColorFragmentProcessors() > 0
594 && !rtc->isGammaCorrect()) {
Brian Salomon0c15ae82017-07-19 15:39:56 +0000595 auto ditherFP = GrDitherEffect::Make(rtc->config());
596 if (ditherFP) {
597 grPaint->addColorFragmentProcessor(std::move(ditherFP));
598 }
krajcevskif461a8f2014-06-19 14:14:06 -0700599 }
600#endif
bsalomonbed83a62015-04-15 14:18:34 -0700601 return true;
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000602}
603
Brian Osman11052242016-10-27 14:47:55 -0400604bool SkPaintToGrPaint(GrContext* context, GrRenderTargetContext* rtc, const SkPaint& skPaint,
brianosman8fe485b2016-07-25 12:31:51 -0700605 const SkMatrix& viewM, GrPaint* grPaint) {
Mike Reed185ba212017-04-28 12:31:05 -0400606 return skpaint_to_grpaint_impl(context, rtc, skPaint, viewM, nullptr, nullptr, grPaint);
bsalomonf1b7a1d2015-09-28 06:26:28 -0700607}
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000608
bsalomonf1b7a1d2015-09-28 06:26:28 -0700609/** Replaces the SkShader (if any) on skPaint with the passed in GrFragmentProcessor. */
610bool SkPaintToGrPaintReplaceShader(GrContext* context,
Brian Osman11052242016-10-27 14:47:55 -0400611 GrRenderTargetContext* rtc,
bsalomonf1b7a1d2015-09-28 06:26:28 -0700612 const SkPaint& skPaint,
Brian Salomonaff329b2017-08-11 09:40:37 -0400613 std::unique_ptr<GrFragmentProcessor> shaderFP,
bsalomonf1b7a1d2015-09-28 06:26:28 -0700614 GrPaint* grPaint) {
615 if (!shaderFP) {
bsalomonc21b09e2015-08-28 18:46:56 -0700616 return false;
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000617 }
Mike Reed185ba212017-04-28 12:31:05 -0400618 return skpaint_to_grpaint_impl(context, rtc, skPaint, SkMatrix::I(), &shaderFP, nullptr,
brianosman8fe485b2016-07-25 12:31:51 -0700619 grPaint);
commit-bot@chromium.org8dcff642014-05-15 20:32:48 +0000620}
reed8b26b992015-05-07 15:36:17 -0700621
bsalomonf1b7a1d2015-09-28 06:26:28 -0700622/** Ignores the SkShader (if any) on skPaint. */
623bool SkPaintToGrPaintNoShader(GrContext* context,
Brian Osman11052242016-10-27 14:47:55 -0400624 GrRenderTargetContext* rtc,
bsalomonf1b7a1d2015-09-28 06:26:28 -0700625 const SkPaint& skPaint,
626 GrPaint* grPaint) {
627 // Use a ptr to a nullptr to to indicate that the SkShader is ignored and not replaced.
Brian Salomonaff329b2017-08-11 09:40:37 -0400628 static std::unique_ptr<GrFragmentProcessor> kNullShaderFP(nullptr);
629 static std::unique_ptr<GrFragmentProcessor>* kIgnoreShader = &kNullShaderFP;
Brian Osman11052242016-10-27 14:47:55 -0400630 return skpaint_to_grpaint_impl(context, rtc, skPaint, SkMatrix::I(), kIgnoreShader, nullptr,
Mike Reed185ba212017-04-28 12:31:05 -0400631 grPaint);
bsalomonf1b7a1d2015-09-28 06:26:28 -0700632}
633
634/** Blends the SkPaint's shader (or color if no shader) with a per-primitive color which must
Mike Reed7d954ad2016-10-28 15:42:34 -0400635be setup as a vertex attribute using the specified SkBlendMode. */
bsalomonf1b7a1d2015-09-28 06:26:28 -0700636bool SkPaintToGrPaintWithXfermode(GrContext* context,
Brian Osman11052242016-10-27 14:47:55 -0400637 GrRenderTargetContext* rtc,
bsalomonf1b7a1d2015-09-28 06:26:28 -0700638 const SkPaint& skPaint,
639 const SkMatrix& viewM,
Mike Reed7d954ad2016-10-28 15:42:34 -0400640 SkBlendMode primColorMode,
bsalomonf1b7a1d2015-09-28 06:26:28 -0700641 GrPaint* grPaint) {
Brian Osman11052242016-10-27 14:47:55 -0400642 return skpaint_to_grpaint_impl(context, rtc, skPaint, viewM, nullptr, &primColorMode,
Mike Reed185ba212017-04-28 12:31:05 -0400643 grPaint);
bsalomonf1b7a1d2015-09-28 06:26:28 -0700644}
645
joshualitt33a5fce2015-11-18 13:28:51 -0800646bool SkPaintToGrPaintWithTexture(GrContext* context,
Brian Osman11052242016-10-27 14:47:55 -0400647 GrRenderTargetContext* rtc,
joshualitt33a5fce2015-11-18 13:28:51 -0800648 const SkPaint& paint,
649 const SkMatrix& viewM,
Brian Salomonaff329b2017-08-11 09:40:37 -0400650 std::unique_ptr<GrFragmentProcessor> fp,
joshualitt33a5fce2015-11-18 13:28:51 -0800651 bool textureIsAlphaOnly,
652 GrPaint* grPaint) {
Brian Salomonaff329b2017-08-11 09:40:37 -0400653 std::unique_ptr<GrFragmentProcessor> shaderFP;
joshualitt33a5fce2015-11-18 13:28:51 -0800654 if (textureIsAlphaOnly) {
Florin Malita4aed1382017-05-25 10:38:07 -0400655 if (const auto* shader = as_SB(paint.getShader())) {
656 shaderFP = shader->asFragmentProcessor(
657 SkShaderBase::AsFPArgs(context, &viewM, nullptr, paint.getFilterQuality(),
658 rtc->getColorSpace()));
joshualitt33a5fce2015-11-18 13:28:51 -0800659 if (!shaderFP) {
660 return false;
661 }
Brian Salomonaff329b2017-08-11 09:40:37 -0400662 std::unique_ptr<GrFragmentProcessor> fpSeries[] = { std::move(shaderFP), std::move(fp) };
bungeman06ca8ec2016-06-09 08:01:03 -0700663 shaderFP = GrFragmentProcessor::RunInSeries(fpSeries, 2);
joshualitt33a5fce2015-11-18 13:28:51 -0800664 } else {
Brian Salomonaff329b2017-08-11 09:40:37 -0400665 shaderFP = GrFragmentProcessor::MakeInputPremulAndMulByOutput(std::move(fp));
joshualitt33a5fce2015-11-18 13:28:51 -0800666 }
667 } else {
Brian Salomonaff329b2017-08-11 09:40:37 -0400668 shaderFP = GrFragmentProcessor::MulOutputByInputAlpha(std::move(fp));
joshualitt33a5fce2015-11-18 13:28:51 -0800669 }
670
Brian Osman11052242016-10-27 14:47:55 -0400671 return SkPaintToGrPaintReplaceShader(context, rtc, paint, std::move(shaderFP), grPaint);
joshualitt33a5fce2015-11-18 13:28:51 -0800672}
673
bsalomonf1b7a1d2015-09-28 06:26:28 -0700674
675////////////////////////////////////////////////////////////////////////////////////////////////
676
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400677GrSamplerState::Filter GrSkFilterQualityToGrFilterMode(SkFilterQuality paintFilterQuality,
678 const SkMatrix& viewM,
679 const SkMatrix& localM,
680 bool* doBicubic) {
joshualitt9bc39542015-08-12 12:57:54 -0700681 *doBicubic = false;
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400682 GrSamplerState::Filter textureFilterMode;
joshualitt9bc39542015-08-12 12:57:54 -0700683 switch (paintFilterQuality) {
684 case kNone_SkFilterQuality:
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400685 textureFilterMode = GrSamplerState::Filter::kNearest;
joshualitt9bc39542015-08-12 12:57:54 -0700686 break;
687 case kLow_SkFilterQuality:
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400688 textureFilterMode = GrSamplerState::Filter::kBilerp;
joshualitt9bc39542015-08-12 12:57:54 -0700689 break;
690 case kMedium_SkFilterQuality: {
691 SkMatrix matrix;
692 matrix.setConcat(viewM, localM);
693 if (matrix.getMinScale() < SK_Scalar1) {
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400694 textureFilterMode = GrSamplerState::Filter::kMipMap;
joshualitt9bc39542015-08-12 12:57:54 -0700695 } else {
696 // Don't trigger MIP level generation unnecessarily.
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400697 textureFilterMode = GrSamplerState::Filter::kBilerp;
joshualitt9bc39542015-08-12 12:57:54 -0700698 }
699 break;
700 }
701 case kHigh_SkFilterQuality: {
702 SkMatrix matrix;
703 matrix.setConcat(viewM, localM);
704 *doBicubic = GrBicubicEffect::ShouldUseBicubic(matrix, &textureFilterMode);
705 break;
706 }
707 default:
Mike Kleine54c75f2016-10-13 14:18:09 -0400708 // Should be unreachable. If not, fall back to mipmaps.
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400709 textureFilterMode = GrSamplerState::Filter::kMipMap;
joshualitt9bc39542015-08-12 12:57:54 -0700710 break;
711
712 }
713 return textureFilterMode;
714}