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