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