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 "SkData.h" 25 #include "SkImage_Base.h" 26 #include "SkImageInfoPriv.h" 27 #include "SkImagePriv.h" 28 #include "SkMaskFilterBase.h" 29 #include "SkMessageBus.h" 30 #include "SkMipMap.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/GrPorterDuffXferProcessor.h" 40 #include "effects/GrXfermodeFragmentProcessor.h" 41 #include "effects/GrSkSLFP.h" 42 43 #if SK_SUPPORT_GPU 44 GR_FP_SRC_STRING SKSL_DITHER_SRC = R"( 45 // This controls the range of values added to color channels 46 layout(key) in int rangeType; 47 48 void main(int x, int y, inout half4 color) { 49 half value; 50 half range; 51 @switch (rangeType) { 52 case 0: 53 range = 1.0 / 255.0; 54 break; 55 case 1: 56 range = 1.0 / 63.0; 57 break; 58 default: 59 // Experimentally this looks better than the expected value of 1/15. 60 range = 1.0 / 15.0; 61 break; 62 } 63 @if (sk_Caps.integerSupport) { 64 // This ordered-dither code is lifted from the cpu backend. 65 uint x = uint(x); 66 uint y = uint(y); 67 uint m = (y & 1) << 5 | (x & 1) << 4 | 68 (y & 2) << 2 | (x & 2) << 1 | 69 (y & 4) >> 1 | (x & 4) >> 2; 70 value = half(m) * 1.0 / 64.0 - 63.0 / 128.0; 71 } else { 72 // Simulate the integer effect used above using step/mod. For speed, simulates a 4x4 73 // dither pattern rather than an 8x8 one. 74 half4 modValues = mod(float4(x, y, x, y), half4(2.0, 2.0, 4.0, 4.0)); 75 half4 stepValues = step(modValues, half4(1.0, 1.0, 2.0, 2.0)); 76 value = dot(stepValues, half4(8.0 / 16.0, 4.0 / 16.0, 2.0 / 16.0, 1.0 / 16.0)) - 15.0 / 32.0; 77 } 78 // For each color channel, add the random offset to the channel value and then clamp 79 // between 0 and alpha to keep the color premultiplied. 80 color = half4(clamp(color.rgb + value * range, 0.0, color.a), color.a); 81 } 82 )"; 83 #endif 84 85 GrSurfaceDesc GrImageInfoToSurfaceDesc(const SkImageInfo& info) { 86 GrSurfaceDesc desc; 87 desc.fFlags = kNone_GrSurfaceFlags; 88 desc.fWidth = info.width(); 89 desc.fHeight = info.height(); 90 desc.fConfig = SkImageInfo2GrPixelConfig(info); 91 desc.fSampleCnt = 1; 92 return desc; 93 } 94 95 void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& imageBounds) { 96 SkASSERT(key); 97 SkASSERT(imageID); 98 SkASSERT(!imageBounds.isEmpty()); 99 static const GrUniqueKey::Domain kImageIDDomain = GrUniqueKey::GenerateDomain(); 100 GrUniqueKey::Builder builder(key, kImageIDDomain, 5, "Image"); 101 builder[0] = imageID; 102 builder[1] = imageBounds.fLeft; 103 builder[2] = imageBounds.fTop; 104 builder[3] = imageBounds.fRight; 105 builder[4] = imageBounds.fBottom; 106 } 107 108 ////////////////////////////////////////////////////////////////////////////// 109 sk_sp<GrTextureProxy> GrUploadBitmapToTextureProxy(GrProxyProvider* proxyProvider, 110 const SkBitmap& bitmap) { 111 if (!bitmap.peekPixels(nullptr)) { 112 return nullptr; 113 } 114 115 if (!SkImageInfoIsValid(bitmap.info())) { 116 return nullptr; 117 } 118 119 // In non-ddl we will always instantiate right away. Thus we never want to copy the SkBitmap 120 // even if it's mutable. In ddl, if the bitmap is mutable then we must make a copy since the 121 // upload of the data to the gpu can happen at anytime and the bitmap may change by then. 122 SkCopyPixelsMode cpyMode = proxyProvider->recordingDDL() ? kIfMutable_SkCopyPixelsMode 123 : kNever_SkCopyPixelsMode; 124 sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(bitmap, cpyMode); 125 126 return proxyProvider->createTextureProxy(std::move(image), kNone_GrSurfaceFlags, 1, 127 SkBudgeted::kYes, SkBackingFit::kExact); 128 } 129 130 //////////////////////////////////////////////////////////////////////////////// 131 132 void GrInstallBitmapUniqueKeyInvalidator(const GrUniqueKey& key, uint32_t contextUniqueID, 133 SkPixelRef* pixelRef) { 134 class Invalidator : public SkPixelRef::GenIDChangeListener { 135 public: 136 explicit Invalidator(const GrUniqueKey& key, uint32_t contextUniqueID) 137 : fMsg(key, contextUniqueID) {} 138 139 private: 140 GrUniqueKeyInvalidatedMessage fMsg; 141 142 void onChange() override { SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(fMsg); } 143 }; 144 145 pixelRef->addGenIDChangeListener(new Invalidator(key, contextUniqueID)); 146 } 147 148 sk_sp<GrTextureProxy> GrCopyBaseMipMapToTextureProxy(GrContext* ctx, GrTextureProxy* baseProxy) { 149 SkASSERT(baseProxy); 150 151 if (!ctx->contextPriv().caps()->isConfigCopyable(baseProxy->config())) { 152 return nullptr; 153 } 154 155 GrProxyProvider* proxyProvider = ctx->contextPriv().proxyProvider(); 156 GrSurfaceDesc desc; 157 desc.fFlags = kNone_GrSurfaceFlags; 158 desc.fWidth = baseProxy->width(); 159 desc.fHeight = baseProxy->height(); 160 desc.fConfig = baseProxy->config(); 161 desc.fSampleCnt = 1; 162 163 GrBackendFormat format = baseProxy->backendFormat().makeTexture2D(); 164 if (!format.isValid()) { 165 return nullptr; 166 } 167 168 sk_sp<GrTextureProxy> proxy = 169 proxyProvider->createMipMapProxy(format, desc, baseProxy->origin(), SkBudgeted::kYes); 170 if (!proxy) { 171 return nullptr; 172 } 173 174 // Copy the base layer to our proxy 175 sk_sp<GrSurfaceContext> sContext = 176 ctx->contextPriv().makeWrappedSurfaceContext(proxy); 177 SkASSERT(sContext); 178 SkAssertResult(sContext->copy(baseProxy)); 179 180 return proxy; 181 } 182 183 sk_sp<GrTextureProxy> GrRefCachedBitmapTextureProxy(GrContext* ctx, 184 const SkBitmap& bitmap, 185 const GrSamplerState& params, 186 SkScalar scaleAdjust[2]) { 187 return GrBitmapTextureMaker(ctx, bitmap).refTextureProxyForParams(params, scaleAdjust); 188 } 189 190 sk_sp<GrTextureProxy> GrMakeCachedBitmapProxy(GrProxyProvider* proxyProvider, 191 const SkBitmap& bitmap, 192 SkBackingFit fit) { 193 if (!bitmap.peekPixels(nullptr)) { 194 return nullptr; 195 } 196 197 // In non-ddl we will always instantiate right away. Thus we never want to copy the SkBitmap 198 // even if its mutable. In ddl, if the bitmap is mutable then we must make a copy since the 199 // upload of the data to the gpu can happen at anytime and the bitmap may change by then. 200 SkCopyPixelsMode cpyMode = proxyProvider->recordingDDL() ? kIfMutable_SkCopyPixelsMode 201 : kNever_SkCopyPixelsMode; 202 sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(bitmap, cpyMode); 203 204 if (!image) { 205 return nullptr; 206 } 207 208 return GrMakeCachedImageProxy(proxyProvider, std::move(image), fit); 209 } 210 211 static void create_unique_key_for_image(const SkImage* image, GrUniqueKey* result) { 212 if (!image) { 213 result->reset(); // will be invalid 214 return; 215 } 216 217 if (const SkBitmap* bm = as_IB(image)->onPeekBitmap()) { 218 if (!bm->isVolatile()) { 219 SkIPoint origin = bm->pixelRefOrigin(); 220 SkIRect subset = SkIRect::MakeXYWH(origin.fX, origin.fY, bm->width(), bm->height()); 221 GrMakeKeyFromImageID(result, bm->getGenerationID(), subset); 222 } 223 return; 224 } 225 226 GrMakeKeyFromImageID(result, image->uniqueID(), image->bounds()); 227 } 228 229 sk_sp<GrTextureProxy> GrMakeCachedImageProxy(GrProxyProvider* proxyProvider, 230 sk_sp<SkImage> srcImage, 231 SkBackingFit fit) { 232 sk_sp<GrTextureProxy> proxy; 233 GrUniqueKey originalKey; 234 235 create_unique_key_for_image(srcImage.get(), &originalKey); 236 237 if (originalKey.isValid()) { 238 proxy = proxyProvider->findOrCreateProxyByUniqueKey(originalKey, kTopLeft_GrSurfaceOrigin); 239 } 240 if (!proxy) { 241 proxy = proxyProvider->createTextureProxy(srcImage, kNone_GrSurfaceFlags, 1, 242 SkBudgeted::kYes, fit); 243 if (proxy && originalKey.isValid()) { 244 proxyProvider->assignUniqueKeyToProxy(originalKey, proxy.get()); 245 const SkBitmap* bm = as_IB(srcImage.get())->onPeekBitmap(); 246 // When recording DDLs we do not want to install change listeners because doing 247 // so isn't threadsafe. 248 if (bm && !proxyProvider->recordingDDL()) { 249 GrInstallBitmapUniqueKeyInvalidator(originalKey, proxyProvider->contextUniqueID(), 250 bm->pixelRef()); 251 } 252 } 253 } 254 255 return proxy; 256 } 257 258 /////////////////////////////////////////////////////////////////////////////// 259 260 SkPMColor4f SkColorToPMColor4f(SkColor c, const GrColorSpaceInfo& colorSpaceInfo) { 261 SkColor4f color = SkColor4f::FromColor(c); 262 if (auto* xform = colorSpaceInfo.colorSpaceXformFromSRGB()) { 263 color = xform->apply(color); 264 } 265 return color.premul(); 266 } 267 268 SkColor4f SkColor4fPrepForDst(SkColor4f color, const GrColorSpaceInfo& colorSpaceInfo, 269 const GrCaps& caps) { 270 if (auto* xform = colorSpaceInfo.colorSpaceXformFromSRGB()) { 271 color = xform->apply(color); 272 } 273 if (!GrPixelConfigIsFloatingPoint(colorSpaceInfo.config()) || 274 !caps.halfFloatVertexAttributeSupport()) { 275 color = { SkTPin(color.fR, 0.0f, 1.0f), 276 SkTPin(color.fG, 0.0f, 1.0f), 277 SkTPin(color.fB, 0.0f, 1.0f), 278 color.fA }; 279 } 280 return color; 281 } 282 283 /////////////////////////////////////////////////////////////////////////////// 284 285 GrPixelConfig SkColorType2GrPixelConfig(const SkColorType type) { 286 switch (type) { 287 case kUnknown_SkColorType: 288 return kUnknown_GrPixelConfig; 289 case kAlpha_8_SkColorType: 290 return kAlpha_8_GrPixelConfig; 291 case kRGB_565_SkColorType: 292 return kRGB_565_GrPixelConfig; 293 case kARGB_4444_SkColorType: 294 return kRGBA_4444_GrPixelConfig; 295 case kRGBA_8888_SkColorType: 296 return kRGBA_8888_GrPixelConfig; 297 case kRGB_888x_SkColorType: 298 return kRGB_888_GrPixelConfig; 299 case kBGRA_8888_SkColorType: 300 return kBGRA_8888_GrPixelConfig; 301 case kRGBA_1010102_SkColorType: 302 return kRGBA_1010102_GrPixelConfig; 303 case kRGB_101010x_SkColorType: 304 return kUnknown_GrPixelConfig; 305 case kGray_8_SkColorType: 306 return kGray_8_GrPixelConfig; 307 case kRGBA_F16_SkColorType: 308 return kRGBA_half_GrPixelConfig; 309 case kRGBA_F32_SkColorType: 310 return kRGBA_float_GrPixelConfig; 311 } 312 SkASSERT(0); // shouldn't get here 313 return kUnknown_GrPixelConfig; 314 } 315 316 GrPixelConfig SkImageInfo2GrPixelConfig(const SkImageInfo& info) { 317 return SkColorType2GrPixelConfig(info.colorType()); 318 } 319 320 bool GrPixelConfigToColorType(GrPixelConfig config, SkColorType* ctOut) { 321 SkColorType ct = GrColorTypeToSkColorType(GrPixelConfigToColorType(config)); 322 if (kUnknown_SkColorType != ct) { 323 if (ctOut) { 324 *ctOut = ct; 325 } 326 return true; 327 } 328 return false; 329 } 330 331 //////////////////////////////////////////////////////////////////////////////////////////////// 332 333 static inline bool blend_requires_shader(const SkBlendMode mode) { 334 return SkBlendMode::kDst != mode; 335 } 336 337 #ifndef SK_IGNORE_GPU_DITHER 338 static inline int32_t dither_range_type_for_config(GrPixelConfig dstConfig) { 339 switch (dstConfig) { 340 case kGray_8_GrPixelConfig: 341 case kGray_8_as_Lum_GrPixelConfig: 342 case kGray_8_as_Red_GrPixelConfig: 343 case kRGBA_8888_GrPixelConfig: 344 case kRGB_888_GrPixelConfig: 345 case kRG_88_GrPixelConfig: 346 case kBGRA_8888_GrPixelConfig: 347 return 0; 348 case kRGB_565_GrPixelConfig: 349 return 1; 350 case kRGBA_4444_GrPixelConfig: 351 return 2; 352 case kUnknown_GrPixelConfig: 353 case kSRGBA_8888_GrPixelConfig: 354 case kSBGRA_8888_GrPixelConfig: 355 case kRGBA_1010102_GrPixelConfig: 356 case kAlpha_half_GrPixelConfig: 357 case kAlpha_half_as_Red_GrPixelConfig: 358 case kRGBA_float_GrPixelConfig: 359 case kRG_float_GrPixelConfig: 360 case kRGBA_half_GrPixelConfig: 361 case kRGB_ETC1_GrPixelConfig: 362 case kAlpha_8_GrPixelConfig: 363 case kAlpha_8_as_Alpha_GrPixelConfig: 364 case kAlpha_8_as_Red_GrPixelConfig: 365 return -1; 366 } 367 SkASSERT(false); 368 return 0; 369 } 370 #endif 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 // Convert SkPaint color to 4f format in the destination color space 380 SkColor4f origColor = SkColor4fPrepForDst(skPaint.getColor4f(), colorSpaceInfo, 381 *context->contextPriv().caps()); 382 383 const GrFPArgs fpArgs(context, &viewM, skPaint.getFilterQuality(), &colorSpaceInfo); 384 385 // Setup the initial color considering the shader, the SkPaint color, and the presence or not 386 // of per-vertex colors. 387 std::unique_ptr<GrFragmentProcessor> shaderFP; 388 if (!primColorMode || blend_requires_shader(*primColorMode)) { 389 if (shaderProcessor) { 390 shaderFP = std::move(*shaderProcessor); 391 } else if (const auto* shader = as_SB(skPaint.getShader())) { 392 shaderFP = shader->asFragmentProcessor(fpArgs); 393 if (!shaderFP) { 394 return false; 395 } 396 } 397 } 398 399 // Set this in below cases if the output of the shader/paint-color/paint-alpha/primXfermode is 400 // a known constant value. In that case we can simply apply a color filter during this 401 // conversion without converting the color filter to a GrFragmentProcessor. 402 bool applyColorFilterToPaintColor = false; 403 if (shaderFP) { 404 if (primColorMode) { 405 // There is a blend between the primitive color and the shader color. The shader sees 406 // the opaque paint color. The shader's output is blended using the provided mode by 407 // the primitive color. The blended color is then modulated by the paint's alpha. 408 409 // The geometry processor will insert the primitive color to start the color chain, so 410 // the GrPaint color will be ignored. 411 412 SkPMColor4f shaderInput = origColor.makeOpaque().premul(); 413 shaderFP = GrFragmentProcessor::OverrideInput(std::move(shaderFP), shaderInput); 414 shaderFP = GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(shaderFP), 415 *primColorMode); 416 417 // The above may return null if compose results in a pass through of the prim color. 418 if (shaderFP) { 419 grPaint->addColorFragmentProcessor(std::move(shaderFP)); 420 } 421 422 // We can ignore origColor here - alpha is unchanged by gamma 423 float paintAlpha = skPaint.getColor4f().fA; 424 if (1.0f != paintAlpha) { 425 // No gamut conversion - paintAlpha is a (linear) alpha value, splatted to all 426 // color channels. It's value should be treated as the same in ANY color space. 427 grPaint->addColorFragmentProcessor(GrConstColorProcessor::Make( 428 { paintAlpha, paintAlpha, paintAlpha, paintAlpha }, 429 GrConstColorProcessor::InputMode::kModulateRGBA)); 430 } 431 } else { 432 // The shader's FP sees the paint *unpremul* color 433 SkPMColor4f origColorAsPM = { origColor.fR, origColor.fG, origColor.fB, origColor.fA }; 434 grPaint->setColor4f(origColorAsPM); 435 grPaint->addColorFragmentProcessor(std::move(shaderFP)); 436 } 437 } else { 438 if (primColorMode) { 439 // There is a blend between the primitive color and the paint color. The blend considers 440 // the opaque paint color. The paint's alpha is applied to the post-blended color. 441 SkPMColor4f opaqueColor = origColor.makeOpaque().premul(); 442 auto processor = GrConstColorProcessor::Make(opaqueColor, 443 GrConstColorProcessor::InputMode::kIgnore); 444 processor = GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(processor), 445 *primColorMode); 446 if (processor) { 447 grPaint->addColorFragmentProcessor(std::move(processor)); 448 } 449 450 grPaint->setColor4f(opaqueColor); 451 452 // We can ignore origColor here - alpha is unchanged by gamma 453 float paintAlpha = skPaint.getColor4f().fA; 454 if (1.0f != paintAlpha) { 455 // No gamut conversion - paintAlpha is a (linear) alpha value, splatted to all 456 // color channels. It's value should be treated as the same in ANY color space. 457 grPaint->addColorFragmentProcessor(GrConstColorProcessor::Make( 458 { paintAlpha, paintAlpha, paintAlpha, paintAlpha }, 459 GrConstColorProcessor::InputMode::kModulateRGBA)); 460 } 461 } else { 462 // No shader, no primitive color. 463 grPaint->setColor4f(origColor.premul()); 464 applyColorFilterToPaintColor = true; 465 } 466 } 467 468 SkColorFilter* colorFilter = skPaint.getColorFilter(); 469 if (colorFilter) { 470 if (applyColorFilterToPaintColor) { 471 grPaint->setColor4f( 472 colorFilter->filterColor4f(origColor, colorSpaceInfo.colorSpace()).premul()); 473 } else { 474 auto cfFP = colorFilter->asFragmentProcessor(context, colorSpaceInfo); 475 if (cfFP) { 476 grPaint->addColorFragmentProcessor(std::move(cfFP)); 477 } else { 478 return false; 479 } 480 } 481 } 482 483 SkMaskFilterBase* maskFilter = as_MFB(skPaint.getMaskFilter()); 484 if (maskFilter) { 485 if (auto mfFP = maskFilter->asFragmentProcessor(fpArgs)) { 486 grPaint->addCoverageFragmentProcessor(std::move(mfFP)); 487 } 488 } 489 490 // When the xfermode is null on the SkPaint (meaning kSrcOver) we need the XPFactory field on 491 // the GrPaint to also be null (also kSrcOver). 492 SkASSERT(!grPaint->getXPFactory()); 493 if (!skPaint.isSrcOver()) { 494 grPaint->setXPFactory(SkBlendMode_AsXPFactory(skPaint.getBlendMode())); 495 } 496 497 #ifndef SK_IGNORE_GPU_DITHER 498 // Conservative default, in case GrPixelConfigToColorType() fails. 499 SkColorType ct = SkColorType::kRGB_565_SkColorType; 500 GrPixelConfigToColorType(colorSpaceInfo.config(), &ct); 501 if (SkPaintPriv::ShouldDither(skPaint, ct) && grPaint->numColorFragmentProcessors() > 0) { 502 int32_t ditherRange = dither_range_type_for_config(colorSpaceInfo.config()); 503 if (ditherRange >= 0) { 504 static int ditherIndex = GrSkSLFP::NewIndex(); 505 auto ditherFP = GrSkSLFP::Make(context, ditherIndex, "Dither", SKSL_DITHER_SRC, 506 &ditherRange, sizeof(ditherRange)); 507 if (ditherFP) { 508 grPaint->addColorFragmentProcessor(std::move(ditherFP)); 509 } 510 } 511 } 512 #endif 513 return true; 514 } 515 516 bool SkPaintToGrPaint(GrContext* context, const GrColorSpaceInfo& colorSpaceInfo, 517 const SkPaint& skPaint, const SkMatrix& viewM, GrPaint* grPaint) { 518 return skpaint_to_grpaint_impl(context, colorSpaceInfo, skPaint, viewM, nullptr, nullptr, 519 grPaint); 520 } 521 522 /** Replaces the SkShader (if any) on skPaint with the passed in GrFragmentProcessor. */ 523 bool SkPaintToGrPaintReplaceShader(GrContext* context, 524 const GrColorSpaceInfo& colorSpaceInfo, 525 const SkPaint& skPaint, 526 std::unique_ptr<GrFragmentProcessor> shaderFP, 527 GrPaint* grPaint) { 528 if (!shaderFP) { 529 return false; 530 } 531 return skpaint_to_grpaint_impl(context, colorSpaceInfo, skPaint, SkMatrix::I(), &shaderFP, 532 nullptr, grPaint); 533 } 534 535 /** Ignores the SkShader (if any) on skPaint. */ 536 bool SkPaintToGrPaintNoShader(GrContext* context, 537 const GrColorSpaceInfo& colorSpaceInfo, 538 const SkPaint& skPaint, 539 GrPaint* grPaint) { 540 // Use a ptr to a nullptr to to indicate that the SkShader is ignored and not replaced. 541 std::unique_ptr<GrFragmentProcessor> nullShaderFP(nullptr); 542 return skpaint_to_grpaint_impl(context, colorSpaceInfo, skPaint, SkMatrix::I(), &nullShaderFP, 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, 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 sharpenMipmappedTextures, 593 bool* doBicubic) { 594 *doBicubic = false; 595 GrSamplerState::Filter textureFilterMode; 596 switch (paintFilterQuality) { 597 case kNone_SkFilterQuality: 598 textureFilterMode = GrSamplerState::Filter::kNearest; 599 break; 600 case kLow_SkFilterQuality: 601 textureFilterMode = GrSamplerState::Filter::kBilerp; 602 break; 603 case kMedium_SkFilterQuality: { 604 SkMatrix matrix; 605 matrix.setConcat(viewM, localM); 606 // With sharp mips, we bias lookups by -0.5. That means our final LOD is >= 0 until the 607 // computed LOD is >= 0.5. At what scale factor does a texture get an LOD of 0.5? 608 // 609 // Want: 0 = log2(1/s) - 0.5 610 // 0.5 = log2(1/s) 611 // 2^0.5 = 1/s 612 // 1/2^0.5 = s 613 // 2^0.5/2 = s 614 SkScalar mipScale = sharpenMipmappedTextures ? SK_ScalarRoot2Over2 : SK_Scalar1; 615 if (matrix.getMinScale() < mipScale) { 616 textureFilterMode = GrSamplerState::Filter::kMipMap; 617 } else { 618 // Don't trigger MIP level generation unnecessarily. 619 textureFilterMode = GrSamplerState::Filter::kBilerp; 620 } 621 break; 622 } 623 case kHigh_SkFilterQuality: { 624 SkMatrix matrix; 625 matrix.setConcat(viewM, localM); 626 *doBicubic = GrBicubicEffect::ShouldUseBicubic(matrix, &textureFilterMode); 627 break; 628 } 629 default: 630 // Should be unreachable. If not, fall back to mipmaps. 631 textureFilterMode = GrSamplerState::Filter::kMipMap; 632 break; 633 634 } 635 return textureFilterMode; 636 } 637