LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/gpu - GrContext.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 516 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 49 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13