GrContext.cpp revision 77b3f32936dd069fa6a27f870b3b30035733d940
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 "GrContextPriv.h" 10#include "GrContextOptions.h" 11#include "GrDrawingManager.h" 12#include "GrRenderTargetContext.h" 13#include "GrResourceCache.h" 14#include "GrResourceProvider.h" 15#include "GrRenderTargetProxy.h" 16#include "GrSoftwarePathRenderer.h" 17#include "GrSurfaceContext.h" 18#include "GrSurfacePriv.h" 19#include "GrSurfaceProxyPriv.h" 20#include "GrTextureContext.h" 21 22#include "SkConfig8888.h" 23#include "SkGrPriv.h" 24 25#include "effects/GrConfigConversionEffect.h" 26#include "text/GrTextBlobCache.h" 27 28#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this) 29#define ASSERT_SINGLE_OWNER \ 30 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(&fSingleOwner);) 31#define ASSERT_SINGLE_OWNER_PRIV \ 32 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(&fContext->fSingleOwner);) 33#define RETURN_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return; } 34#define RETURN_FALSE_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return false; } 35#define RETURN_NULL_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return nullptr; } 36 37//////////////////////////////////////////////////////////////////////////////// 38 39GrContext* GrContext::Create(GrBackend backend, GrBackendContext backendContext) { 40 GrContextOptions defaultOptions; 41 return Create(backend, backendContext, defaultOptions); 42} 43 44GrContext* GrContext::Create(GrBackend backend, GrBackendContext backendContext, 45 const GrContextOptions& options) { 46 GrContext* context = new GrContext; 47 48 if (context->init(backend, backendContext, options)) { 49 return context; 50 } else { 51 context->unref(); 52 return nullptr; 53 } 54} 55 56static int32_t gNextID = 1; 57static int32_t next_id() { 58 int32_t id; 59 do { 60 id = sk_atomic_inc(&gNextID); 61 } while (id == SK_InvalidGenID); 62 return id; 63} 64 65GrContext::GrContext() : fUniqueID(next_id()) { 66 fGpu = nullptr; 67 fCaps = nullptr; 68 fResourceCache = nullptr; 69 fResourceProvider = nullptr; 70 fAtlasGlyphCache = nullptr; 71} 72 73bool GrContext::init(GrBackend backend, GrBackendContext backendContext, 74 const GrContextOptions& options) { 75 ASSERT_SINGLE_OWNER 76 SkASSERT(!fGpu); 77 78 fGpu = GrGpu::Create(backend, backendContext, options, this); 79 if (!fGpu) { 80 return false; 81 } 82 this->initCommon(options); 83 return true; 84} 85 86void GrContext::initCommon(const GrContextOptions& options) { 87 ASSERT_SINGLE_OWNER 88 89 fCaps = SkRef(fGpu->caps()); 90 fResourceCache = new GrResourceCache(fCaps); 91 fResourceProvider = new GrResourceProvider(fGpu, fResourceCache, &fSingleOwner); 92 93 fDidTestPMConversions = false; 94 95 GrRenderTargetOpList::Options rtOpListOptions; 96 rtOpListOptions.fClipDrawOpsToBounds = options.fClipDrawOpsToBounds; 97 rtOpListOptions.fMaxOpCombineLookback = options.fMaxOpCombineLookback; 98 rtOpListOptions.fMaxOpCombineLookahead = options.fMaxOpCombineLookahead; 99 GrPathRendererChain::Options prcOptions; 100 prcOptions.fDisableDistanceFieldRenderer = options.fDisableDistanceFieldPaths; 101 prcOptions.fAllowPathMaskCaching = options.fAllowPathMaskCaching; 102 prcOptions.fDisableAllPathRenderers = options.fForceSWPathMasks; 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 SkSrcPixelInfo srcPI; 230 if (!GrPixelConfigToColorType(srcConfig, &srcPI.fColorType)) { 231 return false; 232 } 233 srcPI.fAlphaType = kUnpremul_SkAlphaType; 234 srcPI.fPixels = inPixels; 235 srcPI.fRowBytes = inRowBytes; 236 237 SkDstPixelInfo dstPI; 238 dstPI.fColorType = srcPI.fColorType; 239 dstPI.fAlphaType = kPremul_SkAlphaType; 240 dstPI.fPixels = outPixels; 241 dstPI.fRowBytes = outRowBytes; 242 243 return srcPI.convertPixelsTo(&dstPI, width, height); 244} 245 246bool GrContext::writeSurfacePixels(GrSurface* surface, SkColorSpace* dstColorSpace, 247 int left, int top, int width, int height, 248 GrPixelConfig srcConfig, SkColorSpace* srcColorSpace, 249 const void* buffer, size_t rowBytes, uint32_t pixelOpsFlags) { 250 // TODO: Color space conversion 251 252 ASSERT_SINGLE_OWNER 253 RETURN_FALSE_IF_ABANDONED 254 ASSERT_OWNED_RESOURCE(surface); 255 SkASSERT(surface); 256 GR_AUDIT_TRAIL_AUTO_FRAME(&fAuditTrail, "GrContext::writeSurfacePixels"); 257 258 this->testPMConversionsIfNecessary(pixelOpsFlags); 259 260 // Trim the params here so that if we wind up making a temporary surface it can be as small as 261 // necessary and because GrGpu::getWritePixelsInfo requires it. 262 if (!GrSurfacePriv::AdjustWritePixelParams(surface->width(), surface->height(), 263 GrBytesPerPixel(srcConfig), &left, &top, &width, 264 &height, &buffer, &rowBytes)) { 265 return false; 266 } 267 268 bool applyPremulToSrc = false; 269 if (kUnpremul_PixelOpsFlag & pixelOpsFlags) { 270 if (!GrPixelConfigIs8888Unorm(srcConfig)) { 271 return false; 272 } 273 applyPremulToSrc = true; 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->didFailPMUPMConversionTest()) { 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> tempTextureProxy; 298 if (GrGpu::kNoDraw_DrawPreference != drawPreference) { 299 sk_sp<GrSurfaceProxy> temp = GrSurfaceProxy::MakeDeferred(*this->caps(), 300 tempDrawInfo.fTempSurfaceDesc, 301 SkBackingFit::kApprox, 302 SkBudgeted::kYes); 303 if (temp) { 304 tempTextureProxy = sk_ref_sp(temp->asTextureProxy()); 305 } 306 if (!tempTextureProxy && GrGpu::kRequireDraw_DrawPreference == drawPreference) { 307 return false; 308 } 309 } 310 311 // temp buffer for doing sw premul conversion, if needed. 312 SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0); 313 if (tempTextureProxy) { 314 sk_sp<GrFragmentProcessor> fp; 315 if (applyPremulToSrc) { 316 fp = this->createUPMToPMEffect(tempTextureProxy, tempDrawInfo.fSwizzle, SkMatrix::I()); 317 // If premultiplying was the only reason for the draw, fall back to a straight write. 318 if (!fp) { 319 if (GrGpu::kCallerPrefersDraw_DrawPreference == drawPreference) { 320 tempTextureProxy.reset(nullptr); 321 } 322 } else { 323 applyPremulToSrc = false; 324 } 325 } 326 if (tempTextureProxy) { 327 if (!fp) { 328 fp = GrConfigConversionEffect::Make(this, tempTextureProxy, tempDrawInfo.fSwizzle, 329 GrConfigConversionEffect::kNone_PMConversion, 330 SkMatrix::I()); 331 if (!fp) { 332 return false; 333 } 334 } 335 GrTexture* texture = tempTextureProxy->instantiate(this->textureProvider()); 336 if (!texture) { 337 return false; 338 } 339 if (texture->surfacePriv().hasPendingIO()) { 340 this->flush(); 341 } 342 if (applyPremulToSrc) { 343 size_t tmpRowBytes = 4 * width; 344 tmpPixels.reset(width * height); 345 if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer, tmpRowBytes, 346 tmpPixels.get())) { 347 return false; 348 } 349 rowBytes = tmpRowBytes; 350 buffer = tmpPixels.get(); 351 applyPremulToSrc = false; 352 } 353 if (!fGpu->writePixels(texture, 0, 0, width, height, 354 tempDrawInfo.fWriteConfig, buffer, 355 rowBytes)) { 356 return false; 357 } 358 SkMatrix matrix; 359 matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top)); 360 // TODO: Need to decide the semantics of this function for color spaces. Do we support 361 // conversion from a passed-in color space? For now, specifying nullptr means that this 362 // path will do no conversion, so it will match the behavior of the non-draw path. 363 GrRenderTarget* renderTarget = surface->asRenderTarget(); 364 SkASSERT(renderTarget); 365 sk_sp<GrRenderTargetContext> renderTargetContext( 366 this->contextPriv().makeWrappedRenderTargetContext(sk_ref_sp(renderTarget), 367 nullptr)); 368 if (!renderTargetContext) { 369 return false; 370 } 371 GrPaint paint; 372 paint.addColorFragmentProcessor(std::move(fp)); 373 paint.setPorterDuffXPFactory(SkBlendMode::kSrc); 374 paint.setAllowSRGBInputs(true); 375 SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)); 376 renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, matrix, rect, 377 nullptr); 378 379 if (kFlushWrites_PixelOp & pixelOpsFlags) { 380 this->flushSurfaceWrites(surface); 381 } 382 } 383 } 384 if (!tempTextureProxy) { 385 if (applyPremulToSrc) { 386 size_t tmpRowBytes = 4 * width; 387 tmpPixels.reset(width * height); 388 if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer, tmpRowBytes, 389 tmpPixels.get())) { 390 return false; 391 } 392 rowBytes = tmpRowBytes; 393 buffer = tmpPixels.get(); 394 applyPremulToSrc = false; 395 } 396 return fGpu->writePixels(surface, left, top, width, height, srcConfig, buffer, rowBytes); 397 } 398 return true; 399} 400 401bool GrContext::readSurfacePixels(GrSurface* src, SkColorSpace* srcColorSpace, 402 int left, int top, int width, int height, 403 GrPixelConfig dstConfig, SkColorSpace* dstColorSpace, 404 void* buffer, size_t rowBytes, uint32_t flags) { 405 // TODO: Color space conversion 406 407 ASSERT_SINGLE_OWNER 408 RETURN_FALSE_IF_ABANDONED 409 ASSERT_OWNED_RESOURCE(src); 410 SkASSERT(src); 411 GR_AUDIT_TRAIL_AUTO_FRAME(&fAuditTrail, "GrContext::readSurfacePixels"); 412 413 this->testPMConversionsIfNecessary(flags); 414 415 // Adjust the params so that if we wind up using an intermediate surface we've already done 416 // all the trimming and the temporary can be the min size required. 417 if (!GrSurfacePriv::AdjustReadPixelParams(src->width(), src->height(), 418 GrBytesPerPixel(dstConfig), &left, 419 &top, &width, &height, &buffer, &rowBytes)) { 420 return false; 421 } 422 423 if (!(kDontFlush_PixelOpsFlag & flags) && src->surfacePriv().hasPendingWrite()) { 424 this->flush(); 425 } 426 427 bool unpremul = SkToBool(kUnpremul_PixelOpsFlag & flags); 428 if (unpremul && !GrPixelConfigIs8888Unorm(dstConfig)) { 429 // The unpremul flag is only allowed for 8888 configs. 430 return false; 431 } 432 // We don't allow conversion between integer configs and float/fixed configs. 433 if (GrPixelConfigIsSint(src->config()) != GrPixelConfigIsSint(dstConfig)) { 434 return false; 435 } 436 437 GrGpu::DrawPreference drawPreference = GrGpu::kNoDraw_DrawPreference; 438 // Don't prefer to draw for the conversion (and thereby access a texture from the cache) when 439 // we've already determined that there isn't a roundtrip preserving conversion processor pair. 440 if (unpremul && !this->didFailPMUPMConversionTest()) { 441 drawPreference = GrGpu::kCallerPrefersDraw_DrawPreference; 442 } 443 444 GrGpu::ReadPixelTempDrawInfo tempDrawInfo; 445 if (!fGpu->getReadPixelsInfo(src, width, height, rowBytes, dstConfig, &drawPreference, 446 &tempDrawInfo)) { 447 return false; 448 } 449 450 sk_sp<GrSurface> surfaceToRead(SkRef(src)); 451 bool didTempDraw = false; 452 if (GrGpu::kNoDraw_DrawPreference != drawPreference) { 453 if (SkBackingFit::kExact == tempDrawInfo.fTempSurfaceFit) { 454 // We only respect this when the entire src is being read. Otherwise we can trigger too 455 // many odd ball texture sizes and trash the cache. 456 if (width != src->width() || height != src->height()) { 457 tempDrawInfo.fTempSurfaceFit= SkBackingFit::kApprox; 458 } 459 } 460 // TODO: Need to decide the semantics of this function for color spaces. Do we support 461 // conversion to a passed-in color space? For now, specifying nullptr means that this 462 // path will do no conversion, so it will match the behavior of the non-draw path. 463 sk_sp<GrRenderTargetContext> tempRTC = this->makeRenderTargetContext( 464 tempDrawInfo.fTempSurfaceFit, 465 tempDrawInfo.fTempSurfaceDesc.fWidth, 466 tempDrawInfo.fTempSurfaceDesc.fHeight, 467 tempDrawInfo.fTempSurfaceDesc.fConfig, 468 nullptr, 469 tempDrawInfo.fTempSurfaceDesc.fSampleCnt, 470 tempDrawInfo.fTempSurfaceDesc.fOrigin); 471 if (tempRTC) { 472 SkMatrix textureMatrix = SkMatrix::MakeTrans(SkIntToScalar(left), SkIntToScalar(top)); 473 sk_sp<GrFragmentProcessor> fp; 474 if (unpremul) { 475 fp = this->createPMToUPMEffect(src->asTexture(), tempDrawInfo.fSwizzle, 476 textureMatrix); 477 if (fp) { 478 unpremul = false; // we no longer need to do this on CPU after the read back. 479 } else if (GrGpu::kCallerPrefersDraw_DrawPreference == drawPreference) { 480 // We only wanted to do the draw in order to perform the unpremul so don't 481 // bother. 482 tempRTC.reset(nullptr); 483 } 484 } 485 if (!fp && tempRTC) { 486 fp = GrConfigConversionEffect::Make(src->asTexture(), tempDrawInfo.fSwizzle, 487 GrConfigConversionEffect::kNone_PMConversion, 488 textureMatrix); 489 } 490 if (fp) { 491 GrPaint paint; 492 paint.addColorFragmentProcessor(std::move(fp)); 493 paint.setPorterDuffXPFactory(SkBlendMode::kSrc); 494 paint.setAllowSRGBInputs(true); 495 SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)); 496 tempRTC->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), rect, 497 nullptr); 498 surfaceToRead.reset(tempRTC->asTexture().release()); 499 left = 0; 500 top = 0; 501 didTempDraw = true; 502 } 503 } 504 } 505 506 if (!surfaceToRead) { 507 return false; 508 } 509 510 if (GrGpu::kRequireDraw_DrawPreference == drawPreference && !didTempDraw) { 511 return false; 512 } 513 GrPixelConfig configToRead = dstConfig; 514 if (didTempDraw) { 515 this->flushSurfaceWrites(surfaceToRead.get()); 516 configToRead = tempDrawInfo.fReadConfig; 517 } 518 if (!fGpu->readPixels(surfaceToRead.get(), left, top, width, height, configToRead, buffer, 519 rowBytes)) { 520 return false; 521 } 522 523 // Perform umpremul conversion if we weren't able to perform it as a draw. 524 if (unpremul) { 525 SkDstPixelInfo dstPI; 526 if (!GrPixelConfigToColorType(dstConfig, &dstPI.fColorType)) { 527 return false; 528 } 529 dstPI.fAlphaType = kUnpremul_SkAlphaType; 530 dstPI.fPixels = buffer; 531 dstPI.fRowBytes = rowBytes; 532 533 SkSrcPixelInfo srcPI; 534 srcPI.fColorType = dstPI.fColorType; 535 srcPI.fAlphaType = kPremul_SkAlphaType; 536 srcPI.fPixels = buffer; 537 srcPI.fRowBytes = rowBytes; 538 539 return srcPI.convertPixelsTo(&dstPI, width, height); 540 } 541 return true; 542} 543 544void GrContext::prepareSurfaceForExternalIO(GrSurface* surface) { 545 ASSERT_SINGLE_OWNER 546 RETURN_IF_ABANDONED 547 SkASSERT(surface); 548 ASSERT_OWNED_RESOURCE(surface); 549 fDrawingManager->prepareSurfaceForExternalIO(surface); 550} 551 552void GrContext::flushSurfaceWrites(GrSurface* surface) { 553 ASSERT_SINGLE_OWNER 554 RETURN_IF_ABANDONED 555 if (surface->surfacePriv().hasPendingWrite()) { 556 this->flush(); 557 } 558} 559 560void GrContext::flushSurfaceIO(GrSurface* surface) { 561 ASSERT_SINGLE_OWNER 562 RETURN_IF_ABANDONED 563 if (surface->surfacePriv().hasPendingIO()) { 564 this->flush(); 565 } 566} 567 568//////////////////////////////////////////////////////////////////////////////// 569int GrContext::getRecommendedSampleCount(GrPixelConfig config, 570 SkScalar dpi) const { 571 ASSERT_SINGLE_OWNER 572 573 if (!this->caps()->isConfigRenderable(config, true)) { 574 return 0; 575 } 576 int chosenSampleCount = 0; 577 if (fGpu->caps()->shaderCaps()->pathRenderingSupport()) { 578 if (dpi >= 250.0f) { 579 chosenSampleCount = 4; 580 } else { 581 chosenSampleCount = 16; 582 } 583 } 584 return chosenSampleCount <= fGpu->caps()->maxSampleCount() ? chosenSampleCount : 0; 585} 586 587sk_sp<GrRenderTargetContext> GrContextPriv::makeWrappedRenderTargetContext( 588 sk_sp<GrRenderTarget> rt, 589 sk_sp<SkColorSpace> colorSpace, 590 const SkSurfaceProps* surfaceProps) { 591 ASSERT_SINGLE_OWNER_PRIV 592 593 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(rt))); 594 if (!proxy) { 595 return nullptr; 596 } 597 598 return this->drawingManager()->makeRenderTargetContext(std::move(proxy), 599 std::move(colorSpace), 600 surfaceProps); 601} 602 603sk_sp<GrSurfaceContext> GrContextPriv::makeWrappedSurfaceContext(sk_sp<GrSurfaceProxy> proxy, 604 sk_sp<SkColorSpace> colorSpace) { 605 ASSERT_SINGLE_OWNER_PRIV 606 607 if (proxy->asRenderTargetProxy()) { 608 return this->drawingManager()->makeRenderTargetContext(std::move(proxy), 609 std::move(colorSpace), nullptr); 610 } else { 611 SkASSERT(proxy->asTextureProxy()); 612 return this->drawingManager()->makeTextureContext(std::move(proxy), std::move(colorSpace)); 613 } 614} 615 616sk_sp<GrSurfaceContext> GrContextPriv::makeWrappedSurfaceContext(sk_sp<GrSurface> surface) { 617 ASSERT_SINGLE_OWNER_PRIV 618 619 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(surface))); 620 if (!proxy) { 621 return nullptr; 622 } 623 624 return this->makeWrappedSurfaceContext(std::move(proxy), nullptr); 625} 626 627sk_sp<GrSurfaceContext> GrContextPriv::makeDeferredSurfaceContext(const GrSurfaceDesc& dstDesc, 628 SkBackingFit fit, 629 SkBudgeted isDstBudgeted) { 630 631 sk_sp<GrSurfaceProxy> proxy = GrSurfaceProxy::MakeDeferred(*fContext->caps(), dstDesc, 632 fit, isDstBudgeted); 633 if (!proxy) { 634 return nullptr; 635 } 636 637 return this->makeWrappedSurfaceContext(std::move(proxy), nullptr); 638} 639 640sk_sp<GrSurfaceContext> GrContextPriv::makeBackendSurfaceContext(const GrBackendTextureDesc& desc, 641 sk_sp<SkColorSpace> colorSpace, 642 GrWrapOwnership ownership) { 643 ASSERT_SINGLE_OWNER_PRIV 644 645 sk_sp<GrSurface> surface(fContext->textureProvider()->wrapBackendTexture(desc, ownership)); 646 if (!surface) { 647 return nullptr; 648 } 649 650 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(surface))); 651 if (!proxy) { 652 return nullptr; 653 } 654 655 return this->makeWrappedSurfaceContext(std::move(proxy), std::move(colorSpace)); 656} 657 658sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendTextureRenderTargetContext( 659 const GrBackendTextureDesc& desc, 660 sk_sp<SkColorSpace> colorSpace, 661 const SkSurfaceProps* props, 662 GrWrapOwnership ownership) { 663 ASSERT_SINGLE_OWNER_PRIV 664 SkASSERT(desc.fFlags & kRenderTarget_GrBackendTextureFlag); 665 666 sk_sp<GrSurface> surface(fContext->textureProvider()->wrapBackendTexture(desc, ownership)); 667 if (!surface) { 668 return nullptr; 669 } 670 671 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(surface))); 672 if (!proxy) { 673 return nullptr; 674 } 675 676 return this->drawingManager()->makeRenderTargetContext(std::move(proxy), 677 std::move(colorSpace), props); 678} 679 680sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendRenderTargetRenderTargetContext( 681 const GrBackendRenderTargetDesc& desc, 682 sk_sp<SkColorSpace> colorSpace, 683 const SkSurfaceProps* surfaceProps) { 684 ASSERT_SINGLE_OWNER_PRIV 685 686 sk_sp<GrRenderTarget> rt(fContext->textureProvider()->wrapBackendRenderTarget(desc)); 687 if (!rt) { 688 return nullptr; 689 } 690 691 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(rt))); 692 if (!proxy) { 693 return nullptr; 694 } 695 696 return this->drawingManager()->makeRenderTargetContext(std::move(proxy), 697 std::move(colorSpace), 698 surfaceProps); 699} 700 701sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendTextureAsRenderTargetRenderTargetContext( 702 const GrBackendTextureDesc& desc, 703 sk_sp<SkColorSpace> colorSpace, 704 const SkSurfaceProps* surfaceProps) { 705 ASSERT_SINGLE_OWNER_PRIV 706 SkASSERT(desc.fFlags & kRenderTarget_GrBackendTextureFlag); 707 708 sk_sp<GrSurface> surface(fContext->resourceProvider()->wrapBackendTextureAsRenderTarget(desc)); 709 if (!surface) { 710 return nullptr; 711 } 712 713 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(surface))); 714 if (!proxy) { 715 return nullptr; 716 } 717 718 return this->drawingManager()->makeRenderTargetContext(std::move(proxy), 719 std::move(colorSpace), 720 surfaceProps); 721} 722 723static inline GrPixelConfig GrPixelConfigFallback(GrPixelConfig config) { 724 switch (config) { 725 case kAlpha_8_GrPixelConfig: 726 case kRGB_565_GrPixelConfig: 727 case kRGBA_4444_GrPixelConfig: 728 case kBGRA_8888_GrPixelConfig: 729 return kRGBA_8888_GrPixelConfig; 730 case kSBGRA_8888_GrPixelConfig: 731 return kSRGBA_8888_GrPixelConfig; 732 case kAlpha_half_GrPixelConfig: 733 return kRGBA_half_GrPixelConfig; 734 default: 735 return kUnknown_GrPixelConfig; 736 } 737} 738 739sk_sp<GrRenderTargetContext> GrContext::makeRenderTargetContextWithFallback( 740 SkBackingFit fit, 741 int width, int height, 742 GrPixelConfig config, 743 sk_sp<SkColorSpace> colorSpace, 744 int sampleCnt, 745 GrSurfaceOrigin origin, 746 const SkSurfaceProps* surfaceProps, 747 SkBudgeted budgeted) { 748 if (!this->caps()->isConfigRenderable(config, sampleCnt > 0)) { 749 config = GrPixelConfigFallback(config); 750 } 751 752 return this->makeRenderTargetContext(fit, width, height, config, std::move(colorSpace), 753 sampleCnt, origin, surfaceProps, budgeted); 754} 755 756sk_sp<GrRenderTargetContext> GrContext::makeDeferredRenderTargetContextWithFallback( 757 SkBackingFit fit, 758 int width, int height, 759 GrPixelConfig config, 760 sk_sp<SkColorSpace> colorSpace, 761 int sampleCnt, 762 GrSurfaceOrigin origin, 763 const SkSurfaceProps* surfaceProps, 764 SkBudgeted budgeted) { 765 if (!this->caps()->isConfigRenderable(config, sampleCnt > 0)) { 766 config = GrPixelConfigFallback(config); 767 } 768 769 return this->makeDeferredRenderTargetContext(fit, width, height, config, std::move(colorSpace), 770 sampleCnt, origin, surfaceProps, budgeted); 771} 772 773sk_sp<GrRenderTargetContext> GrContext::makeRenderTargetContext(SkBackingFit fit, 774 int width, int height, 775 GrPixelConfig config, 776 sk_sp<SkColorSpace> colorSpace, 777 int sampleCnt, 778 GrSurfaceOrigin origin, 779 const SkSurfaceProps* surfaceProps, 780 SkBudgeted budgeted) { 781 if (!this->caps()->isConfigRenderable(config, sampleCnt > 0)) { 782 return nullptr; 783 } 784 785 GrSurfaceDesc desc; 786 desc.fFlags = kRenderTarget_GrSurfaceFlag; 787 desc.fOrigin = origin; 788 desc.fWidth = width; 789 desc.fHeight = height; 790 desc.fConfig = config; 791 desc.fSampleCnt = sampleCnt; 792 793 sk_sp<GrTexture> tex; 794 if (SkBackingFit::kExact == fit) { 795 tex.reset(this->textureProvider()->createTexture(desc, budgeted)); 796 } else { 797 tex.reset(this->textureProvider()->createApproxTexture(desc)); 798 } 799 if (!tex) { 800 return nullptr; 801 } 802 803 sk_sp<GrRenderTargetContext> renderTargetContext( 804 this->contextPriv().makeWrappedRenderTargetContext(sk_ref_sp(tex->asRenderTarget()), 805 std::move(colorSpace), surfaceProps)); 806 if (!renderTargetContext) { 807 return nullptr; 808 } 809 810 return renderTargetContext; 811} 812 813sk_sp<GrRenderTargetContext> GrContext::makeDeferredRenderTargetContext( 814 SkBackingFit fit, 815 int width, int height, 816 GrPixelConfig config, 817 sk_sp<SkColorSpace> colorSpace, 818 int sampleCnt, 819 GrSurfaceOrigin origin, 820 const SkSurfaceProps* surfaceProps, 821 SkBudgeted budgeted) { 822 GrSurfaceDesc desc; 823 desc.fFlags = kRenderTarget_GrSurfaceFlag; 824 desc.fOrigin = origin; 825 desc.fWidth = width; 826 desc.fHeight = height; 827 desc.fConfig = config; 828 desc.fSampleCnt = sampleCnt; 829 830 sk_sp<GrSurfaceProxy> rtp = GrSurfaceProxy::MakeDeferred(*this->caps(), desc, fit, budgeted); 831 if (!rtp) { 832 return nullptr; 833 } 834 835 return fDrawingManager->makeRenderTargetContext(std::move(rtp), 836 std::move(colorSpace), 837 surfaceProps); 838} 839 840bool GrContext::abandoned() const { 841 ASSERT_SINGLE_OWNER 842 return fDrawingManager->wasAbandoned(); 843} 844 845namespace { 846void test_pm_conversions(GrContext* ctx, int* pmToUPMValue, int* upmToPMValue) { 847 GrConfigConversionEffect::PMConversion pmToUPM; 848 GrConfigConversionEffect::PMConversion upmToPM; 849 GrConfigConversionEffect::TestForPreservingPMConversions(ctx, &pmToUPM, &upmToPM); 850 *pmToUPMValue = pmToUPM; 851 *upmToPMValue = upmToPM; 852} 853} 854 855void GrContext::testPMConversionsIfNecessary(uint32_t flags) { 856 ASSERT_SINGLE_OWNER 857 if (SkToBool(kUnpremul_PixelOpsFlag & flags)) { 858 if (!fDidTestPMConversions) { 859 test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion); 860 fDidTestPMConversions = true; 861 } 862 } 863} 864 865sk_sp<GrFragmentProcessor> GrContext::createPMToUPMEffect(GrTexture* texture, 866 const GrSwizzle& swizzle, 867 const SkMatrix& matrix) { 868 ASSERT_SINGLE_OWNER 869 // We should have already called this->testPMConversionsIfNecessary(). 870 SkASSERT(fDidTestPMConversions); 871 GrConfigConversionEffect::PMConversion pmToUPM = 872 static_cast<GrConfigConversionEffect::PMConversion>(fPMToUPMConversion); 873 if (GrConfigConversionEffect::kNone_PMConversion != pmToUPM) { 874 return GrConfigConversionEffect::Make(texture, swizzle, pmToUPM, matrix); 875 } else { 876 return nullptr; 877 } 878} 879 880sk_sp<GrFragmentProcessor> GrContext::createPMToUPMEffect(sk_sp<GrTextureProxy> proxy, 881 const GrSwizzle& swizzle, 882 const SkMatrix& matrix) { 883 ASSERT_SINGLE_OWNER 884 // We should have already called this->testPMConversionsIfNecessary(). 885 SkASSERT(fDidTestPMConversions); 886 GrConfigConversionEffect::PMConversion pmToUPM = 887 static_cast<GrConfigConversionEffect::PMConversion>(fPMToUPMConversion); 888 if (GrConfigConversionEffect::kNone_PMConversion != pmToUPM) { 889 return GrConfigConversionEffect::Make(this, proxy, swizzle, pmToUPM, matrix); 890 } else { 891 return nullptr; 892 } 893} 894 895sk_sp<GrFragmentProcessor> GrContext::createUPMToPMEffect(sk_sp<GrTextureProxy> proxy, 896 const GrSwizzle& swizzle, 897 const SkMatrix& matrix) { 898 ASSERT_SINGLE_OWNER 899 // We should have already called this->testPMConversionsIfNecessary(). 900 SkASSERT(fDidTestPMConversions); 901 GrConfigConversionEffect::PMConversion upmToPM = 902 static_cast<GrConfigConversionEffect::PMConversion>(fUPMToPMConversion); 903 if (GrConfigConversionEffect::kNone_PMConversion != upmToPM) { 904 return GrConfigConversionEffect::Make(this, std::move(proxy), swizzle, upmToPM, matrix); 905 } else { 906 return nullptr; 907 } 908} 909 910bool GrContext::didFailPMUPMConversionTest() const { 911 ASSERT_SINGLE_OWNER 912 // We should have already called this->testPMConversionsIfNecessary(). 913 SkASSERT(fDidTestPMConversions); 914 // The PM<->UPM tests fail or succeed together so we only need to check one. 915 return GrConfigConversionEffect::kNone_PMConversion == fPMToUPMConversion; 916} 917 918////////////////////////////////////////////////////////////////////////////// 919 920void GrContext::getResourceCacheLimits(int* maxTextures, size_t* maxTextureBytes) const { 921 ASSERT_SINGLE_OWNER 922 if (maxTextures) { 923 *maxTextures = fResourceCache->getMaxResourceCount(); 924 } 925 if (maxTextureBytes) { 926 *maxTextureBytes = fResourceCache->getMaxResourceBytes(); 927 } 928} 929 930void GrContext::setResourceCacheLimits(int maxTextures, size_t maxTextureBytes) { 931 ASSERT_SINGLE_OWNER 932 fResourceCache->setLimits(maxTextures, maxTextureBytes); 933} 934 935////////////////////////////////////////////////////////////////////////////// 936 937void GrContext::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const { 938 ASSERT_SINGLE_OWNER 939 fResourceCache->dumpMemoryStatistics(traceMemoryDump); 940} 941