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