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