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