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