1 /* 2 * Copyright 2011 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 "GrContext.h" 9 #include "GrClip.h" 10 #include "GrContextOptions.h" 11 #include "GrContextPriv.h" 12 #include "GrDrawingManager.h" 13 #include "GrRenderTargetContext.h" 14 #include "GrRenderTargetProxy.h" 15 #include "GrResourceCache.h" 16 #include "GrResourceProvider.h" 17 #include "GrSemaphore.h" 18 #include "GrSoftwarePathRenderer.h" 19 #include "GrSurfaceContext.h" 20 #include "GrSurfacePriv.h" 21 #include "GrSurfaceProxyPriv.h" 22 #include "GrTextureContext.h" 23 #include "SkConvertPixels.h" 24 #include "SkGr.h" 25 #include "SkUnPreMultiplyPriv.h" 26 #include "effects/GrConfigConversionEffect.h" 27 #include "text/GrTextBlobCache.h" 28 29 #define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this) 30 #define ASSERT_SINGLE_OWNER \ 31 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(&fSingleOwner);) 32 #define ASSERT_SINGLE_OWNER_PRIV \ 33 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(&fContext->fSingleOwner);) 34 #define RETURN_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return; } 35 #define RETURN_FALSE_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return false; } 36 #define RETURN_NULL_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return nullptr; } 37 38 //////////////////////////////////////////////////////////////////////////////// 39 40 GrContext* GrContext::Create(GrBackend backend, GrBackendContext backendContext) { 41 GrContextOptions defaultOptions; 42 return Create(backend, backendContext, defaultOptions); 43 } 44 45 GrContext* GrContext::Create(GrBackend backend, GrBackendContext backendContext, 46 const GrContextOptions& options) { 47 GrContext* context = new GrContext; 48 49 if (context->init(backend, backendContext, options)) { 50 return context; 51 } else { 52 context->unref(); 53 return nullptr; 54 } 55 } 56 57 static int32_t gNextID = 1; 58 static int32_t next_id() { 59 int32_t id; 60 do { 61 id = sk_atomic_inc(&gNextID); 62 } while (id == SK_InvalidGenID); 63 return id; 64 } 65 66 GrContext::GrContext() : fUniqueID(next_id()) { 67 fGpu = nullptr; 68 fCaps = nullptr; 69 fResourceCache = nullptr; 70 fResourceProvider = nullptr; 71 fAtlasGlyphCache = nullptr; 72 } 73 74 bool GrContext::init(GrBackend backend, GrBackendContext backendContext, 75 const GrContextOptions& options) { 76 ASSERT_SINGLE_OWNER 77 SkASSERT(!fGpu); 78 79 fGpu = GrGpu::Create(backend, backendContext, options, this); 80 if (!fGpu) { 81 return false; 82 } 83 this->initCommon(options); 84 return true; 85 } 86 87 void GrContext::initCommon(const GrContextOptions& options) { 88 ASSERT_SINGLE_OWNER 89 90 fCaps = SkRef(fGpu->caps()); 91 fResourceCache = new GrResourceCache(fCaps); 92 fResourceProvider = new GrResourceProvider(fGpu, fResourceCache, &fSingleOwner); 93 94 fDisableGpuYUVConversion = options.fDisableGpuYUVConversion; 95 fDidTestPMConversions = false; 96 97 GrRenderTargetOpList::Options rtOpListOptions; 98 rtOpListOptions.fMaxOpCombineLookback = options.fMaxOpCombineLookback; 99 rtOpListOptions.fMaxOpCombineLookahead = options.fMaxOpCombineLookahead; 100 GrPathRendererChain::Options prcOptions; 101 prcOptions.fAllowPathMaskCaching = options.fAllowPathMaskCaching; 102 prcOptions.fGpuPathRenderers = options.fGpuPathRenderers; 103 fDrawingManager.reset(new GrDrawingManager(this, rtOpListOptions, prcOptions, 104 options.fImmediateMode, &fSingleOwner)); 105 106 fAtlasGlyphCache = new GrAtlasGlyphCache(this); 107 108 fTextBlobCache.reset(new GrTextBlobCache(TextBlobCacheOverBudgetCB, this)); 109 } 110 111 GrContext::~GrContext() { 112 ASSERT_SINGLE_OWNER 113 114 if (!fGpu) { 115 SkASSERT(!fCaps); 116 return; 117 } 118 119 this->flush(); 120 121 fDrawingManager->cleanup(); 122 123 for (int i = 0; i < fCleanUpData.count(); ++i) { 124 (*fCleanUpData[i].fFunc)(this, fCleanUpData[i].fInfo); 125 } 126 127 delete fResourceProvider; 128 delete fResourceCache; 129 delete fAtlasGlyphCache; 130 131 fGpu->unref(); 132 fCaps->unref(); 133 } 134 135 sk_sp<GrContextThreadSafeProxy> GrContext::threadSafeProxy() { 136 if (!fThreadSafeProxy) { 137 fThreadSafeProxy.reset(new GrContextThreadSafeProxy(sk_ref_sp(fCaps), this->uniqueID())); 138 } 139 return fThreadSafeProxy; 140 } 141 142 void GrContext::abandonContext() { 143 ASSERT_SINGLE_OWNER 144 145 fResourceProvider->abandon(); 146 147 // Need to abandon the drawing manager first so all the render targets 148 // will be released/forgotten before they too are abandoned. 149 fDrawingManager->abandon(); 150 151 // abandon first to so destructors 152 // don't try to free the resources in the API. 153 fResourceCache->abandonAll(); 154 155 fGpu->disconnect(GrGpu::DisconnectType::kAbandon); 156 157 fAtlasGlyphCache->freeAll(); 158 fTextBlobCache->freeAll(); 159 } 160 161 void GrContext::releaseResourcesAndAbandonContext() { 162 ASSERT_SINGLE_OWNER 163 164 fResourceProvider->abandon(); 165 166 // Need to abandon the drawing manager first so all the render targets 167 // will be released/forgotten before they too are abandoned. 168 fDrawingManager->abandon(); 169 170 // Release all resources in the backend 3D API. 171 fResourceCache->releaseAll(); 172 173 fGpu->disconnect(GrGpu::DisconnectType::kCleanup); 174 175 fAtlasGlyphCache->freeAll(); 176 fTextBlobCache->freeAll(); 177 } 178 179 void GrContext::resetContext(uint32_t state) { 180 ASSERT_SINGLE_OWNER 181 fGpu->markContextDirty(state); 182 } 183 184 void GrContext::freeGpuResources() { 185 ASSERT_SINGLE_OWNER 186 187 this->flush(); 188 189 fAtlasGlyphCache->freeAll(); 190 191 fDrawingManager->freeGpuResources(); 192 193 fResourceCache->purgeAllUnlocked(); 194 } 195 196 void GrContext::purgeResourcesNotUsedInMs(std::chrono::milliseconds ms) { 197 ASSERT_SINGLE_OWNER 198 fResourceCache->purgeResourcesNotUsedSince(GrStdSteadyClock::now() - ms); 199 } 200 201 void GrContext::getResourceCacheUsage(int* resourceCount, size_t* resourceBytes) const { 202 ASSERT_SINGLE_OWNER 203 204 if (resourceCount) { 205 *resourceCount = fResourceCache->getBudgetedResourceCount(); 206 } 207 if (resourceBytes) { 208 *resourceBytes = fResourceCache->getBudgetedResourceBytes(); 209 } 210 } 211 212 //////////////////////////////////////////////////////////////////////////////// 213 214 void GrContext::TextBlobCacheOverBudgetCB(void* data) { 215 SkASSERT(data); 216 // TextBlobs are drawn at the SkGpuDevice level, therefore they cannot rely on 217 // GrRenderTargetContext to perform a necessary flush. The solution is to move drawText calls 218 // to below the GrContext level, but this is not trivial because they call drawPath on 219 // SkGpuDevice. 220 GrContext* context = reinterpret_cast<GrContext*>(data); 221 context->flush(); 222 } 223 224 //////////////////////////////////////////////////////////////////////////////// 225 226 void GrContext::flush() { 227 ASSERT_SINGLE_OWNER 228 RETURN_IF_ABANDONED 229 fDrawingManager->flush(); 230 } 231 232 bool sw_convert_to_premul(GrPixelConfig srcConfig, int width, int height, size_t inRowBytes, 233 const void* inPixels, size_t outRowBytes, void* outPixels) { 234 SkColorType colorType; 235 if (!GrPixelConfigToColorType(srcConfig, &colorType) || 236 4 != SkColorTypeBytesPerPixel(colorType)) 237 { 238 return false; 239 } 240 241 for (int y = 0; y < height; y++) { 242 SkOpts::RGBA_to_rgbA((uint32_t*) outPixels, inPixels, width); 243 outPixels = SkTAddOffset<void>(outPixels, outRowBytes); 244 inPixels = SkTAddOffset<const void>(inPixels, inRowBytes); 245 } 246 247 return true; 248 } 249 250 static bool valid_unpremul_config(GrPixelConfig config) { 251 return GrPixelConfigIs8888Unorm(config) || kRGBA_half_GrPixelConfig == config; 252 } 253 254 bool GrContext::writeSurfacePixels(GrSurface* surface, SkColorSpace* dstColorSpace, 255 int left, int top, int width, int height, 256 GrPixelConfig srcConfig, SkColorSpace* srcColorSpace, 257 const void* buffer, size_t rowBytes, uint32_t pixelOpsFlags) { 258 // TODO: Color space conversion 259 260 ASSERT_SINGLE_OWNER 261 RETURN_FALSE_IF_ABANDONED 262 ASSERT_OWNED_RESOURCE(surface); 263 SkASSERT(surface); 264 GR_AUDIT_TRAIL_AUTO_FRAME(&fAuditTrail, "GrContext::writeSurfacePixels"); 265 266 this->testPMConversionsIfNecessary(pixelOpsFlags); 267 268 // Trim the params here so that if we wind up making a temporary surface it can be as small as 269 // necessary and because GrGpu::getWritePixelsInfo requires it. 270 if (!GrSurfacePriv::AdjustWritePixelParams(surface->width(), surface->height(), 271 GrBytesPerPixel(srcConfig), &left, &top, &width, 272 &height, &buffer, &rowBytes)) { 273 return false; 274 } 275 276 bool applyPremulToSrc = SkToBool(kUnpremul_PixelOpsFlag & pixelOpsFlags); 277 if (applyPremulToSrc && !valid_unpremul_config(srcConfig)) { 278 return false; 279 } 280 // We don't allow conversion between integer configs and float/fixed configs. 281 if (GrPixelConfigIsSint(surface->config()) != GrPixelConfigIsSint(srcConfig)) { 282 return false; 283 } 284 285 GrGpu::DrawPreference drawPreference = GrGpu::kNoDraw_DrawPreference; 286 // Don't prefer to draw for the conversion (and thereby access a texture from the cache) when 287 // we've already determined that there isn't a roundtrip preserving conversion processor pair. 288 if (applyPremulToSrc && this->validPMUPMConversionExists(srcConfig)) { 289 drawPreference = GrGpu::kCallerPrefersDraw_DrawPreference; 290 } 291 292 GrGpu::WritePixelTempDrawInfo tempDrawInfo; 293 if (!fGpu->getWritePixelsInfo(surface, width, height, srcConfig, &drawPreference, 294 &tempDrawInfo)) { 295 return false; 296 } 297 298 if (!(kDontFlush_PixelOpsFlag & pixelOpsFlags) && surface->surfacePriv().hasPendingIO()) { 299 this->flush(); 300 } 301 302 sk_sp<GrTextureProxy> tempProxy; 303 if (GrGpu::kNoDraw_DrawPreference != drawPreference) { 304 tempProxy = GrSurfaceProxy::MakeDeferred(this->resourceProvider(), 305 tempDrawInfo.fTempSurfaceDesc, 306 SkBackingFit::kApprox, 307 SkBudgeted::kYes); 308 if (!tempProxy && GrGpu::kRequireDraw_DrawPreference == drawPreference) { 309 return false; 310 } 311 } 312 313 // temp buffer for doing sw premul conversion, if needed. 314 SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0); 315 if (tempProxy) { 316 sk_sp<GrFragmentProcessor> fp; 317 if (applyPremulToSrc) { 318 fp = this->createUPMToPMEffect(tempProxy, SkMatrix::I()); 319 fp = GrFragmentProcessor::SwizzleOutput(std::move(fp), tempDrawInfo.fSwizzle); 320 // If premultiplying was the only reason for the draw, fall back to a straight write. 321 if (!fp) { 322 if (GrGpu::kCallerPrefersDraw_DrawPreference == drawPreference) { 323 tempProxy.reset(nullptr); 324 } 325 } else { 326 applyPremulToSrc = false; 327 } 328 } 329 if (tempProxy) { 330 if (!fp) { 331 fp = GrSimpleTextureEffect::Make(this->resourceProvider(), tempProxy, nullptr, 332 SkMatrix::I()); 333 fp = GrFragmentProcessor::SwizzleOutput(std::move(fp), tempDrawInfo.fSwizzle); 334 335 if (!fp) { 336 return false; 337 } 338 } 339 GrTexture* texture = tempProxy->instantiate(this->resourceProvider()); 340 if (!texture) { 341 return false; 342 } 343 if (texture->surfacePriv().hasPendingIO()) { 344 this->flush(); 345 } 346 if (applyPremulToSrc) { 347 size_t tmpRowBytes = 4 * width; 348 tmpPixels.reset(width * height); 349 if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer, tmpRowBytes, 350 tmpPixels.get())) { 351 return false; 352 } 353 rowBytes = tmpRowBytes; 354 buffer = tmpPixels.get(); 355 applyPremulToSrc = false; 356 } 357 if (!fGpu->writePixels(texture, 0, 0, width, height, 358 tempDrawInfo.fWriteConfig, buffer, 359 rowBytes)) { 360 return false; 361 } 362 SkMatrix matrix; 363 matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top)); 364 // TODO: Need to decide the semantics of this function for color spaces. Do we support 365 // conversion from a passed-in color space? For now, specifying nullptr means that this 366 // path will do no conversion, so it will match the behavior of the non-draw path. 367 GrRenderTarget* renderTarget = surface->asRenderTarget(); 368 SkASSERT(renderTarget); 369 sk_sp<GrRenderTargetContext> renderTargetContext( 370 this->contextPriv().makeWrappedRenderTargetContext(sk_ref_sp(renderTarget), 371 nullptr)); 372 if (!renderTargetContext) { 373 return false; 374 } 375 GrPaint paint; 376 paint.addColorFragmentProcessor(std::move(fp)); 377 paint.setPorterDuffXPFactory(SkBlendMode::kSrc); 378 paint.setAllowSRGBInputs(true); 379 SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)); 380 renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, matrix, rect, 381 nullptr); 382 383 if (kFlushWrites_PixelOp & pixelOpsFlags) { 384 this->flushSurfaceWrites(surface); 385 } 386 } 387 } 388 if (!tempProxy) { 389 if (applyPremulToSrc) { 390 size_t tmpRowBytes = 4 * width; 391 tmpPixels.reset(width * height); 392 if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer, tmpRowBytes, 393 tmpPixels.get())) { 394 return false; 395 } 396 rowBytes = tmpRowBytes; 397 buffer = tmpPixels.get(); 398 applyPremulToSrc = false; 399 } 400 return fGpu->writePixels(surface, left, top, width, height, srcConfig, buffer, rowBytes); 401 } 402 return true; 403 } 404 405 bool GrContext::readSurfacePixels(GrSurface* src, SkColorSpace* srcColorSpace, 406 int left, int top, int width, int height, 407 GrPixelConfig dstConfig, SkColorSpace* dstColorSpace, 408 void* buffer, size_t rowBytes, uint32_t flags) { 409 // TODO: Color space conversion 410 411 ASSERT_SINGLE_OWNER 412 RETURN_FALSE_IF_ABANDONED 413 ASSERT_OWNED_RESOURCE(src); 414 SkASSERT(src); 415 GR_AUDIT_TRAIL_AUTO_FRAME(&fAuditTrail, "GrContext::readSurfacePixels"); 416 417 this->testPMConversionsIfNecessary(flags); 418 419 // Adjust the params so that if we wind up using an intermediate surface we've already done 420 // all the trimming and the temporary can be the min size required. 421 if (!GrSurfacePriv::AdjustReadPixelParams(src->width(), src->height(), 422 GrBytesPerPixel(dstConfig), &left, 423 &top, &width, &height, &buffer, &rowBytes)) { 424 return false; 425 } 426 427 if (!(kDontFlush_PixelOpsFlag & flags) && src->surfacePriv().hasPendingWrite()) { 428 this->flush(); 429 } 430 431 bool unpremul = SkToBool(kUnpremul_PixelOpsFlag & flags); 432 if (unpremul && !valid_unpremul_config(dstConfig)) { 433 // The unpremul flag is only allowed for 8888 and F16 configs. 434 return false; 435 } 436 // We don't allow conversion between integer configs and float/fixed configs. 437 if (GrPixelConfigIsSint(src->config()) != GrPixelConfigIsSint(dstConfig)) { 438 return false; 439 } 440 441 GrGpu::DrawPreference drawPreference = GrGpu::kNoDraw_DrawPreference; 442 // Don't prefer to draw for the conversion (and thereby access a texture from the cache) when 443 // we've already determined that there isn't a roundtrip preserving conversion processor pair. 444 if (unpremul && this->validPMUPMConversionExists(src->config())) { 445 drawPreference = GrGpu::kCallerPrefersDraw_DrawPreference; 446 } 447 448 GrGpu::ReadPixelTempDrawInfo tempDrawInfo; 449 if (!fGpu->getReadPixelsInfo(src, width, height, rowBytes, dstConfig, &drawPreference, 450 &tempDrawInfo)) { 451 return false; 452 } 453 454 sk_sp<GrSurface> surfaceToRead(SkRef(src)); 455 bool didTempDraw = false; 456 if (GrGpu::kNoDraw_DrawPreference != drawPreference) { 457 if (SkBackingFit::kExact == tempDrawInfo.fTempSurfaceFit) { 458 // We only respect this when the entire src is being read. Otherwise we can trigger too 459 // many odd ball texture sizes and trash the cache. 460 if (width != src->width() || height != src->height()) { 461 tempDrawInfo.fTempSurfaceFit= SkBackingFit::kApprox; 462 } 463 } 464 // TODO: Need to decide the semantics of this function for color spaces. Do we support 465 // conversion to a passed-in color space? For now, specifying nullptr means that this 466 // path will do no conversion, so it will match the behavior of the non-draw path. 467 sk_sp<GrRenderTargetContext> tempRTC = this->makeRenderTargetContext( 468 tempDrawInfo.fTempSurfaceFit, 469 tempDrawInfo.fTempSurfaceDesc.fWidth, 470 tempDrawInfo.fTempSurfaceDesc.fHeight, 471 tempDrawInfo.fTempSurfaceDesc.fConfig, 472 nullptr, 473 tempDrawInfo.fTempSurfaceDesc.fSampleCnt, 474 tempDrawInfo.fTempSurfaceDesc.fOrigin); 475 if (tempRTC) { 476 SkMatrix textureMatrix = SkMatrix::MakeTrans(SkIntToScalar(left), SkIntToScalar(top)); 477 sk_sp<GrFragmentProcessor> fp; 478 if (unpremul) { 479 fp = this->createPMToUPMEffect(src->asTexture(), textureMatrix); 480 fp = GrFragmentProcessor::SwizzleOutput(std::move(fp), tempDrawInfo.fSwizzle); 481 if (fp) { 482 unpremul = false; // we no longer need to do this on CPU after the read back. 483 } else if (GrGpu::kCallerPrefersDraw_DrawPreference == drawPreference) { 484 // We only wanted to do the draw in order to perform the unpremul so don't 485 // bother. 486 tempRTC.reset(nullptr); 487 } 488 } 489 if (!fp && tempRTC) { 490 fp = GrSimpleTextureEffect::Make(src->asTexture(), nullptr, textureMatrix); 491 fp = GrFragmentProcessor::SwizzleOutput(std::move(fp), tempDrawInfo.fSwizzle); 492 } 493 if (fp) { 494 GrPaint paint; 495 paint.addColorFragmentProcessor(std::move(fp)); 496 paint.setPorterDuffXPFactory(SkBlendMode::kSrc); 497 paint.setAllowSRGBInputs(true); 498 SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)); 499 tempRTC->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), rect, 500 nullptr); 501 surfaceToRead.reset(tempRTC->asTexture().release()); 502 left = 0; 503 top = 0; 504 didTempDraw = true; 505 } 506 } 507 } 508 509 if (!surfaceToRead) { 510 return false; 511 } 512 513 if (GrGpu::kRequireDraw_DrawPreference == drawPreference && !didTempDraw) { 514 return false; 515 } 516 GrPixelConfig configToRead = dstConfig; 517 if (didTempDraw) { 518 this->flushSurfaceWrites(surfaceToRead.get()); 519 configToRead = tempDrawInfo.fReadConfig; 520 } 521 if (!fGpu->readPixels(surfaceToRead.get(), left, top, width, height, configToRead, buffer, 522 rowBytes)) { 523 return false; 524 } 525 526 // Perform umpremul conversion if we weren't able to perform it as a draw. 527 if (unpremul) { 528 SkColorType colorType; 529 if (!GrPixelConfigToColorType(dstConfig, &colorType) || 530 4 != SkColorTypeBytesPerPixel(colorType)) 531 { 532 return false; 533 } 534 535 for (int y = 0; y < height; y++) { 536 SkUnpremultiplyRow<false>((uint32_t*) buffer, (const uint32_t*) buffer, width); 537 buffer = SkTAddOffset<void>(buffer, rowBytes); 538 } 539 } 540 return true; 541 } 542 543 void GrContext::prepareSurfaceForExternalIO(GrSurface* surface) { 544 ASSERT_SINGLE_OWNER 545 RETURN_IF_ABANDONED 546 SkASSERT(surface); 547 ASSERT_OWNED_RESOURCE(surface); 548 fDrawingManager->prepareSurfaceForExternalIO(surface); 549 } 550 551 void GrContext::flushSurfaceWrites(GrSurface* surface) { 552 ASSERT_SINGLE_OWNER 553 RETURN_IF_ABANDONED 554 if (surface->surfacePriv().hasPendingWrite()) { 555 this->flush(); 556 } 557 } 558 559 void GrContext::flushSurfaceIO(GrSurface* surface) { 560 ASSERT_SINGLE_OWNER 561 RETURN_IF_ABANDONED 562 if (surface->surfacePriv().hasPendingIO()) { 563 this->flush(); 564 } 565 } 566 567 //////////////////////////////////////////////////////////////////////////////// 568 int GrContext::getRecommendedSampleCount(GrPixelConfig config, 569 SkScalar dpi) const { 570 ASSERT_SINGLE_OWNER 571 572 if (!this->caps()->isConfigRenderable(config, true)) { 573 return 0; 574 } 575 int chosenSampleCount = 0; 576 if (fGpu->caps()->shaderCaps()->pathRenderingSupport()) { 577 if (dpi >= 250.0f) { 578 chosenSampleCount = 4; 579 } else { 580 chosenSampleCount = 16; 581 } 582 } 583 return chosenSampleCount <= fGpu->caps()->maxSampleCount() ? chosenSampleCount : 0; 584 } 585 586 sk_sp<GrRenderTargetContext> GrContextPriv::makeWrappedRenderTargetContext( 587 sk_sp<GrRenderTarget> rt, 588 sk_sp<SkColorSpace> colorSpace, 589 const SkSurfaceProps* surfaceProps) { 590 ASSERT_SINGLE_OWNER_PRIV 591 592 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(rt))); 593 if (!proxy) { 594 return nullptr; 595 } 596 597 return this->drawingManager()->makeRenderTargetContext(std::move(proxy), 598 std::move(colorSpace), 599 surfaceProps); 600 } 601 602 sk_sp<GrSurfaceContext> GrContextPriv::makeWrappedSurfaceContext(sk_sp<GrSurfaceProxy> proxy, 603 sk_sp<SkColorSpace> colorSpace) { 604 ASSERT_SINGLE_OWNER_PRIV 605 606 if (proxy->asRenderTargetProxy()) { 607 return this->drawingManager()->makeRenderTargetContext(std::move(proxy), 608 std::move(colorSpace), nullptr); 609 } else { 610 SkASSERT(proxy->asTextureProxy()); 611 return this->drawingManager()->makeTextureContext(std::move(proxy), std::move(colorSpace)); 612 } 613 } 614 615 sk_sp<GrSurfaceContext> GrContextPriv::makeWrappedSurfaceContext(sk_sp<GrSurface> surface) { 616 ASSERT_SINGLE_OWNER_PRIV 617 618 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(surface))); 619 if (!proxy) { 620 return nullptr; 621 } 622 623 return this->makeWrappedSurfaceContext(std::move(proxy), nullptr); 624 } 625 626 sk_sp<GrSurfaceContext> GrContextPriv::makeDeferredSurfaceContext(const GrSurfaceDesc& dstDesc, 627 SkBackingFit fit, 628 SkBudgeted isDstBudgeted) { 629 630 sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferred(fContext->resourceProvider(), 631 dstDesc, fit, isDstBudgeted); 632 if (!proxy) { 633 return nullptr; 634 } 635 636 return this->makeWrappedSurfaceContext(std::move(proxy), nullptr); 637 } 638 639 sk_sp<GrSurfaceContext> GrContextPriv::makeBackendSurfaceContext(const GrBackendTextureDesc& desc, 640 sk_sp<SkColorSpace> colorSpace) { 641 ASSERT_SINGLE_OWNER_PRIV 642 643 sk_sp<GrSurface> surface(fContext->resourceProvider()->wrapBackendTexture(desc)); 644 if (!surface) { 645 return nullptr; 646 } 647 648 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(surface))); 649 if (!proxy) { 650 return nullptr; 651 } 652 653 return this->makeWrappedSurfaceContext(std::move(proxy), std::move(colorSpace)); 654 } 655 656 sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendTextureRenderTargetContext( 657 const GrBackendTextureDesc& desc, 658 sk_sp<SkColorSpace> colorSpace, 659 const SkSurfaceProps* props) { 660 ASSERT_SINGLE_OWNER_PRIV 661 SkASSERT(desc.fFlags & kRenderTarget_GrBackendTextureFlag); 662 663 sk_sp<GrSurface> surface(fContext->resourceProvider()->wrapBackendTexture(desc)); 664 if (!surface) { 665 return nullptr; 666 } 667 668 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(surface))); 669 if (!proxy) { 670 return nullptr; 671 } 672 673 return this->drawingManager()->makeRenderTargetContext(std::move(proxy), 674 std::move(colorSpace), props); 675 } 676 677 sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendRenderTargetRenderTargetContext( 678 const GrBackendRenderTargetDesc& desc, 679 sk_sp<SkColorSpace> colorSpace, 680 const SkSurfaceProps* surfaceProps) { 681 ASSERT_SINGLE_OWNER_PRIV 682 683 sk_sp<GrRenderTarget> rt(fContext->resourceProvider()->wrapBackendRenderTarget(desc)); 684 if (!rt) { 685 return nullptr; 686 } 687 688 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(rt))); 689 if (!proxy) { 690 return nullptr; 691 } 692 693 return this->drawingManager()->makeRenderTargetContext(std::move(proxy), 694 std::move(colorSpace), 695 surfaceProps); 696 } 697 698 sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendTextureAsRenderTargetRenderTargetContext( 699 const GrBackendTextureDesc& desc, 700 sk_sp<SkColorSpace> colorSpace, 701 const SkSurfaceProps* surfaceProps) { 702 ASSERT_SINGLE_OWNER_PRIV 703 SkASSERT(desc.fFlags & kRenderTarget_GrBackendTextureFlag); 704 705 sk_sp<GrSurface> surface(fContext->resourceProvider()->wrapBackendTextureAsRenderTarget(desc)); 706 if (!surface) { 707 return nullptr; 708 } 709 710 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(surface))); 711 if (!proxy) { 712 return nullptr; 713 } 714 715 return this->drawingManager()->makeRenderTargetContext(std::move(proxy), 716 std::move(colorSpace), 717 surfaceProps); 718 } 719 720 void GrContextPriv::addPreFlushCallbackObject(sk_sp<GrPreFlushCallbackObject> preFlushCBObject) { 721 fContext->fDrawingManager->addPreFlushCallbackObject(std::move(preFlushCBObject)); 722 } 723 724 725 static inline GrPixelConfig GrPixelConfigFallback(GrPixelConfig config) { 726 switch (config) { 727 case kAlpha_8_GrPixelConfig: 728 case kRGB_565_GrPixelConfig: 729 case kRGBA_4444_GrPixelConfig: 730 case kBGRA_8888_GrPixelConfig: 731 return kRGBA_8888_GrPixelConfig; 732 case kSBGRA_8888_GrPixelConfig: 733 return kSRGBA_8888_GrPixelConfig; 734 case kAlpha_half_GrPixelConfig: 735 return kRGBA_half_GrPixelConfig; 736 default: 737 return kUnknown_GrPixelConfig; 738 } 739 } 740 741 sk_sp<GrRenderTargetContext> GrContext::makeRenderTargetContextWithFallback( 742 SkBackingFit fit, 743 int width, int height, 744 GrPixelConfig config, 745 sk_sp<SkColorSpace> colorSpace, 746 int sampleCnt, 747 GrSurfaceOrigin origin, 748 const SkSurfaceProps* surfaceProps, 749 SkBudgeted budgeted) { 750 if (!this->caps()->isConfigRenderable(config, sampleCnt > 0)) { 751 config = GrPixelConfigFallback(config); 752 } 753 754 return this->makeRenderTargetContext(fit, width, height, config, std::move(colorSpace), 755 sampleCnt, origin, surfaceProps, budgeted); 756 } 757 758 sk_sp<GrRenderTargetContext> GrContext::makeDeferredRenderTargetContextWithFallback( 759 SkBackingFit fit, 760 int width, int height, 761 GrPixelConfig config, 762 sk_sp<SkColorSpace> colorSpace, 763 int sampleCnt, 764 GrSurfaceOrigin origin, 765 const SkSurfaceProps* surfaceProps, 766 SkBudgeted budgeted) { 767 if (!this->caps()->isConfigRenderable(config, sampleCnt > 0)) { 768 config = GrPixelConfigFallback(config); 769 } 770 771 return this->makeDeferredRenderTargetContext(fit, width, height, config, std::move(colorSpace), 772 sampleCnt, origin, surfaceProps, budgeted); 773 } 774 775 sk_sp<GrRenderTargetContext> GrContext::makeRenderTargetContext(SkBackingFit fit, 776 int width, int height, 777 GrPixelConfig config, 778 sk_sp<SkColorSpace> colorSpace, 779 int sampleCnt, 780 GrSurfaceOrigin origin, 781 const SkSurfaceProps* surfaceProps, 782 SkBudgeted budgeted) { 783 if (!this->caps()->isConfigRenderable(config, sampleCnt > 0)) { 784 return nullptr; 785 } 786 787 GrSurfaceDesc desc; 788 desc.fFlags = kRenderTarget_GrSurfaceFlag; 789 desc.fOrigin = origin; 790 desc.fWidth = width; 791 desc.fHeight = height; 792 desc.fConfig = config; 793 desc.fSampleCnt = sampleCnt; 794 795 sk_sp<GrTexture> tex; 796 if (SkBackingFit::kExact == fit) { 797 tex.reset(this->resourceProvider()->createTexture(desc, budgeted)); 798 } else { 799 tex.reset(this->resourceProvider()->createApproxTexture(desc, 0)); 800 } 801 if (!tex) { 802 return nullptr; 803 } 804 805 sk_sp<GrRenderTargetContext> renderTargetContext( 806 this->contextPriv().makeWrappedRenderTargetContext(sk_ref_sp(tex->asRenderTarget()), 807 std::move(colorSpace), surfaceProps)); 808 if (!renderTargetContext) { 809 return nullptr; 810 } 811 812 return renderTargetContext; 813 } 814 815 sk_sp<GrRenderTargetContext> GrContext::makeDeferredRenderTargetContext( 816 SkBackingFit fit, 817 int width, int height, 818 GrPixelConfig config, 819 sk_sp<SkColorSpace> colorSpace, 820 int sampleCnt, 821 GrSurfaceOrigin origin, 822 const SkSurfaceProps* surfaceProps, 823 SkBudgeted budgeted) { 824 GrSurfaceDesc desc; 825 desc.fFlags = kRenderTarget_GrSurfaceFlag; 826 desc.fOrigin = origin; 827 desc.fWidth = width; 828 desc.fHeight = height; 829 desc.fConfig = config; 830 desc.fSampleCnt = sampleCnt; 831 832 sk_sp<GrTextureProxy> rtp = GrSurfaceProxy::MakeDeferred(this->resourceProvider(), 833 desc, fit, budgeted); 834 if (!rtp) { 835 return nullptr; 836 } 837 838 return fDrawingManager->makeRenderTargetContext(std::move(rtp), 839 std::move(colorSpace), 840 surfaceProps); 841 } 842 843 bool GrContext::abandoned() const { 844 ASSERT_SINGLE_OWNER 845 return fDrawingManager->wasAbandoned(); 846 } 847 848 namespace { 849 void test_pm_conversions(GrContext* ctx, int* pmToUPMValue, int* upmToPMValue) { 850 GrConfigConversionEffect::PMConversion pmToUPM; 851 GrConfigConversionEffect::PMConversion upmToPM; 852 GrConfigConversionEffect::TestForPreservingPMConversions(ctx, &pmToUPM, &upmToPM); 853 *pmToUPMValue = pmToUPM; 854 *upmToPMValue = upmToPM; 855 } 856 } 857 858 void GrContext::testPMConversionsIfNecessary(uint32_t flags) { 859 ASSERT_SINGLE_OWNER 860 if (SkToBool(kUnpremul_PixelOpsFlag & flags)) { 861 if (!fDidTestPMConversions) { 862 test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion); 863 fDidTestPMConversions = true; 864 } 865 } 866 } 867 868 sk_sp<GrFragmentProcessor> GrContext::createPMToUPMEffect(GrTexture* texture, 869 const SkMatrix& matrix) { 870 ASSERT_SINGLE_OWNER 871 // We should have already called this->testPMConversionsIfNecessary(). 872 SkASSERT(fDidTestPMConversions); 873 if (kRGBA_half_GrPixelConfig == texture->config()) { 874 return GrFragmentProcessor::UnpremulOutput( 875 GrSimpleTextureEffect::Make(texture, nullptr, matrix)); 876 } else { 877 GrConfigConversionEffect::PMConversion pmToUPM = 878 static_cast<GrConfigConversionEffect::PMConversion>(fPMToUPMConversion); 879 if (GrConfigConversionEffect::kPMConversionCnt != pmToUPM) { 880 return GrConfigConversionEffect::Make(texture, pmToUPM, matrix); 881 } else { 882 return nullptr; 883 } 884 } 885 } 886 887 sk_sp<GrFragmentProcessor> GrContext::createPMToUPMEffect(sk_sp<GrTextureProxy> proxy, 888 const SkMatrix& matrix) { 889 ASSERT_SINGLE_OWNER 890 // We should have already called this->testPMConversionsIfNecessary(). 891 SkASSERT(fDidTestPMConversions); 892 if (kRGBA_half_GrPixelConfig == proxy->config()) { 893 return GrFragmentProcessor::UnpremulOutput( 894 GrSimpleTextureEffect::Make(this->resourceProvider(), std::move(proxy), 895 nullptr, matrix)); 896 } else { 897 GrConfigConversionEffect::PMConversion pmToUPM = 898 static_cast<GrConfigConversionEffect::PMConversion>(fPMToUPMConversion); 899 if (GrConfigConversionEffect::kPMConversionCnt != pmToUPM) { 900 return GrConfigConversionEffect::Make(this->resourceProvider(), std::move(proxy), 901 pmToUPM, matrix); 902 } else { 903 return nullptr; 904 } 905 } 906 } 907 908 sk_sp<GrFragmentProcessor> GrContext::createUPMToPMEffect(sk_sp<GrTextureProxy> proxy, 909 const SkMatrix& matrix) { 910 ASSERT_SINGLE_OWNER 911 // We should have already called this->testPMConversionsIfNecessary(). 912 SkASSERT(fDidTestPMConversions); 913 if (kRGBA_half_GrPixelConfig == proxy->config()) { 914 return GrFragmentProcessor::PremulOutput( 915 GrSimpleTextureEffect::Make(this->resourceProvider(), std::move(proxy), 916 nullptr, matrix)); 917 } else { 918 GrConfigConversionEffect::PMConversion upmToPM = 919 static_cast<GrConfigConversionEffect::PMConversion>(fUPMToPMConversion); 920 if (GrConfigConversionEffect::kPMConversionCnt != upmToPM) { 921 return GrConfigConversionEffect::Make(this->resourceProvider(), std::move(proxy), 922 upmToPM, matrix); 923 } else { 924 return nullptr; 925 } 926 } 927 } 928 929 bool GrContext::validPMUPMConversionExists(GrPixelConfig config) const { 930 ASSERT_SINGLE_OWNER 931 // We should have already called this->testPMConversionsIfNecessary(). 932 SkASSERT(fDidTestPMConversions); 933 // The PM<->UPM tests fail or succeed together so we only need to check one. 934 // For F16, we always allow PM/UPM conversion on the GPU, even if it doesn't round-trip. 935 return GrConfigConversionEffect::kPMConversionCnt != fPMToUPMConversion || 936 kRGBA_half_GrPixelConfig == config; 937 } 938 939 ////////////////////////////////////////////////////////////////////////////// 940 941 void GrContext::getResourceCacheLimits(int* maxTextures, size_t* maxTextureBytes) const { 942 ASSERT_SINGLE_OWNER 943 if (maxTextures) { 944 *maxTextures = fResourceCache->getMaxResourceCount(); 945 } 946 if (maxTextureBytes) { 947 *maxTextureBytes = fResourceCache->getMaxResourceBytes(); 948 } 949 } 950 951 void GrContext::setResourceCacheLimits(int maxTextures, size_t maxTextureBytes) { 952 ASSERT_SINGLE_OWNER 953 fResourceCache->setLimits(maxTextures, maxTextureBytes); 954 } 955 956 ////////////////////////////////////////////////////////////////////////////// 957 958 void GrContext::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const { 959 ASSERT_SINGLE_OWNER 960 fResourceCache->dumpMemoryStatistics(traceMemoryDump); 961 } 962