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