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