1 /* 2 * Copyright 2019 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 "GrContextPriv.h" 9 10 #include "GrClip.h" 11 #include "GrContextThreadSafeProxy.h" 12 #include "GrContextThreadSafeProxyPriv.h" 13 #include "GrDrawingManager.h" 14 #include "GrGpu.h" 15 #include "GrMemoryPool.h" 16 #include "GrRenderTargetContext.h" 17 #include "GrSkSLFPFactoryCache.h" 18 #include "GrSurfacePriv.h" 19 #include "GrTexture.h" 20 #include "GrTextureContext.h" 21 #include "SkAutoPixmapStorage.h" 22 #include "SkImage_Base.h" 23 #include "SkImage_Gpu.h" 24 #include "SkGr.h" 25 #include "text/GrTextBlobCache.h" 26 27 #define ASSERT_OWNED_PROXY_PRIV(P) \ 28 SkASSERT(!(P) || !((P)->peekTexture()) || (P)->peekTexture()->getContext() == fContext) 29 #define ASSERT_SINGLE_OWNER_PRIV \ 30 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fContext->singleOwner());) 31 #define RETURN_IF_ABANDONED_PRIV if (fContext->abandoned()) { return; } 32 #define RETURN_FALSE_IF_ABANDONED_PRIV if (fContext->abandoned()) { return false; } 33 34 sk_sp<const GrCaps> GrContextPriv::refCaps() const { 35 return fContext->refCaps(); 36 } 37 38 sk_sp<GrSkSLFPFactoryCache> GrContextPriv::fpFactoryCache() { 39 return fContext->fpFactoryCache(); 40 } 41 42 sk_sp<GrOpMemoryPool> GrContextPriv::refOpMemoryPool() { 43 return fContext->refOpMemoryPool(); 44 } 45 46 void GrContextPriv::addOnFlushCallbackObject(GrOnFlushCallbackObject* onFlushCBObject) { 47 fContext->addOnFlushCallbackObject(onFlushCBObject); 48 } 49 50 sk_sp<GrSurfaceContext> GrContextPriv::makeWrappedSurfaceContext( 51 sk_sp<GrSurfaceProxy> proxy, 52 sk_sp<SkColorSpace> colorSpace, 53 const SkSurfaceProps* props) { 54 return fContext->makeWrappedSurfaceContext(std::move(proxy), std::move(colorSpace), props); 55 } 56 57 sk_sp<GrSurfaceContext> GrContextPriv::makeDeferredSurfaceContext( 58 const GrBackendFormat& format, 59 const GrSurfaceDesc& dstDesc, 60 GrSurfaceOrigin origin, 61 GrMipMapped mipMapped, 62 SkBackingFit fit, 63 SkBudgeted isDstBudgeted, 64 sk_sp<SkColorSpace> colorSpace, 65 const SkSurfaceProps* props) { 66 return fContext->makeDeferredSurfaceContext(format, dstDesc, origin, mipMapped, fit, 67 isDstBudgeted, std::move(colorSpace), props); 68 } 69 70 sk_sp<GrRenderTargetContext> GrContextPriv::makeDeferredRenderTargetContext( 71 const GrBackendFormat& format, 72 SkBackingFit fit, 73 int width, int height, 74 GrPixelConfig config, 75 sk_sp<SkColorSpace> colorSpace, 76 int sampleCnt, 77 GrMipMapped mipMapped, 78 GrSurfaceOrigin origin, 79 const SkSurfaceProps* surfaceProps, 80 SkBudgeted budgeted) { 81 return fContext->makeDeferredRenderTargetContext(format, fit, width, height, config, 82 std::move(colorSpace), sampleCnt, mipMapped, 83 origin, surfaceProps, budgeted); 84 } 85 86 sk_sp<GrRenderTargetContext> GrContextPriv::makeDeferredRenderTargetContextWithFallback( 87 const GrBackendFormat& format, 88 SkBackingFit fit, 89 int width, int height, 90 GrPixelConfig config, 91 sk_sp<SkColorSpace> colorSpace, 92 int sampleCnt, 93 GrMipMapped mipMapped, 94 GrSurfaceOrigin origin, 95 const SkSurfaceProps* surfaceProps, 96 SkBudgeted budgeted) { 97 return fContext->makeDeferredRenderTargetContextWithFallback(format, fit, width, height, config, 98 std::move(colorSpace), sampleCnt, 99 mipMapped, origin, surfaceProps, 100 budgeted); 101 } 102 103 sk_sp<GrTextureContext> GrContextPriv::makeBackendTextureContext(const GrBackendTexture& tex, 104 GrSurfaceOrigin origin, 105 sk_sp<SkColorSpace> colorSpace) { 106 ASSERT_SINGLE_OWNER_PRIV 107 108 sk_sp<GrSurfaceProxy> proxy = this->proxyProvider()->wrapBackendTexture( 109 tex, origin, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, kRW_GrIOType); 110 if (!proxy) { 111 return nullptr; 112 } 113 114 return this->drawingManager()->makeTextureContext(std::move(proxy), std::move(colorSpace)); 115 } 116 117 sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendTextureRenderTargetContext( 118 const GrBackendTexture& tex, 119 GrSurfaceOrigin origin, 120 int sampleCnt, 121 sk_sp<SkColorSpace> colorSpace, 122 const SkSurfaceProps* props, 123 ReleaseProc releaseProc, 124 ReleaseContext releaseCtx) { 125 ASSERT_SINGLE_OWNER_PRIV 126 SkASSERT(sampleCnt > 0); 127 128 sk_sp<GrTextureProxy> proxy(this->proxyProvider()->wrapRenderableBackendTexture( 129 tex, origin, sampleCnt, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, releaseProc, 130 releaseCtx)); 131 if (!proxy) { 132 return nullptr; 133 } 134 135 return this->drawingManager()->makeRenderTargetContext(std::move(proxy), 136 std::move(colorSpace), props); 137 } 138 139 sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendRenderTargetRenderTargetContext( 140 const GrBackendRenderTarget& backendRT, 141 GrSurfaceOrigin origin, 142 sk_sp<SkColorSpace> colorSpace, 143 const SkSurfaceProps* surfaceProps, 144 ReleaseProc releaseProc, 145 ReleaseContext releaseCtx) { 146 ASSERT_SINGLE_OWNER_PRIV 147 148 sk_sp<GrSurfaceProxy> proxy = this->proxyProvider()->wrapBackendRenderTarget( 149 backendRT, origin, releaseProc, releaseCtx); 150 if (!proxy) { 151 return nullptr; 152 } 153 154 return this->drawingManager()->makeRenderTargetContext(std::move(proxy), 155 std::move(colorSpace), 156 surfaceProps); 157 } 158 159 sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendTextureAsRenderTargetRenderTargetContext( 160 const GrBackendTexture& tex, 161 GrSurfaceOrigin origin, 162 int sampleCnt, 163 sk_sp<SkColorSpace> colorSpace, 164 const SkSurfaceProps* props) { 165 ASSERT_SINGLE_OWNER_PRIV 166 SkASSERT(sampleCnt > 0); 167 sk_sp<GrSurfaceProxy> proxy( 168 this->proxyProvider()->wrapBackendTextureAsRenderTarget(tex, origin, sampleCnt)); 169 if (!proxy) { 170 return nullptr; 171 } 172 173 return this->drawingManager()->makeRenderTargetContext(std::move(proxy), 174 std::move(colorSpace), 175 props); 176 } 177 178 sk_sp<GrRenderTargetContext> GrContextPriv::makeVulkanSecondaryCBRenderTargetContext( 179 const SkImageInfo& imageInfo, const GrVkDrawableInfo& vkInfo, const SkSurfaceProps* props) { 180 ASSERT_SINGLE_OWNER_PRIV 181 sk_sp<GrSurfaceProxy> proxy( 182 this->proxyProvider()->wrapVulkanSecondaryCBAsRenderTarget(imageInfo, vkInfo)); 183 if (!proxy) { 184 return nullptr; 185 } 186 187 return this->drawingManager()->makeRenderTargetContext(std::move(proxy), 188 imageInfo.refColorSpace(), 189 props); 190 } 191 192 void GrContextPriv::flush(GrSurfaceProxy* proxy) { 193 ASSERT_SINGLE_OWNER_PRIV 194 RETURN_IF_ABANDONED_PRIV 195 ASSERT_OWNED_PROXY_PRIV(proxy); 196 197 fContext->drawingManager()->flush(proxy, SkSurface::BackendSurfaceAccess::kNoAccess, 198 kNone_GrFlushFlags, 0, nullptr, nullptr, nullptr); 199 } 200 201 void GrContextPriv::flushSurfaceWrites(GrSurfaceProxy* proxy) { 202 ASSERT_SINGLE_OWNER_PRIV 203 RETURN_IF_ABANDONED_PRIV 204 SkASSERT(proxy); 205 ASSERT_OWNED_PROXY_PRIV(proxy); 206 if (proxy->priv().hasPendingWrite()) { 207 this->flush(proxy); 208 } 209 } 210 211 void GrContextPriv::flushSurfaceIO(GrSurfaceProxy* proxy) { 212 ASSERT_SINGLE_OWNER_PRIV 213 RETURN_IF_ABANDONED_PRIV 214 SkASSERT(proxy); 215 ASSERT_OWNED_PROXY_PRIV(proxy); 216 if (proxy->priv().hasPendingIO()) { 217 this->flush(proxy); 218 } 219 } 220 221 void GrContextPriv::prepareSurfaceForExternalIO(GrSurfaceProxy* proxy) { 222 ASSERT_SINGLE_OWNER_PRIV 223 RETURN_IF_ABANDONED_PRIV 224 SkASSERT(proxy); 225 ASSERT_OWNED_PROXY_PRIV(proxy); 226 fContext->drawingManager()->prepareSurfaceForExternalIO(proxy, 227 SkSurface::BackendSurfaceAccess::kNoAccess, kNone_GrFlushFlags, 0, nullptr, 228 nullptr, nullptr); 229 } 230 231 static bool valid_premul_color_type(GrColorType ct) { 232 switch (ct) { 233 case GrColorType::kUnknown: return false; 234 case GrColorType::kAlpha_8: return false; 235 case GrColorType::kRGB_565: return false; 236 case GrColorType::kABGR_4444: return true; 237 case GrColorType::kRGBA_8888: return true; 238 case GrColorType::kRGB_888x: return false; 239 case GrColorType::kRG_88: return false; 240 case GrColorType::kBGRA_8888: return true; 241 case GrColorType::kRGBA_1010102: return true; 242 case GrColorType::kGray_8: return false; 243 case GrColorType::kAlpha_F16: return false; 244 case GrColorType::kRGBA_F16: return true; 245 case GrColorType::kRGBA_F16_Clamped: return true; 246 case GrColorType::kRG_F32: return false; 247 case GrColorType::kRGBA_F32: return true; 248 case GrColorType::kRGB_ETC1: return false; 249 } 250 SK_ABORT("Invalid GrColorType"); 251 return false; 252 } 253 254 // TODO: This will be removed when GrSurfaceContexts are aware of their color types. 255 // (skbug.com/6718) 256 static bool valid_premul_config(GrPixelConfig config) { 257 switch (config) { 258 case kUnknown_GrPixelConfig: return false; 259 case kAlpha_8_GrPixelConfig: return false; 260 case kGray_8_GrPixelConfig: return false; 261 case kRGB_565_GrPixelConfig: return false; 262 case kRGBA_4444_GrPixelConfig: return true; 263 case kRGBA_8888_GrPixelConfig: return true; 264 case kRGB_888_GrPixelConfig: return false; 265 case kRGB_888X_GrPixelConfig: return false; 266 case kRG_88_GrPixelConfig: return false; 267 case kBGRA_8888_GrPixelConfig: return true; 268 case kSRGBA_8888_GrPixelConfig: return true; 269 case kSBGRA_8888_GrPixelConfig: return true; 270 case kRGBA_1010102_GrPixelConfig: return true; 271 case kRGBA_float_GrPixelConfig: return true; 272 case kRG_float_GrPixelConfig: return false; 273 case kAlpha_half_GrPixelConfig: return false; 274 case kRGBA_half_GrPixelConfig: return true; 275 case kRGBA_half_Clamped_GrPixelConfig: return true; 276 case kRGB_ETC1_GrPixelConfig: return false; 277 case kAlpha_8_as_Alpha_GrPixelConfig: return false; 278 case kAlpha_8_as_Red_GrPixelConfig: return false; 279 case kAlpha_half_as_Red_GrPixelConfig: return false; 280 case kGray_8_as_Lum_GrPixelConfig: return false; 281 case kGray_8_as_Red_GrPixelConfig: return false; 282 } 283 SK_ABORT("Invalid GrPixelConfig"); 284 return false; 285 } 286 287 static bool valid_pixel_conversion(GrColorType cpuColorType, GrPixelConfig gpuConfig, 288 bool premulConversion) { 289 // We only allow premul <-> unpremul conversions for some formats 290 if (premulConversion && 291 (!valid_premul_color_type(cpuColorType) || !valid_premul_config(gpuConfig))) { 292 return false; 293 } 294 return true; 295 } 296 297 bool GrContextPriv::readSurfacePixels(GrSurfaceContext* src, int left, int top, int width, 298 int height, GrColorType dstColorType, 299 SkColorSpace* dstColorSpace, void* buffer, size_t rowBytes, 300 uint32_t pixelOpsFlags) { 301 ASSERT_SINGLE_OWNER_PRIV 302 RETURN_FALSE_IF_ABANDONED_PRIV 303 SkASSERT(src); 304 SkASSERT(buffer); 305 ASSERT_OWNED_PROXY_PRIV(src->asSurfaceProxy()); 306 GR_CREATE_TRACE_MARKER_CONTEXT("GrContextPriv", "readSurfacePixels", fContext); 307 308 SkASSERT(!(pixelOpsFlags & kDontFlush_PixelOpsFlag)); 309 if (pixelOpsFlags & kDontFlush_PixelOpsFlag) { 310 return false; 311 } 312 313 // MDB TODO: delay this instantiation until later in the method 314 if (!src->asSurfaceProxy()->instantiate(this->resourceProvider())) { 315 return false; 316 } 317 318 GrSurfaceProxy* srcProxy = src->asSurfaceProxy(); 319 GrSurface* srcSurface = srcProxy->peekSurface(); 320 321 if (!GrSurfacePriv::AdjustReadPixelParams(srcSurface->width(), srcSurface->height(), 322 GrColorTypeBytesPerPixel(dstColorType), &left, &top, 323 &width, &height, &buffer, &rowBytes)) { 324 return false; 325 } 326 327 // TODO: Make GrSurfaceContext know its alpha type and pass dst buffer's alpha type. 328 bool unpremul = SkToBool(kUnpremul_PixelOpsFlag & pixelOpsFlags); 329 330 if (!valid_pixel_conversion(dstColorType, srcProxy->config(), unpremul)) { 331 return false; 332 } 333 334 // This is the getImageData equivalent to the canvas2D putImageData fast path. We probably don't 335 // care so much about getImageData performance. However, in order to ensure putImageData/ 336 // getImageData in "legacy" mode are round-trippable we use the GPU to do the complementary 337 // unpremul step to writeSurfacePixels's premul step (which is determined empirically in 338 // fContext->vaildaPMUPMConversionExists()). 339 bool canvas2DFastPath = 340 unpremul && 341 !src->colorSpaceInfo().colorSpace() && 342 (GrColorType::kRGBA_8888 == dstColorType || GrColorType::kBGRA_8888 == dstColorType) && 343 SkToBool(srcProxy->asTextureProxy()) && 344 (srcProxy->config() == kRGBA_8888_GrPixelConfig || 345 srcProxy->config() == kBGRA_8888_GrPixelConfig) && 346 fContext->priv().caps()->isConfigRenderable(kRGBA_8888_GrPixelConfig) && 347 fContext->validPMUPMConversionExists(); 348 349 if (!fContext->priv().caps()->surfaceSupportsReadPixels(srcSurface) || 350 canvas2DFastPath) { 351 GrSurfaceDesc desc; 352 desc.fFlags = canvas2DFastPath ? kRenderTarget_GrSurfaceFlag : kNone_GrSurfaceFlags; 353 desc.fConfig = canvas2DFastPath ? kRGBA_8888_GrPixelConfig : srcProxy->config(); 354 desc.fWidth = width; 355 desc.fHeight = height; 356 desc.fSampleCnt = 1; 357 358 GrBackendFormat format; 359 if (canvas2DFastPath) { 360 desc.fFlags = kRenderTarget_GrSurfaceFlag; 361 desc.fConfig = kRGBA_8888_GrPixelConfig; 362 format = this->caps()->getBackendFormatFromColorType(kRGBA_8888_SkColorType); 363 } else { 364 desc.fFlags = kNone_GrSurfaceFlags; 365 desc.fConfig = srcProxy->config(); 366 format = srcProxy->backendFormat().makeTexture2D(); 367 if (!format.isValid()) { 368 return false; 369 } 370 } 371 372 auto tempProxy = this->proxyProvider()->createProxy( 373 format, desc, kTopLeft_GrSurfaceOrigin, SkBackingFit::kApprox, SkBudgeted::kYes); 374 if (!tempProxy) { 375 return false; 376 } 377 sk_sp<GrSurfaceContext> tempCtx; 378 if (canvas2DFastPath) { 379 tempCtx = this->drawingManager()->makeRenderTargetContext(std::move(tempProxy), nullptr, 380 nullptr); 381 SkASSERT(tempCtx->asRenderTargetContext()); 382 tempCtx->asRenderTargetContext()->discard(); 383 } else { 384 tempCtx = this->drawingManager()->makeTextureContext( 385 std::move(tempProxy), src->colorSpaceInfo().refColorSpace()); 386 } 387 if (!tempCtx) { 388 return false; 389 } 390 if (canvas2DFastPath) { 391 GrPaint paint; 392 paint.setPorterDuffXPFactory(SkBlendMode::kSrc); 393 auto fp = fContext->createPMToUPMEffect( 394 GrSimpleTextureEffect::Make(sk_ref_sp(srcProxy->asTextureProxy()), 395 SkMatrix::I())); 396 if (dstColorType == GrColorType::kBGRA_8888) { 397 fp = GrFragmentProcessor::SwizzleOutput(std::move(fp), GrSwizzle::BGRA()); 398 dstColorType = GrColorType::kRGBA_8888; 399 } 400 if (!fp) { 401 return false; 402 } 403 paint.addColorFragmentProcessor(std::move(fp)); 404 tempCtx->asRenderTargetContext()->fillRectToRect( 405 GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), 406 SkRect::MakeWH(width, height), SkRect::MakeXYWH(left, top, width, height)); 407 } else if (!tempCtx->copy(srcProxy, SkIRect::MakeXYWH(left, top, width, height), {0, 0})) { 408 return false; 409 } 410 uint32_t flags = canvas2DFastPath ? 0 : pixelOpsFlags; 411 return this->readSurfacePixels(tempCtx.get(), 0, 0, width, height, dstColorType, 412 dstColorSpace, buffer, rowBytes, flags); 413 } 414 415 bool convert = unpremul; 416 417 bool flip = srcProxy->origin() == kBottomLeft_GrSurfaceOrigin; 418 if (flip) { 419 top = srcSurface->height() - top - height; 420 } 421 422 GrColorType allowedColorType = fContext->priv().caps()->supportedReadPixelsColorType( 423 srcProxy->config(), dstColorType); 424 convert = convert || (dstColorType != allowedColorType); 425 426 if (!src->colorSpaceInfo().colorSpace()) { 427 // "Legacy" mode - no color space conversions. 428 dstColorSpace = nullptr; 429 } 430 convert = convert || !SkColorSpace::Equals(dstColorSpace, src->colorSpaceInfo().colorSpace()); 431 432 SkAutoPixmapStorage tempPixmap; 433 SkPixmap finalPixmap; 434 if (convert) { 435 SkColorType srcSkColorType = GrColorTypeToSkColorType(allowedColorType); 436 SkColorType dstSkColorType = GrColorTypeToSkColorType(dstColorType); 437 bool srcAlwaysOpaque = SkColorTypeIsAlwaysOpaque(srcSkColorType); 438 bool dstAlwaysOpaque = SkColorTypeIsAlwaysOpaque(dstSkColorType); 439 if (kUnknown_SkColorType == srcSkColorType || kUnknown_SkColorType == dstSkColorType) { 440 return false; 441 } 442 auto tempAT = srcAlwaysOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType; 443 auto tempII = SkImageInfo::Make(width, height, srcSkColorType, tempAT, 444 src->colorSpaceInfo().refColorSpace()); 445 SkASSERT(!unpremul || !dstAlwaysOpaque); 446 auto finalAT = (srcAlwaysOpaque || dstAlwaysOpaque) 447 ? kOpaque_SkAlphaType 448 : unpremul ? kUnpremul_SkAlphaType : kPremul_SkAlphaType; 449 auto finalII = 450 SkImageInfo::Make(width, height, dstSkColorType, finalAT, sk_ref_sp(dstColorSpace)); 451 if (!SkImageInfoValidConversion(finalII, tempII)) { 452 return false; 453 } 454 if (!tempPixmap.tryAlloc(tempII)) { 455 return false; 456 } 457 finalPixmap.reset(finalII, buffer, rowBytes); 458 buffer = tempPixmap.writable_addr(); 459 rowBytes = tempPixmap.rowBytes(); 460 // Chrome msan bots require this. 461 sk_bzero(buffer, tempPixmap.computeByteSize()); 462 } 463 464 if (srcSurface->surfacePriv().hasPendingWrite()) { 465 this->flush(nullptr); // MDB TODO: tighten this 466 } 467 468 if (!fContext->fGpu->readPixels(srcSurface, left, top, width, height, allowedColorType, buffer, 469 rowBytes)) { 470 return false; 471 } 472 473 if (flip) { 474 size_t trimRowBytes = GrColorTypeBytesPerPixel(allowedColorType) * width; 475 std::unique_ptr<char[]> row(new char[trimRowBytes]); 476 char* upper = reinterpret_cast<char*>(buffer); 477 char* lower = reinterpret_cast<char*>(buffer) + (height - 1) * rowBytes; 478 for (int y = 0; y < height / 2; ++y, upper += rowBytes, lower -= rowBytes) { 479 memcpy(row.get(), upper, trimRowBytes); 480 memcpy(upper, lower, trimRowBytes); 481 memcpy(lower, row.get(), trimRowBytes); 482 } 483 } 484 if (convert) { 485 if (!tempPixmap.readPixels(finalPixmap)) { 486 return false; 487 } 488 } 489 return true; 490 } 491 492 bool GrContextPriv::writeSurfacePixels(GrSurfaceContext* dst, int left, int top, int width, 493 int height, GrColorType srcColorType, 494 SkColorSpace* srcColorSpace, const void* buffer, 495 size_t rowBytes, uint32_t pixelOpsFlags) { 496 ASSERT_SINGLE_OWNER_PRIV 497 RETURN_FALSE_IF_ABANDONED_PRIV 498 SkASSERT(dst); 499 SkASSERT(buffer); 500 ASSERT_OWNED_PROXY_PRIV(dst->asSurfaceProxy()); 501 GR_CREATE_TRACE_MARKER_CONTEXT("GrContextPriv", "writeSurfacePixels", fContext); 502 503 if (GrColorType::kUnknown == srcColorType) { 504 return false; 505 } 506 507 if (!dst->asSurfaceProxy()->instantiate(this->resourceProvider())) { 508 return false; 509 } 510 511 GrSurfaceProxy* dstProxy = dst->asSurfaceProxy(); 512 GrSurface* dstSurface = dstProxy->peekSurface(); 513 514 if (!GrSurfacePriv::AdjustWritePixelParams(dstSurface->width(), dstSurface->height(), 515 GrColorTypeBytesPerPixel(srcColorType), &left, &top, 516 &width, &height, &buffer, &rowBytes)) { 517 return false; 518 } 519 520 // TODO: Make GrSurfaceContext know its alpha type and pass src buffer's alpha type. 521 bool premul = SkToBool(kUnpremul_PixelOpsFlag & pixelOpsFlags); 522 523 // For canvas2D putImageData performance we have a special code path for unpremul RGBA_8888 srcs 524 // that are premultiplied on the GPU. This is kept as narrow as possible for now. 525 bool canvas2DFastPath = 526 !fContext->priv().caps()->avoidWritePixelsFastPath() && 527 premul && 528 !dst->colorSpaceInfo().colorSpace() && 529 (srcColorType == GrColorType::kRGBA_8888 || srcColorType == GrColorType::kBGRA_8888) && 530 SkToBool(dst->asRenderTargetContext()) && 531 (dstProxy->config() == kRGBA_8888_GrPixelConfig || 532 dstProxy->config() == kBGRA_8888_GrPixelConfig) && 533 !(pixelOpsFlags & kDontFlush_PixelOpsFlag) && 534 fContext->priv().caps()->isConfigTexturable(kRGBA_8888_GrPixelConfig) && 535 fContext->validPMUPMConversionExists(); 536 537 const GrCaps* caps = this->caps(); 538 if (!caps->surfaceSupportsWritePixels(dstSurface) || 539 canvas2DFastPath) { 540 // We don't expect callers that are skipping flushes to require an intermediate draw. 541 SkASSERT(!(pixelOpsFlags & kDontFlush_PixelOpsFlag)); 542 if (pixelOpsFlags & kDontFlush_PixelOpsFlag) { 543 return false; 544 } 545 546 GrSurfaceDesc desc; 547 desc.fWidth = width; 548 desc.fHeight = height; 549 desc.fSampleCnt = 1; 550 551 GrBackendFormat format; 552 if (canvas2DFastPath) { 553 desc.fConfig = kRGBA_8888_GrPixelConfig; 554 format = 555 fContext->priv().caps()->getBackendFormatFromColorType(kRGBA_8888_SkColorType); 556 } else { 557 desc.fConfig = dstProxy->config(); 558 format = dstProxy->backendFormat().makeTexture2D(); 559 if (!format.isValid()) { 560 return false; 561 } 562 } 563 564 auto tempProxy = this->proxyProvider()->createProxy( 565 format, desc, kTopLeft_GrSurfaceOrigin, SkBackingFit::kApprox, SkBudgeted::kYes); 566 if (!tempProxy) { 567 return false; 568 } 569 auto tempCtx = this->drawingManager()->makeTextureContext( 570 tempProxy, dst->colorSpaceInfo().refColorSpace()); 571 if (!tempCtx) { 572 return false; 573 } 574 uint32_t flags = canvas2DFastPath ? 0 : pixelOpsFlags; 575 // In the fast path we always write the srcData to the temp context as though it were RGBA. 576 // When the data is really BGRA the write will cause the R and B channels to be swapped in 577 // the intermediate surface which gets corrected by a swizzle effect when drawing to the 578 // dst. 579 auto tmpColorType = canvas2DFastPath ? GrColorType::kRGBA_8888 : srcColorType; 580 if (!this->writeSurfacePixels(tempCtx.get(), 0, 0, width, height, tmpColorType, 581 srcColorSpace, buffer, rowBytes, flags)) { 582 return false; 583 } 584 if (canvas2DFastPath) { 585 GrPaint paint; 586 paint.setPorterDuffXPFactory(SkBlendMode::kSrc); 587 auto fp = fContext->createUPMToPMEffect( 588 GrSimpleTextureEffect::Make(std::move(tempProxy), SkMatrix::I())); 589 if (srcColorType == GrColorType::kBGRA_8888) { 590 fp = GrFragmentProcessor::SwizzleOutput(std::move(fp), GrSwizzle::BGRA()); 591 } 592 if (!fp) { 593 return false; 594 } 595 paint.addColorFragmentProcessor(std::move(fp)); 596 dst->asRenderTargetContext()->fillRectToRect( 597 GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), 598 SkRect::MakeXYWH(left, top, width, height), SkRect::MakeWH(width, height)); 599 return true; 600 } else { 601 return dst->copy(tempProxy.get(), SkIRect::MakeWH(width, height), {left, top}); 602 } 603 } 604 605 bool convert = premul; 606 607 if (!valid_pixel_conversion(srcColorType, dstProxy->config(), premul)) { 608 return false; 609 } 610 611 GrColorType allowedColorType = fContext->priv().caps()->supportedWritePixelsColorType( 612 dstProxy->config(), srcColorType); 613 convert = convert || (srcColorType != allowedColorType); 614 615 if (!dst->colorSpaceInfo().colorSpace()) { 616 // "Legacy" mode - no color space conversions. 617 srcColorSpace = nullptr; 618 } 619 convert = convert || !SkColorSpace::Equals(srcColorSpace, dst->colorSpaceInfo().colorSpace()); 620 621 std::unique_ptr<char[]> tempBuffer; 622 if (convert) { 623 auto srcSkColorType = GrColorTypeToSkColorType(srcColorType); 624 auto dstSkColorType = GrColorTypeToSkColorType(allowedColorType); 625 if (kUnknown_SkColorType == srcSkColorType || kUnknown_SkColorType == dstSkColorType) { 626 return false; 627 } 628 auto srcAlphaType = SkColorTypeIsAlwaysOpaque(srcSkColorType) 629 ? kOpaque_SkAlphaType 630 : (premul ? kUnpremul_SkAlphaType : kPremul_SkAlphaType); 631 SkPixmap src(SkImageInfo::Make(width, height, srcSkColorType, srcAlphaType, 632 sk_ref_sp(srcColorSpace)), 633 buffer, rowBytes); 634 auto tempSrcII = SkImageInfo::Make(width, height, dstSkColorType, kPremul_SkAlphaType, 635 dst->colorSpaceInfo().refColorSpace()); 636 auto size = tempSrcII.computeMinByteSize(); 637 if (!size) { 638 return false; 639 } 640 tempBuffer.reset(new char[size]); 641 SkPixmap tempSrc(tempSrcII, tempBuffer.get(), tempSrcII.minRowBytes()); 642 if (!src.readPixels(tempSrc)) { 643 return false; 644 } 645 srcColorType = allowedColorType; 646 buffer = tempSrc.addr(); 647 rowBytes = tempSrc.rowBytes(); 648 if (dstProxy->origin() == kBottomLeft_GrSurfaceOrigin) { 649 std::unique_ptr<char[]> row(new char[rowBytes]); 650 for (int y = 0; y < height / 2; ++y) { 651 memcpy(row.get(), tempSrc.addr(0, y), rowBytes); 652 memcpy(tempSrc.writable_addr(0, y), tempSrc.addr(0, height - 1 - y), rowBytes); 653 memcpy(tempSrc.writable_addr(0, height - 1 - y), row.get(), rowBytes); 654 } 655 top = dstSurface->height() - top - height; 656 } 657 } else if (dstProxy->origin() == kBottomLeft_GrSurfaceOrigin) { 658 size_t trimRowBytes = GrColorTypeBytesPerPixel(srcColorType) * width; 659 tempBuffer.reset(new char[trimRowBytes * height]); 660 char* dst = reinterpret_cast<char*>(tempBuffer.get()) + trimRowBytes * (height - 1); 661 const char* src = reinterpret_cast<const char*>(buffer); 662 for (int i = 0; i < height; ++i, src += rowBytes, dst -= trimRowBytes) { 663 memcpy(dst, src, trimRowBytes); 664 } 665 buffer = tempBuffer.get(); 666 rowBytes = trimRowBytes; 667 top = dstSurface->height() - top - height; 668 } 669 670 if (!(kDontFlush_PixelOpsFlag & pixelOpsFlags) && dstSurface->surfacePriv().hasPendingIO()) { 671 this->flush(nullptr); // MDB TODO: tighten this 672 } 673 674 return this->getGpu()->writePixels(dstSurface, left, top, width, height, srcColorType, buffer, 675 rowBytes); 676 } 677 678 void GrContextPriv::moveOpListsToDDL(SkDeferredDisplayList* ddl) { 679 fContext->drawingManager()->moveOpListsToDDL(ddl); 680 } 681 682 void GrContextPriv::copyOpListsFromDDL(const SkDeferredDisplayList* ddl, 683 GrRenderTargetProxy* newDest) { 684 fContext->drawingManager()->copyOpListsFromDDL(ddl, newDest); 685 } 686 687 ////////////////////////////////////////////////////////////////////////////// 688 #ifdef SK_ENABLE_DUMP_GPU 689 #include "SkJSONWriter.h" 690 SkString GrContextPriv::dump() const { 691 SkDynamicMemoryWStream stream; 692 SkJSONWriter writer(&stream, SkJSONWriter::Mode::kPretty); 693 writer.beginObject(); 694 695 static const char* kBackendStr[] = { 696 "Metal", 697 "OpenGL", 698 "Vulkan", 699 "Mock", 700 }; 701 GR_STATIC_ASSERT(0 == (unsigned)GrBackendApi::kMetal); 702 GR_STATIC_ASSERT(1 == (unsigned)GrBackendApi::kOpenGL); 703 GR_STATIC_ASSERT(2 == (unsigned)GrBackendApi::kVulkan); 704 GR_STATIC_ASSERT(3 == (unsigned)GrBackendApi::kMock); 705 writer.appendString("backend", kBackendStr[(unsigned)fContext->backend()]); 706 707 writer.appendName("caps"); 708 fContext->caps()->dumpJSON(&writer); 709 710 writer.appendName("gpu"); 711 fContext->fGpu->dumpJSON(&writer); 712 713 // Flush JSON to the memory stream 714 writer.endObject(); 715 writer.flush(); 716 717 // Null terminate the JSON data in the memory stream 718 stream.write8(0); 719 720 // Allocate a string big enough to hold all the data, then copy out of the stream 721 SkString result(stream.bytesWritten()); 722 stream.copyToAndReset(result.writable_str()); 723 return result; 724 } 725 #endif 726 727 #if GR_TEST_UTILS 728 void GrContextPriv::resetGpuStats() const { 729 #if GR_GPU_STATS 730 fContext->fGpu->stats()->reset(); 731 #endif 732 } 733 734 void GrContextPriv::dumpCacheStats(SkString* out) const { 735 #if GR_CACHE_STATS 736 fContext->fResourceCache->dumpStats(out); 737 #endif 738 } 739 740 void GrContextPriv::dumpCacheStatsKeyValuePairs(SkTArray<SkString>* keys, 741 SkTArray<double>* values) const { 742 #if GR_CACHE_STATS 743 fContext->fResourceCache->dumpStatsKeyValuePairs(keys, values); 744 #endif 745 } 746 747 void GrContextPriv::printCacheStats() const { 748 SkString out; 749 this->dumpCacheStats(&out); 750 SkDebugf("%s", out.c_str()); 751 } 752 753 void GrContextPriv::dumpGpuStats(SkString* out) const { 754 #if GR_GPU_STATS 755 return fContext->fGpu->stats()->dump(out); 756 #endif 757 } 758 759 void GrContextPriv::dumpGpuStatsKeyValuePairs(SkTArray<SkString>* keys, 760 SkTArray<double>* values) const { 761 #if GR_GPU_STATS 762 return fContext->fGpu->stats()->dumpKeyValuePairs(keys, values); 763 #endif 764 } 765 766 void GrContextPriv::printGpuStats() const { 767 SkString out; 768 this->dumpGpuStats(&out); 769 SkDebugf("%s", out.c_str()); 770 } 771 772 void GrContextPriv::testingOnly_setTextBlobCacheLimit(size_t bytes) { 773 fContext->priv().getTextBlobCache()->setBudget(bytes); 774 } 775 776 sk_sp<SkImage> GrContextPriv::testingOnly_getFontAtlasImage(GrMaskFormat format, unsigned int index) { 777 auto atlasManager = this->getAtlasManager(); 778 if (!atlasManager) { 779 return nullptr; 780 } 781 782 unsigned int numActiveProxies; 783 const sk_sp<GrTextureProxy>* proxies = atlasManager->getProxies(format, &numActiveProxies); 784 if (index >= numActiveProxies || !proxies || !proxies[index]) { 785 return nullptr; 786 } 787 788 SkASSERT(proxies[index]->priv().isExact()); 789 sk_sp<SkImage> image(new SkImage_Gpu(sk_ref_sp(fContext), kNeedNewImageUniqueID, 790 kPremul_SkAlphaType, proxies[index], nullptr)); 791 return image; 792 } 793 794 void GrContextPriv::testingOnly_purgeAllUnlockedResources() { 795 fContext->fResourceCache->purgeAllUnlocked(); 796 } 797 798 void GrContextPriv::testingOnly_flushAndRemoveOnFlushCallbackObject(GrOnFlushCallbackObject* cb) { 799 fContext->flush(); 800 fContext->drawingManager()->testingOnly_removeOnFlushCallbackObject(cb); 801 } 802 #endif 803 804