blob: 2567bf1804a58f811e53386402679a1d65e9396c [file] [log] [blame]
robertphillipsb6c65e92016-02-04 10:52:42 -08001/*
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 */
reedad7604b2016-07-20 16:13:32 -07007
robertphillips83c17fa2016-03-18 08:14:27 -07008#include "SkSpecialImage.h"
reedad7604b2016-07-20 16:13:32 -07009#include "SkBitmap.h"
10#include "SkImage.h"
robertphillips64612512016-04-08 12:10:42 -070011#include "SkBitmapCache.h"
robertphillipsb6c65e92016-02-04 10:52:42 -080012#include "SkCanvas.h"
bsalomon84a4e5a2016-02-29 11:41:52 -080013#include "SkImage_Base.h"
robertphillipsb6c65e92016-02-04 10:52:42 -080014#include "SkSpecialSurface.h"
brianosman898235c2016-04-06 07:38:23 -070015#include "SkSurfacePriv.h"
reedad7604b2016-07-20 16:13:32 -070016#include "SkPixelRef.h"
17
18#if SK_SUPPORT_GPU
19#include "GrContext.h"
20#include "GrTexture.h"
Brian Salomon514baff2016-11-17 15:17:07 -050021#include "GrSamplerParams.h"
Robert Phillips8bc06d02016-11-01 17:28:40 -040022#include "GrTextureProxy.h"
reedad7604b2016-07-20 16:13:32 -070023#include "SkGr.h"
reedad7604b2016-07-20 16:13:32 -070024#include "SkGrPriv.h"
25#endif
robertphillipsb6c65e92016-02-04 10:52:42 -080026
reeda2217ef2016-07-20 06:04:34 -070027// Currently the raster imagefilters can only handle certain imageinfos. Call this to know if
28// a given info is supported.
29static bool valid_for_imagefilters(const SkImageInfo& info) {
30 // no support for other swizzles/depths yet
31 return info.colorType() == kN32_SkColorType;
32}
33
robertphillipsb6c65e92016-02-04 10:52:42 -080034///////////////////////////////////////////////////////////////////////////////
35class SkSpecialImage_Base : public SkSpecialImage {
36public:
robertphillips3e302272016-04-20 11:48:36 -070037 SkSpecialImage_Base(const SkIRect& subset, uint32_t uniqueID, const SkSurfaceProps* props)
38 : INHERITED(subset, uniqueID, props) {
robertphillips3b087f42016-02-18 08:48:03 -080039 }
robertphillips3e302272016-04-20 11:48:36 -070040 ~SkSpecialImage_Base() override { }
robertphillipsb6c65e92016-02-04 10:52:42 -080041
robertphillipse8c34972016-02-16 12:09:36 -080042 virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) const = 0;
robertphillipsb6c65e92016-02-04 10:52:42 -080043
robertphillips64612512016-04-08 12:10:42 -070044 virtual bool onGetROPixels(SkBitmap*) const = 0;
robertphillipsb6c65e92016-02-04 10:52:42 -080045
Robert Phillips8bc06d02016-11-01 17:28:40 -040046 virtual GrContext* onGetContext() const { return nullptr; }
robertphillipsb6c65e92016-02-04 10:52:42 -080047
brianosmanafbf71d2016-07-21 07:15:37 -070048 virtual SkColorSpace* onGetColorSpace() const = 0;
49
robertphillipsc91fd342016-04-25 12:32:54 -070050#if SK_SUPPORT_GPU
51 virtual sk_sp<GrTexture> onAsTextureRef(GrContext* context) const = 0;
Robert Phillips8bc06d02016-11-01 17:28:40 -040052 virtual sk_sp<GrTextureProxy> onAsTextureProxy(GrContext* context) const = 0;
robertphillipsc91fd342016-04-25 12:32:54 -070053#endif
robertphillips4418dba2016-03-07 12:45:14 -080054
robertphillipsb4bd11e2016-03-21 13:44:18 -070055 virtual sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const = 0;
56
brianosmaneed6b0e2016-09-23 13:04:05 -070057 virtual sk_sp<SkSpecialSurface> onMakeSurface(const SkImageFilter::OutputProperties& outProps,
58 const SkISize& size, SkAlphaType at) const = 0;
robertphillipsc5035e72016-03-17 06:58:39 -070059
robertphillipsb4bd11e2016-03-21 13:44:18 -070060 virtual sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const = 0;
61
brianosmaneed6b0e2016-09-23 13:04:05 -070062 virtual sk_sp<SkSurface> onMakeTightSurface(const SkImageFilter::OutputProperties& outProps,
63 const SkISize& size, SkAlphaType at) const = 0;
robertphillipsb6c65e92016-02-04 10:52:42 -080064
65private:
66 typedef SkSpecialImage INHERITED;
67};
68
69///////////////////////////////////////////////////////////////////////////////
bsalomon84a4e5a2016-02-29 11:41:52 -080070static inline const SkSpecialImage_Base* as_SIB(const SkSpecialImage* image) {
robertphillipsb6c65e92016-02-04 10:52:42 -080071 return static_cast<const SkSpecialImage_Base*>(image);
72}
73
robertphillips3e302272016-04-20 11:48:36 -070074SkSpecialImage::SkSpecialImage(const SkIRect& subset,
brianosman898235c2016-04-06 07:38:23 -070075 uint32_t uniqueID,
76 const SkSurfaceProps* props)
77 : fProps(SkSurfacePropsCopyOrDefault(props))
78 , fSubset(subset)
robertphillips3e302272016-04-20 11:48:36 -070079 , fUniqueID(kNeedNewImageUniqueID_SpecialImage == uniqueID ? SkNextID::ImageID() : uniqueID) {
brianosman898235c2016-04-06 07:38:23 -070080}
81
robertphillips3e302272016-04-20 11:48:36 -070082sk_sp<SkSpecialImage> SkSpecialImage::makeTextureImage(GrContext* context) {
robertphillips83c17fa2016-03-18 08:14:27 -070083#if SK_SUPPORT_GPU
84 if (!context) {
85 return nullptr;
86 }
Robert Phillips8bc06d02016-11-01 17:28:40 -040087 if (GrContext* curContext = as_SIB(this)->onGetContext()) {
88 return curContext == context ? sk_sp<SkSpecialImage>(SkRef(this)) : nullptr;
robertphillips83c17fa2016-03-18 08:14:27 -070089 }
90
91 SkBitmap bmp;
reedcf5c8462016-07-20 12:28:40 -070092 // At this point, we are definitely not texture-backed, so we must be raster or generator
93 // backed. If we remove the special-wrapping-an-image subclass, we may be able to assert that
94 // we are strictly raster-backed (i.e. generator images become raster when they are specialized)
95 // in which case getROPixels could turn into peekPixels...
96 if (!this->getROPixels(&bmp)) {
robertphillips83c17fa2016-03-18 08:14:27 -070097 return nullptr;
98 }
99
robertphillips83f2e5a2016-03-24 06:31:25 -0700100 if (bmp.empty()) {
robertphillips3e302272016-04-20 11:48:36 -0700101 return SkSpecialImage::MakeFromRaster(SkIRect::MakeEmpty(), bmp, &this->props());
robertphillips83f2e5a2016-03-24 06:31:25 -0700102 }
103
Brian Osman7b8400d2016-11-08 17:08:54 -0500104 sk_sp<GrTexture> resultTex(
Brian Osman61624f02016-12-09 14:51:59 -0500105 GrRefCachedBitmapTexture(context, bmp, GrSamplerParams::ClampNoFilter()));
robertphillips83c17fa2016-03-18 08:14:27 -0700106 if (!resultTex) {
107 return nullptr;
108 }
109
robertphillips3e302272016-04-20 11:48:36 -0700110 return SkSpecialImage::MakeFromGpu(SkIRect::MakeWH(resultTex->width(), resultTex->height()),
robertphillips83c17fa2016-03-18 08:14:27 -0700111 this->uniqueID(),
brianosmanafbf71d2016-07-21 07:15:37 -0700112 resultTex, sk_ref_sp(this->getColorSpace()), &this->props(),
brianosman80e96082016-08-16 07:09:47 -0700113 this->alphaType());
robertphillips83c17fa2016-03-18 08:14:27 -0700114#else
115 return nullptr;
116#endif
117}
118
robertphillipse8c34972016-02-16 12:09:36 -0800119void SkSpecialImage::draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const {
bsalomon84a4e5a2016-02-29 11:41:52 -0800120 return as_SIB(this)->onDraw(canvas, x, y, paint);
robertphillipsb6c65e92016-02-04 10:52:42 -0800121}
122
robertphillips64612512016-04-08 12:10:42 -0700123bool SkSpecialImage::getROPixels(SkBitmap* bm) const {
124 return as_SIB(this)->onGetROPixels(bm);
robertphillipsb6c65e92016-02-04 10:52:42 -0800125}
126
robertphillips64612512016-04-08 12:10:42 -0700127bool SkSpecialImage::isTextureBacked() const {
Robert Phillips8bc06d02016-11-01 17:28:40 -0400128 return SkToBool(as_SIB(this)->onGetContext());
robertphillipsb6c65e92016-02-04 10:52:42 -0800129}
130
robertphillips64612512016-04-08 12:10:42 -0700131GrContext* SkSpecialImage::getContext() const {
Robert Phillips8bc06d02016-11-01 17:28:40 -0400132 return as_SIB(this)->onGetContext();
robertphillips64612512016-04-08 12:10:42 -0700133}
134
brianosmanafbf71d2016-07-21 07:15:37 -0700135SkColorSpace* SkSpecialImage::getColorSpace() const {
136 return as_SIB(this)->onGetColorSpace();
137}
138
robertphillipsc91fd342016-04-25 12:32:54 -0700139#if SK_SUPPORT_GPU
140sk_sp<GrTexture> SkSpecialImage::asTextureRef(GrContext* context) const {
robertphillips64612512016-04-08 12:10:42 -0700141 return as_SIB(this)->onAsTextureRef(context);
robertphillips4418dba2016-03-07 12:45:14 -0800142}
Robert Phillips8bc06d02016-11-01 17:28:40 -0400143
144sk_sp<GrTextureProxy> SkSpecialImage::asTextureProxy(GrContext* context) const {
145 return as_SIB(this)->onAsTextureProxy(context);
146}
robertphillipsc91fd342016-04-25 12:32:54 -0700147#endif
robertphillips4418dba2016-03-07 12:45:14 -0800148
brianosmaneed6b0e2016-09-23 13:04:05 -0700149sk_sp<SkSpecialSurface> SkSpecialImage::makeSurface(const SkImageFilter::OutputProperties& outProps,
150 const SkISize& size, SkAlphaType at) const {
151 return as_SIB(this)->onMakeSurface(outProps, size, at);
robertphillipsb6c65e92016-02-04 10:52:42 -0800152}
153
brianosmaneed6b0e2016-09-23 13:04:05 -0700154sk_sp<SkSurface> SkSpecialImage::makeTightSurface(const SkImageFilter::OutputProperties& outProps,
155 const SkISize& size, SkAlphaType at) const {
156 return as_SIB(this)->onMakeTightSurface(outProps, size, at);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700157}
158
robertphillips37bd7c32016-03-17 14:31:39 -0700159sk_sp<SkSpecialImage> SkSpecialImage::makeSubset(const SkIRect& subset) const {
160 return as_SIB(this)->onMakeSubset(subset);
robertphillipsc5035e72016-03-17 06:58:39 -0700161}
162
robertphillipsb4bd11e2016-03-21 13:44:18 -0700163sk_sp<SkImage> SkSpecialImage::makeTightSubset(const SkIRect& subset) const {
164 return as_SIB(this)->onMakeTightSubset(subset);
165}
166
robertphillipsb6c65e92016-02-04 10:52:42 -0800167#ifdef SK_DEBUG
168static bool rect_fits(const SkIRect& rect, int width, int height) {
robertphillips4418dba2016-03-07 12:45:14 -0800169 if (0 == width && 0 == height) {
170 SkASSERT(0 == rect.fLeft && 0 == rect.fRight && 0 == rect.fTop && 0 == rect.fBottom);
171 return true;
172 }
173
robertphillipsb6c65e92016-02-04 10:52:42 -0800174 return rect.fLeft >= 0 && rect.fLeft < width && rect.fLeft < rect.fRight &&
175 rect.fRight >= 0 && rect.fRight <= width &&
176 rect.fTop >= 0 && rect.fTop < height && rect.fTop < rect.fBottom &&
177 rect.fBottom >= 0 && rect.fBottom <= height;
178}
179#endif
180
robertphillips3e302272016-04-20 11:48:36 -0700181sk_sp<SkSpecialImage> SkSpecialImage::MakeFromImage(const SkIRect& subset,
brianosman898235c2016-04-06 07:38:23 -0700182 sk_sp<SkImage> image,
Brian Osman61624f02016-12-09 14:51:59 -0500183 SkColorSpace* dstColorSpace,
brianosman898235c2016-04-06 07:38:23 -0700184 const SkSurfaceProps* props) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800185 SkASSERT(rect_fits(subset, image->width(), image->height()));
robertphillips37bd7c32016-03-17 14:31:39 -0700186
reedad7604b2016-07-20 16:13:32 -0700187#if SK_SUPPORT_GPU
188 if (GrTexture* texture = as_IB(image)->peekTexture()) {
brianosmanafbf71d2016-07-21 07:15:37 -0700189 return MakeFromGpu(subset, image->uniqueID(), sk_ref_sp(texture),
190 sk_ref_sp(as_IB(image)->onImageInfo().colorSpace()), props);
reedad7604b2016-07-20 16:13:32 -0700191 } else
192#endif
193 {
194 SkBitmap bm;
Brian Osman61624f02016-12-09 14:51:59 -0500195 if (as_IB(image)->getROPixels(&bm, dstColorSpace)) {
reedad7604b2016-07-20 16:13:32 -0700196 return MakeFromRaster(subset, bm, props);
197 }
reeda2217ef2016-07-20 06:04:34 -0700198 }
reedad7604b2016-07-20 16:13:32 -0700199 return nullptr;
robertphillipsb6c65e92016-02-04 10:52:42 -0800200}
201
202///////////////////////////////////////////////////////////////////////////////
robertphillipsb6c65e92016-02-04 10:52:42 -0800203
204class SkSpecialImage_Raster : public SkSpecialImage_Base {
205public:
robertphillips3e302272016-04-20 11:48:36 -0700206 SkSpecialImage_Raster(const SkIRect& subset, const SkBitmap& bm, const SkSurfaceProps* props)
207 : INHERITED(subset, bm.getGenerationID(), props)
reedbd2bd5c2016-07-25 14:26:02 -0700208 , fBitmap(bm)
209 {
210 SkASSERT(bm.pixelRef());
211
212 // We have to lock now, while bm is still in scope, since it may have come from our
213 // cache, which means we need to keep it locked until we (the special) are done, since
214 // we cannot re-generate the cache entry (if bm came from a generator).
215 fBitmap.lockPixels();
216 SkASSERT(fBitmap.getPixels());
robertphillipsb6c65e92016-02-04 10:52:42 -0800217 }
218
brianosman80e96082016-08-16 07:09:47 -0700219 SkAlphaType alphaType() const override { return fBitmap.alphaType(); }
robertphillips3b087f42016-02-18 08:48:03 -0800220
221 size_t getSize() const override { return fBitmap.getSize(); }
222
robertphillipse8c34972016-02-16 12:09:36 -0800223 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800224 SkRect dst = SkRect::MakeXYWH(x, y,
225 this->subset().width(), this->subset().height());
226
227 canvas->drawBitmapRect(fBitmap, this->subset(),
228 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
229 }
230
robertphillips64612512016-04-08 12:10:42 -0700231 bool onGetROPixels(SkBitmap* bm) const override {
232 *bm = fBitmap;
robertphillips3b087f42016-02-18 08:48:03 -0800233 return true;
234 }
235
brianosmanafbf71d2016-07-21 07:15:37 -0700236 SkColorSpace* onGetColorSpace() const override {
237 return fBitmap.colorSpace();
238 }
239
robertphillips64612512016-04-08 12:10:42 -0700240#if SK_SUPPORT_GPU
robertphillipsc91fd342016-04-25 12:32:54 -0700241 sk_sp<GrTexture> onAsTextureRef(GrContext* context) const override {
robertphillips64612512016-04-08 12:10:42 -0700242 if (context) {
Brian Osman7b8400d2016-11-08 17:08:54 -0500243 return sk_ref_sp(
Brian Osman61624f02016-12-09 14:51:59 -0500244 GrRefCachedBitmapTexture(context, fBitmap, GrSamplerParams::ClampNoFilter()));
robertphillips64612512016-04-08 12:10:42 -0700245 }
robertphillips64612512016-04-08 12:10:42 -0700246
247 return nullptr;
248 }
Robert Phillips8bc06d02016-11-01 17:28:40 -0400249
250 sk_sp<GrTextureProxy> onAsTextureProxy(GrContext* context) const override {
251 if (context) {
Robert Phillips37430132016-11-09 06:50:43 -0500252 sk_sp<GrTexture> tex(sk_ref_sp(GrRefCachedBitmapTexture(
Brian Osman61624f02016-12-09 14:51:59 -0500253 context, fBitmap, GrSamplerParams::ClampNoFilter())));
Robert Phillips37430132016-11-09 06:50:43 -0500254 sk_sp<GrSurfaceProxy> sProxy = GrSurfaceProxy::MakeWrapped(std::move(tex));
255 return sk_ref_sp(sProxy->asTextureProxy());
Robert Phillips8bc06d02016-11-01 17:28:40 -0400256 }
257
258 return nullptr;
259 }
robertphillipsc91fd342016-04-25 12:32:54 -0700260#endif
robertphillips64612512016-04-08 12:10:42 -0700261
brianosmaneed6b0e2016-09-23 13:04:05 -0700262// TODO: The raster implementations of image filters all currently assume that the pixels are
263// legacy N32. Until they actually check the format and operate on sRGB or F16 data appropriately,
264// we can't enable this. (They will continue to produce incorrect results, but less-so).
265#define RASTER_IMAGE_FILTERS_SUPPORT_SRGB_AND_F16 0
266
267 sk_sp<SkSpecialSurface> onMakeSurface(const SkImageFilter::OutputProperties& outProps,
268 const SkISize& size, SkAlphaType at) const override {
269#if RASTER_IMAGE_FILTERS_SUPPORT_SRGB_AND_F16
270 SkColorSpace* colorSpace = outProps.colorSpace();
271#else
272 SkColorSpace* colorSpace = nullptr;
273#endif
274 SkColorType colorType = colorSpace && colorSpace->gammaIsLinear()
275 ? kRGBA_F16_SkColorType : kN32_SkColorType;
276 SkImageInfo info = SkImageInfo::Make(size.width(), size.height(), colorType, at,
277 sk_ref_sp(colorSpace));
robertphillips3e302272016-04-20 11:48:36 -0700278 return SkSpecialSurface::MakeRaster(info, nullptr);
robertphillipsb6c65e92016-02-04 10:52:42 -0800279 }
280
robertphillips37bd7c32016-03-17 14:31:39 -0700281 sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
robertphillipsc5035e72016-03-17 06:58:39 -0700282 SkBitmap subsetBM;
halcanary9d524f22016-03-29 09:03:52 -0700283
robertphillipsc5035e72016-03-17 06:58:39 -0700284 if (!fBitmap.extractSubset(&subsetBM, subset)) {
285 return nullptr;
286 }
287
robertphillips3e302272016-04-20 11:48:36 -0700288 return SkSpecialImage::MakeFromRaster(SkIRect::MakeWH(subset.width(), subset.height()),
brianosman898235c2016-04-06 07:38:23 -0700289 subsetBM,
290 &this->props());
robertphillipsc5035e72016-03-17 06:58:39 -0700291 }
292
robertphillipsb4bd11e2016-03-21 13:44:18 -0700293 sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const override {
294 SkBitmap subsetBM;
295
296 if (!fBitmap.extractSubset(&subsetBM, subset)) {
297 return nullptr;
298 }
299
300 return SkImage::MakeFromBitmap(subsetBM);
301 }
302
brianosmaneed6b0e2016-09-23 13:04:05 -0700303 sk_sp<SkSurface> onMakeTightSurface(const SkImageFilter::OutputProperties& outProps,
304 const SkISize& size, SkAlphaType at) const override {
305#if RASTER_IMAGE_FILTERS_SUPPORT_SRGB_AND_F16
306 SkColorSpace* colorSpace = outProps.colorSpace();
307#else
308 SkColorSpace* colorSpace = nullptr;
309#endif
310 SkColorType colorType = colorSpace && colorSpace->gammaIsLinear()
311 ? kRGBA_F16_SkColorType : kN32_SkColorType;
312 SkImageInfo info = SkImageInfo::Make(size.width(), size.height(), colorType, at,
313 sk_ref_sp(colorSpace));
reede8f30622016-03-23 18:59:25 -0700314 return SkSurface::MakeRaster(info);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700315 }
316
robertphillipsb6c65e92016-02-04 10:52:42 -0800317private:
318 SkBitmap fBitmap;
319
320 typedef SkSpecialImage_Base INHERITED;
321};
322
robertphillips3e302272016-04-20 11:48:36 -0700323sk_sp<SkSpecialImage> SkSpecialImage::MakeFromRaster(const SkIRect& subset,
brianosman898235c2016-04-06 07:38:23 -0700324 const SkBitmap& bm,
325 const SkSurfaceProps* props) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800326 SkASSERT(rect_fits(subset, bm.width(), bm.height()));
robertphillips37bd7c32016-03-17 14:31:39 -0700327
reedbd2bd5c2016-07-25 14:26:02 -0700328 if (!bm.pixelRef()) {
329 return nullptr;
330 }
331
reeda2217ef2016-07-20 06:04:34 -0700332 const SkBitmap* srcBM = &bm;
333 SkBitmap tmpStorage;
334 // ImageFilters only handle N32 at the moment, so force our src to be that
335 if (!valid_for_imagefilters(bm.info())) {
336 if (!bm.copyTo(&tmpStorage, kN32_SkColorType)) {
337 return nullptr;
338 }
339 srcBM = &tmpStorage;
340 }
341 return sk_make_sp<SkSpecialImage_Raster>(subset, *srcBM, props);
robertphillipsb6c65e92016-02-04 10:52:42 -0800342}
343
344#if SK_SUPPORT_GPU
345///////////////////////////////////////////////////////////////////////////////
robertphillipsed086ca2016-04-26 15:02:25 -0700346#include "GrTexture.h"
robertphillipsb4bd11e2016-03-21 13:44:18 -0700347#include "SkImage_Gpu.h"
robertphillipsb6c65e92016-02-04 10:52:42 -0800348
robertphillipsed086ca2016-04-26 15:02:25 -0700349class SkSpecialImage_Gpu : public SkSpecialImage_Base {
350public:
351 SkSpecialImage_Gpu(const SkIRect& subset,
352 uint32_t uniqueID, sk_sp<GrTexture> tex, SkAlphaType at,
brianosmanafbf71d2016-07-21 07:15:37 -0700353 sk_sp<SkColorSpace> colorSpace, const SkSurfaceProps* props)
robertphillipsed086ca2016-04-26 15:02:25 -0700354 : INHERITED(subset, uniqueID, props)
Robert Phillips8bc06d02016-11-01 17:28:40 -0400355 , fContext(tex->getContext())
356 , fAlphaType(at)
357 , fColorSpace(std::move(colorSpace))
358 , fAddedRasterVersionToCache(false) {
Robert Phillips37430132016-11-09 06:50:43 -0500359 fSurfaceProxy = GrSurfaceProxy::MakeWrapped(std::move(tex));
Robert Phillips8bc06d02016-11-01 17:28:40 -0400360 }
361
362 SkSpecialImage_Gpu(GrContext* context, const SkIRect& subset,
Robert Phillips37430132016-11-09 06:50:43 -0500363 uint32_t uniqueID, sk_sp<GrSurfaceProxy> proxy, SkAlphaType at,
Robert Phillips8bc06d02016-11-01 17:28:40 -0400364 sk_sp<SkColorSpace> colorSpace, const SkSurfaceProps* props)
365 : INHERITED(subset, uniqueID, props)
366 , fContext(context)
Robert Phillips37430132016-11-09 06:50:43 -0500367 , fSurfaceProxy(std::move(proxy))
robertphillipsed086ca2016-04-26 15:02:25 -0700368 , fAlphaType(at)
brianosmanafbf71d2016-07-21 07:15:37 -0700369 , fColorSpace(std::move(colorSpace))
robertphillipsed086ca2016-04-26 15:02:25 -0700370 , fAddedRasterVersionToCache(false) {
371 }
372
373 ~SkSpecialImage_Gpu() override {
374 if (fAddedRasterVersionToCache.load()) {
375 SkNotifyBitmapGenIDIsStale(this->uniqueID());
376 }
377 }
378
brianosman80e96082016-08-16 07:09:47 -0700379 SkAlphaType alphaType() const override { return fAlphaType; }
robertphillipsed086ca2016-04-26 15:02:25 -0700380
Robert Phillips37430132016-11-09 06:50:43 -0500381 size_t getSize() const override { return fSurfaceProxy->gpuMemorySize(); }
robertphillipsed086ca2016-04-26 15:02:25 -0700382
383 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
384 SkRect dst = SkRect::MakeXYWH(x, y,
385 this->subset().width(), this->subset().height());
386
Robert Phillips8bc06d02016-11-01 17:28:40 -0400387 // TODO: add GrTextureProxy-backed SkImage_Gpus
Robert Phillips37430132016-11-09 06:50:43 -0500388 GrSurface* surf = fSurfaceProxy->instantiate(fContext->textureProvider());
Robert Phillipse60ad622016-11-17 10:22:48 -0500389 if (!surf) {
390 return;
391 }
Robert Phillips8bc06d02016-11-01 17:28:40 -0400392
Robert Phillips7f6cd902016-11-10 17:03:43 -0500393 // TODO: In this instance we know we're going to draw a sub-portion of the backing
394 // texture into the canvas so it is okay to wrap it in an SkImage. This poses
395 // some problems for full deferral however in that when the deferred SkImage_Gpu
396 // instantiates itself it is going to have to either be okay with having a larger
397 // than expected backing texture (unlikely) or the 'fit' of the SurfaceProxy needs
398 // to be tightened (if it is deferred).
399 auto img = sk_sp<SkImage>(new SkImage_Gpu(surf->width(), surf->height(),
Robert Phillips37430132016-11-09 06:50:43 -0500400 this->uniqueID(), fAlphaType,
401 sk_ref_sp(surf->asTexture()),
brianosmanafbf71d2016-07-21 07:15:37 -0700402 fColorSpace, SkBudgeted::kNo));
robertphillipsed086ca2016-04-26 15:02:25 -0700403
reed77d6f7d2016-07-13 12:24:48 -0700404 canvas->drawImageRect(img, this->subset(),
Robert Phillips7f6cd902016-11-10 17:03:43 -0500405 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
robertphillipsed086ca2016-04-26 15:02:25 -0700406 }
407
Robert Phillips8bc06d02016-11-01 17:28:40 -0400408 GrContext* onGetContext() const override { return fContext; }
robertphillipsed086ca2016-04-26 15:02:25 -0700409
Robert Phillips8bc06d02016-11-01 17:28:40 -0400410 // This entry point should go away in favor of asTextureProxy
411 sk_sp<GrTexture> onAsTextureRef(GrContext* context) const override {
Robert Phillips37430132016-11-09 06:50:43 -0500412 GrSurface* surf = fSurfaceProxy->instantiate(context->textureProvider());
Robert Phillipse60ad622016-11-17 10:22:48 -0500413 if (!surf) {
414 return nullptr;
415 }
Robert Phillips37430132016-11-09 06:50:43 -0500416 return sk_ref_sp(surf->asTexture());
Robert Phillips8bc06d02016-11-01 17:28:40 -0400417 }
418
419 sk_sp<GrTextureProxy> onAsTextureProxy(GrContext*) const override {
Robert Phillips37430132016-11-09 06:50:43 -0500420 return sk_ref_sp(fSurfaceProxy->asTextureProxy());
Robert Phillips8bc06d02016-11-01 17:28:40 -0400421 }
robertphillipsed086ca2016-04-26 15:02:25 -0700422
423 bool onGetROPixels(SkBitmap* dst) const override {
424 if (SkBitmapCache::Find(this->uniqueID(), dst)) {
425 SkASSERT(dst->getGenerationID() == this->uniqueID());
426 SkASSERT(dst->isImmutable());
427 SkASSERT(dst->getPixels());
428 return true;
429 }
430
431 SkImageInfo info = SkImageInfo::MakeN32(this->width(), this->height(),
brianosman80e96082016-08-16 07:09:47 -0700432 this->alphaType(), fColorSpace);
robertphillipsed086ca2016-04-26 15:02:25 -0700433
434 if (!dst->tryAllocPixels(info)) {
435 return false;
436 }
437
Robert Phillips8bc06d02016-11-01 17:28:40 -0400438 // Reading back to an SkBitmap ends deferral
Robert Phillips37430132016-11-09 06:50:43 -0500439 GrSurface* surface = fSurfaceProxy->instantiate(fContext->textureProvider());
Robert Phillipse60ad622016-11-17 10:22:48 -0500440 if (!surface) {
441 return false;
442 }
Robert Phillips8bc06d02016-11-01 17:28:40 -0400443
Robert Phillips37430132016-11-09 06:50:43 -0500444 if (!surface->readPixels(0, 0, dst->width(), dst->height(), kSkia8888_GrPixelConfig,
Robert Phillips8bc06d02016-11-01 17:28:40 -0400445 dst->getPixels(), dst->rowBytes())) {
robertphillipsed086ca2016-04-26 15:02:25 -0700446 return false;
447 }
448
449 dst->pixelRef()->setImmutableWithID(this->uniqueID());
450 SkBitmapCache::Add(this->uniqueID(), *dst);
451 fAddedRasterVersionToCache.store(true);
452 return true;
453 }
454
brianosmanafbf71d2016-07-21 07:15:37 -0700455 SkColorSpace* onGetColorSpace() const override {
456 return fColorSpace.get();
457 }
458
brianosmaneed6b0e2016-09-23 13:04:05 -0700459 sk_sp<SkSpecialSurface> onMakeSurface(const SkImageFilter::OutputProperties& outProps,
460 const SkISize& size, SkAlphaType at) const override {
Robert Phillips8bc06d02016-11-01 17:28:40 -0400461 if (!fContext) {
robertphillipsed086ca2016-04-26 15:02:25 -0700462 return nullptr;
463 }
464
brianosmaneed6b0e2016-09-23 13:04:05 -0700465 SkColorSpace* colorSpace = outProps.colorSpace();
466 return SkSpecialSurface::MakeRenderTarget(
Robert Phillips8bc06d02016-11-01 17:28:40 -0400467 fContext, size.width(), size.height(),
brianosmaneed6b0e2016-09-23 13:04:05 -0700468 GrRenderableConfigForColorSpace(colorSpace), sk_ref_sp(colorSpace));
robertphillipsed086ca2016-04-26 15:02:25 -0700469 }
470
471 sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
Robert Phillips8bc06d02016-11-01 17:28:40 -0400472 return SkSpecialImage::MakeDeferredFromGpu(fContext,
473 subset,
474 this->uniqueID(),
Robert Phillips37430132016-11-09 06:50:43 -0500475 fSurfaceProxy,
Robert Phillips8bc06d02016-11-01 17:28:40 -0400476 fColorSpace,
477 &this->props(),
478 fAlphaType);
robertphillipsed086ca2016-04-26 15:02:25 -0700479 }
480
481 sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const override {
Robert Phillips8bc06d02016-11-01 17:28:40 -0400482 // TODO: add GrTextureProxy-backed SkImage_Gpus
Robert Phillips37430132016-11-09 06:50:43 -0500483 GrSurface* surf = fSurfaceProxy->instantiate(fContext->textureProvider());
Robert Phillipse60ad622016-11-17 10:22:48 -0500484 if (!surf) {
485 return nullptr;
486 }
Robert Phillips8bc06d02016-11-01 17:28:40 -0400487
robertphillipsed086ca2016-04-26 15:02:25 -0700488 if (0 == subset.fLeft && 0 == subset.fTop &&
Robert Phillips37430132016-11-09 06:50:43 -0500489 fSurfaceProxy->width() == subset.width() &&
490 fSurfaceProxy->height() == subset.height()) {
robertphillipsed086ca2016-04-26 15:02:25 -0700491 // The existing GrTexture is already tight so reuse it in the SkImage
Robert Phillips37430132016-11-09 06:50:43 -0500492 return sk_make_sp<SkImage_Gpu>(surf->width(), surf->height(),
493 kNeedNewImageUniqueID, fAlphaType,
494 sk_ref_sp(surf->asTexture()),
495 fColorSpace, SkBudgeted::kYes);
robertphillipsed086ca2016-04-26 15:02:25 -0700496 }
497
Robert Phillips37430132016-11-09 06:50:43 -0500498 GrSurfaceDesc desc = fSurfaceProxy->desc();
robertphillipsed086ca2016-04-26 15:02:25 -0700499 desc.fWidth = subset.width();
500 desc.fHeight = subset.height();
501
Robert Phillips8bc06d02016-11-01 17:28:40 -0400502 sk_sp<GrTexture> subTx(fContext->textureProvider()->createTexture(desc, SkBudgeted::kYes));
robertphillipsed086ca2016-04-26 15:02:25 -0700503 if (!subTx) {
504 return nullptr;
505 }
Robert Phillips37430132016-11-09 06:50:43 -0500506 fContext->copySurface(subTx.get(), surf, subset, SkIPoint::Make(0, 0));
robertphillipsed086ca2016-04-26 15:02:25 -0700507 return sk_make_sp<SkImage_Gpu>(desc.fWidth, desc.fHeight, kNeedNewImageUniqueID,
bungeman6bd52842016-10-27 09:30:08 -0700508 fAlphaType, std::move(subTx), fColorSpace, SkBudgeted::kYes);
robertphillipsed086ca2016-04-26 15:02:25 -0700509 }
510
brianosmaneed6b0e2016-09-23 13:04:05 -0700511 sk_sp<SkSurface> onMakeTightSurface(const SkImageFilter::OutputProperties& outProps,
512 const SkISize& size, SkAlphaType at) const override {
513 SkColorSpace* colorSpace = outProps.colorSpace();
514 SkColorType colorType = colorSpace && colorSpace->gammaIsLinear()
515 ? kRGBA_F16_SkColorType : kRGBA_8888_SkColorType;
516 SkImageInfo info = SkImageInfo::Make(size.width(), size.height(), colorType, at,
517 sk_ref_sp(colorSpace));
Robert Phillips8bc06d02016-11-01 17:28:40 -0400518 return SkSurface::MakeRenderTarget(fContext, SkBudgeted::kYes, info);
robertphillipsed086ca2016-04-26 15:02:25 -0700519 }
520
521private:
Robert Phillips8bc06d02016-11-01 17:28:40 -0400522 GrContext* fContext;
Robert Phillips37430132016-11-09 06:50:43 -0500523 sk_sp<GrSurfaceProxy> fSurfaceProxy;
robertphillipsed086ca2016-04-26 15:02:25 -0700524 const SkAlphaType fAlphaType;
brianosmanafbf71d2016-07-21 07:15:37 -0700525 sk_sp<SkColorSpace> fColorSpace;
robertphillipsed086ca2016-04-26 15:02:25 -0700526 mutable SkAtomic<bool> fAddedRasterVersionToCache;
527
528 typedef SkSpecialImage_Base INHERITED;
529};
530
robertphillips3e302272016-04-20 11:48:36 -0700531sk_sp<SkSpecialImage> SkSpecialImage::MakeFromGpu(const SkIRect& subset,
robertphillips37bd7c32016-03-17 14:31:39 -0700532 uint32_t uniqueID,
robertphillipsc91fd342016-04-25 12:32:54 -0700533 sk_sp<GrTexture> tex,
brianosmanafbf71d2016-07-21 07:15:37 -0700534 sk_sp<SkColorSpace> colorSpace,
brianosman898235c2016-04-06 07:38:23 -0700535 const SkSurfaceProps* props,
robertphillips37bd7c32016-03-17 14:31:39 -0700536 SkAlphaType at) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800537 SkASSERT(rect_fits(subset, tex->width(), tex->height()));
brianosmanafbf71d2016-07-21 07:15:37 -0700538 return sk_make_sp<SkSpecialImage_Gpu>(subset, uniqueID, std::move(tex), at,
539 std::move(colorSpace), props);
robertphillipsb6c65e92016-02-04 10:52:42 -0800540}
541
Robert Phillips8bc06d02016-11-01 17:28:40 -0400542sk_sp<SkSpecialImage> SkSpecialImage::MakeDeferredFromGpu(GrContext* context,
543 const SkIRect& subset,
544 uint32_t uniqueID,
Robert Phillips37430132016-11-09 06:50:43 -0500545 sk_sp<GrSurfaceProxy> proxy,
Robert Phillips8bc06d02016-11-01 17:28:40 -0400546 sk_sp<SkColorSpace> colorSpace,
547 const SkSurfaceProps* props,
548 SkAlphaType at) {
549 SkASSERT(rect_fits(subset, proxy->width(), proxy->height()));
550 return sk_make_sp<SkSpecialImage_Gpu>(context, subset, uniqueID, std::move(proxy), at,
551 std::move(colorSpace), props);
552}
robertphillipsb6c65e92016-02-04 10:52:42 -0800553#endif