• 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/SkBlenderBase.h"
23 #include "src/core/SkColorFilterBase.h"
24 #include "src/core/SkColorSpacePriv.h"
25 #include "src/core/SkImagePriv.h"
26 #include "src/core/SkMaskFilterBase.h"
27 #include "src/core/SkMessageBus.h"
28 #include "src/core/SkMipmap.h"
29 #include "src/core/SkPaintPriv.h"
30 #include "src/core/SkResourceCache.h"
31 #include "src/core/SkRuntimeEffectPriv.h"
32 #include "src/core/SkTraceEvent.h"
33 #include "src/gpu/GrCaps.h"
34 #include "src/gpu/GrColorInfo.h"
35 #include "src/gpu/GrColorSpaceXform.h"
36 #include "src/gpu/GrGpuResourcePriv.h"
37 #include "src/gpu/GrPaint.h"
38 #include "src/gpu/GrProxyProvider.h"
39 #include "src/gpu/GrRecordingContextPriv.h"
40 #include "src/gpu/GrTextureProxy.h"
41 #include "src/gpu/GrXferProcessor.h"
42 #include "src/gpu/SkGr.h"
43 #include "src/gpu/effects/GrBicubicEffect.h"
44 #include "src/gpu/effects/GrBlendFragmentProcessor.h"
45 #include "src/gpu/effects/GrPorterDuffXferProcessor.h"
46 #include "src/gpu/effects/GrSkSLFP.h"
47 #include "src/gpu/effects/GrTextureEffect.h"
48 #include "src/image/SkImage_Base.h"
49 #include "src/shaders/SkShaderBase.h"
50 
GrMakeKeyFromImageID(GrUniqueKey * key,uint32_t imageID,const SkIRect & imageBounds)51 void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& imageBounds) {
52     SkASSERT(key);
53     SkASSERT(imageID);
54     SkASSERT(!imageBounds.isEmpty());
55     static const GrUniqueKey::Domain kImageIDDomain = GrUniqueKey::GenerateDomain();
56     GrUniqueKey::Builder builder(key, kImageIDDomain, 5, "Image");
57     builder[0] = imageID;
58     builder[1] = imageBounds.fLeft;
59     builder[2] = imageBounds.fTop;
60     builder[3] = imageBounds.fRight;
61     builder[4] = imageBounds.fBottom;
62 }
63 
64 ////////////////////////////////////////////////////////////////////////////////
65 
GrMakeUniqueKeyInvalidationListener(GrUniqueKey * key,uint32_t contextID)66 sk_sp<SkIDChangeListener> GrMakeUniqueKeyInvalidationListener(GrUniqueKey* key,
67                                                               uint32_t contextID) {
68     class Listener : public SkIDChangeListener {
69     public:
70         Listener(const GrUniqueKey& key, uint32_t contextUniqueID) : fMsg(key, contextUniqueID) {}
71 
72         void changed() override {
73             SkMessageBus<GrUniqueKeyInvalidatedMessage, uint32_t>::Post(fMsg);
74         }
75 
76     private:
77         GrUniqueKeyInvalidatedMessage fMsg;
78     };
79 
80     auto listener = sk_make_sp<Listener>(*key, contextID);
81 
82     // We stick a SkData on the key that calls invalidateListener in its destructor.
83     auto invalidateListener = [](const void* ptr, void* /*context*/) {
84         auto listener = reinterpret_cast<const sk_sp<Listener>*>(ptr);
85         (*listener)->markShouldDeregister();
86         delete listener;
87     };
88     auto data = SkData::MakeWithProc(new sk_sp<Listener>(listener),
89                                      sizeof(sk_sp<Listener>),
90                                      invalidateListener,
91                                      nullptr);
92     SkASSERT(!key->getCustomData());
93     key->setCustomData(std::move(data));
94     return std::move(listener);
95 }
96 
GrCopyBaseMipMapToTextureProxy(GrRecordingContext * ctx,sk_sp<GrSurfaceProxy> baseProxy,GrSurfaceOrigin origin,SkBudgeted budgeted)97 sk_sp<GrSurfaceProxy> GrCopyBaseMipMapToTextureProxy(GrRecordingContext* ctx,
98                                                      sk_sp<GrSurfaceProxy> baseProxy,
99                                                      GrSurfaceOrigin origin,
100                                                      SkBudgeted budgeted) {
101     SkASSERT(baseProxy);
102 
103     // We don't allow this for promise proxies i.e. if they need mips they need to give them
104     // to us upfront.
105     if (baseProxy->isPromiseProxy()) {
106         return nullptr;
107     }
108     if (!ctx->priv().caps()->isFormatCopyable(baseProxy->backendFormat())) {
109         return nullptr;
110     }
111     auto copy = GrSurfaceProxy::Copy(ctx, std::move(baseProxy), origin, GrMipmapped::kYes,
112                                      SkBackingFit::kExact, budgeted);
113     if (!copy) {
114         return nullptr;
115     }
116     SkASSERT(copy->asTextureProxy());
117     return copy;
118 }
119 
GrCopyBaseMipMapToView(GrRecordingContext * context,GrSurfaceProxyView src,SkBudgeted budgeted)120 GrSurfaceProxyView GrCopyBaseMipMapToView(GrRecordingContext* context,
121                                           GrSurfaceProxyView src,
122                                           SkBudgeted budgeted) {
123     auto origin = src.origin();
124     auto swizzle = src.swizzle();
125     auto proxy = src.refProxy();
126     return {GrCopyBaseMipMapToTextureProxy(context, proxy, origin, budgeted), origin, swizzle};
127 }
128 
adjust_mipmapped(GrMipmapped mipmapped,const SkBitmap & bitmap,const GrCaps * caps)129 static GrMipmapped adjust_mipmapped(GrMipmapped mipmapped,
130                                     const SkBitmap& bitmap,
131                                     const GrCaps* caps) {
132     if (!caps->mipmapSupport() || bitmap.dimensions().area() <= 1) {
133         return GrMipmapped::kNo;
134     }
135     return mipmapped;
136 }
137 
choose_bmp_texture_colortype(const GrCaps * caps,const SkBitmap & bitmap)138 static GrColorType choose_bmp_texture_colortype(const GrCaps* caps, const SkBitmap& bitmap) {
139     GrColorType ct = SkColorTypeToGrColorType(bitmap.info().colorType());
140     if (caps->getDefaultBackendFormat(ct, GrRenderable::kNo).isValid()) {
141         return ct;
142     }
143     return GrColorType::kRGBA_8888;
144 }
145 
make_bmp_proxy(GrProxyProvider * proxyProvider,const SkBitmap & bitmap,GrColorType ct,GrMipmapped mipmapped,SkBackingFit fit,SkBudgeted budgeted)146 static sk_sp<GrTextureProxy> make_bmp_proxy(GrProxyProvider* proxyProvider,
147                                             const SkBitmap& bitmap,
148                                             GrColorType ct,
149                                             GrMipmapped mipmapped,
150                                             SkBackingFit fit,
151                                             SkBudgeted budgeted) {
152     SkBitmap bmpToUpload;
153     if (ct != SkColorTypeToGrColorType(bitmap.info().colorType())) {
154         SkColorType skCT = GrColorTypeToSkColorType(ct);
155         if (!bmpToUpload.tryAllocPixels(bitmap.info().makeColorType(skCT)) ||
156             !bitmap.readPixels(bmpToUpload.pixmap())) {
157             return {};
158         }
159         bmpToUpload.setImmutable();
160     } else {
161         bmpToUpload = bitmap;
162     }
163     auto proxy = proxyProvider->createProxyFromBitmap(bmpToUpload, mipmapped, fit, budgeted);
164     SkASSERT(!proxy || mipmapped == GrMipmapped::kNo || proxy->mipmapped() == GrMipmapped::kYes);
165     return proxy;
166 }
167 
168 std::tuple<GrSurfaceProxyView, GrColorType>
GrMakeCachedBitmapProxyView(GrRecordingContext * rContext,const SkBitmap & bitmap,GrMipmapped mipmapped)169 GrMakeCachedBitmapProxyView(GrRecordingContext* rContext,
170                             const SkBitmap& bitmap,
171                             GrMipmapped mipmapped) {
172     if (!bitmap.peekPixels(nullptr)) {
173         return {};
174     }
175 
176     GrProxyProvider* proxyProvider = rContext->priv().proxyProvider();
177     const GrCaps* caps = rContext->priv().caps();
178 
179     GrUniqueKey key;
180     SkIPoint origin = bitmap.pixelRefOrigin();
181     SkIRect subset = SkIRect::MakePtSize(origin, bitmap.dimensions());
182     GrMakeKeyFromImageID(&key, bitmap.pixelRef()->getGenerationID(), subset);
183 
184     mipmapped = adjust_mipmapped(mipmapped, bitmap, caps);
185     GrColorType ct = choose_bmp_texture_colortype(caps, bitmap);
186 
187     auto installKey = [&](GrTextureProxy* proxy) {
188         auto listener = GrMakeUniqueKeyInvalidationListener(&key, proxyProvider->contextID());
189         bitmap.pixelRef()->addGenIDChangeListener(std::move(listener));
190         proxyProvider->assignUniqueKeyToProxy(key, proxy);
191     };
192 
193     sk_sp<GrTextureProxy> proxy = proxyProvider->findOrCreateProxyByUniqueKey(key);
194     if (!proxy) {
195         proxy = make_bmp_proxy(proxyProvider,
196                                bitmap,
197                                ct,
198                                mipmapped,
199                                SkBackingFit::kExact,
200                                SkBudgeted::kYes);
201         if (!proxy) {
202             return {};
203         }
204         SkASSERT(mipmapped == GrMipmapped::kNo || proxy->mipmapped() == GrMipmapped::kYes);
205         installKey(proxy.get());
206     }
207 
208     GrSwizzle swizzle = caps->getReadSwizzle(proxy->backendFormat(), ct);
209     if (mipmapped == GrMipmapped::kNo || proxy->mipmapped() == GrMipmapped::kYes) {
210         return {{std::move(proxy), kTopLeft_GrSurfaceOrigin, swizzle}, ct};
211     }
212 
213     // We need a mipped proxy, but we found a proxy earlier that wasn't mipped. Thus we generate
214     // a new mipped surface and copy the original proxy into the base layer. We will then let
215     // the gpu generate the rest of the mips.
216     auto mippedProxy = GrCopyBaseMipMapToTextureProxy(rContext, proxy, kTopLeft_GrSurfaceOrigin);
217     if (!mippedProxy) {
218         // We failed to make a mipped proxy with the base copied into it. This could have
219         // been from failure to make the proxy or failure to do the copy. Thus we will fall
220         // back to just using the non mipped proxy; See skbug.com/7094.
221         return {{std::move(proxy), kTopLeft_GrSurfaceOrigin, swizzle}, ct};
222     }
223     // In this case we are stealing the key from the original proxy which should only happen
224     // when we have just generated mipmaps for an originally unmipped proxy/texture. This
225     // means that all future uses of the key will access the mipmapped version. The texture
226     // backing the unmipped version will remain in the resource cache until the last texture
227     // proxy referencing it is deleted at which time it too will be deleted or recycled.
228     SkASSERT(proxy->getUniqueKey() == key);
229     proxyProvider->removeUniqueKeyFromProxy(proxy.get());
230     installKey(mippedProxy->asTextureProxy());
231     return {{std::move(mippedProxy), kTopLeft_GrSurfaceOrigin, swizzle}, ct};
232 }
233 
234 std::tuple<GrSurfaceProxyView, GrColorType>
GrMakeUncachedBitmapProxyView(GrRecordingContext * rContext,const SkBitmap & bitmap,GrMipmapped mipmapped,SkBackingFit fit,SkBudgeted budgeted)235 GrMakeUncachedBitmapProxyView(GrRecordingContext* rContext,
236                               const SkBitmap& bitmap,
237                               GrMipmapped mipmapped,
238                               SkBackingFit fit,
239                               SkBudgeted budgeted) {
240     GrProxyProvider* proxyProvider = rContext->priv().proxyProvider();
241     const GrCaps* caps = rContext->priv().caps();
242 
243     mipmapped = adjust_mipmapped(mipmapped, bitmap, caps);
244     GrColorType ct = choose_bmp_texture_colortype(caps, bitmap);
245 
246     if (auto proxy = make_bmp_proxy(proxyProvider, bitmap, ct, mipmapped, fit, budgeted)) {
247         GrSwizzle swizzle = caps->getReadSwizzle(proxy->backendFormat(), ct);
248         SkASSERT(mipmapped == GrMipmapped::kNo || proxy->mipmapped() == GrMipmapped::kYes);
249         return {{std::move(proxy), kTopLeft_GrSurfaceOrigin, swizzle}, ct};
250     }
251     return {};
252 }
253 ///////////////////////////////////////////////////////////////////////////////
254 
SkColorToPMColor4f(SkColor c,const GrColorInfo & colorInfo)255 SkPMColor4f SkColorToPMColor4f(SkColor c, const GrColorInfo& colorInfo) {
256     SkColor4f color = SkColor4f::FromColor(c);
257     if (auto* xform = colorInfo.colorSpaceXformFromSRGB()) {
258         color = xform->apply(color);
259     }
260     return color.premul();
261 }
262 
SkColor4fPrepForDst(SkColor4f color,const GrColorInfo & colorInfo)263 SkColor4f SkColor4fPrepForDst(SkColor4f color, const GrColorInfo& colorInfo) {
264     if (auto* xform = colorInfo.colorSpaceXformFromSRGB()) {
265         color = xform->apply(color);
266     }
267     return color;
268 }
269 
270 ///////////////////////////////////////////////////////////////////////////////
271 
blend_requires_shader(const SkBlendMode mode)272 static inline bool blend_requires_shader(const SkBlendMode mode) {
273     return SkBlendMode::kDst != mode;
274 }
275 
276 #ifndef SK_IGNORE_GPU_DITHER
dither_range_for_config(GrColorType dstColorType)277 static inline float dither_range_for_config(GrColorType dstColorType) {
278     // We use 1 / (2^bitdepth-1) as the range since each channel can hold 2^bitdepth values
279     switch (dstColorType) {
280         // 4 bit
281         case GrColorType::kABGR_4444:
282         case GrColorType::kARGB_4444:
283         case GrColorType::kBGRA_4444:
284             return 1 / 15.f;
285         // 6 bit
286         case GrColorType::kBGR_565:
287             return 1 / 63.f;
288         // 8 bit
289         case GrColorType::kUnknown:
290         case GrColorType::kAlpha_8:
291         case GrColorType::kAlpha_8xxx:
292         case GrColorType::kGray_8:
293         case GrColorType::kGrayAlpha_88:
294         case GrColorType::kGray_8xxx:
295         case GrColorType::kR_8:
296         case GrColorType::kRG_88:
297         case GrColorType::kRGB_888:
298         case GrColorType::kRGB_888x:
299         case GrColorType::kRGBA_8888:
300         case GrColorType::kRGBA_8888_SRGB:
301         case GrColorType::kBGRA_8888:
302             return 1 / 255.f;
303         // 10 bit
304         case GrColorType::kRGBA_1010102:
305         case GrColorType::kBGRA_1010102:
306             return 1 / 1023.f;
307         // 16 bit
308         case GrColorType::kAlpha_16:
309         case GrColorType::kR_16:
310         case GrColorType::kRG_1616:
311         case GrColorType::kRGBA_16161616:
312             return 1 / 32767.f;
313         // Half
314         case GrColorType::kAlpha_F16:
315         case GrColorType::kGray_F16:
316         case GrColorType::kR_F16:
317         case GrColorType::kRG_F16:
318         case GrColorType::kRGBA_F16:
319         case GrColorType::kRGBA_F16_Clamped:
320         // Float
321         case GrColorType::kAlpha_F32xxx:
322         case GrColorType::kRGBA_F32:
323             return 0.f; // no dithering
324     }
325     SkUNREACHABLE;
326 }
327 
make_dither_lut()328 static SkBitmap make_dither_lut() {
329     static constexpr struct DitherTable {
330         constexpr DitherTable() : data() {
331             for (int x = 0; x < 8; ++x) {
332                 for (int y = 0; y < 8; ++y) {
333                     // The computation of 'm' and 'value' is lifted from CPU backend.
334                     unsigned int m = (y & 1) << 5 | (x & 1) << 4 |
335                                      (y & 2) << 2 | (x & 2) << 1 |
336                                      (y & 4) >> 1 | (x & 4) >> 2;
337                     float value = float(m) * 1.0 / 64.0 - 63.0 / 128.0;
338                     // Bias by 0.5 to be in 0..1, mul by 255 and round to nearest int to make byte.
339                     data[y * 8 + x] = (uint8_t)((value + 0.5) * 255.f + 0.5f);
340                 }
341             }
342         }
343         uint8_t data[64];
344     } gTable;
345     SkBitmap bmp;
346     bmp.setInfo(SkImageInfo::MakeA8(8, 8));
347     bmp.setPixels(const_cast<uint8_t*>(gTable.data));
348     bmp.setImmutable();
349     return bmp;
350 }
351 
make_dither_effect(GrRecordingContext * rContext,std::unique_ptr<GrFragmentProcessor> inputFP,float range,const GrCaps * caps)352 static std::unique_ptr<GrFragmentProcessor> make_dither_effect(
353         GrRecordingContext* rContext,
354         std::unique_ptr<GrFragmentProcessor> inputFP,
355         float range,
356         const GrCaps* caps) {
357     if (range == 0 || inputFP == nullptr) {
358         return inputFP;
359     }
360 
361     if (caps->avoidDithering()) {
362         return inputFP;
363     }
364 
365     // We used to use integer math on sk_FragCoord, when supported, and a fallback using floating
366     // point (on a 4x4 rather than 8x8 grid). Now we precompute a 8x8 table in a texture because
367     // it was shown to be significantly faster on several devices. Test was done with the following
368     // running in viewer with the stats layer enabled and looking at total frame time:
369     //      SkRandom r;
370     //      for (int i = 0; i < N; ++i) {
371     //          SkColor c[2] = {r.nextU(), r.nextU()};
372     //          SkPoint pts[2] = {{r.nextRangeScalar(0, 500), r.nextRangeScalar(0, 500)},
373     //                            {r.nextRangeScalar(0, 500), r.nextRangeScalar(0, 500)}};
374     //          SkPaint p;
375     //          p.setDither(true);
376     //          p.setShader(SkGradientShader::MakeLinear(pts, c, nullptr, 2, SkTileMode::kRepeat));
377     //          canvas->drawPaint(p);
378     //      }
379     // Device            GPU             N      no dither    int math dither   table dither
380     // Linux desktop     QuadroP1000     5000   304ms        400ms (1.31x)     383ms (1.26x)
381     // TecnoSpark3Pro    PowerVRGE8320   200    299ms        820ms (2.74x)     592ms (1.98x)
382     // Pixel 4           Adreno640       500    110ms        221ms (2.01x)     214ms (1.95x)
383     // Galaxy S20 FE     Mali-G77 MP11   600    165ms        360ms (2.18x)     260ms (1.58x)
384     static const SkBitmap gLUT = make_dither_lut();
385     auto [tex, ct] = GrMakeCachedBitmapProxyView(rContext, gLUT, GrMipmapped::kNo);
386     if (!tex) {
387         return inputFP;
388     }
389     SkASSERT(ct == GrColorType::kAlpha_8);
390     GrSamplerState sampler(GrSamplerState::WrapMode::kRepeat, SkFilterMode::kNearest);
391     auto te = GrTextureEffect::Make(
392             std::move(tex), kPremul_SkAlphaType, SkMatrix::I(), sampler, *caps);
393     static auto effect = SkMakeRuntimeEffect(SkRuntimeEffect::MakeForShader, R"(
394         uniform half range;
395         uniform shader table;
396         half4 main(float2 xy, half4 color) {
397             half value = table.eval(sk_FragCoord.xy).a - 0.5; // undo the bias in the table
398             // For each color channel, add the random offset to the channel value and then clamp
399             // between 0 and alpha to keep the color premultiplied.
400             return half4(clamp(color.rgb + value * range, 0.0, color.a), color.a);
401         }
402     )", SkRuntimeEffectPriv::ES3Options());
403     return GrSkSLFP::Make(effect,
404                           "Dither",
405                           std::move(inputFP),
406                           GrSkSLFP::OptFlags::kPreservesOpaqueInput,
407                           "range",
408                           range,
409                           "table",
410                           std::move(te));
411 }
412 #endif
413 
skpaint_to_grpaint_impl(GrRecordingContext * context,const GrColorInfo & dstColorInfo,const SkPaint & skPaint,const SkMatrixProvider & matrixProvider,std::unique_ptr<GrFragmentProcessor> * shaderProcessor,SkBlendMode * primColorMode,GrPaint * grPaint)414 static inline bool skpaint_to_grpaint_impl(GrRecordingContext* context,
415                                            const GrColorInfo& dstColorInfo,
416                                            const SkPaint& skPaint,
417                                            const SkMatrixProvider& matrixProvider,
418                                            std::unique_ptr<GrFragmentProcessor>* shaderProcessor,
419                                            SkBlendMode* primColorMode,
420                                            GrPaint* grPaint) {
421     // Convert SkPaint color to 4f format in the destination color space
422     SkColor4f origColor = SkColor4fPrepForDst(skPaint.getColor4f(), dstColorInfo);
423 
424     GrFPArgs fpArgs(context, matrixProvider, &dstColorInfo);
425 
426     // Setup the initial color considering the shader, the SkPaint color, and the presence or not
427     // of per-vertex colors.
428     std::unique_ptr<GrFragmentProcessor> paintFP;
429     if (!primColorMode || blend_requires_shader(*primColorMode)) {
430         if (shaderProcessor) {
431             paintFP = std::move(*shaderProcessor);
432         } else {
433             if (const SkShaderBase* shader = as_SB(skPaint.getShader())) {
434                 paintFP = shader->asFragmentProcessor(fpArgs);
435                 if (paintFP == nullptr) {
436                     return false;
437                 }
438             }
439         }
440     }
441 
442     // Set this in below cases if the output of the shader/paint-color/paint-alpha/primXfermode is
443     // a known constant value. In that case we can simply apply a color filter during this
444     // conversion without converting the color filter to a GrFragmentProcessor.
445     bool applyColorFilterToPaintColor = false;
446     if (paintFP) {
447         if (primColorMode) {
448             // There is a blend between the primitive color and the shader color. The shader sees
449             // the opaque paint color. The shader's output is blended using the provided mode by
450             // the primitive color. The blended color is then modulated by the paint's alpha.
451 
452             // The geometry processor will insert the primitive color to start the color chain, so
453             // the GrPaint color will be ignored.
454 
455             SkPMColor4f shaderInput = origColor.makeOpaque().premul();
456             paintFP = GrFragmentProcessor::OverrideInput(std::move(paintFP), shaderInput);
457             paintFP = GrBlendFragmentProcessor::Make(std::move(paintFP),
458                                                      /*dst=*/nullptr,
459                                                      *primColorMode);
460 
461             // We can ignore origColor here - alpha is unchanged by gamma
462             float paintAlpha = skPaint.getColor4f().fA;
463             if (1.0f != paintAlpha) {
464                 // No gamut conversion - paintAlpha is a (linear) alpha value, splatted to all
465                 // color channels. It's value should be treated as the same in ANY color space.
466                 paintFP = GrFragmentProcessor::ModulateRGBA(
467                         std::move(paintFP), {paintAlpha, paintAlpha, paintAlpha, paintAlpha});
468             }
469         } else {
470             float paintAlpha = skPaint.getColor4f().fA;
471             if (paintAlpha != 1.0f) {
472                 // This invokes the shader's FP tree with an opaque version of the paint color,
473                 // then multiplies the final result by the incoming (paint) alpha.
474                 // We're actually putting the *unpremul* paint color on the GrPaint. This is okay,
475                 // because the shader is supposed to see the original (opaque) RGB from the paint.
476                 // ApplyPaintAlpha then creates a valid premul color by applying the paint alpha.
477                 // Think of this as equivalent to (but faster than) putting origColor.premul() on
478                 // the GrPaint, and ApplyPaintAlpha unpremuling it before passing it to the child.
479                 paintFP = GrFragmentProcessor::ApplyPaintAlpha(std::move(paintFP));
480                 grPaint->setColor4f({origColor.fR, origColor.fG, origColor.fB, origColor.fA});
481             } else {
482                 // paintFP will ignore its input color, so we must disable coverage-as-alpha.
483                 // TODO(skbug:11942): The alternative would be to always use ApplyPaintAlpha, but
484                 // we'd need to measure the cost of that shader math against the CAA benefit.
485                 paintFP = GrFragmentProcessor::DisableCoverageAsAlpha(std::move(paintFP));
486                 grPaint->setColor4f(origColor.premul());
487             }
488         }
489     } else {
490         if (primColorMode) {
491             // Examining all of the SkPaintToGrPaintFoo methods and their uses, it turns out that
492             // we can only encounter this code path when we're *just* using the primitive color.
493             // Literally no code path cares about blending the primitive color with the paint
494             // color. This makes sense, if you think about the SkCanvas draw calls that use
495             // primitive color - none of them are specified to do anything with paint color.
496             SkASSERT(*primColorMode == SkBlendMode::kDst);
497 
498             // There is no "blend" - the output of that blend is just the primitive color.
499             // We still put the opaque paint color on the GrPaint.
500             // TODO: Is this even necessary? It seems entirely superfluous. Any op that uses this
501             // code path should be ignoring the paint color, right?
502             grPaint->setColor4f(origColor.makeOpaque().premul());
503 
504             // The paint's *alpha* is applied to the primitive color:
505 
506             // We can ignore origColor here - alpha is unchanged by gamma
507             float paintAlpha = skPaint.getColor4f().fA;
508             if (1.0f != paintAlpha) {
509                 // No gamut conversion - paintAlpha is a (linear) alpha value, splatted to all
510                 // color channels. It's value should be treated as the same in ANY color space.
511                 paintFP = GrFragmentProcessor::ModulateRGBA(
512                         std::move(paintFP), {paintAlpha, paintAlpha, paintAlpha, paintAlpha});
513             }
514         } else {
515             // No shader, no primitive color.
516             grPaint->setColor4f(origColor.premul());
517             applyColorFilterToPaintColor = true;
518         }
519     }
520 
521     SkColorFilter* colorFilter = skPaint.getColorFilter();
522     if (colorFilter) {
523         if (applyColorFilterToPaintColor) {
524             SkColorSpace* dstCS = dstColorInfo.colorSpace();
525             grPaint->setColor4f(colorFilter->filterColor4f(origColor, dstCS, dstCS).premul());
526         } else {
527             auto [success, fp] = as_CFB(colorFilter)->asFragmentProcessor(std::move(paintFP),
528                                                                           context, dstColorInfo);
529             if (!success) {
530                 return false;
531             }
532             paintFP = std::move(fp);
533         }
534     }
535 
536     SkMaskFilterBase* maskFilter = as_MFB(skPaint.getMaskFilter());
537     if (maskFilter) {
538         if (auto mfFP = maskFilter->asFragmentProcessor(fpArgs)) {
539             grPaint->setCoverageFragmentProcessor(std::move(mfFP));
540         }
541     }
542 
543 #ifndef SK_IGNORE_GPU_DITHER
544     GrColorType ct = dstColorInfo.colorType();
545     if (SkPaintPriv::ShouldDither(skPaint, GrColorTypeToSkColorType(ct)) && paintFP != nullptr) {
546         float ditherRange = dither_range_for_config(ct);
547         paintFP = make_dither_effect(
548                 context, std::move(paintFP), ditherRange, context->priv().caps());
549     }
550 #endif
551 
552     if (auto bm = skPaint.asBlendMode()) {
553         // When the xfermode is null on the SkPaint (meaning kSrcOver) we need the XPFactory field
554         // on the GrPaint to also be null (also kSrcOver).
555         SkASSERT(!grPaint->getXPFactory());
556         if (bm.value() != SkBlendMode::kSrcOver) {
557             grPaint->setXPFactory(SkBlendMode_AsXPFactory(bm.value()));
558         }
559     } else {
560         // Apply a custom blend against the surface color, and force the XP to kSrc so that the
561         // computed result is applied directly to the canvas while still honoring the alpha.
562         paintFP = as_BB(skPaint.getBlender())->asFragmentProcessor(
563                 std::move(paintFP),
564                 GrFragmentProcessor::SurfaceColor(),
565                 fpArgs);
566         grPaint->setXPFactory(SkBlendMode_AsXPFactory(SkBlendMode::kSrc));
567     }
568 
569     if (GrColorTypeClampType(dstColorInfo.colorType()) == GrClampType::kManual) {
570         if (paintFP != nullptr) {
571             paintFP = GrFragmentProcessor::ClampOutput(std::move(paintFP));
572         } else {
573             auto color = grPaint->getColor4f();
574             grPaint->setColor4f({SkTPin(color.fR, 0.f, 1.f),
575                                  SkTPin(color.fG, 0.f, 1.f),
576                                  SkTPin(color.fB, 0.f, 1.f),
577                                  SkTPin(color.fA, 0.f, 1.f)});
578         }
579     }
580 
581     if (paintFP) {
582         grPaint->setColorFragmentProcessor(std::move(paintFP));
583     }
584 
585     return true;
586 }
587 
SkPaintToGrPaint(GrRecordingContext * context,const GrColorInfo & dstColorInfo,const SkPaint & skPaint,const SkMatrixProvider & matrixProvider,GrPaint * grPaint)588 bool SkPaintToGrPaint(GrRecordingContext* context,
589                       const GrColorInfo& dstColorInfo,
590                       const SkPaint& skPaint,
591                       const SkMatrixProvider& matrixProvider,
592                       GrPaint* grPaint) {
593     return skpaint_to_grpaint_impl(context, dstColorInfo, skPaint, matrixProvider,
594                                    /*shaderProcessor=*/nullptr, /*primColorMode=*/nullptr, grPaint);
595 }
596 
597 /** 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)598 bool SkPaintToGrPaintReplaceShader(GrRecordingContext* context,
599                                    const GrColorInfo& dstColorInfo,
600                                    const SkPaint& skPaint,
601                                    const SkMatrixProvider& matrixProvider,
602                                    std::unique_ptr<GrFragmentProcessor> shaderFP,
603                                    GrPaint* grPaint) {
604     if (!shaderFP) {
605         return false;
606     }
607     return skpaint_to_grpaint_impl(context, dstColorInfo, skPaint, matrixProvider, &shaderFP,
608                                    /*primColorMode=*/nullptr, grPaint);
609 }
610 
611 /** Blends the SkPaint's shader (or color if no shader) with a per-primitive color which must
612     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)613 bool SkPaintToGrPaintWithBlend(GrRecordingContext* context,
614                                const GrColorInfo& dstColorInfo,
615                                const SkPaint& skPaint,
616                                const SkMatrixProvider& matrixProvider,
617                                SkBlendMode primColorMode,
618                                GrPaint* grPaint) {
619     return skpaint_to_grpaint_impl(context, dstColorInfo, skPaint, matrixProvider,
620                                    /*shaderProcessor=*/nullptr, &primColorMode, grPaint);
621 }
622