Home | History | Annotate | Download | only in gpu
      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 
     43 GrSurfaceDesc 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 
     54 void 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 //////////////////////////////////////////////////////////////////////////////
     68 sk_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 
     81 sk_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 
    101 void 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 
    114 sk_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 
    158 sk_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 
    188 sk_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 
    203 sk_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 
    212 sk_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 
    244 GrColor4f 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 
    249 GrColor4f SkColorToPremulGrColor4fLegacy(SkColor c) {
    250     return GrColor4f::FromGrColor(SkColorToUnpremulGrColor(c)).premul();
    251 }
    252 
    253 GrColor4f 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 
    272 GrPixelConfig 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 
    306 GrPixelConfig SkImageInfo2GrPixelConfig(const SkImageInfo& info, const GrCaps& caps) {
    307     return SkImageInfo2GrPixelConfig(info.colorType(), info.colorSpace(), caps);
    308 }
    309 
    310 bool 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 
    353 GrPixelConfig 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 
    368 static inline bool blend_requires_shader(const SkBlendMode mode) {
    369     return SkBlendMode::kDst != mode;
    370 }
    371 
    372 static 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 
    515 bool 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. */
    522 bool 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. */
    535 bool 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
    547 be setup as a vertex attribute using the specified SkBlendMode. */
    548 bool 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 
    558 bool 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 
    589 GrSamplerState::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