LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/core - SkSpecialImage.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 41 213 19.2 %
Date: 2017-07-14 16:53:18 Functions: 14 50 28.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2016 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 "SkSpecialImage.h"
       9             : #include "SkBitmap.h"
      10             : #include "SkImage.h"
      11             : #include "SkBitmapCache.h"
      12             : #include "SkCanvas.h"
      13             : #include "SkImage_Base.h"
      14             : #include "SkSpecialSurface.h"
      15             : #include "SkSurfacePriv.h"
      16             : #include "SkPixelRef.h"
      17             : 
      18             : #if SK_SUPPORT_GPU
      19             : #include "GrContext.h"
      20             : #include "GrContextPriv.h"
      21             : #include "GrResourceProvider.h"
      22             : #include "GrSurfaceContext.h"
      23             : #include "GrSurfaceProxyPriv.h"
      24             : #include "GrTexture.h"
      25             : #include "GrSamplerParams.h"
      26             : #include "GrTextureProxy.h"
      27             : #include "SkGr.h"
      28             : #include "SkImage_Gpu.h"
      29             : #endif
      30             : 
      31             : // Currently the raster imagefilters can only handle certain imageinfos. Call this to know if
      32             : // a given info is supported.
      33           3 : static bool valid_for_imagefilters(const SkImageInfo& info) {
      34             :     // no support for other swizzles/depths yet
      35           3 :     return info.colorType() == kN32_SkColorType;
      36             : }
      37             : 
      38             : ///////////////////////////////////////////////////////////////////////////////
      39             : class SkSpecialImage_Base : public SkSpecialImage {
      40             : public:
      41           3 :     SkSpecialImage_Base(const SkIRect& subset, uint32_t uniqueID, const SkSurfaceProps* props)
      42           3 :         : INHERITED(subset, uniqueID, props) {
      43           3 :     }
      44           3 :     ~SkSpecialImage_Base() override { }
      45             : 
      46             :     virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) const = 0;
      47             : 
      48             :     virtual bool onGetROPixels(SkBitmap*) const = 0;
      49             : 
      50           3 :     virtual GrContext* onGetContext() const { return nullptr; }
      51             : 
      52             :     virtual SkColorSpace* onGetColorSpace() const = 0;
      53             : 
      54             : #if SK_SUPPORT_GPU
      55             :     virtual sk_sp<GrTextureProxy> onAsTextureProxyRef(GrContext* context) const = 0;
      56             : #endif
      57             : 
      58             :     virtual sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const = 0;
      59             : 
      60             :     virtual sk_sp<SkSpecialSurface> onMakeSurface(const SkImageFilter::OutputProperties& outProps,
      61             :                                                   const SkISize& size, SkAlphaType at) const = 0;
      62             : 
      63             :     virtual sk_sp<SkImage> onAsImage(const SkIRect* subset) const = 0;
      64             : 
      65             :     virtual sk_sp<SkSurface> onMakeTightSurface(const SkImageFilter::OutputProperties& outProps,
      66             :                                                 const SkISize& size, SkAlphaType at) const = 0;
      67             : 
      68             : private:
      69             :     typedef SkSpecialImage INHERITED;
      70             : };
      71             : 
      72             : ///////////////////////////////////////////////////////////////////////////////
      73           6 : static inline const SkSpecialImage_Base* as_SIB(const SkSpecialImage* image) {
      74           6 :     return static_cast<const SkSpecialImage_Base*>(image);
      75             : }
      76             : 
      77           3 : SkSpecialImage::SkSpecialImage(const SkIRect& subset,
      78             :                                uint32_t uniqueID,
      79           3 :                                const SkSurfaceProps* props)
      80             :     : fProps(SkSurfacePropsCopyOrDefault(props))
      81             :     , fSubset(subset)
      82           3 :     , fUniqueID(kNeedNewImageUniqueID_SpecialImage == uniqueID ? SkNextID::ImageID() : uniqueID) {
      83           3 : }
      84             : 
      85           0 : sk_sp<SkSpecialImage> SkSpecialImage::makeTextureImage(GrContext* context) {
      86             : #if SK_SUPPORT_GPU
      87           0 :     if (!context) {
      88           0 :         return nullptr;
      89             :     }
      90           0 :     if (GrContext* curContext = as_SIB(this)->onGetContext()) {
      91           0 :         return curContext == context ? sk_sp<SkSpecialImage>(SkRef(this)) : nullptr;
      92             :     }
      93             : 
      94           0 :     SkBitmap bmp;
      95             :     // At this point, we are definitely not texture-backed, so we must be raster or generator
      96             :     // backed. If we remove the special-wrapping-an-image subclass, we may be able to assert that
      97             :     // we are strictly raster-backed (i.e. generator images become raster when they are specialized)
      98             :     // in which case getROPixels could turn into peekPixels...
      99           0 :     if (!this->getROPixels(&bmp)) {
     100           0 :         return nullptr;
     101             :     }
     102             : 
     103           0 :     if (bmp.empty()) {
     104           0 :         return SkSpecialImage::MakeFromRaster(SkIRect::MakeEmpty(), bmp, &this->props());
     105             :     }
     106             : 
     107             :     // TODO: this is a tight copy of 'bmp' but it doesn't have to be (given SkSpecialImage's
     108             :     // semantics). Since this is cached though we would have to bake the fit into the cache key.
     109           0 :     sk_sp<GrTextureProxy> proxy = GrMakeCachedBitmapProxy(context->resourceProvider(), bmp);
     110           0 :     if (!proxy) {
     111           0 :         return nullptr;
     112             :     }
     113             : 
     114           0 :     const SkIRect rect = SkIRect::MakeWH(proxy->width(), proxy->height());
     115             : 
     116             :     // GrMakeCachedBitmapProxy has uploaded only the specified subset of 'bmp' so we need not
     117             :     // bother with SkBitmap::getSubset
     118             :     return SkSpecialImage::MakeDeferredFromGpu(context,
     119             :                                                rect,
     120             :                                                this->uniqueID(),
     121           0 :                                                std::move(proxy),
     122           0 :                                                sk_ref_sp(this->getColorSpace()),
     123           0 :                                                &this->props(),
     124           0 :                                                this->alphaType());
     125             : #else
     126             :     return nullptr;
     127             : #endif
     128             : }
     129             : 
     130           0 : void SkSpecialImage::draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const {
     131           0 :     return as_SIB(this)->onDraw(canvas, x, y, paint);
     132             : }
     133             : 
     134           3 : bool SkSpecialImage::getROPixels(SkBitmap* bm) const {
     135           3 :     return as_SIB(this)->onGetROPixels(bm);
     136             : }
     137             : 
     138           3 : bool SkSpecialImage::isTextureBacked() const {
     139           3 :     return SkToBool(as_SIB(this)->onGetContext());
     140             : }
     141             : 
     142           0 : GrContext* SkSpecialImage::getContext() const {
     143           0 :     return as_SIB(this)->onGetContext();
     144             : }
     145             : 
     146           0 : SkColorSpace* SkSpecialImage::getColorSpace() const {
     147           0 :     return as_SIB(this)->onGetColorSpace();
     148             : }
     149             : 
     150             : #if SK_SUPPORT_GPU
     151           0 : sk_sp<GrTextureProxy> SkSpecialImage::asTextureProxyRef(GrContext* context) const {
     152           0 :     return as_SIB(this)->onAsTextureProxyRef(context);
     153             : }
     154             : #endif
     155             : 
     156           0 : sk_sp<SkSpecialSurface> SkSpecialImage::makeSurface(const SkImageFilter::OutputProperties& outProps,
     157             :                                                     const SkISize& size, SkAlphaType at) const {
     158           0 :     return as_SIB(this)->onMakeSurface(outProps, size, at);
     159             : }
     160             : 
     161           0 : sk_sp<SkSurface> SkSpecialImage::makeTightSurface(const SkImageFilter::OutputProperties& outProps,
     162             :                                                   const SkISize& size, SkAlphaType at) const {
     163           0 :     return as_SIB(this)->onMakeTightSurface(outProps, size, at);
     164             : }
     165             : 
     166           0 : sk_sp<SkSpecialImage> SkSpecialImage::makeSubset(const SkIRect& subset) const {
     167           0 :     return as_SIB(this)->onMakeSubset(subset);
     168             : }
     169             : 
     170           0 : sk_sp<SkImage> SkSpecialImage::asImage(const SkIRect* subset) const {
     171           0 :     return as_SIB(this)->onAsImage(subset);
     172             : }
     173             : 
     174             : 
     175             : #ifdef SK_DEBUG
     176           3 : static bool rect_fits(const SkIRect& rect, int width, int height) {
     177           3 :     if (0 == width && 0 == height) {
     178           0 :         SkASSERT(0 == rect.fLeft && 0 == rect.fRight && 0 == rect.fTop && 0 == rect.fBottom);
     179           0 :         return true;
     180             :     }
     181             : 
     182           9 :     return rect.fLeft >= 0 && rect.fLeft < width && rect.fLeft < rect.fRight &&
     183           9 :            rect.fRight >= 0 && rect.fRight <= width &&
     184           9 :            rect.fTop >= 0 && rect.fTop < height && rect.fTop < rect.fBottom &&
     185           9 :            rect.fBottom >= 0 && rect.fBottom <= height;
     186             : }
     187             : #endif
     188             : 
     189           0 : sk_sp<SkSpecialImage> SkSpecialImage::MakeFromImage(const SkIRect& subset,
     190             :                                                     sk_sp<SkImage> image,
     191             :                                                     SkColorSpace* dstColorSpace,
     192             :                                                     const SkSurfaceProps* props) {
     193           0 :     SkASSERT(rect_fits(subset, image->width(), image->height()));
     194             : 
     195             : #if SK_SUPPORT_GPU
     196           0 :     if (sk_sp<GrTextureProxy> proxy = as_IB(image)->asTextureProxyRef()) {
     197           0 :         GrContext* context = ((SkImage_Gpu*) as_IB(image))->context();
     198             : 
     199           0 :         return MakeDeferredFromGpu(context, subset, image->uniqueID(), std::move(proxy),
     200           0 :                                    as_IB(image)->onImageInfo().refColorSpace(), props);
     201             :     } else
     202             : #endif
     203             :     {
     204           0 :         SkBitmap bm;
     205           0 :         if (as_IB(image)->getROPixels(&bm, dstColorSpace)) {
     206           0 :             return MakeFromRaster(subset, bm, props);
     207             :         }
     208             :     }
     209           0 :     return nullptr;
     210             : }
     211             : 
     212             : ///////////////////////////////////////////////////////////////////////////////
     213             : 
     214           9 : class SkSpecialImage_Raster : public SkSpecialImage_Base {
     215             : public:
     216           3 :     SkSpecialImage_Raster(const SkIRect& subset, const SkBitmap& bm, const SkSurfaceProps* props)
     217           3 :         : INHERITED(subset, bm.getGenerationID(), props)
     218           3 :         , fBitmap(bm)
     219             :     {
     220           3 :         SkASSERT(bm.pixelRef());
     221             : 
     222             :         // We have to lock now, while bm is still in scope, since it may have come from our
     223             :         // cache, which means we need to keep it locked until we (the special) are done, since
     224             :         // we cannot re-generate the cache entry (if bm came from a generator).
     225           3 :         fBitmap.lockPixels();
     226           3 :         SkASSERT(fBitmap.getPixels());
     227           3 :     }
     228             : 
     229           0 :     SkAlphaType alphaType() const override { return fBitmap.alphaType(); }
     230             : 
     231           0 :     size_t getSize() const override { return fBitmap.getSize(); }
     232             : 
     233           0 :     void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
     234             :         SkRect dst = SkRect::MakeXYWH(x, y,
     235           0 :                                       this->subset().width(), this->subset().height());
     236             : 
     237           0 :         canvas->drawBitmapRect(fBitmap, this->subset(),
     238           0 :                                dst, paint, SkCanvas::kStrict_SrcRectConstraint);
     239           0 :     }
     240             : 
     241           3 :     bool onGetROPixels(SkBitmap* bm) const override {
     242           3 :         *bm = fBitmap;
     243           3 :         return true;
     244             :     }
     245             : 
     246           0 :     SkColorSpace* onGetColorSpace() const override {
     247           0 :         return fBitmap.colorSpace();
     248             :     }
     249             : 
     250             : #if SK_SUPPORT_GPU
     251           0 :     sk_sp<GrTextureProxy> onAsTextureProxyRef(GrContext* context) const override {
     252           0 :         if (context) {
     253           0 :             return GrMakeCachedBitmapProxy(context->resourceProvider(), fBitmap);
     254             :         }
     255             : 
     256           0 :         return nullptr;
     257             :     }
     258             : #endif
     259             : 
     260             : // TODO: The raster implementations of image filters all currently assume that the pixels are
     261             : // legacy N32. Until they actually check the format and operate on sRGB or F16 data appropriately,
     262             : // we can't enable this. (They will continue to produce incorrect results, but less-so).
     263             : #define RASTER_IMAGE_FILTERS_SUPPORT_SRGB_AND_F16 0
     264             : 
     265           0 :     sk_sp<SkSpecialSurface> onMakeSurface(const SkImageFilter::OutputProperties& outProps,
     266             :                                           const SkISize& size, SkAlphaType at) const override {
     267             : #if RASTER_IMAGE_FILTERS_SUPPORT_SRGB_AND_F16
     268             :         SkColorSpace* colorSpace = outProps.colorSpace();
     269             : #else
     270           0 :         SkColorSpace* colorSpace = nullptr;
     271             : #endif
     272           0 :         SkColorType colorType = colorSpace && colorSpace->gammaIsLinear()
     273           0 :             ? kRGBA_F16_SkColorType : kN32_SkColorType;
     274             :         SkImageInfo info = SkImageInfo::Make(size.width(), size.height(), colorType, at,
     275           0 :                                              sk_ref_sp(colorSpace));
     276           0 :         return SkSpecialSurface::MakeRaster(info, nullptr);
     277             :     }
     278             : 
     279           0 :     sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
     280           0 :         SkBitmap subsetBM;
     281             : 
     282           0 :         if (!fBitmap.extractSubset(&subsetBM, subset)) {
     283           0 :             return nullptr;
     284             :         }
     285             : 
     286           0 :         return SkSpecialImage::MakeFromRaster(SkIRect::MakeWH(subset.width(), subset.height()),
     287             :                                               subsetBM,
     288           0 :                                               &this->props());
     289             :     }
     290             : 
     291           0 :     sk_sp<SkImage> onAsImage(const SkIRect* subset) const override {
     292           0 :         if (subset) {
     293           0 :             SkBitmap subsetBM;
     294             : 
     295           0 :             if (!fBitmap.extractSubset(&subsetBM, *subset)) {
     296           0 :                 return nullptr;
     297             :             }
     298             : 
     299           0 :             return SkImage::MakeFromBitmap(subsetBM);
     300             :         }
     301             : 
     302           0 :         return SkImage::MakeFromBitmap(fBitmap);
     303             :     }
     304             : 
     305           0 :     sk_sp<SkSurface> onMakeTightSurface(const SkImageFilter::OutputProperties& outProps,
     306             :                                         const SkISize& size, SkAlphaType at) const override {
     307             : #if RASTER_IMAGE_FILTERS_SUPPORT_SRGB_AND_F16
     308             :         SkColorSpace* colorSpace = outProps.colorSpace();
     309             : #else
     310           0 :         SkColorSpace* colorSpace = nullptr;
     311             : #endif
     312           0 :         SkColorType colorType = colorSpace && colorSpace->gammaIsLinear()
     313           0 :             ? kRGBA_F16_SkColorType : kN32_SkColorType;
     314             :         SkImageInfo info = SkImageInfo::Make(size.width(), size.height(), colorType, at,
     315           0 :                                              sk_ref_sp(colorSpace));
     316           0 :         return SkSurface::MakeRaster(info);
     317             :     }
     318             : 
     319             : private:
     320             :     SkBitmap fBitmap;
     321             : 
     322             :     typedef SkSpecialImage_Base INHERITED;
     323             : };
     324             : 
     325           3 : sk_sp<SkSpecialImage> SkSpecialImage::MakeFromRaster(const SkIRect& subset,
     326             :                                                      const SkBitmap& bm,
     327             :                                                      const SkSurfaceProps* props) {
     328           3 :     SkASSERT(rect_fits(subset, bm.width(), bm.height()));
     329             : 
     330           3 :     if (!bm.pixelRef()) {
     331           0 :         return nullptr;
     332             :     }
     333             : 
     334           3 :     const SkBitmap* srcBM = &bm;
     335           6 :     SkBitmap tmpStorage;
     336             :     // ImageFilters only handle N32 at the moment, so force our src to be that
     337           3 :     if (!valid_for_imagefilters(bm.info())) {
     338           0 :         if (!bm.copyTo(&tmpStorage, kN32_SkColorType)) {
     339           0 :             return nullptr;
     340             :         }
     341           0 :         srcBM = &tmpStorage;
     342             :     }
     343           3 :     return sk_make_sp<SkSpecialImage_Raster>(subset, *srcBM, props);
     344             : }
     345             : 
     346             : #if SK_SUPPORT_GPU
     347             : ///////////////////////////////////////////////////////////////////////////////
     348             : #include "GrTexture.h"
     349             : 
     350           0 : static sk_sp<SkImage> wrap_proxy_in_image(GrContext* context, sk_sp<GrTextureProxy> proxy,
     351             :                                           SkAlphaType alphaType, sk_sp<SkColorSpace> colorSpace) {
     352           0 :     return sk_make_sp<SkImage_Gpu>(context, kNeedNewImageUniqueID, alphaType,
     353           0 :                                    std::move(proxy), std::move(colorSpace), SkBudgeted::kYes);
     354             : }
     355             : 
     356             : class SkSpecialImage_Gpu : public SkSpecialImage_Base {
     357             : public:
     358           0 :     SkSpecialImage_Gpu(GrContext* context, const SkIRect& subset,
     359             :                        uint32_t uniqueID, sk_sp<GrTextureProxy> proxy, SkAlphaType at,
     360             :                        sk_sp<SkColorSpace> colorSpace, const SkSurfaceProps* props)
     361           0 :         : INHERITED(subset, uniqueID, props)
     362             :         , fContext(context)
     363           0 :         , fTextureProxy(std::move(proxy))
     364             :         , fAlphaType(at)
     365           0 :         , fColorSpace(std::move(colorSpace))
     366           0 :         , fAddedRasterVersionToCache(false) {
     367           0 :     }
     368             : 
     369           0 :     ~SkSpecialImage_Gpu() override {
     370           0 :         if (fAddedRasterVersionToCache.load()) {
     371           0 :             SkNotifyBitmapGenIDIsStale(this->uniqueID());
     372             :         }
     373           0 :     }
     374             : 
     375           0 :     SkAlphaType alphaType() const override { return fAlphaType; }
     376             : 
     377           0 :     size_t getSize() const override { return fTextureProxy->gpuMemorySize(); }
     378             : 
     379           0 :     void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
     380             :         SkRect dst = SkRect::MakeXYWH(x, y,
     381           0 :                                       this->subset().width(), this->subset().height());
     382             : 
     383             :         // TODO: In this instance we know we're going to draw a sub-portion of the backing
     384             :         // texture into the canvas so it is okay to wrap it in an SkImage. This poses
     385             :         // some problems for full deferral however in that when the deferred SkImage_Gpu
     386             :         // instantiates itself it is going to have to either be okay with having a larger
     387             :         // than expected backing texture (unlikely) or the 'fit' of the SurfaceProxy needs
     388             :         // to be tightened (if it is deferred).
     389           0 :         sk_sp<SkImage> img = sk_sp<SkImage>(new SkImage_Gpu(canvas->getGrContext(),
     390           0 :                                                             this->uniqueID(), fAlphaType,
     391             :                                                             fTextureProxy,
     392           0 :                                                             fColorSpace, SkBudgeted::kNo));
     393             : 
     394           0 :         canvas->drawImageRect(img, this->subset(),
     395           0 :                               dst, paint, SkCanvas::kStrict_SrcRectConstraint);
     396           0 :     }
     397             : 
     398           0 :     GrContext* onGetContext() const override { return fContext; }
     399             : 
     400           0 :     sk_sp<GrTextureProxy> onAsTextureProxyRef(GrContext*) const override {
     401           0 :         return fTextureProxy;
     402             :     }
     403             : 
     404           0 :     bool onGetROPixels(SkBitmap* dst) const override {
     405           0 :         const auto desc = SkBitmapCacheDesc::Make(this->uniqueID(), this->width(), this->height());
     406           0 :         if (SkBitmapCache::Find(desc, dst)) {
     407           0 :             SkASSERT(dst->getGenerationID() == this->uniqueID());
     408           0 :             SkASSERT(dst->isImmutable());
     409           0 :             SkASSERT(dst->getPixels());
     410           0 :             return true;
     411             :         }
     412             : 
     413           0 :         SkPixmap pmap;
     414             :         SkImageInfo info = SkImageInfo::MakeN32(this->width(), this->height(),
     415           0 :                                                 this->alphaType(), fColorSpace);
     416           0 :         auto rec = SkBitmapCache::Alloc(desc, info, &pmap);
     417           0 :         if (!rec) {
     418           0 :             return false;
     419             :         }
     420             : 
     421           0 :         sk_sp<GrSurfaceContext> sContext = fContext->contextPriv().makeWrappedSurfaceContext(
     422           0 :                                                                           fTextureProxy, nullptr);
     423           0 :         if (!sContext) {
     424           0 :             return false;
     425             :         }
     426             : 
     427           0 :         if (!sContext->readPixels(info, pmap.writable_addr(), pmap.rowBytes(), 0, 0)) {
     428           0 :             return false;
     429             :         }
     430             : 
     431           0 :         SkBitmapCache::Add(std::move(rec), dst);
     432           0 :         fAddedRasterVersionToCache.store(true);
     433           0 :         return true;
     434             :     }
     435             : 
     436           0 :     SkColorSpace* onGetColorSpace() const override {
     437           0 :         return fColorSpace.get();
     438             :     }
     439             : 
     440           0 :     sk_sp<SkSpecialSurface> onMakeSurface(const SkImageFilter::OutputProperties& outProps,
     441             :                                           const SkISize& size, SkAlphaType at) const override {
     442           0 :         if (!fContext) {
     443           0 :             return nullptr;
     444             :         }
     445             : 
     446           0 :         SkColorSpace* colorSpace = outProps.colorSpace();
     447             :         return SkSpecialSurface::MakeRenderTarget(
     448           0 :             fContext, size.width(), size.height(),
     449           0 :             GrRenderableConfigForColorSpace(colorSpace), sk_ref_sp(colorSpace));
     450             :     }
     451             : 
     452           0 :     sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
     453           0 :         return SkSpecialImage::MakeDeferredFromGpu(fContext,
     454             :                                                    subset,
     455             :                                                    this->uniqueID(),
     456             :                                                    fTextureProxy,
     457             :                                                    fColorSpace,
     458           0 :                                                    &this->props(),
     459           0 :                                                    fAlphaType);
     460             :     }
     461             : 
     462             :     // TODO: move all the logic here into the subset-flavor GrSurfaceProxy::copy?
     463           0 :     sk_sp<SkImage> onAsImage(const SkIRect* subset) const override {
     464           0 :         if (subset) {
     465             :             // TODO: if this becomes a bottle neck we could base this logic on what the size
     466             :             // will be when it is finally instantiated - but that is more fraught.
     467           0 :             if (GrResourceProvider::IsFunctionallyExact(fTextureProxy.get()) &&
     468           0 :                 0 == subset->fLeft && 0 == subset->fTop &&
     469           0 :                 fTextureProxy->width() == subset->width() &&
     470           0 :                 fTextureProxy->height() == subset->height()) {
     471             :                 // The existing GrTexture is already tight so reuse it in the SkImage
     472           0 :                 return wrap_proxy_in_image(fContext, fTextureProxy, fAlphaType, fColorSpace);
     473             :             }
     474             : 
     475           0 :             sk_sp<GrTextureProxy> subsetProxy(GrSurfaceProxy::Copy(fContext, fTextureProxy.get(),
     476           0 :                                                                    *subset, SkBudgeted::kYes));
     477           0 :             if (!subsetProxy) {
     478           0 :                 return nullptr;
     479             :             }
     480             : 
     481           0 :             SkASSERT(subsetProxy->priv().isExact());
     482             :             // MDB: this is acceptable (wrapping subsetProxy in an SkImage) bc Copy will
     483             :             // return a kExact-backed proxy
     484           0 :             return wrap_proxy_in_image(fContext, std::move(subsetProxy), fAlphaType, fColorSpace);
     485             :         }
     486             : 
     487           0 :         fTextureProxy->priv().exactify();
     488             : 
     489           0 :         return wrap_proxy_in_image(fContext, fTextureProxy, fAlphaType, fColorSpace);
     490             :     }
     491             : 
     492           0 :     sk_sp<SkSurface> onMakeTightSurface(const SkImageFilter::OutputProperties& outProps,
     493             :                                         const SkISize& size, SkAlphaType at) const override {
     494           0 :         SkColorSpace* colorSpace = outProps.colorSpace();
     495           0 :         SkColorType colorType = colorSpace && colorSpace->gammaIsLinear()
     496           0 :             ? kRGBA_F16_SkColorType : kRGBA_8888_SkColorType;
     497             :         SkImageInfo info = SkImageInfo::Make(size.width(), size.height(), colorType, at,
     498           0 :                                              sk_ref_sp(colorSpace));
     499           0 :         return SkSurface::MakeRenderTarget(fContext, SkBudgeted::kYes, info);
     500             :     }
     501             : 
     502             : private:
     503             :     GrContext*              fContext;
     504             :     sk_sp<GrTextureProxy>   fTextureProxy;
     505             :     const SkAlphaType       fAlphaType;
     506             :     sk_sp<SkColorSpace>     fColorSpace;
     507             :     mutable SkAtomic<bool>  fAddedRasterVersionToCache;
     508             : 
     509             :     typedef SkSpecialImage_Base INHERITED;
     510             : };
     511             : 
     512           0 : sk_sp<SkSpecialImage> SkSpecialImage::MakeDeferredFromGpu(GrContext* context,
     513             :                                                           const SkIRect& subset,
     514             :                                                           uint32_t uniqueID,
     515             :                                                           sk_sp<GrTextureProxy> proxy,
     516             :                                                           sk_sp<SkColorSpace> colorSpace,
     517             :                                                           const SkSurfaceProps* props,
     518             :                                                           SkAlphaType at) {
     519           0 :     SkASSERT(rect_fits(subset, proxy->width(), proxy->height()));
     520           0 :     return sk_make_sp<SkSpecialImage_Gpu>(context, subset, uniqueID, std::move(proxy), at,
     521           0 :                                           std::move(colorSpace), props);
     522             : }
     523             : #endif

Generated by: LCOV version 1.13