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