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