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 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 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 ////////////////////////////////////////////////////////////////////////////// 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 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 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 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 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 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 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 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 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 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 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 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 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 339 GrPixelConfig SkImageInfo2GrPixelConfig(const SkImageInfo& info, const GrCaps& caps) { 340 return SkImageInfo2GrPixelConfig(info.colorType(), info.colorSpace(), caps); 341 } 342 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 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 397 static inline bool blend_requires_shader(const SkBlendMode mode) { 398 return SkBlendMode::kDst != mode; 399 } 400 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 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. */ 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. */ 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. */ 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 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 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