• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "src/core/SkSpecialImage.h"
9 
10 #include "include/core/SkBitmap.h"
11 #include "include/core/SkCanvas.h"
12 #include "include/core/SkImage.h"
13 #include "src/core/SkBitmapCache.h"
14 #include "src/core/SkSpecialSurface.h"
15 #include "src/core/SkSurfacePriv.h"
16 #include "src/image/SkImage_Base.h"
17 #include <atomic>
18 
19 #if SK_SUPPORT_GPU
20 #include "include/gpu/GrContext.h"
21 #include "include/private/GrRecordingContext.h"
22 #include "src/gpu/GrContextPriv.h"
23 #include "src/gpu/GrImageInfo.h"
24 #include "src/gpu/GrProxyProvider.h"
25 #include "src/gpu/GrRecordingContextPriv.h"
26 #include "src/gpu/GrSurfaceContext.h"
27 #include "src/gpu/GrTextureProxy.h"
28 #include "src/image/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.
valid_for_imagefilters(const SkImageInfo & info)33 static bool valid_for_imagefilters(const SkImageInfo& info) {
34     // no support for other swizzles/depths yet
35     return info.colorType() == kN32_SkColorType;
36 }
37 
38 ///////////////////////////////////////////////////////////////////////////////
39 class SkSpecialImage_Base : public SkSpecialImage {
40 public:
SkSpecialImage_Base(const SkIRect & subset,uint32_t uniqueID,const SkSurfaceProps * props)41     SkSpecialImage_Base(const SkIRect& subset, uint32_t uniqueID, const SkSurfaceProps* props)
42         : INHERITED(subset, uniqueID, props) {
43     }
~SkSpecialImage_Base()44     ~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 
onGetContext() const50     virtual GrRecordingContext* onGetContext() const { return nullptr; }
51 
52     virtual SkColorSpace* onGetColorSpace() const = 0;
53 
54 #if SK_SUPPORT_GPU
55     virtual GrSurfaceProxyView onView(GrRecordingContext* context) const = 0;
56 #endif
57 
58     // This subset is relative to the backing store's coordinate frame, it has already been mapped
59     // from the content rect by the non-virtual makeSubset().
60     virtual sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const = 0;
61 
62     virtual sk_sp<SkSpecialSurface> onMakeSurface(
63             SkColorType colorType, const SkColorSpace* colorSpace, const SkISize& size,
64             SkAlphaType at, const SkSurfaceProps* = nullptr) const = 0;
65 
66     // This subset (when not null) is relative to the backing store's coordinate frame, it has
67     // already been mapped from the content rect by the non-virtual asImage().
68     virtual sk_sp<SkImage> onAsImage(const SkIRect* subset) const = 0;
69 
70     virtual sk_sp<SkSurface> onMakeTightSurface(
71             SkColorType colorType, const SkColorSpace* colorSpace,
72             const SkISize& size, SkAlphaType at) const = 0;
73 
74 private:
75     typedef SkSpecialImage INHERITED;
76 };
77 
78 ///////////////////////////////////////////////////////////////////////////////
as_SIB(const SkSpecialImage * image)79 static inline const SkSpecialImage_Base* as_SIB(const SkSpecialImage* image) {
80     return static_cast<const SkSpecialImage_Base*>(image);
81 }
82 
SkSpecialImage(const SkIRect & subset,uint32_t uniqueID,const SkSurfaceProps * props)83 SkSpecialImage::SkSpecialImage(const SkIRect& subset,
84                                uint32_t uniqueID,
85                                const SkSurfaceProps* props)
86     : fProps(SkSurfacePropsCopyOrDefault(props))
87     , fSubset(subset)
88     , fUniqueID(kNeedNewImageUniqueID_SpecialImage == uniqueID ? SkNextID::ImageID() : uniqueID) {
89 }
90 
makeTextureImage(GrRecordingContext * context) const91 sk_sp<SkSpecialImage> SkSpecialImage::makeTextureImage(GrRecordingContext* context) const {
92 #if SK_SUPPORT_GPU
93     if (!context) {
94         return nullptr;
95     }
96     if (GrRecordingContext* curContext = as_SIB(this)->onGetContext()) {
97         return curContext->priv().matches(context) ? sk_ref_sp(this) : nullptr;
98     }
99 
100     SkBitmap bmp;
101     // At this point, we are definitely not texture-backed, so we must be raster or generator
102     // backed. If we remove the special-wrapping-an-image subclass, we may be able to assert that
103     // we are strictly raster-backed (i.e. generator images become raster when they are specialized)
104     // in which case getROPixels could turn into peekPixels...
105     if (!this->getROPixels(&bmp)) {
106         return nullptr;
107     }
108 
109     if (bmp.empty()) {
110         return SkSpecialImage::MakeFromRaster(SkIRect::MakeEmpty(), bmp, &this->props());
111     }
112 
113     // TODO: this is a tight copy of 'bmp' but it doesn't have to be (given SkSpecialImage's
114     // semantics). Since this is cached though we would have to bake the fit into the cache key.
115     auto view = GrMakeCachedBitmapProxyView(context, bmp);
116     if (!view.proxy()) {
117         return nullptr;
118     }
119 
120     const SkIRect rect = SkIRect::MakeSize(view.proxy()->dimensions());
121 
122     // GrMakeCachedBitmapProxyView has uploaded only the specified subset of 'bmp' so we need not
123     // bother with SkBitmap::getSubset
124     return SkSpecialImage::MakeDeferredFromGpu(context,
125                                                rect,
126                                                this->uniqueID(),
127                                                std::move(view),
128                                                SkColorTypeToGrColorType(bmp.colorType()),
129                                                sk_ref_sp(this->getColorSpace()),
130                                                &this->props(),
131                                                this->alphaType());
132 #else
133     return nullptr;
134 #endif
135 }
136 
draw(SkCanvas * canvas,SkScalar x,SkScalar y,const SkPaint * paint) const137 void SkSpecialImage::draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const {
138     return as_SIB(this)->onDraw(canvas, x, y, paint);
139 }
140 
getROPixels(SkBitmap * bm) const141 bool SkSpecialImage::getROPixels(SkBitmap* bm) const {
142     return as_SIB(this)->onGetROPixels(bm);
143 }
144 
isTextureBacked() const145 bool SkSpecialImage::isTextureBacked() const {
146     return SkToBool(as_SIB(this)->onGetContext());
147 }
148 
getContext() const149 GrRecordingContext* SkSpecialImage::getContext() const {
150     return as_SIB(this)->onGetContext();
151 }
152 
getColorSpace() const153 SkColorSpace* SkSpecialImage::getColorSpace() const {
154     return as_SIB(this)->onGetColorSpace();
155 }
156 
157 #if SK_SUPPORT_GPU
view(GrRecordingContext * context) const158 GrSurfaceProxyView SkSpecialImage::view(GrRecordingContext* context) const {
159     return as_SIB(this)->onView(context);
160 }
161 #endif
162 
makeSurface(SkColorType colorType,const SkColorSpace * colorSpace,const SkISize & size,SkAlphaType at,const SkSurfaceProps * props) const163 sk_sp<SkSpecialSurface> SkSpecialImage::makeSurface(
164         SkColorType colorType, const SkColorSpace* colorSpace, const SkISize& size,
165         SkAlphaType at, const SkSurfaceProps* props) const {
166     return as_SIB(this)->onMakeSurface(colorType, colorSpace, size, at, props);
167 }
168 
makeTightSurface(SkColorType colorType,const SkColorSpace * colorSpace,const SkISize & size,SkAlphaType at) const169 sk_sp<SkSurface> SkSpecialImage::makeTightSurface(
170         SkColorType colorType, const SkColorSpace* colorSpace, const SkISize& size,
171         SkAlphaType at) const {
172     return as_SIB(this)->onMakeTightSurface(colorType, colorSpace, size, at);
173 }
174 
makeSubset(const SkIRect & subset) const175 sk_sp<SkSpecialImage> SkSpecialImage::makeSubset(const SkIRect& subset) const {
176     SkIRect absolute = subset.makeOffset(this->subset().topLeft());
177     return as_SIB(this)->onMakeSubset(absolute);
178 }
179 
asImage(const SkIRect * subset) const180 sk_sp<SkImage> SkSpecialImage::asImage(const SkIRect* subset) const {
181     if (subset) {
182         SkIRect absolute = subset->makeOffset(this->subset().topLeft());
183         return as_SIB(this)->onAsImage(&absolute);
184     } else {
185         return as_SIB(this)->onAsImage(nullptr);
186     }
187 }
188 
189 #if defined(SK_DEBUG) || SK_SUPPORT_GPU
rect_fits(const SkIRect & rect,int width,int height)190 static bool rect_fits(const SkIRect& rect, int width, int height) {
191     if (0 == width && 0 == height) {
192         SkASSERT(0 == rect.fLeft && 0 == rect.fRight && 0 == rect.fTop && 0 == rect.fBottom);
193         return true;
194     }
195 
196     return rect.fLeft >= 0 && rect.fLeft < width && rect.fLeft < rect.fRight &&
197            rect.fRight >= 0 && rect.fRight <= width &&
198            rect.fTop >= 0 && rect.fTop < height && rect.fTop < rect.fBottom &&
199            rect.fBottom >= 0 && rect.fBottom <= height;
200 }
201 #endif
202 
MakeFromImage(GrRecordingContext * context,const SkIRect & subset,sk_sp<SkImage> image,const SkSurfaceProps * props)203 sk_sp<SkSpecialImage> SkSpecialImage::MakeFromImage(GrRecordingContext* context,
204                                                     const SkIRect& subset,
205                                                     sk_sp<SkImage> image,
206                                                     const SkSurfaceProps* props) {
207     SkASSERT(rect_fits(subset, image->width(), image->height()));
208 
209 #if SK_SUPPORT_GPU
210     if (const GrSurfaceProxyView* view = as_IB(image)->view(context)) {
211         if (!as_IB(image)->context()->priv().matches(context)) {
212             return nullptr;
213         }
214 
215         return MakeDeferredFromGpu(context, subset, image->uniqueID(), *view,
216                                    SkColorTypeToGrColorType(image->colorType()),
217                                    image->refColorSpace(), props);
218     } else
219 #endif
220     {
221         SkBitmap bm;
222         if (as_IB(image)->getROPixels(&bm)) {
223             return MakeFromRaster(subset, bm, props);
224         }
225     }
226     return nullptr;
227 }
228 
229 ///////////////////////////////////////////////////////////////////////////////
230 
231 class SkSpecialImage_Raster : public SkSpecialImage_Base {
232 public:
SkSpecialImage_Raster(const SkIRect & subset,const SkBitmap & bm,const SkSurfaceProps * props)233     SkSpecialImage_Raster(const SkIRect& subset, const SkBitmap& bm, const SkSurfaceProps* props)
234         : INHERITED(subset, bm.getGenerationID(), props)
235         , fBitmap(bm)
236     {
237         SkASSERT(bm.pixelRef());
238         SkASSERT(fBitmap.getPixels());
239     }
240 
alphaType() const241     SkAlphaType alphaType() const override { return fBitmap.alphaType(); }
242 
colorType() const243     SkColorType colorType() const override { return fBitmap.colorType(); }
244 
getSize() const245     size_t getSize() const override { return fBitmap.computeByteSize(); }
246 
onDraw(SkCanvas * canvas,SkScalar x,SkScalar y,const SkPaint * paint) const247     void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
248         SkRect dst = SkRect::MakeXYWH(x, y,
249                                       this->subset().width(), this->subset().height());
250 
251         canvas->drawBitmapRect(fBitmap, this->subset(),
252                                dst, paint, SkCanvas::kStrict_SrcRectConstraint);
253     }
254 
onGetROPixels(SkBitmap * bm) const255     bool onGetROPixels(SkBitmap* bm) const override {
256         return fBitmap.extractSubset(bm, this->subset());
257     }
258 
onGetColorSpace() const259     SkColorSpace* onGetColorSpace() const override {
260         return fBitmap.colorSpace();
261     }
262 
263 #if SK_SUPPORT_GPU
onView(GrRecordingContext * context) const264     GrSurfaceProxyView onView(GrRecordingContext* context) const override {
265         if (context) {
266             return GrMakeCachedBitmapProxyView(context, fBitmap);
267         }
268 
269         return {};
270     }
271 #endif
272 
onMakeSurface(SkColorType colorType,const SkColorSpace * colorSpace,const SkISize & size,SkAlphaType at,const SkSurfaceProps * props) const273     sk_sp<SkSpecialSurface> onMakeSurface(SkColorType colorType, const SkColorSpace* colorSpace,
274                                           const SkISize& size, SkAlphaType at,
275                                           const SkSurfaceProps* props) const override {
276         // Ignore the requested color type, the raster backend currently only supports N32
277         colorType = kN32_SkColorType;   // TODO: find ways to allow f16
278         SkImageInfo info = SkImageInfo::Make(size, colorType, at, sk_ref_sp(colorSpace));
279         return SkSpecialSurface::MakeRaster(info, props);
280     }
281 
onMakeSubset(const SkIRect & subset) const282     sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
283         // No need to extract subset, onGetROPixels handles that when needed
284         return SkSpecialImage::MakeFromRaster(subset, fBitmap, &this->props());
285     }
286 
onAsImage(const SkIRect * subset) const287     sk_sp<SkImage> onAsImage(const SkIRect* subset) const override {
288         if (subset) {
289             SkBitmap subsetBM;
290 
291             if (!fBitmap.extractSubset(&subsetBM, *subset)) {
292                 return nullptr;
293             }
294 
295             return SkImage::MakeFromBitmap(subsetBM);
296         }
297 
298         return SkImage::MakeFromBitmap(fBitmap);
299     }
300 
onMakeTightSurface(SkColorType colorType,const SkColorSpace * colorSpace,const SkISize & size,SkAlphaType at) const301 sk_sp<SkSurface> onMakeTightSurface(SkColorType colorType, const SkColorSpace* colorSpace,
302                                         const SkISize& size, SkAlphaType at) const override {
303         // Ignore the requested color type, the raster backend currently only supports N32
304         colorType = kN32_SkColorType;   // TODO: find ways to allow f16
305         SkImageInfo info = SkImageInfo::Make(size, colorType, at, sk_ref_sp(colorSpace));
306         return SkSurface::MakeRaster(info);
307     }
308 
309 private:
310     SkBitmap fBitmap;
311 
312     typedef SkSpecialImage_Base INHERITED;
313 };
314 
MakeFromRaster(const SkIRect & subset,const SkBitmap & bm,const SkSurfaceProps * props)315 sk_sp<SkSpecialImage> SkSpecialImage::MakeFromRaster(const SkIRect& subset,
316                                                      const SkBitmap& bm,
317                                                      const SkSurfaceProps* props) {
318     SkASSERT(rect_fits(subset, bm.width(), bm.height()));
319 
320     if (!bm.pixelRef()) {
321         return nullptr;
322     }
323 
324     const SkBitmap* srcBM = &bm;
325     SkBitmap tmp;
326     // ImageFilters only handle N32 at the moment, so force our src to be that
327     if (!valid_for_imagefilters(bm.info())) {
328         if (!tmp.tryAllocPixels(bm.info().makeColorType(kN32_SkColorType)) ||
329             !bm.readPixels(tmp.info(), tmp.getPixels(), tmp.rowBytes(), 0, 0))
330         {
331             return nullptr;
332         }
333         srcBM = &tmp;
334     }
335     return sk_make_sp<SkSpecialImage_Raster>(subset, *srcBM, props);
336 }
337 
CopyFromRaster(const SkIRect & subset,const SkBitmap & bm,const SkSurfaceProps * props)338 sk_sp<SkSpecialImage> SkSpecialImage::CopyFromRaster(const SkIRect& subset,
339                                                      const SkBitmap& bm,
340                                                      const SkSurfaceProps* props) {
341     SkASSERT(rect_fits(subset, bm.width(), bm.height()));
342 
343     if (!bm.pixelRef()) {
344         return nullptr;
345     }
346 
347     SkBitmap tmp;
348     SkImageInfo info = bm.info().makeDimensions(subset.size());
349     // As in MakeFromRaster, must force src to N32 for ImageFilters
350     if (!valid_for_imagefilters(bm.info())) {
351         info = info.makeColorType(kN32_SkColorType);
352     }
353     if (!tmp.tryAllocPixels(info)) {
354         return nullptr;
355     }
356     if (!bm.readPixels(tmp.info(), tmp.getPixels(), tmp.rowBytes(), subset.x(), subset.y())) {
357         return nullptr;
358     }
359 
360     // Since we're making a copy of the raster, the resulting special image is the exact size
361     // of the requested subset of the original and no longer needs to be offset by subset's left
362     // and top, since those were relative to the original's buffer.
363     return sk_make_sp<SkSpecialImage_Raster>(
364             SkIRect::MakeWH(subset.width(), subset.height()), tmp, props);
365 }
366 
367 #if SK_SUPPORT_GPU
368 ///////////////////////////////////////////////////////////////////////////////
wrap_proxy_in_image(GrRecordingContext * context,GrSurfaceProxyView view,SkColorType colorType,SkAlphaType alphaType,sk_sp<SkColorSpace> colorSpace)369 static sk_sp<SkImage> wrap_proxy_in_image(GrRecordingContext* context, GrSurfaceProxyView view,
370                                           SkColorType colorType, SkAlphaType alphaType,
371                                           sk_sp<SkColorSpace> colorSpace) {
372     // CONTEXT TODO: remove this use of 'backdoor' to create an SkImage
373     return sk_make_sp<SkImage_Gpu>(sk_ref_sp(context->priv().backdoor()),
374                                    kNeedNewImageUniqueID, std::move(view), colorType, alphaType,
375                                    std::move(colorSpace));
376 }
377 
378 class SkSpecialImage_Gpu : public SkSpecialImage_Base {
379 public:
SkSpecialImage_Gpu(GrRecordingContext * context,const SkIRect & subset,uint32_t uniqueID,GrSurfaceProxyView view,GrColorType ct,SkAlphaType at,sk_sp<SkColorSpace> colorSpace,const SkSurfaceProps * props)380     SkSpecialImage_Gpu(GrRecordingContext* context, const SkIRect& subset,
381                        uint32_t uniqueID, GrSurfaceProxyView view, GrColorType ct,
382                        SkAlphaType at, sk_sp<SkColorSpace> colorSpace, const SkSurfaceProps* props)
383         : INHERITED(subset, uniqueID, props)
384         , fContext(context)
385         , fView(std::move(view))
386         , fColorType(ct)
387         , fAlphaType(at)
388         , fColorSpace(std::move(colorSpace))
389         , fAddedRasterVersionToCache(false) {
390     }
391 
~SkSpecialImage_Gpu()392     ~SkSpecialImage_Gpu() override {
393         if (fAddedRasterVersionToCache.load()) {
394             SkNotifyBitmapGenIDIsStale(this->uniqueID());
395         }
396     }
397 
alphaType() const398     SkAlphaType alphaType() const override { return fAlphaType; }
399 
colorType() const400     SkColorType colorType() const override { return GrColorTypeToSkColorType(fColorType); }
401 
getSize() const402     size_t getSize() const override {
403         return fView.proxy()->gpuMemorySize(*fContext->priv().caps());
404     }
405 
onDraw(SkCanvas * canvas,SkScalar x,SkScalar y,const SkPaint * paint) const406     void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
407         SkRect dst = SkRect::MakeXYWH(x, y,
408                                       this->subset().width(), this->subset().height());
409 
410         // TODO: In this instance we know we're going to draw a sub-portion of the backing
411         // texture into the canvas so it is okay to wrap it in an SkImage. This poses
412         // some problems for full deferral however in that when the deferred SkImage_Gpu
413         // instantiates itself it is going to have to either be okay with having a larger
414         // than expected backing texture (unlikely) or the 'fit' of the SurfaceProxy needs
415         // to be tightened (if it is deferred).
416         sk_sp<SkImage> img =
417                 sk_sp<SkImage>(new SkImage_Gpu(sk_ref_sp(canvas->getGrContext()), this->uniqueID(),
418                                                fView, this->colorType(), fAlphaType, fColorSpace));
419 
420         canvas->drawImageRect(img, this->subset(),
421                               dst, paint, SkCanvas::kStrict_SrcRectConstraint);
422     }
423 
onGetContext() const424     GrRecordingContext* onGetContext() const override { return fContext; }
425 
onView(GrRecordingContext * context) const426     GrSurfaceProxyView onView(GrRecordingContext* context) const override { return fView; }
427 
onGetROPixels(SkBitmap * dst) const428     bool onGetROPixels(SkBitmap* dst) const override {
429         const auto desc = SkBitmapCacheDesc::Make(this->uniqueID(), this->subset());
430         if (SkBitmapCache::Find(desc, dst)) {
431             SkASSERT(dst->getGenerationID() == this->uniqueID());
432             SkASSERT(dst->isImmutable());
433             SkASSERT(dst->getPixels());
434             return true;
435         }
436 
437         SkPixmap pmap;
438         SkImageInfo info = SkImageInfo::MakeN32(this->width(), this->height(),
439                                                 this->alphaType(), fColorSpace);
440         auto rec = SkBitmapCache::Alloc(desc, info, &pmap);
441         if (!rec) {
442             return false;
443         }
444         auto sContext = GrSurfaceContext::Make(fContext, fView, fColorType, this->alphaType(),
445                                                fColorSpace);
446         if (!sContext) {
447             return false;
448         }
449 
450         if (!sContext->readPixels(info, pmap.writable_addr(), pmap.rowBytes(),
451                                   {this->subset().left(), this->subset().top()})) {
452             return false;
453         }
454 
455         SkBitmapCache::Add(std::move(rec), dst);
456         fAddedRasterVersionToCache.store(true);
457         return true;
458     }
459 
onGetColorSpace() const460     SkColorSpace* onGetColorSpace() const override {
461         return fColorSpace.get();
462     }
463 
onMakeSurface(SkColorType colorType,const SkColorSpace * colorSpace,const SkISize & size,SkAlphaType at,const SkSurfaceProps * props) const464     sk_sp<SkSpecialSurface> onMakeSurface(SkColorType colorType, const SkColorSpace* colorSpace,
465                                           const SkISize& size, SkAlphaType at,
466                                           const SkSurfaceProps* props) const override {
467         if (!fContext) {
468             return nullptr;
469         }
470 
471         return SkSpecialSurface::MakeRenderTarget(fContext, size.width(), size.height(),
472                                                   SkColorTypeToGrColorType(colorType),
473                                                   sk_ref_sp(colorSpace), props);
474     }
475 
onMakeSubset(const SkIRect & subset) const476     sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
477         return SkSpecialImage::MakeDeferredFromGpu(fContext,
478                                                    subset,
479                                                    this->uniqueID(),
480                                                    fView,
481                                                    fColorType,
482                                                    fColorSpace,
483                                                    &this->props(),
484                                                    fAlphaType);
485     }
486 
487     // TODO: move all the logic here into the subset-flavor GrSurfaceProxy::copy?
onAsImage(const SkIRect * subset) const488     sk_sp<SkImage> onAsImage(const SkIRect* subset) const override {
489         GrSurfaceProxy* proxy = fView.proxy();
490         if (subset) {
491             if (proxy->isFunctionallyExact() && *subset == SkIRect::MakeSize(proxy->dimensions())) {
492                 proxy->priv().exactify(false);
493                 // The existing GrTexture is already tight so reuse it in the SkImage
494                 return wrap_proxy_in_image(fContext, fView, this->colorType(), fAlphaType,
495                                            fColorSpace);
496             }
497 
498             GrSurfaceProxyView subsetView =
499                     GrSurfaceProxy::Copy(fContext, proxy, fView.origin(), fColorType,
500                                          GrMipMapped::kNo, *subset, SkBackingFit::kExact,
501                                          SkBudgeted::kYes);
502             if (!subsetView.proxy()) {
503                 return nullptr;
504             }
505             SkASSERT(subsetView.asTextureProxy());
506             SkASSERT(subsetView.proxy()->priv().isExact());
507 
508             // MDB: this is acceptable (wrapping subsetProxy in an SkImage) bc Copy will
509             // return a kExact-backed proxy
510             return wrap_proxy_in_image(fContext, std::move(subsetView), this->colorType(),
511                                        fAlphaType, fColorSpace);
512         }
513 
514         proxy->priv().exactify(true);
515 
516         return wrap_proxy_in_image(fContext, fView, this->colorType(), fAlphaType, fColorSpace);
517     }
518 
onMakeTightSurface(SkColorType colorType,const SkColorSpace * colorSpace,const SkISize & size,SkAlphaType at) const519     sk_sp<SkSurface> onMakeTightSurface(SkColorType colorType, const SkColorSpace* colorSpace,
520                                         const SkISize& size, SkAlphaType at) const override {
521         // TODO (michaelludwig): Why does this ignore colorType but onMakeSurface doesn't ignore it?
522         //    Once makeTightSurface() goes away, should this type overriding behavior be moved into
523         //    onMakeSurface() or is this unnecessary?
524         colorType = colorSpace && colorSpace->gammaIsLinear()
525             ? kRGBA_F16_SkColorType : kRGBA_8888_SkColorType;
526         SkImageInfo info = SkImageInfo::Make(size, colorType, at, sk_ref_sp(colorSpace));
527         // CONTEXT TODO: remove this use of 'backdoor' to create an SkSurface
528         return SkSurface::MakeRenderTarget(fContext->priv().backdoor(), SkBudgeted::kYes, info);
529     }
530 
531 private:
532     GrRecordingContext*       fContext;
533     GrSurfaceProxyView        fView;
534     const GrColorType         fColorType;
535     const SkAlphaType         fAlphaType;
536     sk_sp<SkColorSpace>       fColorSpace;
537     mutable std::atomic<bool> fAddedRasterVersionToCache;
538 
539     typedef SkSpecialImage_Base INHERITED;
540 };
541 
MakeDeferredFromGpu(GrRecordingContext * context,const SkIRect & subset,uint32_t uniqueID,GrSurfaceProxyView view,GrColorType colorType,sk_sp<SkColorSpace> colorSpace,const SkSurfaceProps * props,SkAlphaType at)542 sk_sp<SkSpecialImage> SkSpecialImage::MakeDeferredFromGpu(GrRecordingContext* context,
543                                                           const SkIRect& subset,
544                                                           uint32_t uniqueID,
545                                                           GrSurfaceProxyView view,
546                                                           GrColorType colorType,
547                                                           sk_sp<SkColorSpace> colorSpace,
548                                                           const SkSurfaceProps* props,
549                                                           SkAlphaType at) {
550     if (!context || context->priv().abandoned() || !view.asTextureProxy()) {
551         return nullptr;
552     }
553     SkASSERT_RELEASE(rect_fits(subset, view.proxy()->width(), view.proxy()->height()));
554     return sk_make_sp<SkSpecialImage_Gpu>(context, subset, uniqueID, std::move(view), colorType,
555                                           at, std::move(colorSpace), props);
556 }
557 #endif
558