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