Home | History | Annotate | Download | only in gpu
      1 /*
      2  * Copyright 2019 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 "GrContextPriv.h"
      9 
     10 #include "GrClip.h"
     11 #include "GrContextThreadSafeProxy.h"
     12 #include "GrContextThreadSafeProxyPriv.h"
     13 #include "GrDrawingManager.h"
     14 #include "GrGpu.h"
     15 #include "GrMemoryPool.h"
     16 #include "GrRenderTargetContext.h"
     17 #include "GrSkSLFPFactoryCache.h"
     18 #include "GrSurfacePriv.h"
     19 #include "GrTexture.h"
     20 #include "GrTextureContext.h"
     21 #include "SkAutoPixmapStorage.h"
     22 #include "SkImage_Base.h"
     23 #include "SkImage_Gpu.h"
     24 #include "SkGr.h"
     25 #include "text/GrTextBlobCache.h"
     26 
     27 #define ASSERT_OWNED_PROXY_PRIV(P) \
     28     SkASSERT(!(P) || !((P)->peekTexture()) || (P)->peekTexture()->getContext() == fContext)
     29 #define ASSERT_SINGLE_OWNER_PRIV \
     30     SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fContext->singleOwner());)
     31 #define RETURN_IF_ABANDONED_PRIV if (fContext->abandoned()) { return; }
     32 #define RETURN_FALSE_IF_ABANDONED_PRIV if (fContext->abandoned()) { return false; }
     33 
     34 sk_sp<const GrCaps> GrContextPriv::refCaps() const {
     35     return fContext->refCaps();
     36 }
     37 
     38 sk_sp<GrSkSLFPFactoryCache> GrContextPriv::fpFactoryCache() {
     39     return fContext->fpFactoryCache();
     40 }
     41 
     42 sk_sp<GrOpMemoryPool> GrContextPriv::refOpMemoryPool() {
     43     return fContext->refOpMemoryPool();
     44 }
     45 
     46 void GrContextPriv::addOnFlushCallbackObject(GrOnFlushCallbackObject* onFlushCBObject) {
     47     fContext->addOnFlushCallbackObject(onFlushCBObject);
     48 }
     49 
     50 sk_sp<GrSurfaceContext> GrContextPriv::makeWrappedSurfaceContext(
     51                                                     sk_sp<GrSurfaceProxy> proxy,
     52                                                     sk_sp<SkColorSpace> colorSpace,
     53                                                     const SkSurfaceProps* props) {
     54     return fContext->makeWrappedSurfaceContext(std::move(proxy), std::move(colorSpace), props);
     55 }
     56 
     57 sk_sp<GrSurfaceContext> GrContextPriv::makeDeferredSurfaceContext(
     58                                                     const GrBackendFormat& format,
     59                                                     const GrSurfaceDesc& dstDesc,
     60                                                     GrSurfaceOrigin origin,
     61                                                     GrMipMapped mipMapped,
     62                                                     SkBackingFit fit,
     63                                                     SkBudgeted isDstBudgeted,
     64                                                     sk_sp<SkColorSpace> colorSpace,
     65                                                     const SkSurfaceProps* props) {
     66     return fContext->makeDeferredSurfaceContext(format, dstDesc, origin, mipMapped, fit,
     67                                                 isDstBudgeted, std::move(colorSpace), props);
     68 }
     69 
     70 sk_sp<GrRenderTargetContext> GrContextPriv::makeDeferredRenderTargetContext(
     71                                         const GrBackendFormat& format,
     72                                         SkBackingFit fit,
     73                                         int width, int height,
     74                                         GrPixelConfig config,
     75                                         sk_sp<SkColorSpace> colorSpace,
     76                                         int sampleCnt,
     77                                         GrMipMapped mipMapped,
     78                                         GrSurfaceOrigin origin,
     79                                         const SkSurfaceProps* surfaceProps,
     80                                         SkBudgeted budgeted) {
     81     return fContext->makeDeferredRenderTargetContext(format, fit, width, height, config,
     82                                                      std::move(colorSpace), sampleCnt, mipMapped,
     83                                                      origin, surfaceProps, budgeted);
     84 }
     85 
     86 sk_sp<GrRenderTargetContext> GrContextPriv::makeDeferredRenderTargetContextWithFallback(
     87                                         const GrBackendFormat& format,
     88                                         SkBackingFit fit,
     89                                         int width, int height,
     90                                         GrPixelConfig config,
     91                                         sk_sp<SkColorSpace> colorSpace,
     92                                         int sampleCnt,
     93                                         GrMipMapped mipMapped,
     94                                         GrSurfaceOrigin origin,
     95                                         const SkSurfaceProps* surfaceProps,
     96                                         SkBudgeted budgeted) {
     97     return fContext->makeDeferredRenderTargetContextWithFallback(format, fit, width, height, config,
     98                                                                  std::move(colorSpace), sampleCnt,
     99                                                                  mipMapped, origin, surfaceProps,
    100                                                                  budgeted);
    101 }
    102 
    103 sk_sp<GrTextureContext> GrContextPriv::makeBackendTextureContext(const GrBackendTexture& tex,
    104                                                                  GrSurfaceOrigin origin,
    105                                                                  sk_sp<SkColorSpace> colorSpace) {
    106     ASSERT_SINGLE_OWNER_PRIV
    107 
    108     sk_sp<GrSurfaceProxy> proxy = this->proxyProvider()->wrapBackendTexture(
    109             tex, origin, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, kRW_GrIOType);
    110     if (!proxy) {
    111         return nullptr;
    112     }
    113 
    114     return this->drawingManager()->makeTextureContext(std::move(proxy), std::move(colorSpace));
    115 }
    116 
    117 sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendTextureRenderTargetContext(
    118                                                                    const GrBackendTexture& tex,
    119                                                                    GrSurfaceOrigin origin,
    120                                                                    int sampleCnt,
    121                                                                    sk_sp<SkColorSpace> colorSpace,
    122                                                                    const SkSurfaceProps* props,
    123                                                                    ReleaseProc releaseProc,
    124                                                                    ReleaseContext releaseCtx) {
    125     ASSERT_SINGLE_OWNER_PRIV
    126     SkASSERT(sampleCnt > 0);
    127 
    128     sk_sp<GrTextureProxy> proxy(this->proxyProvider()->wrapRenderableBackendTexture(
    129             tex, origin, sampleCnt, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, releaseProc,
    130             releaseCtx));
    131     if (!proxy) {
    132         return nullptr;
    133     }
    134 
    135     return this->drawingManager()->makeRenderTargetContext(std::move(proxy),
    136                                                            std::move(colorSpace), props);
    137 }
    138 
    139 sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendRenderTargetRenderTargetContext(
    140                                                 const GrBackendRenderTarget& backendRT,
    141                                                 GrSurfaceOrigin origin,
    142                                                 sk_sp<SkColorSpace> colorSpace,
    143                                                 const SkSurfaceProps* surfaceProps,
    144                                                 ReleaseProc releaseProc,
    145                                                 ReleaseContext releaseCtx) {
    146     ASSERT_SINGLE_OWNER_PRIV
    147 
    148     sk_sp<GrSurfaceProxy> proxy = this->proxyProvider()->wrapBackendRenderTarget(
    149             backendRT, origin, releaseProc, releaseCtx);
    150     if (!proxy) {
    151         return nullptr;
    152     }
    153 
    154     return this->drawingManager()->makeRenderTargetContext(std::move(proxy),
    155                                                            std::move(colorSpace),
    156                                                            surfaceProps);
    157 }
    158 
    159 sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendTextureAsRenderTargetRenderTargetContext(
    160                                                      const GrBackendTexture& tex,
    161                                                      GrSurfaceOrigin origin,
    162                                                      int sampleCnt,
    163                                                      sk_sp<SkColorSpace> colorSpace,
    164                                                      const SkSurfaceProps* props) {
    165     ASSERT_SINGLE_OWNER_PRIV
    166     SkASSERT(sampleCnt > 0);
    167     sk_sp<GrSurfaceProxy> proxy(
    168             this->proxyProvider()->wrapBackendTextureAsRenderTarget(tex, origin, sampleCnt));
    169     if (!proxy) {
    170         return nullptr;
    171     }
    172 
    173     return this->drawingManager()->makeRenderTargetContext(std::move(proxy),
    174                                                            std::move(colorSpace),
    175                                                            props);
    176 }
    177 
    178 sk_sp<GrRenderTargetContext> GrContextPriv::makeVulkanSecondaryCBRenderTargetContext(
    179         const SkImageInfo& imageInfo, const GrVkDrawableInfo& vkInfo, const SkSurfaceProps* props) {
    180     ASSERT_SINGLE_OWNER_PRIV
    181     sk_sp<GrSurfaceProxy> proxy(
    182             this->proxyProvider()->wrapVulkanSecondaryCBAsRenderTarget(imageInfo, vkInfo));
    183     if (!proxy) {
    184         return nullptr;
    185     }
    186 
    187     return this->drawingManager()->makeRenderTargetContext(std::move(proxy),
    188                                                            imageInfo.refColorSpace(),
    189                                                            props);
    190 }
    191 
    192 void GrContextPriv::flush(GrSurfaceProxy* proxy) {
    193     ASSERT_SINGLE_OWNER_PRIV
    194     RETURN_IF_ABANDONED_PRIV
    195     ASSERT_OWNED_PROXY_PRIV(proxy);
    196 
    197     fContext->drawingManager()->flush(proxy, SkSurface::BackendSurfaceAccess::kNoAccess,
    198                                       kNone_GrFlushFlags, 0, nullptr, nullptr, nullptr);
    199 }
    200 
    201 void GrContextPriv::flushSurfaceWrites(GrSurfaceProxy* proxy) {
    202     ASSERT_SINGLE_OWNER_PRIV
    203     RETURN_IF_ABANDONED_PRIV
    204     SkASSERT(proxy);
    205     ASSERT_OWNED_PROXY_PRIV(proxy);
    206     if (proxy->priv().hasPendingWrite()) {
    207         this->flush(proxy);
    208     }
    209 }
    210 
    211 void GrContextPriv::flushSurfaceIO(GrSurfaceProxy* proxy) {
    212     ASSERT_SINGLE_OWNER_PRIV
    213     RETURN_IF_ABANDONED_PRIV
    214     SkASSERT(proxy);
    215     ASSERT_OWNED_PROXY_PRIV(proxy);
    216     if (proxy->priv().hasPendingIO()) {
    217         this->flush(proxy);
    218     }
    219 }
    220 
    221 void GrContextPriv::prepareSurfaceForExternalIO(GrSurfaceProxy* proxy) {
    222     ASSERT_SINGLE_OWNER_PRIV
    223     RETURN_IF_ABANDONED_PRIV
    224     SkASSERT(proxy);
    225     ASSERT_OWNED_PROXY_PRIV(proxy);
    226     fContext->drawingManager()->prepareSurfaceForExternalIO(proxy,
    227             SkSurface::BackendSurfaceAccess::kNoAccess, kNone_GrFlushFlags, 0, nullptr,
    228             nullptr, nullptr);
    229 }
    230 
    231 static bool valid_premul_color_type(GrColorType ct) {
    232     switch (ct) {
    233         case GrColorType::kUnknown:          return false;
    234         case GrColorType::kAlpha_8:          return false;
    235         case GrColorType::kRGB_565:          return false;
    236         case GrColorType::kABGR_4444:        return true;
    237         case GrColorType::kRGBA_8888:        return true;
    238         case GrColorType::kRGB_888x:         return false;
    239         case GrColorType::kRG_88:            return false;
    240         case GrColorType::kBGRA_8888:        return true;
    241         case GrColorType::kRGBA_1010102:     return true;
    242         case GrColorType::kGray_8:           return false;
    243         case GrColorType::kAlpha_F16:        return false;
    244         case GrColorType::kRGBA_F16:         return true;
    245         case GrColorType::kRGBA_F16_Clamped: return true;
    246         case GrColorType::kRG_F32:           return false;
    247         case GrColorType::kRGBA_F32:         return true;
    248         case GrColorType::kRGB_ETC1:         return false;
    249     }
    250     SK_ABORT("Invalid GrColorType");
    251     return false;
    252 }
    253 
    254 // TODO: This will be removed when GrSurfaceContexts are aware of their color types.
    255 // (skbug.com/6718)
    256 static bool valid_premul_config(GrPixelConfig config) {
    257     switch (config) {
    258         case kUnknown_GrPixelConfig:            return false;
    259         case kAlpha_8_GrPixelConfig:            return false;
    260         case kGray_8_GrPixelConfig:             return false;
    261         case kRGB_565_GrPixelConfig:            return false;
    262         case kRGBA_4444_GrPixelConfig:          return true;
    263         case kRGBA_8888_GrPixelConfig:          return true;
    264         case kRGB_888_GrPixelConfig:            return false;
    265         case kRGB_888X_GrPixelConfig:           return false;
    266         case kRG_88_GrPixelConfig:              return false;
    267         case kBGRA_8888_GrPixelConfig:          return true;
    268         case kSRGBA_8888_GrPixelConfig:         return true;
    269         case kSBGRA_8888_GrPixelConfig:         return true;
    270         case kRGBA_1010102_GrPixelConfig:       return true;
    271         case kRGBA_float_GrPixelConfig:         return true;
    272         case kRG_float_GrPixelConfig:           return false;
    273         case kAlpha_half_GrPixelConfig:         return false;
    274         case kRGBA_half_GrPixelConfig:          return true;
    275         case kRGBA_half_Clamped_GrPixelConfig:  return true;
    276         case kRGB_ETC1_GrPixelConfig:           return false;
    277         case kAlpha_8_as_Alpha_GrPixelConfig:   return false;
    278         case kAlpha_8_as_Red_GrPixelConfig:     return false;
    279         case kAlpha_half_as_Red_GrPixelConfig:  return false;
    280         case kGray_8_as_Lum_GrPixelConfig:      return false;
    281         case kGray_8_as_Red_GrPixelConfig:      return false;
    282     }
    283     SK_ABORT("Invalid GrPixelConfig");
    284     return false;
    285 }
    286 
    287 static bool valid_pixel_conversion(GrColorType cpuColorType, GrPixelConfig gpuConfig,
    288                                    bool premulConversion) {
    289     // We only allow premul <-> unpremul conversions for some formats
    290     if (premulConversion &&
    291         (!valid_premul_color_type(cpuColorType) || !valid_premul_config(gpuConfig))) {
    292         return false;
    293     }
    294     return true;
    295 }
    296 
    297 bool GrContextPriv::readSurfacePixels(GrSurfaceContext* src, int left, int top, int width,
    298                                       int height, GrColorType dstColorType,
    299                                       SkColorSpace* dstColorSpace, void* buffer, size_t rowBytes,
    300                                       uint32_t pixelOpsFlags) {
    301     ASSERT_SINGLE_OWNER_PRIV
    302     RETURN_FALSE_IF_ABANDONED_PRIV
    303     SkASSERT(src);
    304     SkASSERT(buffer);
    305     ASSERT_OWNED_PROXY_PRIV(src->asSurfaceProxy());
    306     GR_CREATE_TRACE_MARKER_CONTEXT("GrContextPriv", "readSurfacePixels", fContext);
    307 
    308     SkASSERT(!(pixelOpsFlags & kDontFlush_PixelOpsFlag));
    309     if (pixelOpsFlags & kDontFlush_PixelOpsFlag) {
    310         return false;
    311     }
    312 
    313     // MDB TODO: delay this instantiation until later in the method
    314     if (!src->asSurfaceProxy()->instantiate(this->resourceProvider())) {
    315         return false;
    316     }
    317 
    318     GrSurfaceProxy* srcProxy = src->asSurfaceProxy();
    319     GrSurface* srcSurface = srcProxy->peekSurface();
    320 
    321     if (!GrSurfacePriv::AdjustReadPixelParams(srcSurface->width(), srcSurface->height(),
    322                                               GrColorTypeBytesPerPixel(dstColorType), &left, &top,
    323                                               &width, &height, &buffer, &rowBytes)) {
    324         return false;
    325     }
    326 
    327     // TODO: Make GrSurfaceContext know its alpha type and pass dst buffer's alpha type.
    328     bool unpremul = SkToBool(kUnpremul_PixelOpsFlag & pixelOpsFlags);
    329 
    330     if (!valid_pixel_conversion(dstColorType, srcProxy->config(), unpremul)) {
    331         return false;
    332     }
    333 
    334     // This is the getImageData equivalent to the canvas2D putImageData fast path. We probably don't
    335     // care so much about getImageData performance. However, in order to ensure putImageData/
    336     // getImageData in "legacy" mode are round-trippable we use the GPU to do the complementary
    337     // unpremul step to writeSurfacePixels's premul step (which is determined empirically in
    338     // fContext->vaildaPMUPMConversionExists()).
    339     bool canvas2DFastPath =
    340             unpremul &&
    341             !src->colorSpaceInfo().colorSpace() &&
    342             (GrColorType::kRGBA_8888 == dstColorType || GrColorType::kBGRA_8888 == dstColorType) &&
    343             SkToBool(srcProxy->asTextureProxy()) &&
    344             (srcProxy->config() == kRGBA_8888_GrPixelConfig ||
    345              srcProxy->config() == kBGRA_8888_GrPixelConfig) &&
    346             fContext->priv().caps()->isConfigRenderable(kRGBA_8888_GrPixelConfig) &&
    347             fContext->validPMUPMConversionExists();
    348 
    349     if (!fContext->priv().caps()->surfaceSupportsReadPixels(srcSurface) ||
    350         canvas2DFastPath) {
    351         GrSurfaceDesc desc;
    352         desc.fFlags = canvas2DFastPath ? kRenderTarget_GrSurfaceFlag : kNone_GrSurfaceFlags;
    353         desc.fConfig = canvas2DFastPath ? kRGBA_8888_GrPixelConfig : srcProxy->config();
    354         desc.fWidth = width;
    355         desc.fHeight = height;
    356         desc.fSampleCnt = 1;
    357 
    358         GrBackendFormat format;
    359         if (canvas2DFastPath) {
    360             desc.fFlags = kRenderTarget_GrSurfaceFlag;
    361             desc.fConfig = kRGBA_8888_GrPixelConfig;
    362             format = this->caps()->getBackendFormatFromColorType(kRGBA_8888_SkColorType);
    363         } else {
    364             desc.fFlags = kNone_GrSurfaceFlags;
    365             desc.fConfig = srcProxy->config();
    366             format = srcProxy->backendFormat().makeTexture2D();
    367             if (!format.isValid()) {
    368                 return false;
    369             }
    370         }
    371 
    372         auto tempProxy = this->proxyProvider()->createProxy(
    373                 format, desc, kTopLeft_GrSurfaceOrigin, SkBackingFit::kApprox, SkBudgeted::kYes);
    374         if (!tempProxy) {
    375             return false;
    376         }
    377         sk_sp<GrSurfaceContext> tempCtx;
    378         if (canvas2DFastPath) {
    379             tempCtx = this->drawingManager()->makeRenderTargetContext(std::move(tempProxy), nullptr,
    380                                                                       nullptr);
    381             SkASSERT(tempCtx->asRenderTargetContext());
    382             tempCtx->asRenderTargetContext()->discard();
    383         } else {
    384             tempCtx = this->drawingManager()->makeTextureContext(
    385                     std::move(tempProxy), src->colorSpaceInfo().refColorSpace());
    386         }
    387         if (!tempCtx) {
    388             return false;
    389         }
    390         if (canvas2DFastPath) {
    391             GrPaint paint;
    392             paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
    393             auto fp = fContext->createPMToUPMEffect(
    394                     GrSimpleTextureEffect::Make(sk_ref_sp(srcProxy->asTextureProxy()),
    395                                                 SkMatrix::I()));
    396             if (dstColorType == GrColorType::kBGRA_8888) {
    397                 fp = GrFragmentProcessor::SwizzleOutput(std::move(fp), GrSwizzle::BGRA());
    398                 dstColorType = GrColorType::kRGBA_8888;
    399             }
    400             if (!fp) {
    401                 return false;
    402             }
    403             paint.addColorFragmentProcessor(std::move(fp));
    404             tempCtx->asRenderTargetContext()->fillRectToRect(
    405                     GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
    406                     SkRect::MakeWH(width, height), SkRect::MakeXYWH(left, top, width, height));
    407         } else if (!tempCtx->copy(srcProxy, SkIRect::MakeXYWH(left, top, width, height), {0, 0})) {
    408             return false;
    409         }
    410         uint32_t flags = canvas2DFastPath ? 0 : pixelOpsFlags;
    411         return this->readSurfacePixels(tempCtx.get(), 0, 0, width, height, dstColorType,
    412                                        dstColorSpace, buffer, rowBytes, flags);
    413     }
    414 
    415     bool convert = unpremul;
    416 
    417     bool flip = srcProxy->origin() == kBottomLeft_GrSurfaceOrigin;
    418     if (flip) {
    419         top = srcSurface->height() - top - height;
    420     }
    421 
    422     GrColorType allowedColorType = fContext->priv().caps()->supportedReadPixelsColorType(
    423             srcProxy->config(), dstColorType);
    424     convert = convert || (dstColorType != allowedColorType);
    425 
    426     if (!src->colorSpaceInfo().colorSpace()) {
    427         // "Legacy" mode - no color space conversions.
    428         dstColorSpace = nullptr;
    429     }
    430     convert = convert || !SkColorSpace::Equals(dstColorSpace, src->colorSpaceInfo().colorSpace());
    431 
    432     SkAutoPixmapStorage tempPixmap;
    433     SkPixmap finalPixmap;
    434     if (convert) {
    435         SkColorType srcSkColorType = GrColorTypeToSkColorType(allowedColorType);
    436         SkColorType dstSkColorType = GrColorTypeToSkColorType(dstColorType);
    437         bool srcAlwaysOpaque = SkColorTypeIsAlwaysOpaque(srcSkColorType);
    438         bool dstAlwaysOpaque = SkColorTypeIsAlwaysOpaque(dstSkColorType);
    439         if (kUnknown_SkColorType == srcSkColorType || kUnknown_SkColorType == dstSkColorType) {
    440             return false;
    441         }
    442         auto tempAT = srcAlwaysOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
    443         auto tempII = SkImageInfo::Make(width, height, srcSkColorType, tempAT,
    444                                         src->colorSpaceInfo().refColorSpace());
    445         SkASSERT(!unpremul || !dstAlwaysOpaque);
    446         auto finalAT = (srcAlwaysOpaque || dstAlwaysOpaque)
    447                                ? kOpaque_SkAlphaType
    448                                : unpremul ? kUnpremul_SkAlphaType : kPremul_SkAlphaType;
    449         auto finalII =
    450                 SkImageInfo::Make(width, height, dstSkColorType, finalAT, sk_ref_sp(dstColorSpace));
    451         if (!SkImageInfoValidConversion(finalII, tempII)) {
    452             return false;
    453         }
    454         if (!tempPixmap.tryAlloc(tempII)) {
    455             return false;
    456         }
    457         finalPixmap.reset(finalII, buffer, rowBytes);
    458         buffer = tempPixmap.writable_addr();
    459         rowBytes = tempPixmap.rowBytes();
    460         // Chrome msan bots require this.
    461         sk_bzero(buffer, tempPixmap.computeByteSize());
    462     }
    463 
    464     if (srcSurface->surfacePriv().hasPendingWrite()) {
    465         this->flush(nullptr);  // MDB TODO: tighten this
    466     }
    467 
    468     if (!fContext->fGpu->readPixels(srcSurface, left, top, width, height, allowedColorType, buffer,
    469                                     rowBytes)) {
    470         return false;
    471     }
    472 
    473     if (flip) {
    474         size_t trimRowBytes = GrColorTypeBytesPerPixel(allowedColorType) * width;
    475         std::unique_ptr<char[]> row(new char[trimRowBytes]);
    476         char* upper = reinterpret_cast<char*>(buffer);
    477         char* lower = reinterpret_cast<char*>(buffer) + (height - 1) * rowBytes;
    478         for (int y = 0; y < height / 2; ++y, upper += rowBytes, lower -= rowBytes) {
    479             memcpy(row.get(), upper, trimRowBytes);
    480             memcpy(upper, lower, trimRowBytes);
    481             memcpy(lower, row.get(), trimRowBytes);
    482         }
    483     }
    484     if (convert) {
    485         if (!tempPixmap.readPixels(finalPixmap)) {
    486             return false;
    487         }
    488     }
    489     return true;
    490 }
    491 
    492 bool GrContextPriv::writeSurfacePixels(GrSurfaceContext* dst, int left, int top, int width,
    493                                        int height, GrColorType srcColorType,
    494                                        SkColorSpace* srcColorSpace, const void* buffer,
    495                                        size_t rowBytes, uint32_t pixelOpsFlags) {
    496     ASSERT_SINGLE_OWNER_PRIV
    497     RETURN_FALSE_IF_ABANDONED_PRIV
    498     SkASSERT(dst);
    499     SkASSERT(buffer);
    500     ASSERT_OWNED_PROXY_PRIV(dst->asSurfaceProxy());
    501     GR_CREATE_TRACE_MARKER_CONTEXT("GrContextPriv", "writeSurfacePixels", fContext);
    502 
    503     if (GrColorType::kUnknown == srcColorType) {
    504         return false;
    505     }
    506 
    507     if (!dst->asSurfaceProxy()->instantiate(this->resourceProvider())) {
    508         return false;
    509     }
    510 
    511     GrSurfaceProxy* dstProxy = dst->asSurfaceProxy();
    512     GrSurface* dstSurface = dstProxy->peekSurface();
    513 
    514     if (!GrSurfacePriv::AdjustWritePixelParams(dstSurface->width(), dstSurface->height(),
    515                                                GrColorTypeBytesPerPixel(srcColorType), &left, &top,
    516                                                &width, &height, &buffer, &rowBytes)) {
    517         return false;
    518     }
    519 
    520     // TODO: Make GrSurfaceContext know its alpha type and pass src buffer's alpha type.
    521     bool premul = SkToBool(kUnpremul_PixelOpsFlag & pixelOpsFlags);
    522 
    523     // For canvas2D putImageData performance we have a special code path for unpremul RGBA_8888 srcs
    524     // that are premultiplied on the GPU. This is kept as narrow as possible for now.
    525     bool canvas2DFastPath =
    526             !fContext->priv().caps()->avoidWritePixelsFastPath() &&
    527             premul &&
    528             !dst->colorSpaceInfo().colorSpace() &&
    529             (srcColorType == GrColorType::kRGBA_8888 || srcColorType == GrColorType::kBGRA_8888) &&
    530             SkToBool(dst->asRenderTargetContext()) &&
    531             (dstProxy->config() == kRGBA_8888_GrPixelConfig ||
    532              dstProxy->config() == kBGRA_8888_GrPixelConfig) &&
    533             !(pixelOpsFlags & kDontFlush_PixelOpsFlag) &&
    534             fContext->priv().caps()->isConfigTexturable(kRGBA_8888_GrPixelConfig) &&
    535             fContext->validPMUPMConversionExists();
    536 
    537     const GrCaps* caps = this->caps();
    538     if (!caps->surfaceSupportsWritePixels(dstSurface) ||
    539         canvas2DFastPath) {
    540         // We don't expect callers that are skipping flushes to require an intermediate draw.
    541         SkASSERT(!(pixelOpsFlags & kDontFlush_PixelOpsFlag));
    542         if (pixelOpsFlags & kDontFlush_PixelOpsFlag) {
    543             return false;
    544         }
    545 
    546         GrSurfaceDesc desc;
    547         desc.fWidth = width;
    548         desc.fHeight = height;
    549         desc.fSampleCnt = 1;
    550 
    551         GrBackendFormat format;
    552         if (canvas2DFastPath) {
    553             desc.fConfig = kRGBA_8888_GrPixelConfig;
    554             format =
    555               fContext->priv().caps()->getBackendFormatFromColorType(kRGBA_8888_SkColorType);
    556         } else {
    557             desc.fConfig =  dstProxy->config();
    558             format = dstProxy->backendFormat().makeTexture2D();
    559             if (!format.isValid()) {
    560                 return false;
    561             }
    562         }
    563 
    564         auto tempProxy = this->proxyProvider()->createProxy(
    565                 format, desc, kTopLeft_GrSurfaceOrigin, SkBackingFit::kApprox, SkBudgeted::kYes);
    566         if (!tempProxy) {
    567             return false;
    568         }
    569         auto tempCtx = this->drawingManager()->makeTextureContext(
    570                 tempProxy, dst->colorSpaceInfo().refColorSpace());
    571         if (!tempCtx) {
    572             return false;
    573         }
    574         uint32_t flags = canvas2DFastPath ? 0 : pixelOpsFlags;
    575         // In the fast path we always write the srcData to the temp context as though it were RGBA.
    576         // When the data is really BGRA the write will cause the R and B channels to be swapped in
    577         // the intermediate surface which gets corrected by a swizzle effect when drawing to the
    578         // dst.
    579         auto tmpColorType = canvas2DFastPath ? GrColorType::kRGBA_8888 : srcColorType;
    580         if (!this->writeSurfacePixels(tempCtx.get(), 0, 0, width, height, tmpColorType,
    581                                       srcColorSpace, buffer, rowBytes, flags)) {
    582             return false;
    583         }
    584         if (canvas2DFastPath) {
    585             GrPaint paint;
    586             paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
    587             auto fp = fContext->createUPMToPMEffect(
    588                     GrSimpleTextureEffect::Make(std::move(tempProxy), SkMatrix::I()));
    589             if (srcColorType == GrColorType::kBGRA_8888) {
    590                 fp = GrFragmentProcessor::SwizzleOutput(std::move(fp), GrSwizzle::BGRA());
    591             }
    592             if (!fp) {
    593                 return false;
    594             }
    595             paint.addColorFragmentProcessor(std::move(fp));
    596             dst->asRenderTargetContext()->fillRectToRect(
    597                     GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
    598                     SkRect::MakeXYWH(left, top, width, height), SkRect::MakeWH(width, height));
    599             return true;
    600         } else {
    601             return dst->copy(tempProxy.get(), SkIRect::MakeWH(width, height), {left, top});
    602         }
    603     }
    604 
    605     bool convert = premul;
    606 
    607     if (!valid_pixel_conversion(srcColorType, dstProxy->config(), premul)) {
    608         return false;
    609     }
    610 
    611     GrColorType allowedColorType = fContext->priv().caps()->supportedWritePixelsColorType(
    612             dstProxy->config(), srcColorType);
    613     convert = convert || (srcColorType != allowedColorType);
    614 
    615     if (!dst->colorSpaceInfo().colorSpace()) {
    616         // "Legacy" mode - no color space conversions.
    617         srcColorSpace = nullptr;
    618     }
    619     convert = convert || !SkColorSpace::Equals(srcColorSpace, dst->colorSpaceInfo().colorSpace());
    620 
    621     std::unique_ptr<char[]> tempBuffer;
    622     if (convert) {
    623         auto srcSkColorType = GrColorTypeToSkColorType(srcColorType);
    624         auto dstSkColorType = GrColorTypeToSkColorType(allowedColorType);
    625         if (kUnknown_SkColorType == srcSkColorType || kUnknown_SkColorType == dstSkColorType) {
    626             return false;
    627         }
    628         auto srcAlphaType = SkColorTypeIsAlwaysOpaque(srcSkColorType)
    629                 ? kOpaque_SkAlphaType
    630                 : (premul ? kUnpremul_SkAlphaType : kPremul_SkAlphaType);
    631         SkPixmap src(SkImageInfo::Make(width, height, srcSkColorType, srcAlphaType,
    632                                        sk_ref_sp(srcColorSpace)),
    633                      buffer, rowBytes);
    634         auto tempSrcII = SkImageInfo::Make(width, height, dstSkColorType, kPremul_SkAlphaType,
    635                                            dst->colorSpaceInfo().refColorSpace());
    636         auto size = tempSrcII.computeMinByteSize();
    637         if (!size) {
    638             return false;
    639         }
    640         tempBuffer.reset(new char[size]);
    641         SkPixmap tempSrc(tempSrcII, tempBuffer.get(), tempSrcII.minRowBytes());
    642         if (!src.readPixels(tempSrc)) {
    643             return false;
    644         }
    645         srcColorType = allowedColorType;
    646         buffer = tempSrc.addr();
    647         rowBytes = tempSrc.rowBytes();
    648         if (dstProxy->origin() == kBottomLeft_GrSurfaceOrigin) {
    649             std::unique_ptr<char[]> row(new char[rowBytes]);
    650             for (int y = 0; y < height / 2; ++y) {
    651                 memcpy(row.get(), tempSrc.addr(0, y), rowBytes);
    652                 memcpy(tempSrc.writable_addr(0, y), tempSrc.addr(0, height - 1 - y), rowBytes);
    653                 memcpy(tempSrc.writable_addr(0, height - 1 - y), row.get(), rowBytes);
    654             }
    655             top = dstSurface->height() - top - height;
    656         }
    657     } else if (dstProxy->origin() == kBottomLeft_GrSurfaceOrigin) {
    658         size_t trimRowBytes = GrColorTypeBytesPerPixel(srcColorType) * width;
    659         tempBuffer.reset(new char[trimRowBytes * height]);
    660         char* dst = reinterpret_cast<char*>(tempBuffer.get()) + trimRowBytes * (height - 1);
    661         const char* src = reinterpret_cast<const char*>(buffer);
    662         for (int i = 0; i < height; ++i, src += rowBytes, dst -= trimRowBytes) {
    663             memcpy(dst, src, trimRowBytes);
    664         }
    665         buffer = tempBuffer.get();
    666         rowBytes = trimRowBytes;
    667         top = dstSurface->height() - top - height;
    668     }
    669 
    670     if (!(kDontFlush_PixelOpsFlag & pixelOpsFlags) && dstSurface->surfacePriv().hasPendingIO()) {
    671         this->flush(nullptr);  // MDB TODO: tighten this
    672     }
    673 
    674     return this->getGpu()->writePixels(dstSurface, left, top, width, height, srcColorType, buffer,
    675                                        rowBytes);
    676 }
    677 
    678 void GrContextPriv::moveOpListsToDDL(SkDeferredDisplayList* ddl) {
    679     fContext->drawingManager()->moveOpListsToDDL(ddl);
    680 }
    681 
    682 void GrContextPriv::copyOpListsFromDDL(const SkDeferredDisplayList* ddl,
    683                                        GrRenderTargetProxy* newDest) {
    684     fContext->drawingManager()->copyOpListsFromDDL(ddl, newDest);
    685 }
    686 
    687 //////////////////////////////////////////////////////////////////////////////
    688 #ifdef SK_ENABLE_DUMP_GPU
    689 #include "SkJSONWriter.h"
    690 SkString GrContextPriv::dump() const {
    691     SkDynamicMemoryWStream stream;
    692     SkJSONWriter writer(&stream, SkJSONWriter::Mode::kPretty);
    693     writer.beginObject();
    694 
    695     static const char* kBackendStr[] = {
    696         "Metal",
    697         "OpenGL",
    698         "Vulkan",
    699         "Mock",
    700     };
    701     GR_STATIC_ASSERT(0 == (unsigned)GrBackendApi::kMetal);
    702     GR_STATIC_ASSERT(1 == (unsigned)GrBackendApi::kOpenGL);
    703     GR_STATIC_ASSERT(2 == (unsigned)GrBackendApi::kVulkan);
    704     GR_STATIC_ASSERT(3 == (unsigned)GrBackendApi::kMock);
    705     writer.appendString("backend", kBackendStr[(unsigned)fContext->backend()]);
    706 
    707     writer.appendName("caps");
    708     fContext->caps()->dumpJSON(&writer);
    709 
    710     writer.appendName("gpu");
    711     fContext->fGpu->dumpJSON(&writer);
    712 
    713     // Flush JSON to the memory stream
    714     writer.endObject();
    715     writer.flush();
    716 
    717     // Null terminate the JSON data in the memory stream
    718     stream.write8(0);
    719 
    720     // Allocate a string big enough to hold all the data, then copy out of the stream
    721     SkString result(stream.bytesWritten());
    722     stream.copyToAndReset(result.writable_str());
    723     return result;
    724 }
    725 #endif
    726 
    727 #if GR_TEST_UTILS
    728 void GrContextPriv::resetGpuStats() const {
    729 #if GR_GPU_STATS
    730     fContext->fGpu->stats()->reset();
    731 #endif
    732 }
    733 
    734 void GrContextPriv::dumpCacheStats(SkString* out) const {
    735 #if GR_CACHE_STATS
    736     fContext->fResourceCache->dumpStats(out);
    737 #endif
    738 }
    739 
    740 void GrContextPriv::dumpCacheStatsKeyValuePairs(SkTArray<SkString>* keys,
    741                                                 SkTArray<double>* values) const {
    742 #if GR_CACHE_STATS
    743     fContext->fResourceCache->dumpStatsKeyValuePairs(keys, values);
    744 #endif
    745 }
    746 
    747 void GrContextPriv::printCacheStats() const {
    748     SkString out;
    749     this->dumpCacheStats(&out);
    750     SkDebugf("%s", out.c_str());
    751 }
    752 
    753 void GrContextPriv::dumpGpuStats(SkString* out) const {
    754 #if GR_GPU_STATS
    755     return fContext->fGpu->stats()->dump(out);
    756 #endif
    757 }
    758 
    759 void GrContextPriv::dumpGpuStatsKeyValuePairs(SkTArray<SkString>* keys,
    760                                               SkTArray<double>* values) const {
    761 #if GR_GPU_STATS
    762     return fContext->fGpu->stats()->dumpKeyValuePairs(keys, values);
    763 #endif
    764 }
    765 
    766 void GrContextPriv::printGpuStats() const {
    767     SkString out;
    768     this->dumpGpuStats(&out);
    769     SkDebugf("%s", out.c_str());
    770 }
    771 
    772 void GrContextPriv::testingOnly_setTextBlobCacheLimit(size_t bytes) {
    773     fContext->priv().getTextBlobCache()->setBudget(bytes);
    774 }
    775 
    776 sk_sp<SkImage> GrContextPriv::testingOnly_getFontAtlasImage(GrMaskFormat format, unsigned int index) {
    777     auto atlasManager = this->getAtlasManager();
    778     if (!atlasManager) {
    779         return nullptr;
    780     }
    781 
    782     unsigned int numActiveProxies;
    783     const sk_sp<GrTextureProxy>* proxies = atlasManager->getProxies(format, &numActiveProxies);
    784     if (index >= numActiveProxies || !proxies || !proxies[index]) {
    785         return nullptr;
    786     }
    787 
    788     SkASSERT(proxies[index]->priv().isExact());
    789     sk_sp<SkImage> image(new SkImage_Gpu(sk_ref_sp(fContext), kNeedNewImageUniqueID,
    790                                          kPremul_SkAlphaType, proxies[index], nullptr));
    791     return image;
    792 }
    793 
    794 void GrContextPriv::testingOnly_purgeAllUnlockedResources() {
    795     fContext->fResourceCache->purgeAllUnlocked();
    796 }
    797 
    798 void GrContextPriv::testingOnly_flushAndRemoveOnFlushCallbackObject(GrOnFlushCallbackObject* cb) {
    799     fContext->flush();
    800     fContext->drawingManager()->testingOnly_removeOnFlushCallbackObject(cb);
    801 }
    802 #endif
    803 
    804