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