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