blob: ecde3d97c8f309557f25b1801426a07ede236f89 [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"
21#include "GrTextureParams.h"
22#include "SkGr.h"
23#include "SkGrPixelRef.h"
24#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
46 virtual GrTexture* onPeekTexture() const { return nullptr; }
47
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;
52#endif
robertphillips4418dba2016-03-07 12:45:14 -080053
robertphillips3b087f42016-02-18 08:48:03 -080054 // Delete this entry point ASAP (see skbug.com/4965)
robertphillipsab01ccd2016-03-08 10:45:32 -080055 virtual bool getBitmapDeprecated(SkBitmap* result) const = 0;
robertphillips3b087f42016-02-18 08:48:03 -080056
robertphillipsb4bd11e2016-03-21 13:44:18 -070057 virtual sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const = 0;
58
robertphillips37bd7c32016-03-17 14:31:39 -070059 virtual sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const = 0;
robertphillipsc5035e72016-03-17 06:58:39 -070060
robertphillipsb4bd11e2016-03-21 13:44:18 -070061 virtual sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const = 0;
62
reede8f30622016-03-23 18:59:25 -070063 virtual sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) 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 }
robertphillips64612512016-04-08 12:10:42 -070087 if (GrTexture* peek = as_SIB(this)->onPeekTexture()) {
robertphillips83c17fa2016-03-18 08:14:27 -070088 return peek->getContext() == context ? sk_sp<SkSpecialImage>(SkRef(this)) : nullptr;
89 }
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
robertphillipsc91fd342016-04-25 12:32:54 -0700104 sk_sp<GrTexture> resultTex(GrRefCachedBitmapTexture(context,
105 bmp,
brianosman982eb7f2016-06-06 13:10:58 -0700106 GrTextureParams::ClampNoFilter(),
107 SkSourceGammaTreatment::kRespect));
robertphillips83c17fa2016-03-18 08:14:27 -0700108 if (!resultTex) {
109 return nullptr;
110 }
111
112 SkAlphaType at = this->isOpaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
113
robertphillips3e302272016-04-20 11:48:36 -0700114 return SkSpecialImage::MakeFromGpu(SkIRect::MakeWH(resultTex->width(), resultTex->height()),
robertphillips83c17fa2016-03-18 08:14:27 -0700115 this->uniqueID(),
brianosmanafbf71d2016-07-21 07:15:37 -0700116 resultTex, sk_ref_sp(this->getColorSpace()), &this->props(),
117 at);
robertphillips83c17fa2016-03-18 08:14:27 -0700118#else
119 return nullptr;
120#endif
121}
122
robertphillipse8c34972016-02-16 12:09:36 -0800123void SkSpecialImage::draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const {
bsalomon84a4e5a2016-02-29 11:41:52 -0800124 return as_SIB(this)->onDraw(canvas, x, y, paint);
robertphillipsb6c65e92016-02-04 10:52:42 -0800125}
126
robertphillips64612512016-04-08 12:10:42 -0700127bool SkSpecialImage::getROPixels(SkBitmap* bm) const {
128 return as_SIB(this)->onGetROPixels(bm);
robertphillipsb6c65e92016-02-04 10:52:42 -0800129}
130
robertphillips64612512016-04-08 12:10:42 -0700131bool SkSpecialImage::isTextureBacked() const {
132#if SK_SUPPORT_GPU
133 return as_SIB(this)->onPeekTexture() && as_SIB(this)->onPeekTexture()->getContext();
134#else
135 return false;
136#endif
robertphillipsb6c65e92016-02-04 10:52:42 -0800137}
138
robertphillips64612512016-04-08 12:10:42 -0700139GrContext* SkSpecialImage::getContext() const {
140#if SK_SUPPORT_GPU
141 GrTexture* texture = as_SIB(this)->onPeekTexture();
142
143 if (texture) {
144 return texture->getContext();
145 }
146#endif
147 return nullptr;
148}
149
brianosmanafbf71d2016-07-21 07:15:37 -0700150SkColorSpace* SkSpecialImage::getColorSpace() const {
151 return as_SIB(this)->onGetColorSpace();
152}
153
robertphillipsc91fd342016-04-25 12:32:54 -0700154#if SK_SUPPORT_GPU
155sk_sp<GrTexture> SkSpecialImage::asTextureRef(GrContext* context) const {
robertphillips64612512016-04-08 12:10:42 -0700156 return as_SIB(this)->onAsTextureRef(context);
robertphillips4418dba2016-03-07 12:45:14 -0800157}
robertphillipsc91fd342016-04-25 12:32:54 -0700158#endif
robertphillips4418dba2016-03-07 12:45:14 -0800159
robertphillips37bd7c32016-03-17 14:31:39 -0700160sk_sp<SkSpecialSurface> SkSpecialImage::makeSurface(const SkImageInfo& info) const {
161 return as_SIB(this)->onMakeSurface(info);
robertphillipsb6c65e92016-02-04 10:52:42 -0800162}
163
robertphillipsb4bd11e2016-03-21 13:44:18 -0700164sk_sp<SkSurface> SkSpecialImage::makeTightSurface(const SkImageInfo& info) const {
reede8f30622016-03-23 18:59:25 -0700165 return as_SIB(this)->onMakeTightSurface(info);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700166}
167
robertphillips37bd7c32016-03-17 14:31:39 -0700168sk_sp<SkSpecialImage> SkSpecialImage::makeSubset(const SkIRect& subset) const {
169 return as_SIB(this)->onMakeSubset(subset);
robertphillipsc5035e72016-03-17 06:58:39 -0700170}
171
robertphillipsb4bd11e2016-03-21 13:44:18 -0700172sk_sp<SkImage> SkSpecialImage::makeTightSubset(const SkIRect& subset) const {
173 return as_SIB(this)->onMakeTightSubset(subset);
174}
175
robertphillipsb6c65e92016-02-04 10:52:42 -0800176#ifdef SK_DEBUG
177static bool rect_fits(const SkIRect& rect, int width, int height) {
robertphillips4418dba2016-03-07 12:45:14 -0800178 if (0 == width && 0 == height) {
179 SkASSERT(0 == rect.fLeft && 0 == rect.fRight && 0 == rect.fTop && 0 == rect.fBottom);
180 return true;
181 }
182
robertphillipsb6c65e92016-02-04 10:52:42 -0800183 return rect.fLeft >= 0 && rect.fLeft < width && rect.fLeft < rect.fRight &&
184 rect.fRight >= 0 && rect.fRight <= width &&
185 rect.fTop >= 0 && rect.fTop < height && rect.fTop < rect.fBottom &&
186 rect.fBottom >= 0 && rect.fBottom <= height;
187}
188#endif
189
robertphillips3e302272016-04-20 11:48:36 -0700190sk_sp<SkSpecialImage> SkSpecialImage::MakeFromImage(const SkIRect& subset,
brianosman898235c2016-04-06 07:38:23 -0700191 sk_sp<SkImage> image,
192 const SkSurfaceProps* props) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800193 SkASSERT(rect_fits(subset, image->width(), image->height()));
robertphillips37bd7c32016-03-17 14:31:39 -0700194
reedad7604b2016-07-20 16:13:32 -0700195#if SK_SUPPORT_GPU
196 if (GrTexture* texture = as_IB(image)->peekTexture()) {
brianosmanafbf71d2016-07-21 07:15:37 -0700197 return MakeFromGpu(subset, image->uniqueID(), sk_ref_sp(texture),
198 sk_ref_sp(as_IB(image)->onImageInfo().colorSpace()), props);
reedad7604b2016-07-20 16:13:32 -0700199 } else
200#endif
201 {
202 SkBitmap bm;
203 if (as_IB(image)->getROPixels(&bm)) {
204 return MakeFromRaster(subset, bm, props);
205 }
reeda2217ef2016-07-20 06:04:34 -0700206 }
reedad7604b2016-07-20 16:13:32 -0700207 return nullptr;
robertphillipsb6c65e92016-02-04 10:52:42 -0800208}
209
210///////////////////////////////////////////////////////////////////////////////
robertphillipsb6c65e92016-02-04 10:52:42 -0800211
212class SkSpecialImage_Raster : public SkSpecialImage_Base {
213public:
robertphillips3e302272016-04-20 11:48:36 -0700214 SkSpecialImage_Raster(const SkIRect& subset, const SkBitmap& bm, const SkSurfaceProps* props)
215 : INHERITED(subset, bm.getGenerationID(), props)
robertphillipsb6c65e92016-02-04 10:52:42 -0800216 , fBitmap(bm) {
robertphillips4418dba2016-03-07 12:45:14 -0800217 if (bm.pixelRef() && bm.pixelRef()->isPreLocked()) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800218 // we only preemptively lock if there is no chance of triggering something expensive
219 // like a lazy decode or imagegenerator. PreLocked means it is flat pixels already.
220 fBitmap.lockPixels();
221 }
222 }
223
robertphillips3b087f42016-02-18 08:48:03 -0800224 bool isOpaque() const override { return fBitmap.isOpaque(); }
225
226 size_t getSize() const override { return fBitmap.getSize(); }
227
robertphillipse8c34972016-02-16 12:09:36 -0800228 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800229 SkRect dst = SkRect::MakeXYWH(x, y,
230 this->subset().width(), this->subset().height());
231
232 canvas->drawBitmapRect(fBitmap, this->subset(),
233 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
234 }
235
robertphillips64612512016-04-08 12:10:42 -0700236 bool onGetROPixels(SkBitmap* bm) const override {
237 *bm = fBitmap;
robertphillips3b087f42016-02-18 08:48:03 -0800238 return true;
239 }
240
brianosmanafbf71d2016-07-21 07:15:37 -0700241 SkColorSpace* onGetColorSpace() const override {
242 return fBitmap.colorSpace();
243 }
244
robertphillips64612512016-04-08 12:10:42 -0700245#if SK_SUPPORT_GPU
robertphillipsc91fd342016-04-25 12:32:54 -0700246 sk_sp<GrTexture> onAsTextureRef(GrContext* context) const override {
robertphillips64612512016-04-08 12:10:42 -0700247 if (context) {
robertphillipsc91fd342016-04-25 12:32:54 -0700248 return sk_ref_sp(GrRefCachedBitmapTexture(context,
249 fBitmap,
brianosman982eb7f2016-06-06 13:10:58 -0700250 GrTextureParams::ClampNoFilter(),
251 SkSourceGammaTreatment::kRespect));
robertphillips64612512016-04-08 12:10:42 -0700252 }
robertphillips64612512016-04-08 12:10:42 -0700253
254 return nullptr;
255 }
robertphillipsc91fd342016-04-25 12:32:54 -0700256#endif
robertphillips64612512016-04-08 12:10:42 -0700257
258 bool getBitmapDeprecated(SkBitmap* result) const override {
robertphillips4418dba2016-03-07 12:45:14 -0800259 *result = fBitmap;
260 return true;
261 }
262
robertphillips37bd7c32016-03-17 14:31:39 -0700263 sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const override {
robertphillips3e302272016-04-20 11:48:36 -0700264 return SkSpecialSurface::MakeRaster(info, nullptr);
robertphillipsb6c65e92016-02-04 10:52:42 -0800265 }
266
robertphillips37bd7c32016-03-17 14:31:39 -0700267 sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
robertphillipsc5035e72016-03-17 06:58:39 -0700268 SkBitmap subsetBM;
halcanary9d524f22016-03-29 09:03:52 -0700269
robertphillipsc5035e72016-03-17 06:58:39 -0700270 if (!fBitmap.extractSubset(&subsetBM, subset)) {
271 return nullptr;
272 }
273
robertphillips3e302272016-04-20 11:48:36 -0700274 return SkSpecialImage::MakeFromRaster(SkIRect::MakeWH(subset.width(), subset.height()),
brianosman898235c2016-04-06 07:38:23 -0700275 subsetBM,
276 &this->props());
robertphillipsc5035e72016-03-17 06:58:39 -0700277 }
278
robertphillipsb4bd11e2016-03-21 13:44:18 -0700279 sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const override {
280 SkBitmap subsetBM;
281
282 if (!fBitmap.extractSubset(&subsetBM, subset)) {
283 return nullptr;
284 }
285
286 return SkImage::MakeFromBitmap(subsetBM);
287 }
288
reede8f30622016-03-23 18:59:25 -0700289 sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const override {
290 return SkSurface::MakeRaster(info);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700291 }
292
robertphillipsb6c65e92016-02-04 10:52:42 -0800293private:
294 SkBitmap fBitmap;
295
296 typedef SkSpecialImage_Base INHERITED;
297};
298
robertphillips3e302272016-04-20 11:48:36 -0700299sk_sp<SkSpecialImage> SkSpecialImage::MakeFromRaster(const SkIRect& subset,
brianosman898235c2016-04-06 07:38:23 -0700300 const SkBitmap& bm,
301 const SkSurfaceProps* props) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800302 SkASSERT(nullptr == bm.getTexture());
303 SkASSERT(rect_fits(subset, bm.width(), bm.height()));
robertphillips37bd7c32016-03-17 14:31:39 -0700304
reeda2217ef2016-07-20 06:04:34 -0700305 const SkBitmap* srcBM = &bm;
306 SkBitmap tmpStorage;
307 // ImageFilters only handle N32 at the moment, so force our src to be that
308 if (!valid_for_imagefilters(bm.info())) {
309 if (!bm.copyTo(&tmpStorage, kN32_SkColorType)) {
310 return nullptr;
311 }
312 srcBM = &tmpStorage;
313 }
314 return sk_make_sp<SkSpecialImage_Raster>(subset, *srcBM, props);
robertphillipsb6c65e92016-02-04 10:52:42 -0800315}
316
317#if SK_SUPPORT_GPU
318///////////////////////////////////////////////////////////////////////////////
robertphillipsed086ca2016-04-26 15:02:25 -0700319#include "GrTexture.h"
robertphillipsb4bd11e2016-03-21 13:44:18 -0700320#include "SkImage_Gpu.h"
robertphillipsb6c65e92016-02-04 10:52:42 -0800321
robertphillipsed086ca2016-04-26 15:02:25 -0700322class SkSpecialImage_Gpu : public SkSpecialImage_Base {
323public:
324 SkSpecialImage_Gpu(const SkIRect& subset,
325 uint32_t uniqueID, sk_sp<GrTexture> tex, SkAlphaType at,
brianosmanafbf71d2016-07-21 07:15:37 -0700326 sk_sp<SkColorSpace> colorSpace, const SkSurfaceProps* props)
robertphillipsed086ca2016-04-26 15:02:25 -0700327 : INHERITED(subset, uniqueID, props)
328 , fTexture(std::move(tex))
329 , fAlphaType(at)
brianosmanafbf71d2016-07-21 07:15:37 -0700330 , fColorSpace(std::move(colorSpace))
robertphillipsed086ca2016-04-26 15:02:25 -0700331 , fAddedRasterVersionToCache(false) {
332 }
333
334 ~SkSpecialImage_Gpu() override {
335 if (fAddedRasterVersionToCache.load()) {
336 SkNotifyBitmapGenIDIsStale(this->uniqueID());
337 }
338 }
339
340 bool isOpaque() const override {
341 return GrPixelConfigIsOpaque(fTexture->config()) || fAlphaType == kOpaque_SkAlphaType;
342 }
343
344 size_t getSize() const override { return fTexture->gpuMemorySize(); }
345
346 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
347 SkRect dst = SkRect::MakeXYWH(x, y,
348 this->subset().width(), this->subset().height());
349
reed77d6f7d2016-07-13 12:24:48 -0700350 auto img = sk_sp<SkImage>(new SkImage_Gpu(fTexture->width(), fTexture->height(),
351 this->uniqueID(), fAlphaType, fTexture.get(),
brianosmanafbf71d2016-07-21 07:15:37 -0700352 fColorSpace, SkBudgeted::kNo));
robertphillipsed086ca2016-04-26 15:02:25 -0700353
reed77d6f7d2016-07-13 12:24:48 -0700354 canvas->drawImageRect(img, this->subset(),
robertphillipsed086ca2016-04-26 15:02:25 -0700355 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
356 }
357
358 GrTexture* onPeekTexture() const override { return fTexture.get(); }
359
360 sk_sp<GrTexture> onAsTextureRef(GrContext*) const override { return fTexture; }
361
362 bool onGetROPixels(SkBitmap* dst) const override {
363 if (SkBitmapCache::Find(this->uniqueID(), dst)) {
364 SkASSERT(dst->getGenerationID() == this->uniqueID());
365 SkASSERT(dst->isImmutable());
366 SkASSERT(dst->getPixels());
367 return true;
368 }
369
370 SkImageInfo info = SkImageInfo::MakeN32(this->width(), this->height(),
371 this->isOpaque() ? kOpaque_SkAlphaType
brianosmanafbf71d2016-07-21 07:15:37 -0700372 : kPremul_SkAlphaType,
373 fColorSpace);
robertphillipsed086ca2016-04-26 15:02:25 -0700374
375 if (!dst->tryAllocPixels(info)) {
376 return false;
377 }
378
379 if (!fTexture->readPixels(0, 0, dst->width(), dst->height(), kSkia8888_GrPixelConfig,
380 dst->getPixels(), dst->rowBytes())) {
381 return false;
382 }
383
384 dst->pixelRef()->setImmutableWithID(this->uniqueID());
385 SkBitmapCache::Add(this->uniqueID(), *dst);
386 fAddedRasterVersionToCache.store(true);
387 return true;
388 }
389
brianosmanafbf71d2016-07-21 07:15:37 -0700390 SkColorSpace* onGetColorSpace() const override {
391 return fColorSpace.get();
392 }
393
robertphillipsed086ca2016-04-26 15:02:25 -0700394 bool getBitmapDeprecated(SkBitmap* result) const override {
395 const SkImageInfo info = GrMakeInfoFromTexture(fTexture.get(),
396 this->width(), this->height(),
brianosmanafbf71d2016-07-21 07:15:37 -0700397 this->isOpaque(), fColorSpace);
robertphillipsed086ca2016-04-26 15:02:25 -0700398 if (!result->setInfo(info)) {
399 return false;
400 }
401
402 const SkImageInfo prInfo = info.makeWH(fTexture->width(), fTexture->height());
403
404 SkAutoTUnref<SkGrPixelRef> pixelRef(new SkGrPixelRef(prInfo, fTexture.get()));
405 result->setPixelRef(pixelRef, this->subset().fLeft, this->subset().fTop);
406 return true;
407 }
408
409 sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const override {
410 if (!fTexture->getContext()) {
411 return nullptr;
412 }
413
robertphillips4df16562016-04-28 15:09:34 -0700414 GrPixelConfig config = SkImageInfo2GrPixelConfig(info, *fTexture->getContext()->caps());
robertphillipsed086ca2016-04-26 15:02:25 -0700415
robertphillips4df16562016-04-28 15:09:34 -0700416 return SkSpecialSurface::MakeRenderTarget(fTexture->getContext(),
417 info.width(), info.height(),
418 config);
robertphillipsed086ca2016-04-26 15:02:25 -0700419 }
420
421 sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
422 return SkSpecialImage::MakeFromGpu(subset,
423 this->uniqueID(),
424 fTexture,
brianosmanafbf71d2016-07-21 07:15:37 -0700425 fColorSpace,
robertphillipsed086ca2016-04-26 15:02:25 -0700426 &this->props(),
427 fAlphaType);
428 }
429
430 sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const override {
431 if (0 == subset.fLeft && 0 == subset.fTop &&
432 fTexture->width() == subset.width() &&
433 fTexture->height() == subset.height()) {
434 // The existing GrTexture is already tight so reuse it in the SkImage
435 return sk_make_sp<SkImage_Gpu>(fTexture->width(), fTexture->height(),
436 kNeedNewImageUniqueID,
brianosmanafbf71d2016-07-21 07:15:37 -0700437 fAlphaType, fTexture.get(), fColorSpace,
438 SkBudgeted::kYes);
robertphillipsed086ca2016-04-26 15:02:25 -0700439 }
440
441 GrContext* ctx = fTexture->getContext();
442 GrSurfaceDesc desc = fTexture->desc();
443 desc.fWidth = subset.width();
444 desc.fHeight = subset.height();
445
446 sk_sp<GrTexture> subTx(ctx->textureProvider()->createTexture(desc, SkBudgeted::kYes));
447 if (!subTx) {
448 return nullptr;
449 }
450 ctx->copySurface(subTx.get(), fTexture.get(), subset, SkIPoint::Make(0, 0));
451 return sk_make_sp<SkImage_Gpu>(desc.fWidth, desc.fHeight, kNeedNewImageUniqueID,
brianosmanafbf71d2016-07-21 07:15:37 -0700452 fAlphaType, subTx.get(), fColorSpace, SkBudgeted::kYes);
robertphillipsed086ca2016-04-26 15:02:25 -0700453 }
454
455 sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const override {
456 return SkSurface::MakeRenderTarget(fTexture->getContext(), SkBudgeted::kYes, info);
457 }
458
459private:
460 sk_sp<GrTexture> fTexture;
461 const SkAlphaType fAlphaType;
brianosmanafbf71d2016-07-21 07:15:37 -0700462 sk_sp<SkColorSpace> fColorSpace;
robertphillipsed086ca2016-04-26 15:02:25 -0700463 mutable SkAtomic<bool> fAddedRasterVersionToCache;
464
465 typedef SkSpecialImage_Base INHERITED;
466};
467
robertphillips3e302272016-04-20 11:48:36 -0700468sk_sp<SkSpecialImage> SkSpecialImage::MakeFromGpu(const SkIRect& subset,
robertphillips37bd7c32016-03-17 14:31:39 -0700469 uint32_t uniqueID,
robertphillipsc91fd342016-04-25 12:32:54 -0700470 sk_sp<GrTexture> tex,
brianosmanafbf71d2016-07-21 07:15:37 -0700471 sk_sp<SkColorSpace> colorSpace,
brianosman898235c2016-04-06 07:38:23 -0700472 const SkSurfaceProps* props,
robertphillips37bd7c32016-03-17 14:31:39 -0700473 SkAlphaType at) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800474 SkASSERT(rect_fits(subset, tex->width(), tex->height()));
brianosmanafbf71d2016-07-21 07:15:37 -0700475 return sk_make_sp<SkSpecialImage_Gpu>(subset, uniqueID, std::move(tex), at,
476 std::move(colorSpace), props);
robertphillipsb6c65e92016-02-04 10:52:42 -0800477}
478
479#endif