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