• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * 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.
6  */
7 
8 #include "src/gpu/SkGr.h"
9 
10 #include "include/core/SkCanvas.h"
11 #include "include/core/SkColorFilter.h"
12 #include "include/core/SkData.h"
13 #include "include/core/SkPixelRef.h"
14 #include "include/effects/SkRuntimeEffect.h"
15 #include "include/gpu/GrRecordingContext.h"
16 #include "include/private/SkIDChangeListener.h"
17 #include "include/private/SkImageInfoPriv.h"
18 #include "include/private/SkTPin.h"
19 #include "include/private/SkTemplates.h"
20 #include "src/core/SkAutoMalloc.h"
21 #include "src/core/SkBlendModePriv.h"
22 #include "src/core/SkColorFilterBase.h"
23 #include "src/core/SkColorSpacePriv.h"
24 #include "src/core/SkImagePriv.h"
25 #include "src/core/SkMaskFilterBase.h"
26 #include "src/core/SkMessageBus.h"
27 #include "src/core/SkMipmap.h"
28 #include "src/core/SkPaintPriv.h"
29 #include "src/core/SkResourceCache.h"
30 #include "src/core/SkTraceEvent.h"
31 #include "src/gpu/GrCaps.h"
32 #include "src/gpu/GrColorInfo.h"
33 #include "src/gpu/GrColorSpaceXform.h"
34 #include "src/gpu/GrGpuResourcePriv.h"
35 #include "src/gpu/GrPaint.h"
36 #include "src/gpu/GrProxyProvider.h"
37 #include "src/gpu/GrRecordingContextPriv.h"
38 #include "src/gpu/GrTextureProxy.h"
39 #include "src/gpu/GrXferProcessor.h"
40 #include "src/gpu/SkGr.h"
41 #include "src/gpu/effects/GrBicubicEffect.h"
42 #include "src/gpu/effects/GrBlendFragmentProcessor.h"
43 #include "src/gpu/effects/GrPorterDuffXferProcessor.h"
44 #include "src/gpu/effects/generated/GrClampFragmentProcessor.h"
45 #include "src/gpu/effects/generated/GrDitherEffect.h"
46 #include "src/image/SkImage_Base.h"
47 #include "src/shaders/SkShaderBase.h"
48 
GrMakeKeyFromImageID(GrUniqueKey * key,uint32_t imageID,const SkIRect & imageBounds)49 void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& imageBounds) {
50     SkASSERT(key);
51     SkASSERT(imageID);
52     SkASSERT(!imageBounds.isEmpty());
53     static const GrUniqueKey::Domain kImageIDDomain = GrUniqueKey::GenerateDomain();
54     GrUniqueKey::Builder builder(key, kImageIDDomain, 5, "Image");
55     builder[0] = imageID;
56     builder[1] = imageBounds.fLeft;
57     builder[2] = imageBounds.fTop;
58     builder[3] = imageBounds.fRight;
59     builder[4] = imageBounds.fBottom;
60 }
61 
62 ////////////////////////////////////////////////////////////////////////////////
63 
GrMakeUniqueKeyInvalidationListener(GrUniqueKey * key,uint32_t contextID)64 sk_sp<SkIDChangeListener> GrMakeUniqueKeyInvalidationListener(GrUniqueKey* key,
65                                                               uint32_t contextID) {
66     class Listener : public SkIDChangeListener {
67     public:
68         Listener(const GrUniqueKey& key, uint32_t contextUniqueID) : fMsg(key, contextUniqueID) {}
69 
70         void changed() override {
71             SkMessageBus<GrUniqueKeyInvalidatedMessage, uint32_t>::Post(fMsg);
72         }
73 
74     private:
75         GrUniqueKeyInvalidatedMessage fMsg;
76     };
77 
78     auto listener = sk_make_sp<Listener>(*key, contextID);
79 
80     // We stick a SkData on the key that calls invalidateListener in its destructor.
81     auto invalidateListener = [](const void* ptr, void* /*context*/) {
82         auto listener = reinterpret_cast<const sk_sp<Listener>*>(ptr);
83         (*listener)->markShouldDeregister();
84         delete listener;
85     };
86     auto data = SkData::MakeWithProc(new sk_sp<Listener>(listener),
87                                      sizeof(sk_sp<Listener>),
88                                      invalidateListener,
89                                      nullptr);
90     SkASSERT(!key->getCustomData());
91     key->setCustomData(std::move(data));
92     return std::move(listener);
93 }
94 
GrCopyBaseMipMapToTextureProxy(GrRecordingContext * ctx,sk_sp<GrSurfaceProxy> baseProxy,GrSurfaceOrigin origin,SkBudgeted budgeted)95 sk_sp<GrSurfaceProxy> GrCopyBaseMipMapToTextureProxy(GrRecordingContext* ctx,
96                                                      sk_sp<GrSurfaceProxy> baseProxy,
97                                                      GrSurfaceOrigin origin,
98                                                      SkBudgeted budgeted) {
99     SkASSERT(baseProxy);
100 
101     // We don't allow this for promise proxies i.e. if they need mips they need to give them
102     // to us upfront.
103     if (baseProxy->isPromiseProxy()) {
104         return nullptr;
105     }
106     if (!ctx->priv().caps()->isFormatCopyable(baseProxy->backendFormat())) {
107         return nullptr;
108     }
109     auto copy = GrSurfaceProxy::Copy(ctx, std::move(baseProxy), origin, GrMipmapped::kYes,
110                                      SkBackingFit::kExact, budgeted);
111     if (!copy) {
112         return nullptr;
113     }
114     SkASSERT(copy->asTextureProxy());
115     return copy;
116 }
117 
GrCopyBaseMipMapToView(GrRecordingContext * context,GrSurfaceProxyView src,SkBudgeted budgeted)118 GrSurfaceProxyView GrCopyBaseMipMapToView(GrRecordingContext* context,
119                                           GrSurfaceProxyView src,
120                                           SkBudgeted budgeted) {
121     auto origin = src.origin();
122     auto swizzle = src.swizzle();
123     auto proxy = src.refProxy();
124     return {GrCopyBaseMipMapToTextureProxy(context, proxy, origin, budgeted), origin, swizzle};
125 }
126 
adjust_mipmapped(GrMipmapped mipmapped,const SkBitmap & bitmap,const GrCaps * caps)127 static GrMipmapped adjust_mipmapped(GrMipmapped mipmapped,
128                                     const SkBitmap& bitmap,
129                                     const GrCaps* caps) {
130     if (!caps->mipmapSupport() || bitmap.dimensions().area() <= 1) {
131         return GrMipmapped::kNo;
132     }
133     return mipmapped;
134 }
135 
choose_bmp_texture_colortype(const GrCaps * caps,const SkBitmap & bitmap)136 static GrColorType choose_bmp_texture_colortype(const GrCaps* caps, const SkBitmap& bitmap) {
137     GrColorType ct = SkColorTypeToGrColorType(bitmap.info().colorType());
138     if (caps->getDefaultBackendFormat(ct, GrRenderable::kNo).isValid()) {
139         return ct;
140     }
141     return GrColorType::kRGBA_8888;
142 }
143 
make_bmp_proxy(GrProxyProvider * proxyProvider,const SkBitmap & bitmap,GrColorType ct,GrMipmapped mipmapped,SkBackingFit fit,SkBudgeted budgeted)144 static sk_sp<GrTextureProxy> make_bmp_proxy(GrProxyProvider* proxyProvider,
145                                             const SkBitmap& bitmap,
146                                             GrColorType ct,
147                                             GrMipmapped mipmapped,
148                                             SkBackingFit fit,
149                                             SkBudgeted budgeted) {
150     SkBitmap bmpToUpload;
151     if (ct != SkColorTypeToGrColorType(bitmap.info().colorType())) {
152         SkColorType skCT = GrColorTypeToSkColorType(ct);
153         if (!bmpToUpload.tryAllocPixels(bitmap.info().makeColorType(skCT)) ||
154             !bitmap.readPixels(bmpToUpload.pixmap())) {
155             return {};
156         }
157         bmpToUpload.setImmutable();
158     } else {
159         bmpToUpload = bitmap;
160     }
161     auto proxy = proxyProvider->createProxyFromBitmap(bmpToUpload, mipmapped, fit, budgeted);
162     SkASSERT(!proxy || mipmapped == GrMipmapped::kNo || proxy->mipmapped() == GrMipmapped::kYes);
163     return proxy;
164 }
165 
166 std::tuple<GrSurfaceProxyView, GrColorType>
GrMakeCachedBitmapProxyView(GrRecordingContext * rContext,const SkBitmap & bitmap,GrMipmapped mipmapped)167 GrMakeCachedBitmapProxyView(GrRecordingContext* rContext,
168                             const SkBitmap& bitmap,
169                             GrMipmapped mipmapped) {
170     if (!bitmap.peekPixels(nullptr)) {
171         return {};
172     }
173 
174     GrProxyProvider* proxyProvider = rContext->priv().proxyProvider();
175     const GrCaps* caps = rContext->priv().caps();
176 
177     GrUniqueKey key;
178     SkIPoint origin = bitmap.pixelRefOrigin();
179     SkIRect subset = SkIRect::MakePtSize(origin, bitmap.dimensions());
180     GrMakeKeyFromImageID(&key, bitmap.pixelRef()->getGenerationID(), subset);
181 
182     mipmapped = adjust_mipmapped(mipmapped, bitmap, caps);
183     GrColorType ct = choose_bmp_texture_colortype(caps, bitmap);
184 
185     auto installKey = [&](GrTextureProxy* proxy) {
186         auto listener = GrMakeUniqueKeyInvalidationListener(&key, proxyProvider->contextID());
187         bitmap.pixelRef()->addGenIDChangeListener(std::move(listener));
188         proxyProvider->assignUniqueKeyToProxy(key, proxy);
189     };
190 
191     sk_sp<GrTextureProxy> proxy = proxyProvider->findOrCreateProxyByUniqueKey(key);
192     if (!proxy) {
193         proxy = make_bmp_proxy(proxyProvider,
194                                bitmap,
195                                ct,
196                                mipmapped,
197                                SkBackingFit::kExact,
198                                SkBudgeted::kYes);
199         if (!proxy) {
200             return {};
201         }
202         SkASSERT(mipmapped == GrMipmapped::kNo || proxy->mipmapped() == GrMipmapped::kYes);
203         installKey(proxy.get());
204     }
205 
206     GrSwizzle swizzle = caps->getReadSwizzle(proxy->backendFormat(), ct);
207     if (mipmapped == GrMipmapped::kNo || proxy->mipmapped() == GrMipmapped::kYes) {
208         return {{std::move(proxy), kTopLeft_GrSurfaceOrigin, swizzle}, ct};
209     }
210 
211     // We need a mipped proxy, but we found a proxy earlier that wasn't mipped. Thus we generate
212     // a new mipped surface and copy the original proxy into the base layer. We will then let
213     // the gpu generate the rest of the mips.
214     auto mippedProxy = GrCopyBaseMipMapToTextureProxy(rContext, proxy, kTopLeft_GrSurfaceOrigin);
215     if (!mippedProxy) {
216         // We failed to make a mipped proxy with the base copied into it. This could have
217         // been from failure to make the proxy or failure to do the copy. Thus we will fall
218         // back to just using the non mipped proxy; See skbug.com/7094.
219         return {{std::move(proxy), kTopLeft_GrSurfaceOrigin, swizzle}, ct};
220     }
221     // In this case we are stealing the key from the original proxy which should only happen
222     // when we have just generated mipmaps for an originally unmipped proxy/texture. This
223     // means that all future uses of the key will access the mipmapped version. The texture
224     // backing the unmipped version will remain in the resource cache until the last texture
225     // proxy referencing it is deleted at which time it too will be deleted or recycled.
226     SkASSERT(proxy->getUniqueKey() == key);
227     proxyProvider->removeUniqueKeyFromProxy(proxy.get());
228     installKey(mippedProxy->asTextureProxy());
229     return {{std::move(mippedProxy), kTopLeft_GrSurfaceOrigin, swizzle}, ct};
230 }
231 
232 std::tuple<GrSurfaceProxyView, GrColorType>
GrMakeUncachedBitmapProxyView(GrRecordingContext * rContext,const SkBitmap & bitmap,GrMipmapped mipmapped,SkBackingFit fit,SkBudgeted budgeted)233 GrMakeUncachedBitmapProxyView(GrRecordingContext* rContext,
234                               const SkBitmap& bitmap,
235                               GrMipmapped mipmapped,
236                               SkBackingFit fit,
237                               SkBudgeted budgeted) {
238     GrProxyProvider* proxyProvider = rContext->priv().proxyProvider();
239     const GrCaps* caps = rContext->priv().caps();
240 
241     mipmapped = adjust_mipmapped(mipmapped, bitmap, caps);
242     GrColorType ct = choose_bmp_texture_colortype(caps, bitmap);
243 
244     if (auto proxy = make_bmp_proxy(proxyProvider, bitmap, ct, mipmapped, fit, budgeted)) {
245         GrSwizzle swizzle = caps->getReadSwizzle(proxy->backendFormat(), ct);
246         SkASSERT(mipmapped == GrMipmapped::kNo || proxy->mipmapped() == GrMipmapped::kYes);
247         return {{std::move(proxy), kTopLeft_GrSurfaceOrigin, swizzle}, ct};
248     }
249     return {};
250 }
251 ///////////////////////////////////////////////////////////////////////////////
252 
SkColorToPMColor4f(SkColor c,const GrColorInfo & colorInfo)253 SkPMColor4f SkColorToPMColor4f(SkColor c, const GrColorInfo& colorInfo) {
254     SkColor4f color = SkColor4f::FromColor(c);
255     if (auto* xform = colorInfo.colorSpaceXformFromSRGB()) {
256         color = xform->apply(color);
257     }
258     return color.premul();
259 }
260 
SkColor4fPrepForDst(SkColor4f color,const GrColorInfo & colorInfo)261 SkColor4f SkColor4fPrepForDst(SkColor4f color, const GrColorInfo& colorInfo) {
262     if (auto* xform = colorInfo.colorSpaceXformFromSRGB()) {
263         color = xform->apply(color);
264     }
265     return color;
266 }
267 
268 ///////////////////////////////////////////////////////////////////////////////
269 
blend_requires_shader(const SkBlendMode mode)270 static inline bool blend_requires_shader(const SkBlendMode mode) {
271     return SkBlendMode::kDst != mode;
272 }
273 
274 #ifndef SK_IGNORE_GPU_DITHER
dither_range_for_config(GrColorType dstColorType)275 static inline float dither_range_for_config(GrColorType dstColorType) {
276     // We use 1 / (2^bitdepth-1) as the range since each channel can hold 2^bitdepth values
277     switch (dstColorType) {
278         // 4 bit
279         case GrColorType::kABGR_4444:
280         case GrColorType::kARGB_4444:
281         case GrColorType::kBGRA_4444:
282             return 1 / 15.f;
283         // 6 bit
284         case GrColorType::kBGR_565:
285             return 1 / 63.f;
286         // 8 bit
287         case GrColorType::kUnknown:
288         case GrColorType::kAlpha_8:
289         case GrColorType::kAlpha_8xxx:
290         case GrColorType::kGray_8:
291         case GrColorType::kGrayAlpha_88:
292         case GrColorType::kGray_8xxx:
293         case GrColorType::kR_8:
294         case GrColorType::kRG_88:
295         case GrColorType::kRGB_888:
296         case GrColorType::kRGB_888x:
297         case GrColorType::kRGBA_8888:
298         case GrColorType::kRGBA_8888_SRGB:
299         case GrColorType::kBGRA_8888:
300             return 1 / 255.f;
301         // 10 bit
302         case GrColorType::kRGBA_1010102:
303         case GrColorType::kBGRA_1010102:
304             return 1 / 1023.f;
305         // 16 bit
306         case GrColorType::kAlpha_16:
307         case GrColorType::kR_16:
308         case GrColorType::kRG_1616:
309         case GrColorType::kRGBA_16161616:
310             return 1 / 32767.f;
311         // Half
312         case GrColorType::kAlpha_F16:
313         case GrColorType::kGray_F16:
314         case GrColorType::kR_F16:
315         case GrColorType::kRG_F16:
316         case GrColorType::kRGBA_F16:
317         case GrColorType::kRGBA_F16_Clamped:
318         // Float
319         case GrColorType::kAlpha_F32xxx:
320         case GrColorType::kRGBA_F32:
321             return 0.f; // no dithering
322     }
323     SkUNREACHABLE;
324 }
325 #endif
326 
skpaint_to_grpaint_impl(GrRecordingContext * context,const GrColorInfo & dstColorInfo,const SkPaint & skPaint,const SkMatrixProvider & matrixProvider,std::unique_ptr<GrFragmentProcessor> * shaderProcessor,SkBlendMode * primColorMode,GrPaint * grPaint)327 static inline bool skpaint_to_grpaint_impl(GrRecordingContext* context,
328                                            const GrColorInfo& dstColorInfo,
329                                            const SkPaint& skPaint,
330                                            const SkMatrixProvider& matrixProvider,
331                                            std::unique_ptr<GrFragmentProcessor>* shaderProcessor,
332                                            SkBlendMode* primColorMode,
333                                            GrPaint* grPaint) {
334     // Convert SkPaint color to 4f format in the destination color space
335     SkColor4f origColor = SkColor4fPrepForDst(skPaint.getColor4f(), dstColorInfo);
336 
337     GrFPArgs fpArgs(context, matrixProvider, &dstColorInfo);
338 
339     // Setup the initial color considering the shader, the SkPaint color, and the presence or not
340     // of per-vertex colors.
341     std::unique_ptr<GrFragmentProcessor> paintFP;
342     if (!primColorMode || blend_requires_shader(*primColorMode)) {
343         fpArgs.fInputColorIsOpaque = origColor.isOpaque();
344         if (shaderProcessor) {
345             paintFP = std::move(*shaderProcessor);
346         } else {
347             if (const SkShaderBase* shader = as_SB(skPaint.getShader())) {
348                 paintFP = shader->asFragmentProcessor(fpArgs);
349                 if (paintFP == nullptr) {
350                     return false;
351                 }
352             }
353         }
354     }
355 
356     // Set this in below cases if the output of the shader/paint-color/paint-alpha/primXfermode is
357     // a known constant value. In that case we can simply apply a color filter during this
358     // conversion without converting the color filter to a GrFragmentProcessor.
359     bool applyColorFilterToPaintColor = false;
360     if (paintFP) {
361         if (primColorMode) {
362             // There is a blend between the primitive color and the shader color. The shader sees
363             // the opaque paint color. The shader's output is blended using the provided mode by
364             // the primitive color. The blended color is then modulated by the paint's alpha.
365 
366             // The geometry processor will insert the primitive color to start the color chain, so
367             // the GrPaint color will be ignored.
368 
369             SkPMColor4f shaderInput = origColor.makeOpaque().premul();
370             paintFP = GrFragmentProcessor::OverrideInput(std::move(paintFP), shaderInput);
371             paintFP = GrBlendFragmentProcessor::Make(std::move(paintFP), /*dst=*/nullptr,
372                                                      *primColorMode);
373 
374             // We can ignore origColor here - alpha is unchanged by gamma
375             float paintAlpha = skPaint.getColor4f().fA;
376             if (1.0f != paintAlpha) {
377                 // No gamut conversion - paintAlpha is a (linear) alpha value, splatted to all
378                 // color channels. It's value should be treated as the same in ANY color space.
379                 paintFP = GrFragmentProcessor::ModulateRGBA(
380                         std::move(paintFP), {paintAlpha, paintAlpha, paintAlpha, paintAlpha});
381             }
382         } else {
383             grPaint->setColor4f(origColor.premul());
384         }
385     } else {
386         if (primColorMode) {
387             // There is a blend between the primitive color and the paint color. The blend considers
388             // the opaque paint color. The paint's alpha is applied to the post-blended color.
389             SkPMColor4f opaqueColor = origColor.makeOpaque().premul();
390             paintFP = GrFragmentProcessor::MakeColor(opaqueColor);
391             paintFP = GrBlendFragmentProcessor::Make(std::move(paintFP), /*dst=*/nullptr,
392                                                      *primColorMode);
393             grPaint->setColor4f(opaqueColor);
394 
395             // We can ignore origColor here - alpha is unchanged by gamma
396             float paintAlpha = skPaint.getColor4f().fA;
397             if (1.0f != paintAlpha) {
398                 // No gamut conversion - paintAlpha is a (linear) alpha value, splatted to all
399                 // color channels. It's value should be treated as the same in ANY color space.
400                 paintFP = GrFragmentProcessor::ModulateRGBA(
401                         std::move(paintFP), {paintAlpha, paintAlpha, paintAlpha, paintAlpha});
402             }
403         } else {
404             // No shader, no primitive color.
405             grPaint->setColor4f(origColor.premul());
406             applyColorFilterToPaintColor = true;
407         }
408     }
409 
410     SkColorFilter* colorFilter = skPaint.getColorFilter();
411     if (colorFilter) {
412         if (applyColorFilterToPaintColor) {
413             SkColorSpace* dstCS = dstColorInfo.colorSpace();
414             grPaint->setColor4f(colorFilter->filterColor4f(origColor, dstCS, dstCS).premul());
415         } else {
416             auto [success, fp] = as_CFB(colorFilter)->asFragmentProcessor(std::move(paintFP),
417                                                                           context, dstColorInfo);
418             if (!success) {
419                 return false;
420             }
421             paintFP = std::move(fp);
422         }
423     }
424 
425     SkMaskFilterBase* maskFilter = as_MFB(skPaint.getMaskFilter());
426     if (maskFilter) {
427         // We may have set this before passing to the SkShader.
428         fpArgs.fInputColorIsOpaque = false;
429         if (auto mfFP = maskFilter->asFragmentProcessor(fpArgs)) {
430             grPaint->setCoverageFragmentProcessor(std::move(mfFP));
431         }
432     }
433 
434     // When the xfermode is null on the SkPaint (meaning kSrcOver) we need the XPFactory field on
435     // the GrPaint to also be null (also kSrcOver).
436     SkASSERT(!grPaint->getXPFactory());
437     if (!skPaint.isSrcOver()) {
438         grPaint->setXPFactory(SkBlendMode_AsXPFactory(skPaint.getBlendMode()));
439     }
440 
441 #ifndef SK_IGNORE_GPU_DITHER
442     GrColorType ct = dstColorInfo.colorType();
443     if (SkPaintPriv::ShouldDither(skPaint, GrColorTypeToSkColorType(ct)) && paintFP != nullptr) {
444         float ditherRange = dither_range_for_config(ct);
445         paintFP = GrDitherEffect::Make(std::move(paintFP), ditherRange);
446     }
447 #endif
448 
449     if (GrColorTypeClampType(dstColorInfo.colorType()) == GrClampType::kManual) {
450         if (paintFP != nullptr) {
451             paintFP = GrClampFragmentProcessor::Make(std::move(paintFP), /*clampToPremul=*/false);
452         } else {
453             auto color = grPaint->getColor4f();
454             grPaint->setColor4f({SkTPin(color.fR, 0.f, 1.f),
455                                  SkTPin(color.fG, 0.f, 1.f),
456                                  SkTPin(color.fB, 0.f, 1.f),
457                                  SkTPin(color.fA, 0.f, 1.f)});
458         }
459     }
460 
461     if (paintFP) {
462         grPaint->setColorFragmentProcessor(std::move(paintFP));
463     }
464 
465     return true;
466 }
467 
SkPaintToGrPaint(GrRecordingContext * context,const GrColorInfo & dstColorInfo,const SkPaint & skPaint,const SkMatrixProvider & matrixProvider,GrPaint * grPaint)468 bool SkPaintToGrPaint(GrRecordingContext* context,
469                       const GrColorInfo& dstColorInfo,
470                       const SkPaint& skPaint,
471                       const SkMatrixProvider& matrixProvider,
472                       GrPaint* grPaint) {
473     return skpaint_to_grpaint_impl(context, dstColorInfo, skPaint, matrixProvider,
474                                    /*shaderProcessor=*/nullptr, /*primColorMode=*/nullptr, grPaint);
475 }
476 
477 /** Replaces the SkShader (if any) on skPaint with the passed in GrFragmentProcessor. */
SkPaintToGrPaintReplaceShader(GrRecordingContext * context,const GrColorInfo & dstColorInfo,const SkPaint & skPaint,const SkMatrixProvider & matrixProvider,std::unique_ptr<GrFragmentProcessor> shaderFP,GrPaint * grPaint)478 bool SkPaintToGrPaintReplaceShader(GrRecordingContext* context,
479                                    const GrColorInfo& dstColorInfo,
480                                    const SkPaint& skPaint,
481                                    const SkMatrixProvider& matrixProvider,
482                                    std::unique_ptr<GrFragmentProcessor> shaderFP,
483                                    GrPaint* grPaint) {
484     if (!shaderFP) {
485         return false;
486     }
487     return skpaint_to_grpaint_impl(context, dstColorInfo, skPaint, matrixProvider, &shaderFP,
488                                    /*primColorMode=*/nullptr, grPaint);
489 }
490 
491 /** Ignores the SkShader (if any) on skPaint. */
SkPaintToGrPaintNoShader(GrRecordingContext * context,const GrColorInfo & dstColorInfo,const SkPaint & skPaint,const SkMatrixProvider & matrixProvider,GrPaint * grPaint)492 bool SkPaintToGrPaintNoShader(GrRecordingContext* context,
493                               const GrColorInfo& dstColorInfo,
494                               const SkPaint& skPaint,
495                               const SkMatrixProvider& matrixProvider,
496                               GrPaint* grPaint) {
497     // Use a ptr to a nullptr to to indicate that the SkShader is ignored and not replaced.
498     std::unique_ptr<GrFragmentProcessor> nullShaderFP(nullptr);
499     return skpaint_to_grpaint_impl(context, dstColorInfo, skPaint, matrixProvider, &nullShaderFP,
500                                    /*primColorMode=*/nullptr, grPaint);
501 }
502 
503 /** Blends the SkPaint's shader (or color if no shader) with a per-primitive color which must
504     be setup as a vertex attribute using the specified SkBlendMode. */
SkPaintToGrPaintWithBlend(GrRecordingContext * context,const GrColorInfo & dstColorInfo,const SkPaint & skPaint,const SkMatrixProvider & matrixProvider,SkBlendMode primColorMode,GrPaint * grPaint)505 bool SkPaintToGrPaintWithBlend(GrRecordingContext* context,
506                                const GrColorInfo& dstColorInfo,
507                                const SkPaint& skPaint,
508                                const SkMatrixProvider& matrixProvider,
509                                SkBlendMode primColorMode,
510                                GrPaint* grPaint) {
511     return skpaint_to_grpaint_impl(context, dstColorInfo, skPaint, matrixProvider,
512                                    /*shaderProcessor=*/nullptr, &primColorMode, grPaint);
513 }
514 
515 /** Blends the passed-in shader with a per-primitive color which must be setup as a vertex attribute
516     using the specified SkBlendMode. */
SkPaintToGrPaintWithBlendReplaceShader(GrRecordingContext * context,const GrColorInfo & dstColorInfo,const SkPaint & skPaint,const SkMatrixProvider & matrixProvider,std::unique_ptr<GrFragmentProcessor> shaderFP,SkBlendMode primColorMode,GrPaint * grPaint)517 bool SkPaintToGrPaintWithBlendReplaceShader(GrRecordingContext* context,
518                                             const GrColorInfo& dstColorInfo,
519                                             const SkPaint& skPaint,
520                                             const SkMatrixProvider& matrixProvider,
521                                             std::unique_ptr<GrFragmentProcessor> shaderFP,
522                                             SkBlendMode primColorMode,
523                                             GrPaint* grPaint) {
524     if (!shaderFP) {
525         return false;
526     }
527     return skpaint_to_grpaint_impl(context, dstColorInfo, skPaint, matrixProvider, &shaderFP,
528                                    &primColorMode, grPaint);
529 }
530 
SkPaintToGrPaintWithTexture(GrRecordingContext * context,const GrColorInfo & dstColorInfo,const SkPaint & paint,const SkMatrixProvider & matrixProvider,std::unique_ptr<GrFragmentProcessor> fp,bool textureIsAlphaOnly,GrPaint * grPaint)531 bool SkPaintToGrPaintWithTexture(GrRecordingContext* context,
532                                  const GrColorInfo& dstColorInfo,
533                                  const SkPaint& paint,
534                                  const SkMatrixProvider& matrixProvider,
535                                  std::unique_ptr<GrFragmentProcessor> fp,
536                                  bool textureIsAlphaOnly,
537                                  GrPaint* grPaint) {
538     std::unique_ptr<GrFragmentProcessor> shaderFP;
539     if (textureIsAlphaOnly) {
540         if (const auto* shader = as_SB(paint.getShader())) {
541             shaderFP = shader->asFragmentProcessor(
542                     GrFPArgs(context, matrixProvider, &dstColorInfo));
543             if (!shaderFP) {
544                 return false;
545             }
546             shaderFP = GrFragmentProcessor::Compose(std::move(fp), std::move(shaderFP));
547         } else {
548             shaderFP = GrFragmentProcessor::MakeInputPremulAndMulByOutput(std::move(fp));
549         }
550     } else {
551         if (paint.getColor4f().isOpaque()) {
552             shaderFP = GrFragmentProcessor::OverrideInput(std::move(fp), SK_PMColor4fWHITE, false);
553         } else {
554             shaderFP = GrFragmentProcessor::MulChildByInputAlpha(std::move(fp));
555         }
556     }
557 
558     return SkPaintToGrPaintReplaceShader(context, dstColorInfo, paint, matrixProvider,
559                                          std::move(shaderFP), grPaint);
560 }
561