GrContext.cpp revision 485c499a2797c1eb0e750fa4aaec57192799b424
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 "SkConvertPixels.h" 23#include "SkGrPriv.h" 24#include "SkUnPreMultiplyPriv.h" 25 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.fClipDrawOpsToBounds = options.fClipDrawOpsToBounds; 99 rtOpListOptions.fMaxOpCombineLookback = options.fMaxOpCombineLookback; 100 rtOpListOptions.fMaxOpCombineLookahead = options.fMaxOpCombineLookahead; 101 GrPathRendererChain::Options prcOptions; 102 prcOptions.fDisableDistanceFieldRenderer = options.fDisableDistanceFieldPaths; 103 prcOptions.fAllowPathMaskCaching = options.fAllowPathMaskCaching; 104 prcOptions.fDisableAllPathRenderers = options.fForceSWPathMasks; 105 fDrawingManager.reset(new GrDrawingManager(this, rtOpListOptions, prcOptions, 106 options.fImmediateMode, &fSingleOwner)); 107 108 fAtlasGlyphCache = new GrAtlasGlyphCache(this); 109 110 fTextBlobCache.reset(new GrTextBlobCache(TextBlobCacheOverBudgetCB, this)); 111} 112 113GrContext::~GrContext() { 114 ASSERT_SINGLE_OWNER 115 116 if (!fGpu) { 117 SkASSERT(!fCaps); 118 return; 119 } 120 121 this->flush(); 122 123 fDrawingManager->cleanup(); 124 125 for (int i = 0; i < fCleanUpData.count(); ++i) { 126 (*fCleanUpData[i].fFunc)(this, fCleanUpData[i].fInfo); 127 } 128 129 delete fResourceProvider; 130 delete fResourceCache; 131 delete fAtlasGlyphCache; 132 133 fGpu->unref(); 134 fCaps->unref(); 135} 136 137sk_sp<GrContextThreadSafeProxy> GrContext::threadSafeProxy() { 138 if (!fThreadSafeProxy) { 139 fThreadSafeProxy.reset(new GrContextThreadSafeProxy(sk_ref_sp(fCaps), this->uniqueID())); 140 } 141 return fThreadSafeProxy; 142} 143 144void GrContext::abandonContext() { 145 ASSERT_SINGLE_OWNER 146 147 fResourceProvider->abandon(); 148 149 // Need to abandon the drawing manager first so all the render targets 150 // will be released/forgotten before they too are abandoned. 151 fDrawingManager->abandon(); 152 153 // abandon first to so destructors 154 // don't try to free the resources in the API. 155 fResourceCache->abandonAll(); 156 157 fGpu->disconnect(GrGpu::DisconnectType::kAbandon); 158 159 fAtlasGlyphCache->freeAll(); 160 fTextBlobCache->freeAll(); 161} 162 163void GrContext::releaseResourcesAndAbandonContext() { 164 ASSERT_SINGLE_OWNER 165 166 fResourceProvider->abandon(); 167 168 // Need to abandon the drawing manager first so all the render targets 169 // will be released/forgotten before they too are abandoned. 170 fDrawingManager->abandon(); 171 172 // Release all resources in the backend 3D API. 173 fResourceCache->releaseAll(); 174 175 fGpu->disconnect(GrGpu::DisconnectType::kCleanup); 176 177 fAtlasGlyphCache->freeAll(); 178 fTextBlobCache->freeAll(); 179} 180 181void GrContext::resetContext(uint32_t state) { 182 ASSERT_SINGLE_OWNER 183 fGpu->markContextDirty(state); 184} 185 186void GrContext::freeGpuResources() { 187 ASSERT_SINGLE_OWNER 188 189 this->flush(); 190 191 fAtlasGlyphCache->freeAll(); 192 193 fDrawingManager->freeGpuResources(); 194 195 fResourceCache->purgeAllUnlocked(); 196} 197 198void GrContext::getResourceCacheUsage(int* resourceCount, size_t* resourceBytes) const { 199 ASSERT_SINGLE_OWNER 200 201 if (resourceCount) { 202 *resourceCount = fResourceCache->getBudgetedResourceCount(); 203 } 204 if (resourceBytes) { 205 *resourceBytes = fResourceCache->getBudgetedResourceBytes(); 206 } 207} 208 209//////////////////////////////////////////////////////////////////////////////// 210 211void GrContext::TextBlobCacheOverBudgetCB(void* data) { 212 SkASSERT(data); 213 // TextBlobs are drawn at the SkGpuDevice level, therefore they cannot rely on 214 // GrRenderTargetContext to perform a necessary flush. The solution is to move drawText calls 215 // to below the GrContext level, but this is not trivial because they call drawPath on 216 // SkGpuDevice. 217 GrContext* context = reinterpret_cast<GrContext*>(data); 218 context->flush(); 219} 220 221//////////////////////////////////////////////////////////////////////////////// 222 223void GrContext::flush() { 224 ASSERT_SINGLE_OWNER 225 RETURN_IF_ABANDONED 226 fDrawingManager->flush(); 227} 228 229bool sw_convert_to_premul(GrPixelConfig srcConfig, int width, int height, size_t inRowBytes, 230 const void* inPixels, size_t outRowBytes, void* outPixels) { 231 SkColorType colorType; 232 if (!GrPixelConfigToColorType(srcConfig, &colorType) || 233 4 != SkColorTypeBytesPerPixel(colorType)) 234 { 235 return false; 236 } 237 238 for (int y = 0; y < height; y++) { 239 SkOpts::RGBA_to_rgbA((uint32_t*) outPixels, inPixels, width); 240 outPixels = SkTAddOffset<void>(outPixels, outRowBytes); 241 inPixels = SkTAddOffset<const void>(inPixels, inRowBytes); 242 } 243 244 return true; 245} 246 247bool GrContext::writeSurfacePixels(GrSurface* surface, SkColorSpace* dstColorSpace, 248 int left, int top, int width, int height, 249 GrPixelConfig srcConfig, SkColorSpace* srcColorSpace, 250 const void* buffer, size_t rowBytes, uint32_t pixelOpsFlags) { 251 // TODO: Color space conversion 252 253 ASSERT_SINGLE_OWNER 254 RETURN_FALSE_IF_ABANDONED 255 ASSERT_OWNED_RESOURCE(surface); 256 SkASSERT(surface); 257 GR_AUDIT_TRAIL_AUTO_FRAME(&fAuditTrail, "GrContext::writeSurfacePixels"); 258 259 this->testPMConversionsIfNecessary(pixelOpsFlags); 260 261 // Trim the params here so that if we wind up making a temporary surface it can be as small as 262 // necessary and because GrGpu::getWritePixelsInfo requires it. 263 if (!GrSurfacePriv::AdjustWritePixelParams(surface->width(), surface->height(), 264 GrBytesPerPixel(srcConfig), &left, &top, &width, 265 &height, &buffer, &rowBytes)) { 266 return false; 267 } 268 269 bool applyPremulToSrc = false; 270 if (kUnpremul_PixelOpsFlag & pixelOpsFlags) { 271 if (!GrPixelConfigIs8888Unorm(srcConfig)) { 272 return false; 273 } 274 applyPremulToSrc = true; 275 } 276 // We don't allow conversion between integer configs and float/fixed configs. 277 if (GrPixelConfigIsSint(surface->config()) != GrPixelConfigIsSint(srcConfig)) { 278 return false; 279 } 280 281 GrGpu::DrawPreference drawPreference = GrGpu::kNoDraw_DrawPreference; 282 // Don't prefer to draw for the conversion (and thereby access a texture from the cache) when 283 // we've already determined that there isn't a roundtrip preserving conversion processor pair. 284 if (applyPremulToSrc && !this->didFailPMUPMConversionTest()) { 285 drawPreference = GrGpu::kCallerPrefersDraw_DrawPreference; 286 } 287 288 GrGpu::WritePixelTempDrawInfo tempDrawInfo; 289 if (!fGpu->getWritePixelsInfo(surface, width, height, srcConfig, &drawPreference, 290 &tempDrawInfo)) { 291 return false; 292 } 293 294 if (!(kDontFlush_PixelOpsFlag & pixelOpsFlags) && surface->surfacePriv().hasPendingIO()) { 295 this->flush(); 296 } 297 298 sk_sp<GrTextureProxy> tempTextureProxy; 299 if (GrGpu::kNoDraw_DrawPreference != drawPreference) { 300 sk_sp<GrSurfaceProxy> temp = GrSurfaceProxy::MakeDeferred(*this->caps(), 301 tempDrawInfo.fTempSurfaceDesc, 302 SkBackingFit::kApprox, 303 SkBudgeted::kYes); 304 if (temp) { 305 tempTextureProxy = sk_ref_sp(temp->asTextureProxy()); 306 } 307 if (!tempTextureProxy && GrGpu::kRequireDraw_DrawPreference == drawPreference) { 308 return false; 309 } 310 } 311 312 // temp buffer for doing sw premul conversion, if needed. 313 SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0); 314 if (tempTextureProxy) { 315 sk_sp<GrFragmentProcessor> fp; 316 if (applyPremulToSrc) { 317 fp = this->createUPMToPMEffect(tempTextureProxy, tempDrawInfo.fSwizzle, SkMatrix::I()); 318 // If premultiplying was the only reason for the draw, fall back to a straight write. 319 if (!fp) { 320 if (GrGpu::kCallerPrefersDraw_DrawPreference == drawPreference) { 321 tempTextureProxy.reset(nullptr); 322 } 323 } else { 324 applyPremulToSrc = false; 325 } 326 } 327 if (tempTextureProxy) { 328 if (!fp) { 329 fp = GrConfigConversionEffect::Make(this, tempTextureProxy, tempDrawInfo.fSwizzle, 330 GrConfigConversionEffect::kNone_PMConversion, 331 SkMatrix::I()); 332 if (!fp) { 333 return false; 334 } 335 } 336 GrTexture* texture = tempTextureProxy->instantiate(this->textureProvider()); 337 if (!texture) { 338 return false; 339 } 340 if (texture->surfacePriv().hasPendingIO()) { 341 this->flush(); 342 } 343 if (applyPremulToSrc) { 344 size_t tmpRowBytes = 4 * width; 345 tmpPixels.reset(width * height); 346 if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer, tmpRowBytes, 347 tmpPixels.get())) { 348 return false; 349 } 350 rowBytes = tmpRowBytes; 351 buffer = tmpPixels.get(); 352 applyPremulToSrc = false; 353 } 354 if (!fGpu->writePixels(texture, 0, 0, width, height, 355 tempDrawInfo.fWriteConfig, buffer, 356 rowBytes)) { 357 return false; 358 } 359 SkMatrix matrix; 360 matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top)); 361 // TODO: Need to decide the semantics of this function for color spaces. Do we support 362 // conversion from a passed-in color space? For now, specifying nullptr means that this 363 // path will do no conversion, so it will match the behavior of the non-draw path. 364 GrRenderTarget* renderTarget = surface->asRenderTarget(); 365 SkASSERT(renderTarget); 366 sk_sp<GrRenderTargetContext> renderTargetContext( 367 this->contextPriv().makeWrappedRenderTargetContext(sk_ref_sp(renderTarget), 368 nullptr)); 369 if (!renderTargetContext) { 370 return false; 371 } 372 GrPaint paint; 373 paint.addColorFragmentProcessor(std::move(fp)); 374 paint.setPorterDuffXPFactory(SkBlendMode::kSrc); 375 paint.setAllowSRGBInputs(true); 376 SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)); 377 renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, matrix, rect, 378 nullptr); 379 380 if (kFlushWrites_PixelOp & pixelOpsFlags) { 381 this->flushSurfaceWrites(surface); 382 } 383 } 384 } 385 if (!tempTextureProxy) { 386 if (applyPremulToSrc) { 387 size_t tmpRowBytes = 4 * width; 388 tmpPixels.reset(width * height); 389 if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer, tmpRowBytes, 390 tmpPixels.get())) { 391 return false; 392 } 393 rowBytes = tmpRowBytes; 394 buffer = tmpPixels.get(); 395 applyPremulToSrc = false; 396 } 397 return fGpu->writePixels(surface, left, top, width, height, srcConfig, buffer, rowBytes); 398 } 399 return true; 400} 401 402bool GrContext::readSurfacePixels(GrSurface* src, SkColorSpace* srcColorSpace, 403 int left, int top, int width, int height, 404 GrPixelConfig dstConfig, SkColorSpace* dstColorSpace, 405 void* buffer, size_t rowBytes, uint32_t flags) { 406 // TODO: Color space conversion 407 408 ASSERT_SINGLE_OWNER 409 RETURN_FALSE_IF_ABANDONED 410 ASSERT_OWNED_RESOURCE(src); 411 SkASSERT(src); 412 GR_AUDIT_TRAIL_AUTO_FRAME(&fAuditTrail, "GrContext::readSurfacePixels"); 413 414 this->testPMConversionsIfNecessary(flags); 415 416 // Adjust the params so that if we wind up using an intermediate surface we've already done 417 // all the trimming and the temporary can be the min size required. 418 if (!GrSurfacePriv::AdjustReadPixelParams(src->width(), src->height(), 419 GrBytesPerPixel(dstConfig), &left, 420 &top, &width, &height, &buffer, &rowBytes)) { 421 return false; 422 } 423 424 if (!(kDontFlush_PixelOpsFlag & flags) && src->surfacePriv().hasPendingWrite()) { 425 this->flush(); 426 } 427 428 bool unpremul = SkToBool(kUnpremul_PixelOpsFlag & flags); 429 if (unpremul && !GrPixelConfigIs8888Unorm(dstConfig)) { 430 // The unpremul flag is only allowed for 8888 configs. 431 return false; 432 } 433 // We don't allow conversion between integer configs and float/fixed configs. 434 if (GrPixelConfigIsSint(src->config()) != GrPixelConfigIsSint(dstConfig)) { 435 return false; 436 } 437 438 GrGpu::DrawPreference drawPreference = GrGpu::kNoDraw_DrawPreference; 439 // Don't prefer to draw for the conversion (and thereby access a texture from the cache) when 440 // we've already determined that there isn't a roundtrip preserving conversion processor pair. 441 if (unpremul && !this->didFailPMUPMConversionTest()) { 442 drawPreference = GrGpu::kCallerPrefersDraw_DrawPreference; 443 } 444 445 GrGpu::ReadPixelTempDrawInfo tempDrawInfo; 446 if (!fGpu->getReadPixelsInfo(src, width, height, rowBytes, dstConfig, &drawPreference, 447 &tempDrawInfo)) { 448 return false; 449 } 450 451 sk_sp<GrSurface> surfaceToRead(SkRef(src)); 452 bool didTempDraw = false; 453 if (GrGpu::kNoDraw_DrawPreference != drawPreference) { 454 if (SkBackingFit::kExact == tempDrawInfo.fTempSurfaceFit) { 455 // We only respect this when the entire src is being read. Otherwise we can trigger too 456 // many odd ball texture sizes and trash the cache. 457 if (width != src->width() || height != src->height()) { 458 tempDrawInfo.fTempSurfaceFit= SkBackingFit::kApprox; 459 } 460 } 461 // TODO: Need to decide the semantics of this function for color spaces. Do we support 462 // conversion to a passed-in color space? For now, specifying nullptr means that this 463 // path will do no conversion, so it will match the behavior of the non-draw path. 464 sk_sp<GrRenderTargetContext> tempRTC = this->makeRenderTargetContext( 465 tempDrawInfo.fTempSurfaceFit, 466 tempDrawInfo.fTempSurfaceDesc.fWidth, 467 tempDrawInfo.fTempSurfaceDesc.fHeight, 468 tempDrawInfo.fTempSurfaceDesc.fConfig, 469 nullptr, 470 tempDrawInfo.fTempSurfaceDesc.fSampleCnt, 471 tempDrawInfo.fTempSurfaceDesc.fOrigin); 472 if (tempRTC) { 473 SkMatrix textureMatrix = SkMatrix::MakeTrans(SkIntToScalar(left), SkIntToScalar(top)); 474 sk_sp<GrFragmentProcessor> fp; 475 if (unpremul) { 476 fp = this->createPMToUPMEffect(src->asTexture(), tempDrawInfo.fSwizzle, 477 textureMatrix); 478 if (fp) { 479 unpremul = false; // we no longer need to do this on CPU after the read back. 480 } else if (GrGpu::kCallerPrefersDraw_DrawPreference == drawPreference) { 481 // We only wanted to do the draw in order to perform the unpremul so don't 482 // bother. 483 tempRTC.reset(nullptr); 484 } 485 } 486 if (!fp && tempRTC) { 487 fp = GrConfigConversionEffect::Make(src->asTexture(), tempDrawInfo.fSwizzle, 488 GrConfigConversionEffect::kNone_PMConversion, 489 textureMatrix); 490 } 491 if (fp) { 492 GrPaint paint; 493 paint.addColorFragmentProcessor(std::move(fp)); 494 paint.setPorterDuffXPFactory(SkBlendMode::kSrc); 495 paint.setAllowSRGBInputs(true); 496 SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)); 497 tempRTC->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), rect, 498 nullptr); 499 surfaceToRead.reset(tempRTC->asTexture().release()); 500 left = 0; 501 top = 0; 502 didTempDraw = true; 503 } 504 } 505 } 506 507 if (!surfaceToRead) { 508 return false; 509 } 510 511 if (GrGpu::kRequireDraw_DrawPreference == drawPreference && !didTempDraw) { 512 return false; 513 } 514 GrPixelConfig configToRead = dstConfig; 515 if (didTempDraw) { 516 this->flushSurfaceWrites(surfaceToRead.get()); 517 configToRead = tempDrawInfo.fReadConfig; 518 } 519 if (!fGpu->readPixels(surfaceToRead.get(), left, top, width, height, configToRead, buffer, 520 rowBytes)) { 521 return false; 522 } 523 524 // Perform umpremul conversion if we weren't able to perform it as a draw. 525 if (unpremul) { 526 SkColorType colorType; 527 if (!GrPixelConfigToColorType(dstConfig, &colorType) || 528 4 != SkColorTypeBytesPerPixel(colorType)) 529 { 530 return false; 531 } 532 533 for (int y = 0; y < height; y++) { 534 SkUnpremultiplyRow<false>((uint32_t*) buffer, (const uint32_t*) buffer, width); 535 buffer = SkTAddOffset<void>(buffer, rowBytes); 536 } 537 } 538 return true; 539} 540 541void GrContext::prepareSurfaceForExternalIO(GrSurface* surface) { 542 ASSERT_SINGLE_OWNER 543 RETURN_IF_ABANDONED 544 SkASSERT(surface); 545 ASSERT_OWNED_RESOURCE(surface); 546 fDrawingManager->prepareSurfaceForExternalIO(surface); 547} 548 549void GrContext::flushSurfaceWrites(GrSurface* surface) { 550 ASSERT_SINGLE_OWNER 551 RETURN_IF_ABANDONED 552 if (surface->surfacePriv().hasPendingWrite()) { 553 this->flush(); 554 } 555} 556 557void GrContext::flushSurfaceIO(GrSurface* surface) { 558 ASSERT_SINGLE_OWNER 559 RETURN_IF_ABANDONED 560 if (surface->surfacePriv().hasPendingIO()) { 561 this->flush(); 562 } 563} 564 565//////////////////////////////////////////////////////////////////////////////// 566int GrContext::getRecommendedSampleCount(GrPixelConfig config, 567 SkScalar dpi) const { 568 ASSERT_SINGLE_OWNER 569 570 if (!this->caps()->isConfigRenderable(config, true)) { 571 return 0; 572 } 573 int chosenSampleCount = 0; 574 if (fGpu->caps()->shaderCaps()->pathRenderingSupport()) { 575 if (dpi >= 250.0f) { 576 chosenSampleCount = 4; 577 } else { 578 chosenSampleCount = 16; 579 } 580 } 581 return chosenSampleCount <= fGpu->caps()->maxSampleCount() ? chosenSampleCount : 0; 582} 583 584sk_sp<GrRenderTargetContext> GrContextPriv::makeWrappedRenderTargetContext( 585 sk_sp<GrRenderTarget> rt, 586 sk_sp<SkColorSpace> colorSpace, 587 const SkSurfaceProps* surfaceProps) { 588 ASSERT_SINGLE_OWNER_PRIV 589 590 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(rt))); 591 if (!proxy) { 592 return nullptr; 593 } 594 595 return this->drawingManager()->makeRenderTargetContext(std::move(proxy), 596 std::move(colorSpace), 597 surfaceProps); 598} 599 600sk_sp<GrSurfaceContext> GrContextPriv::makeWrappedSurfaceContext(sk_sp<GrSurfaceProxy> proxy, 601 sk_sp<SkColorSpace> colorSpace) { 602 ASSERT_SINGLE_OWNER_PRIV 603 604 if (proxy->asRenderTargetProxy()) { 605 return this->drawingManager()->makeRenderTargetContext(std::move(proxy), 606 std::move(colorSpace), nullptr); 607 } else { 608 SkASSERT(proxy->asTextureProxy()); 609 return this->drawingManager()->makeTextureContext(std::move(proxy), std::move(colorSpace)); 610 } 611} 612 613sk_sp<GrSurfaceContext> GrContextPriv::makeWrappedSurfaceContext(sk_sp<GrSurface> surface) { 614 ASSERT_SINGLE_OWNER_PRIV 615 616 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(surface))); 617 if (!proxy) { 618 return nullptr; 619 } 620 621 return this->makeWrappedSurfaceContext(std::move(proxy), nullptr); 622} 623 624sk_sp<GrSurfaceContext> GrContextPriv::makeDeferredSurfaceContext(const GrSurfaceDesc& dstDesc, 625 SkBackingFit fit, 626 SkBudgeted isDstBudgeted) { 627 628 sk_sp<GrSurfaceProxy> proxy = GrSurfaceProxy::MakeDeferred(*fContext->caps(), dstDesc, 629 fit, isDstBudgeted); 630 if (!proxy) { 631 return nullptr; 632 } 633 634 return this->makeWrappedSurfaceContext(std::move(proxy), nullptr); 635} 636 637sk_sp<GrSurfaceContext> GrContextPriv::makeBackendSurfaceContext(const GrBackendTextureDesc& desc, 638 sk_sp<SkColorSpace> colorSpace, 639 GrWrapOwnership ownership) { 640 ASSERT_SINGLE_OWNER_PRIV 641 642 sk_sp<GrSurface> surface(fContext->textureProvider()->wrapBackendTexture(desc, ownership)); 643 if (!surface) { 644 return nullptr; 645 } 646 647 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(surface))); 648 if (!proxy) { 649 return nullptr; 650 } 651 652 return this->makeWrappedSurfaceContext(std::move(proxy), std::move(colorSpace)); 653} 654 655sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendTextureRenderTargetContext( 656 const GrBackendTextureDesc& desc, 657 sk_sp<SkColorSpace> colorSpace, 658 const SkSurfaceProps* props, 659 GrWrapOwnership ownership) { 660 ASSERT_SINGLE_OWNER_PRIV 661 SkASSERT(desc.fFlags & kRenderTarget_GrBackendTextureFlag); 662 663 sk_sp<GrSurface> surface(fContext->textureProvider()->wrapBackendTexture(desc, ownership)); 664 if (!surface) { 665 return nullptr; 666 } 667 668 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(surface))); 669 if (!proxy) { 670 return nullptr; 671 } 672 673 return this->drawingManager()->makeRenderTargetContext(std::move(proxy), 674 std::move(colorSpace), props); 675} 676 677sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendRenderTargetRenderTargetContext( 678 const GrBackendRenderTargetDesc& desc, 679 sk_sp<SkColorSpace> colorSpace, 680 const SkSurfaceProps* surfaceProps) { 681 ASSERT_SINGLE_OWNER_PRIV 682 683 sk_sp<GrRenderTarget> rt(fContext->textureProvider()->wrapBackendRenderTarget(desc)); 684 if (!rt) { 685 return nullptr; 686 } 687 688 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(rt))); 689 if (!proxy) { 690 return nullptr; 691 } 692 693 return this->drawingManager()->makeRenderTargetContext(std::move(proxy), 694 std::move(colorSpace), 695 surfaceProps); 696} 697 698sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendTextureAsRenderTargetRenderTargetContext( 699 const GrBackendTextureDesc& desc, 700 sk_sp<SkColorSpace> colorSpace, 701 const SkSurfaceProps* surfaceProps) { 702 ASSERT_SINGLE_OWNER_PRIV 703 SkASSERT(desc.fFlags & kRenderTarget_GrBackendTextureFlag); 704 705 sk_sp<GrSurface> surface(fContext->resourceProvider()->wrapBackendTextureAsRenderTarget(desc)); 706 if (!surface) { 707 return nullptr; 708 } 709 710 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(surface))); 711 if (!proxy) { 712 return nullptr; 713 } 714 715 return this->drawingManager()->makeRenderTargetContext(std::move(proxy), 716 std::move(colorSpace), 717 surfaceProps); 718} 719 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->textureProvider()->createTexture(desc, budgeted)); 793 } else { 794 tex.reset(this->textureProvider()->createApproxTexture(desc)); 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<GrSurfaceProxy> rtp = GrSurfaceProxy::MakeDeferred(*this->caps(), desc, fit, budgeted); 828 if (!rtp) { 829 return nullptr; 830 } 831 832 return fDrawingManager->makeRenderTargetContext(std::move(rtp), 833 std::move(colorSpace), 834 surfaceProps); 835} 836 837bool GrContext::abandoned() const { 838 ASSERT_SINGLE_OWNER 839 return fDrawingManager->wasAbandoned(); 840} 841 842namespace { 843void test_pm_conversions(GrContext* ctx, int* pmToUPMValue, int* upmToPMValue) { 844 GrConfigConversionEffect::PMConversion pmToUPM; 845 GrConfigConversionEffect::PMConversion upmToPM; 846 GrConfigConversionEffect::TestForPreservingPMConversions(ctx, &pmToUPM, &upmToPM); 847 *pmToUPMValue = pmToUPM; 848 *upmToPMValue = upmToPM; 849} 850} 851 852void GrContext::testPMConversionsIfNecessary(uint32_t flags) { 853 ASSERT_SINGLE_OWNER 854 if (SkToBool(kUnpremul_PixelOpsFlag & flags)) { 855 if (!fDidTestPMConversions) { 856 test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion); 857 fDidTestPMConversions = true; 858 } 859 } 860} 861 862sk_sp<GrFragmentProcessor> GrContext::createPMToUPMEffect(GrTexture* texture, 863 const GrSwizzle& swizzle, 864 const SkMatrix& matrix) { 865 ASSERT_SINGLE_OWNER 866 // We should have already called this->testPMConversionsIfNecessary(). 867 SkASSERT(fDidTestPMConversions); 868 GrConfigConversionEffect::PMConversion pmToUPM = 869 static_cast<GrConfigConversionEffect::PMConversion>(fPMToUPMConversion); 870 if (GrConfigConversionEffect::kNone_PMConversion != pmToUPM) { 871 return GrConfigConversionEffect::Make(texture, swizzle, pmToUPM, matrix); 872 } else { 873 return nullptr; 874 } 875} 876 877sk_sp<GrFragmentProcessor> GrContext::createPMToUPMEffect(sk_sp<GrTextureProxy> proxy, 878 const GrSwizzle& swizzle, 879 const SkMatrix& matrix) { 880 ASSERT_SINGLE_OWNER 881 // We should have already called this->testPMConversionsIfNecessary(). 882 SkASSERT(fDidTestPMConversions); 883 GrConfigConversionEffect::PMConversion pmToUPM = 884 static_cast<GrConfigConversionEffect::PMConversion>(fPMToUPMConversion); 885 if (GrConfigConversionEffect::kNone_PMConversion != pmToUPM) { 886 return GrConfigConversionEffect::Make(this, proxy, swizzle, pmToUPM, matrix); 887 } else { 888 return nullptr; 889 } 890} 891 892sk_sp<GrFragmentProcessor> GrContext::createUPMToPMEffect(sk_sp<GrTextureProxy> proxy, 893 const GrSwizzle& swizzle, 894 const SkMatrix& matrix) { 895 ASSERT_SINGLE_OWNER 896 // We should have already called this->testPMConversionsIfNecessary(). 897 SkASSERT(fDidTestPMConversions); 898 GrConfigConversionEffect::PMConversion upmToPM = 899 static_cast<GrConfigConversionEffect::PMConversion>(fUPMToPMConversion); 900 if (GrConfigConversionEffect::kNone_PMConversion != upmToPM) { 901 return GrConfigConversionEffect::Make(this, std::move(proxy), swizzle, upmToPM, matrix); 902 } else { 903 return nullptr; 904 } 905} 906 907bool GrContext::didFailPMUPMConversionTest() const { 908 ASSERT_SINGLE_OWNER 909 // We should have already called this->testPMConversionsIfNecessary(). 910 SkASSERT(fDidTestPMConversions); 911 // The PM<->UPM tests fail or succeed together so we only need to check one. 912 return GrConfigConversionEffect::kNone_PMConversion == fPMToUPMConversion; 913} 914 915////////////////////////////////////////////////////////////////////////////// 916 917void GrContext::getResourceCacheLimits(int* maxTextures, size_t* maxTextureBytes) const { 918 ASSERT_SINGLE_OWNER 919 if (maxTextures) { 920 *maxTextures = fResourceCache->getMaxResourceCount(); 921 } 922 if (maxTextureBytes) { 923 *maxTextureBytes = fResourceCache->getMaxResourceBytes(); 924 } 925} 926 927void GrContext::setResourceCacheLimits(int maxTextures, size_t maxTextureBytes) { 928 ASSERT_SINGLE_OWNER 929 fResourceCache->setLimits(maxTextures, maxTextureBytes); 930} 931 932////////////////////////////////////////////////////////////////////////////// 933 934void GrContext::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const { 935 ASSERT_SINGLE_OWNER 936 fResourceCache->dumpMemoryStatistics(traceMemoryDump); 937} 938