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 "SkGr.h"
9#include "GrBitmapTextureMaker.h"
10#include "GrCaps.h"
11#include "GrColorSpaceXform.h"
12#include "GrContext.h"
13#include "GrContextPriv.h"
14#include "GrGpuResourcePriv.h"
15#include "GrPaint.h"
16#include "GrProxyProvider.h"
17#include "GrTextureProxy.h"
18#include "GrTypes.h"
19#include "GrXferProcessor.h"
20#include "SkAutoMalloc.h"
21#include "SkBlendModePriv.h"
22#include "SkCanvas.h"
23#include "SkColorFilter.h"
24#include "SkConvertPixels.h"
25#include "SkData.h"
26#include "SkImageInfoPriv.h"
27#include "SkMaskFilterBase.h"
28#include "SkMessageBus.h"
29#include "SkMipMap.h"
30#include "SkPM4fPriv.h"
31#include "SkPaintPriv.h"
32#include "SkPixelRef.h"
33#include "SkResourceCache.h"
34#include "SkShaderBase.h"
35#include "SkTemplates.h"
36#include "SkTraceEvent.h"
37#include "effects/GrBicubicEffect.h"
38#include "effects/GrConstColorProcessor.h"
39#include "effects/GrDitherEffect.h"
40#include "effects/GrPorterDuffXferProcessor.h"
41#include "effects/GrXfermodeFragmentProcessor.h"
42
43GrSurfaceDesc GrImageInfoToSurfaceDesc(const SkImageInfo& info, const GrCaps& caps) {
44    GrSurfaceDesc desc;
45    desc.fFlags = kNone_GrSurfaceFlags;
46    desc.fOrigin = kTopLeft_GrSurfaceOrigin;
47    desc.fWidth = info.width();
48    desc.fHeight = info.height();
49    desc.fConfig = SkImageInfo2GrPixelConfig(info, caps);
50    desc.fSampleCnt = 1;
51    return desc;
52}
53
54void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& imageBounds) {
55    SkASSERT(key);
56    SkASSERT(imageID);
57    SkASSERT(!imageBounds.isEmpty());
58    static const GrUniqueKey::Domain kImageIDDomain = GrUniqueKey::GenerateDomain();
59    GrUniqueKey::Builder builder(key, kImageIDDomain, 5);
60    builder[0] = imageID;
61    builder[1] = imageBounds.fLeft;
62    builder[2] = imageBounds.fTop;
63    builder[3] = imageBounds.fRight;
64    builder[4] = imageBounds.fBottom;
65}
66
67//////////////////////////////////////////////////////////////////////////////
68sk_sp<GrTextureProxy> GrUploadBitmapToTextureProxy(GrProxyProvider* proxyProvider,
69                                                   const SkBitmap& bitmap,
70                                                   SkColorSpace* dstColorSpace) {
71    if (!bitmap.readyToDraw()) {
72        return nullptr;
73    }
74    SkPixmap pixmap;
75    if (!bitmap.peekPixels(&pixmap)) {
76        return nullptr;
77    }
78    return GrUploadPixmapToTextureProxy(proxyProvider, pixmap, SkBudgeted::kYes, dstColorSpace);
79}
80
81sk_sp<GrTextureProxy> GrUploadPixmapToTextureProxy(GrProxyProvider* proxyProvider,
82                                                   const SkPixmap& pixmap,
83                                                   SkBudgeted budgeted,
84                                                   SkColorSpace* dstColorSpace) {
85    SkDestinationSurfaceColorMode colorMode = dstColorSpace
86        ? SkDestinationSurfaceColorMode::kGammaAndColorSpaceAware
87        : SkDestinationSurfaceColorMode::kLegacy;
88
89    if (!SkImageInfoIsValid(pixmap.info(), colorMode)) {
90        return nullptr;
91    }
92
93    ATRACE_ANDROID_FRAMEWORK("Upload Texture [%ux%u]", pixmap.width(), pixmap.height());
94    GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(pixmap.info(), *proxyProvider->caps());
95
96    return proxyProvider->createTextureProxy(desc, budgeted, pixmap.addr(), pixmap.rowBytes());
97}
98
99////////////////////////////////////////////////////////////////////////////////
100
101void GrInstallBitmapUniqueKeyInvalidator(const GrUniqueKey& key, SkPixelRef* pixelRef) {
102    class Invalidator : public SkPixelRef::GenIDChangeListener {
103    public:
104        explicit Invalidator(const GrUniqueKey& key) : fMsg(key) {}
105    private:
106        GrUniqueKeyInvalidatedMessage fMsg;
107
108        void onChange() override { SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(fMsg); }
109    };
110
111    pixelRef->addGenIDChangeListener(new Invalidator(key));
112}
113
114sk_sp<GrTextureProxy> GrGenerateMipMapsAndUploadToTextureProxy(GrProxyProvider* proxyProvider,
115                                                               const SkBitmap& bitmap,
116                                                               SkColorSpace* dstColorSpace) {
117    SkDestinationSurfaceColorMode colorMode = dstColorSpace
118        ? SkDestinationSurfaceColorMode::kGammaAndColorSpaceAware
119        : SkDestinationSurfaceColorMode::kLegacy;
120
121    if (!SkImageInfoIsValid(bitmap.info(), colorMode)) {
122        return nullptr;
123    }
124
125    SkPixmap pixmap;
126    if (!bitmap.peekPixels(&pixmap)) {
127        return nullptr;
128    }
129
130    ATRACE_ANDROID_FRAMEWORK("Upload MipMap Texture [%ux%u]", pixmap.width(), pixmap.height());
131    GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(pixmap.info(), *proxyProvider->caps());
132    std::unique_ptr<SkMipMap> mipmaps(SkMipMap::Build(pixmap, colorMode, nullptr));
133    if (!mipmaps) {
134        return nullptr;
135    }
136
137    const int mipLevelCount = mipmaps->countLevels() + 1;
138    if (mipLevelCount < 1) {
139        return nullptr;
140    }
141
142    std::unique_ptr<GrMipLevel[]> texels(new GrMipLevel[mipLevelCount]);
143
144    texels[0].fPixels = pixmap.addr();
145    texels[0].fRowBytes = pixmap.rowBytes();
146
147    for (int i = 1; i < mipLevelCount; ++i) {
148        SkMipMap::Level generatedMipLevel;
149        mipmaps->getLevel(i - 1, &generatedMipLevel);
150        texels[i].fPixels = generatedMipLevel.fPixmap.addr();
151        texels[i].fRowBytes = generatedMipLevel.fPixmap.rowBytes();
152    }
153
154    return proxyProvider->createMipMapProxy(desc, SkBudgeted::kYes, texels.get(), mipLevelCount,
155                                            colorMode);
156}
157
158sk_sp<GrTextureProxy> GrCopyBaseMipMapToTextureProxy(GrContext* ctx, GrTextureProxy* baseProxy) {
159    SkASSERT(baseProxy);
160
161    if (!ctx->caps()->isConfigCopyable(baseProxy->config())) {
162        return nullptr;
163    }
164
165    GrProxyProvider* proxyProvider = ctx->contextPriv().proxyProvider();
166    GrSurfaceDesc desc;
167    desc.fFlags = kNone_GrSurfaceFlags;
168    desc.fOrigin = baseProxy->origin();
169    desc.fWidth = baseProxy->width();
170    desc.fHeight = baseProxy->height();
171    desc.fConfig = baseProxy->config();
172    desc.fSampleCnt = 1;
173
174    sk_sp<GrTextureProxy> proxy = proxyProvider->createMipMapProxy(desc, SkBudgeted::kYes);
175    if (!proxy) {
176        return nullptr;
177    }
178
179    // Copy the base layer to our proxy
180    sk_sp<GrSurfaceContext> sContext = ctx->contextPriv().makeWrappedSurfaceContext(proxy);
181    SkASSERT(sContext);
182    SkAssertResult(sContext->copy(baseProxy));
183
184    return proxy;
185}
186
187
188sk_sp<GrTextureProxy> GrUploadMipMapToTextureProxy(GrProxyProvider* proxyProvider,
189                                                   const SkImageInfo& info,
190                                                   const GrMipLevel texels[],
191                                                   int mipLevelCount,
192                                                   SkDestinationSurfaceColorMode colorMode) {
193    if (!SkImageInfoIsValid(info, colorMode)) {
194        return nullptr;
195    }
196
197    GrSurfaceDesc desc(GrImageInfoToSurfaceDesc(info, *proxyProvider->caps()));
198
199    return proxyProvider->createMipMapProxy(desc, SkBudgeted::kYes,
200                                            texels, mipLevelCount, colorMode);
201}
202
203sk_sp<GrTextureProxy> GrRefCachedBitmapTextureProxy(GrContext* ctx,
204                                                    const SkBitmap& bitmap,
205                                                    const GrSamplerState& params,
206                                                    SkScalar scaleAdjust[2]) {
207    // Caller doesn't care about the texture's color space (they can always get it from the bitmap)
208    return GrBitmapTextureMaker(ctx, bitmap).refTextureProxyForParams(params, nullptr,
209                                                                      nullptr, scaleAdjust);
210}
211
212sk_sp<GrTextureProxy> GrMakeCachedBitmapProxy(GrProxyProvider* proxyProvider,
213                                              const SkBitmap& bitmap) {
214    GrUniqueKey originalKey;
215
216    if (!bitmap.isVolatile()) {
217        SkIPoint origin = bitmap.pixelRefOrigin();
218        SkIRect subset = SkIRect::MakeXYWH(origin.fX, origin.fY, bitmap.width(), bitmap.height());
219        GrMakeKeyFromImageID(&originalKey, bitmap.pixelRef()->getGenerationID(), subset);
220    }
221
222    sk_sp<GrTextureProxy> proxy;
223
224    if (originalKey.isValid()) {
225        proxy = proxyProvider->findOrCreateProxyByUniqueKey(originalKey, kTopLeft_GrSurfaceOrigin);
226    }
227    if (!proxy) {
228        // Pass nullptr for |dstColorSpace|.  This is lenient - we allow a wider range of
229        // color spaces in legacy mode.  Unfortunately, we have to be lenient here, since
230        // we can't necessarily know the |dstColorSpace| at this time.
231        proxy = GrUploadBitmapToTextureProxy(proxyProvider, bitmap, nullptr);
232        if (proxy && originalKey.isValid()) {
233            SkASSERT(proxy->origin() == kTopLeft_GrSurfaceOrigin);
234            proxyProvider->assignUniqueKeyToProxy(originalKey, proxy.get());
235            GrInstallBitmapUniqueKeyInvalidator(originalKey, bitmap.pixelRef());
236        }
237    }
238
239    return proxy;
240}
241
242///////////////////////////////////////////////////////////////////////////////
243
244GrColor4f SkColorToPremulGrColor4f(SkColor c, const GrColorSpaceInfo& colorSpaceInfo) {
245    // We want to premultiply after linearizing, so this is easy:
246    return SkColorToUnpremulGrColor4f(c, colorSpaceInfo).premul();
247}
248
249GrColor4f SkColorToPremulGrColor4fLegacy(SkColor c) {
250    return GrColor4f::FromGrColor(SkColorToUnpremulGrColor(c)).premul();
251}
252
253GrColor4f SkColorToUnpremulGrColor4f(SkColor c, const GrColorSpaceInfo& colorSpaceInfo) {
254    GrColor4f color;
255    if (colorSpaceInfo.colorSpace()) {
256        // SkColor4f::FromColor does sRGB -> Linear
257        color = GrColor4f::FromSkColor4f(SkColor4f::FromColor(c));
258    } else {
259        // GrColor4f::FromGrColor just multiplies by 1/255
260        color = GrColor4f::FromGrColor(SkColorToUnpremulGrColor(c));
261    }
262
263    if (auto* xform = colorSpaceInfo.colorSpaceXformFromSRGB()) {
264        color = xform->clampedXform(color);
265    }
266
267    return color;
268}
269
270///////////////////////////////////////////////////////////////////////////////
271
272GrPixelConfig SkImageInfo2GrPixelConfig(const SkColorType type, SkColorSpace* cs,
273                                        const GrCaps& caps) {
274    switch (type) {
275        case kUnknown_SkColorType:
276            return kUnknown_GrPixelConfig;
277        case kAlpha_8_SkColorType:
278            return kAlpha_8_GrPixelConfig;
279        case kRGB_565_SkColorType:
280            return kRGB_565_GrPixelConfig;
281        case kARGB_4444_SkColorType:
282            return kRGBA_4444_GrPixelConfig;
283        case kRGBA_8888_SkColorType:
284            return (caps.srgbSupport() && cs && cs->gammaCloseToSRGB())
285                   ? kSRGBA_8888_GrPixelConfig : kRGBA_8888_GrPixelConfig;
286        // TODO: We're checking for srgbSupport, but we can then end up picking sBGRA as our pixel
287        // config (which may not be supported). We need a better test here.
288        case kRGB_888x_SkColorType:
289            return kUnknown_GrPixelConfig;
290        case kBGRA_8888_SkColorType:
291            return (caps.srgbSupport() && cs && cs->gammaCloseToSRGB())
292                   ? kSBGRA_8888_GrPixelConfig : kBGRA_8888_GrPixelConfig;
293        case kRGBA_1010102_SkColorType:
294            return kUnknown_GrPixelConfig;
295        case kRGB_101010x_SkColorType:
296            return kUnknown_GrPixelConfig;
297        case kGray_8_SkColorType:
298            return kGray_8_GrPixelConfig;
299        case kRGBA_F16_SkColorType:
300            return kRGBA_half_GrPixelConfig;
301    }
302    SkASSERT(0);    // shouldn't get here
303    return kUnknown_GrPixelConfig;
304}
305
306GrPixelConfig SkImageInfo2GrPixelConfig(const SkImageInfo& info, const GrCaps& caps) {
307    return SkImageInfo2GrPixelConfig(info.colorType(), info.colorSpace(), caps);
308}
309
310bool GrPixelConfigToColorType(GrPixelConfig config, SkColorType* ctOut) {
311    SkColorType ct;
312    switch (config) {
313        case kAlpha_8_GrPixelConfig: // fall through
314        case kAlpha_8_as_Alpha_GrPixelConfig: // fall through
315        case kAlpha_8_as_Red_GrPixelConfig:
316            ct = kAlpha_8_SkColorType;
317            break;
318        case kGray_8_GrPixelConfig: // fall through
319        case kGray_8_as_Lum_GrPixelConfig: // fall through
320        case kGray_8_as_Red_GrPixelConfig:
321            ct = kGray_8_SkColorType;
322            break;
323        case kRGB_565_GrPixelConfig:
324            ct = kRGB_565_SkColorType;
325            break;
326        case kRGBA_4444_GrPixelConfig:
327            ct = kARGB_4444_SkColorType;
328            break;
329        case kRGBA_8888_GrPixelConfig:
330            ct = kRGBA_8888_SkColorType;
331            break;
332        case kBGRA_8888_GrPixelConfig:
333            ct = kBGRA_8888_SkColorType;
334            break;
335        case kSRGBA_8888_GrPixelConfig:
336            ct = kRGBA_8888_SkColorType;
337            break;
338        case kSBGRA_8888_GrPixelConfig:
339            ct = kBGRA_8888_SkColorType;
340            break;
341        case kRGBA_half_GrPixelConfig:
342            ct = kRGBA_F16_SkColorType;
343            break;
344        default:
345            return false;
346    }
347    if (ctOut) {
348        *ctOut = ct;
349    }
350    return true;
351}
352
353GrPixelConfig GrRenderableConfigForColorSpace(const SkColorSpace* colorSpace) {
354    if (!colorSpace) {
355        return kRGBA_8888_GrPixelConfig;
356    } else if (colorSpace->gammaIsLinear()) {
357        return kRGBA_half_GrPixelConfig;
358    } else if (colorSpace->gammaCloseToSRGB()) {
359        return kSRGBA_8888_GrPixelConfig;
360    } else {
361        SkDEBUGFAIL("No renderable config exists for color space with strange gamma");
362        return kUnknown_GrPixelConfig;
363    }
364}
365
366////////////////////////////////////////////////////////////////////////////////////////////////
367
368static inline bool blend_requires_shader(const SkBlendMode mode) {
369    return SkBlendMode::kDst != mode;
370}
371
372static inline bool skpaint_to_grpaint_impl(GrContext* context,
373                                           const GrColorSpaceInfo& colorSpaceInfo,
374                                           const SkPaint& skPaint,
375                                           const SkMatrix& viewM,
376                                           std::unique_ptr<GrFragmentProcessor>* shaderProcessor,
377                                           SkBlendMode* primColorMode,
378                                           GrPaint* grPaint) {
379    grPaint->setAllowSRGBInputs(colorSpaceInfo.isGammaCorrect());
380
381    // Convert SkPaint color to 4f format, including optional linearizing and gamut conversion.
382    GrColor4f origColor = SkColorToUnpremulGrColor4f(skPaint.getColor(), colorSpaceInfo);
383
384    const GrFPArgs fpArgs(context, &viewM, skPaint.getFilterQuality(), &colorSpaceInfo);
385
386    // Setup the initial color considering the shader, the SkPaint color, and the presence or not
387    // of per-vertex colors.
388    std::unique_ptr<GrFragmentProcessor> shaderFP;
389    if (!primColorMode || blend_requires_shader(*primColorMode)) {
390        if (shaderProcessor) {
391            shaderFP = std::move(*shaderProcessor);
392        } else if (const auto* shader = as_SB(skPaint.getShader())) {
393            shaderFP = shader->asFragmentProcessor(fpArgs);
394        }
395    }
396
397    // Set this in below cases if the output of the shader/paint-color/paint-alpha/primXfermode is
398    // a known constant value. In that case we can simply apply a color filter during this
399    // conversion without converting the color filter to a GrFragmentProcessor.
400    bool applyColorFilterToPaintColor = false;
401    if (shaderFP) {
402        if (primColorMode) {
403            // There is a blend between the primitive color and the shader color. The shader sees
404            // the opaque paint color. The shader's output is blended using the provided mode by
405            // the primitive color. The blended color is then modulated by the paint's alpha.
406
407            // The geometry processor will insert the primitive color to start the color chain, so
408            // the GrPaint color will be ignored.
409
410            GrColor4f shaderInput = origColor.opaque();
411            shaderFP = GrFragmentProcessor::OverrideInput(std::move(shaderFP), shaderInput);
412            shaderFP = GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(shaderFP),
413                                                                         *primColorMode);
414
415            // The above may return null if compose results in a pass through of the prim color.
416            if (shaderFP) {
417                grPaint->addColorFragmentProcessor(std::move(shaderFP));
418            }
419
420            // We can ignore origColor here - alpha is unchanged by gamma
421            GrColor paintAlpha = SkColorAlphaToGrColor(skPaint.getColor());
422            if (GrColor_WHITE != paintAlpha) {
423                // No gamut conversion - paintAlpha is a (linear) alpha value, splatted to all
424                // color channels. It's value should be treated as the same in ANY color space.
425                grPaint->addColorFragmentProcessor(GrConstColorProcessor::Make(
426                    GrColor4f::FromGrColor(paintAlpha),
427                    GrConstColorProcessor::InputMode::kModulateRGBA));
428            }
429        } else {
430            // The shader's FP sees the paint unpremul color
431            grPaint->setColor4f(origColor);
432            grPaint->addColorFragmentProcessor(std::move(shaderFP));
433        }
434    } else {
435        if (primColorMode) {
436            // There is a blend between the primitive color and the paint color. The blend considers
437            // the opaque paint color. The paint's alpha is applied to the post-blended color.
438            auto processor = GrConstColorProcessor::Make(origColor.opaque(),
439                                                         GrConstColorProcessor::InputMode::kIgnore);
440            processor = GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(processor),
441                                                                          *primColorMode);
442            if (processor) {
443                grPaint->addColorFragmentProcessor(std::move(processor));
444            }
445
446            grPaint->setColor4f(origColor.opaque());
447
448            // We can ignore origColor here - alpha is unchanged by gamma
449            GrColor paintAlpha = SkColorAlphaToGrColor(skPaint.getColor());
450            if (GrColor_WHITE != paintAlpha) {
451                // No gamut conversion - paintAlpha is a (linear) alpha value, splatted to all
452                // color channels. It's value should be treated as the same in ANY color space.
453                grPaint->addColorFragmentProcessor(GrConstColorProcessor::Make(
454                    GrColor4f::FromGrColor(paintAlpha),
455                    GrConstColorProcessor::InputMode::kModulateRGBA));
456            }
457        } else {
458            // No shader, no primitive color.
459            grPaint->setColor4f(origColor.premul());
460            applyColorFilterToPaintColor = true;
461        }
462    }
463
464    SkColorFilter* colorFilter = skPaint.getColorFilter();
465    if (colorFilter) {
466        if (applyColorFilterToPaintColor) {
467            // If we're in legacy mode, we *must* avoid using the 4f version of the color filter,
468            // because that will combine with the linearized version of the stored color.
469            if (colorSpaceInfo.isGammaCorrect()) {
470                grPaint->setColor4f(GrColor4f::FromSkColor4f(
471                    colorFilter->filterColor4f(origColor.toSkColor4f())).premul());
472            } else {
473                grPaint->setColor4f(SkColorToPremulGrColor4fLegacy(
474                        colorFilter->filterColor(skPaint.getColor())));
475            }
476        } else {
477            auto cfFP = colorFilter->asFragmentProcessor(context, colorSpaceInfo);
478            if (cfFP) {
479                grPaint->addColorFragmentProcessor(std::move(cfFP));
480            } else {
481                return false;
482            }
483        }
484    }
485
486    SkMaskFilterBase* maskFilter = as_MFB(skPaint.getMaskFilter());
487    if (maskFilter) {
488        if (auto mfFP = maskFilter->asFragmentProcessor(fpArgs)) {
489            grPaint->addCoverageFragmentProcessor(std::move(mfFP));
490        }
491    }
492
493    // When the xfermode is null on the SkPaint (meaning kSrcOver) we need the XPFactory field on
494    // the GrPaint to also be null (also kSrcOver).
495    SkASSERT(!grPaint->getXPFactory());
496    if (!skPaint.isSrcOver()) {
497        grPaint->setXPFactory(SkBlendMode_AsXPFactory(skPaint.getBlendMode()));
498    }
499
500#ifndef SK_IGNORE_GPU_DITHER
501    // Conservative default, in case GrPixelConfigToColorType() fails.
502    SkColorType ct = SkColorType::kRGB_565_SkColorType;
503    GrPixelConfigToColorType(colorSpaceInfo.config(), &ct);
504    if (SkPaintPriv::ShouldDither(skPaint, ct) && grPaint->numColorFragmentProcessors() > 0 &&
505        !colorSpaceInfo.isGammaCorrect()) {
506        auto ditherFP = GrDitherEffect::Make(colorSpaceInfo.config());
507        if (ditherFP) {
508            grPaint->addColorFragmentProcessor(std::move(ditherFP));
509        }
510    }
511#endif
512    return true;
513}
514
515bool SkPaintToGrPaint(GrContext* context, const GrColorSpaceInfo& colorSpaceInfo,
516                      const SkPaint& skPaint, const SkMatrix& viewM, GrPaint* grPaint) {
517    return skpaint_to_grpaint_impl(context, colorSpaceInfo, skPaint, viewM, nullptr, nullptr,
518                                   grPaint);
519}
520
521/** Replaces the SkShader (if any) on skPaint with the passed in GrFragmentProcessor. */
522bool SkPaintToGrPaintReplaceShader(GrContext* context,
523                                   const GrColorSpaceInfo& colorSpaceInfo,
524                                   const SkPaint& skPaint,
525                                   std::unique_ptr<GrFragmentProcessor> shaderFP,
526                                   GrPaint* grPaint) {
527    if (!shaderFP) {
528        return false;
529    }
530    return skpaint_to_grpaint_impl(context, colorSpaceInfo, skPaint, SkMatrix::I(), &shaderFP,
531                                   nullptr, grPaint);
532}
533
534/** Ignores the SkShader (if any) on skPaint. */
535bool SkPaintToGrPaintNoShader(GrContext* context,
536                              const GrColorSpaceInfo& colorSpaceInfo,
537                              const SkPaint& skPaint,
538                              GrPaint* grPaint) {
539    // Use a ptr to a nullptr to to indicate that the SkShader is ignored and not replaced.
540    static std::unique_ptr<GrFragmentProcessor> kNullShaderFP(nullptr);
541    static std::unique_ptr<GrFragmentProcessor>* kIgnoreShader = &kNullShaderFP;
542    return skpaint_to_grpaint_impl(context, colorSpaceInfo, skPaint, SkMatrix::I(), kIgnoreShader,
543                                   nullptr, grPaint);
544}
545
546/** Blends the SkPaint's shader (or color if no shader) with a per-primitive color which must
547be setup as a vertex attribute using the specified SkBlendMode. */
548bool SkPaintToGrPaintWithXfermode(GrContext* context,
549                                  const GrColorSpaceInfo& colorSpaceInfo,
550                                  const SkPaint& skPaint,
551                                  const SkMatrix& viewM,
552                                  SkBlendMode primColorMode,
553                                  GrPaint* grPaint) {
554    return skpaint_to_grpaint_impl(context, colorSpaceInfo, skPaint, viewM, nullptr, &primColorMode,
555                                   grPaint);
556}
557
558bool SkPaintToGrPaintWithTexture(GrContext* context,
559                                 const GrColorSpaceInfo& colorSpaceInfo,
560                                 const SkPaint& paint,
561                                 const SkMatrix& viewM,
562                                 std::unique_ptr<GrFragmentProcessor> fp,
563                                 bool textureIsAlphaOnly,
564                                 GrPaint* grPaint) {
565    std::unique_ptr<GrFragmentProcessor> shaderFP;
566    if (textureIsAlphaOnly) {
567        if (const auto* shader = as_SB(paint.getShader())) {
568            shaderFP = shader->asFragmentProcessor(GrFPArgs(
569                    context, &viewM, nullptr, paint.getFilterQuality(), &colorSpaceInfo));
570            if (!shaderFP) {
571                return false;
572            }
573            std::unique_ptr<GrFragmentProcessor> fpSeries[] = { std::move(shaderFP), std::move(fp) };
574            shaderFP = GrFragmentProcessor::RunInSeries(fpSeries, 2);
575        } else {
576            shaderFP = GrFragmentProcessor::MakeInputPremulAndMulByOutput(std::move(fp));
577        }
578    } else {
579        shaderFP = GrFragmentProcessor::MulChildByInputAlpha(std::move(fp));
580    }
581
582    return SkPaintToGrPaintReplaceShader(context, colorSpaceInfo, paint, std::move(shaderFP),
583                                         grPaint);
584}
585
586
587////////////////////////////////////////////////////////////////////////////////////////////////
588
589GrSamplerState::Filter GrSkFilterQualityToGrFilterMode(SkFilterQuality paintFilterQuality,
590                                                       const SkMatrix& viewM,
591                                                       const SkMatrix& localM,
592                                                       bool* doBicubic) {
593    *doBicubic = false;
594    GrSamplerState::Filter textureFilterMode;
595    switch (paintFilterQuality) {
596        case kNone_SkFilterQuality:
597            textureFilterMode = GrSamplerState::Filter::kNearest;
598            break;
599        case kLow_SkFilterQuality:
600            textureFilterMode = GrSamplerState::Filter::kBilerp;
601            break;
602        case kMedium_SkFilterQuality: {
603            SkMatrix matrix;
604            matrix.setConcat(viewM, localM);
605            if (matrix.getMinScale() < SK_Scalar1) {
606                textureFilterMode = GrSamplerState::Filter::kMipMap;
607            } else {
608                // Don't trigger MIP level generation unnecessarily.
609                textureFilterMode = GrSamplerState::Filter::kBilerp;
610            }
611            break;
612        }
613        case kHigh_SkFilterQuality: {
614            SkMatrix matrix;
615            matrix.setConcat(viewM, localM);
616            *doBicubic = GrBicubicEffect::ShouldUseBicubic(matrix, &textureFilterMode);
617            break;
618        }
619        default:
620            // Should be unreachable.  If not, fall back to mipmaps.
621            textureFilterMode = GrSamplerState::Filter::kMipMap;
622            break;
623
624    }
625    return textureFilterMode;
626}
627