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