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