blob: c10e88e0ca99f6203eb66d6f711039302839f1a9 [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"
reedad7604b2016-07-20 16:13:32 -070023#include "SkGrPriv.h"
24#endif
robertphillipsb6c65e92016-02-04 10:52:42 -080025
reeda2217ef2016-07-20 06:04:34 -070026// Currently the raster imagefilters can only handle certain imageinfos. Call this to know if
27// a given info is supported.
28static bool valid_for_imagefilters(const SkImageInfo& info) {
29 // no support for other swizzles/depths yet
30 return info.colorType() == kN32_SkColorType;
31}
32
robertphillipsb6c65e92016-02-04 10:52:42 -080033///////////////////////////////////////////////////////////////////////////////
34class SkSpecialImage_Base : public SkSpecialImage {
35public:
robertphillips3e302272016-04-20 11:48:36 -070036 SkSpecialImage_Base(const SkIRect& subset, uint32_t uniqueID, const SkSurfaceProps* props)
37 : INHERITED(subset, uniqueID, props) {
robertphillips3b087f42016-02-18 08:48:03 -080038 }
robertphillips3e302272016-04-20 11:48:36 -070039 ~SkSpecialImage_Base() override { }
robertphillipsb6c65e92016-02-04 10:52:42 -080040
robertphillipse8c34972016-02-16 12:09:36 -080041 virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) const = 0;
robertphillipsb6c65e92016-02-04 10:52:42 -080042
robertphillips64612512016-04-08 12:10:42 -070043 virtual bool onGetROPixels(SkBitmap*) const = 0;
robertphillipsb6c65e92016-02-04 10:52:42 -080044
45 virtual GrTexture* onPeekTexture() const { return nullptr; }
46
brianosmanafbf71d2016-07-21 07:15:37 -070047 virtual SkColorSpace* onGetColorSpace() const = 0;
48
robertphillipsc91fd342016-04-25 12:32:54 -070049#if SK_SUPPORT_GPU
50 virtual sk_sp<GrTexture> onAsTextureRef(GrContext* context) const = 0;
51#endif
robertphillips4418dba2016-03-07 12:45:14 -080052
robertphillipsb4bd11e2016-03-21 13:44:18 -070053 virtual sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const = 0;
54
robertphillips37bd7c32016-03-17 14:31:39 -070055 virtual sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const = 0;
robertphillipsc5035e72016-03-17 06:58:39 -070056
robertphillipsb4bd11e2016-03-21 13:44:18 -070057 virtual sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const = 0;
58
reede8f30622016-03-23 18:59:25 -070059 virtual sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const = 0;
robertphillipsb6c65e92016-02-04 10:52:42 -080060
61private:
62 typedef SkSpecialImage INHERITED;
63};
64
65///////////////////////////////////////////////////////////////////////////////
bsalomon84a4e5a2016-02-29 11:41:52 -080066static inline const SkSpecialImage_Base* as_SIB(const SkSpecialImage* image) {
robertphillipsb6c65e92016-02-04 10:52:42 -080067 return static_cast<const SkSpecialImage_Base*>(image);
68}
69
robertphillips3e302272016-04-20 11:48:36 -070070SkSpecialImage::SkSpecialImage(const SkIRect& subset,
brianosman898235c2016-04-06 07:38:23 -070071 uint32_t uniqueID,
72 const SkSurfaceProps* props)
73 : fProps(SkSurfacePropsCopyOrDefault(props))
74 , fSubset(subset)
robertphillips3e302272016-04-20 11:48:36 -070075 , fUniqueID(kNeedNewImageUniqueID_SpecialImage == uniqueID ? SkNextID::ImageID() : uniqueID) {
brianosman898235c2016-04-06 07:38:23 -070076}
77
robertphillips3e302272016-04-20 11:48:36 -070078sk_sp<SkSpecialImage> SkSpecialImage::makeTextureImage(GrContext* context) {
robertphillips83c17fa2016-03-18 08:14:27 -070079#if SK_SUPPORT_GPU
80 if (!context) {
81 return nullptr;
82 }
robertphillips64612512016-04-08 12:10:42 -070083 if (GrTexture* peek = as_SIB(this)->onPeekTexture()) {
robertphillips83c17fa2016-03-18 08:14:27 -070084 return peek->getContext() == context ? sk_sp<SkSpecialImage>(SkRef(this)) : nullptr;
85 }
86
87 SkBitmap bmp;
reedcf5c8462016-07-20 12:28:40 -070088 // At this point, we are definitely not texture-backed, so we must be raster or generator
89 // backed. If we remove the special-wrapping-an-image subclass, we may be able to assert that
90 // we are strictly raster-backed (i.e. generator images become raster when they are specialized)
91 // in which case getROPixels could turn into peekPixels...
92 if (!this->getROPixels(&bmp)) {
robertphillips83c17fa2016-03-18 08:14:27 -070093 return nullptr;
94 }
95
robertphillips83f2e5a2016-03-24 06:31:25 -070096 if (bmp.empty()) {
robertphillips3e302272016-04-20 11:48:36 -070097 return SkSpecialImage::MakeFromRaster(SkIRect::MakeEmpty(), bmp, &this->props());
robertphillips83f2e5a2016-03-24 06:31:25 -070098 }
99
robertphillipsc91fd342016-04-25 12:32:54 -0700100 sk_sp<GrTexture> resultTex(GrRefCachedBitmapTexture(context,
101 bmp,
brianosman982eb7f2016-06-06 13:10:58 -0700102 GrTextureParams::ClampNoFilter(),
103 SkSourceGammaTreatment::kRespect));
robertphillips83c17fa2016-03-18 08:14:27 -0700104 if (!resultTex) {
105 return nullptr;
106 }
107
108 SkAlphaType at = this->isOpaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
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(),
113 at);
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 {
128#if SK_SUPPORT_GPU
129 return as_SIB(this)->onPeekTexture() && as_SIB(this)->onPeekTexture()->getContext();
130#else
131 return false;
132#endif
robertphillipsb6c65e92016-02-04 10:52:42 -0800133}
134
robertphillips64612512016-04-08 12:10:42 -0700135GrContext* SkSpecialImage::getContext() const {
136#if SK_SUPPORT_GPU
137 GrTexture* texture = as_SIB(this)->onPeekTexture();
138
139 if (texture) {
140 return texture->getContext();
141 }
142#endif
143 return nullptr;
144}
145
brianosmanafbf71d2016-07-21 07:15:37 -0700146SkColorSpace* SkSpecialImage::getColorSpace() const {
147 return as_SIB(this)->onGetColorSpace();
148}
149
robertphillipsc91fd342016-04-25 12:32:54 -0700150#if SK_SUPPORT_GPU
151sk_sp<GrTexture> SkSpecialImage::asTextureRef(GrContext* context) const {
robertphillips64612512016-04-08 12:10:42 -0700152 return as_SIB(this)->onAsTextureRef(context);
robertphillips4418dba2016-03-07 12:45:14 -0800153}
robertphillipsc91fd342016-04-25 12:32:54 -0700154#endif
robertphillips4418dba2016-03-07 12:45:14 -0800155
robertphillips37bd7c32016-03-17 14:31:39 -0700156sk_sp<SkSpecialSurface> SkSpecialImage::makeSurface(const SkImageInfo& info) const {
157 return as_SIB(this)->onMakeSurface(info);
robertphillipsb6c65e92016-02-04 10:52:42 -0800158}
159
robertphillipsb4bd11e2016-03-21 13:44:18 -0700160sk_sp<SkSurface> SkSpecialImage::makeTightSurface(const SkImageInfo& info) const {
reede8f30622016-03-23 18:59:25 -0700161 return as_SIB(this)->onMakeTightSurface(info);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700162}
163
robertphillips37bd7c32016-03-17 14:31:39 -0700164sk_sp<SkSpecialImage> SkSpecialImage::makeSubset(const SkIRect& subset) const {
165 return as_SIB(this)->onMakeSubset(subset);
robertphillipsc5035e72016-03-17 06:58:39 -0700166}
167
robertphillipsb4bd11e2016-03-21 13:44:18 -0700168sk_sp<SkImage> SkSpecialImage::makeTightSubset(const SkIRect& subset) const {
169 return as_SIB(this)->onMakeTightSubset(subset);
170}
171
robertphillipsb6c65e92016-02-04 10:52:42 -0800172#ifdef SK_DEBUG
173static bool rect_fits(const SkIRect& rect, int width, int height) {
robertphillips4418dba2016-03-07 12:45:14 -0800174 if (0 == width && 0 == height) {
175 SkASSERT(0 == rect.fLeft && 0 == rect.fRight && 0 == rect.fTop && 0 == rect.fBottom);
176 return true;
177 }
178
robertphillipsb6c65e92016-02-04 10:52:42 -0800179 return rect.fLeft >= 0 && rect.fLeft < width && rect.fLeft < rect.fRight &&
180 rect.fRight >= 0 && rect.fRight <= width &&
181 rect.fTop >= 0 && rect.fTop < height && rect.fTop < rect.fBottom &&
182 rect.fBottom >= 0 && rect.fBottom <= height;
183}
184#endif
185
robertphillips3e302272016-04-20 11:48:36 -0700186sk_sp<SkSpecialImage> SkSpecialImage::MakeFromImage(const SkIRect& subset,
brianosman898235c2016-04-06 07:38:23 -0700187 sk_sp<SkImage> image,
188 const SkSurfaceProps* props) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800189 SkASSERT(rect_fits(subset, image->width(), image->height()));
robertphillips37bd7c32016-03-17 14:31:39 -0700190
reedad7604b2016-07-20 16:13:32 -0700191#if SK_SUPPORT_GPU
192 if (GrTexture* texture = as_IB(image)->peekTexture()) {
brianosmanafbf71d2016-07-21 07:15:37 -0700193 return MakeFromGpu(subset, image->uniqueID(), sk_ref_sp(texture),
194 sk_ref_sp(as_IB(image)->onImageInfo().colorSpace()), props);
reedad7604b2016-07-20 16:13:32 -0700195 } else
196#endif
197 {
198 SkBitmap bm;
199 if (as_IB(image)->getROPixels(&bm)) {
200 return MakeFromRaster(subset, bm, props);
201 }
reeda2217ef2016-07-20 06:04:34 -0700202 }
reedad7604b2016-07-20 16:13:32 -0700203 return nullptr;
robertphillipsb6c65e92016-02-04 10:52:42 -0800204}
205
206///////////////////////////////////////////////////////////////////////////////
robertphillipsb6c65e92016-02-04 10:52:42 -0800207
208class SkSpecialImage_Raster : public SkSpecialImage_Base {
209public:
robertphillips3e302272016-04-20 11:48:36 -0700210 SkSpecialImage_Raster(const SkIRect& subset, const SkBitmap& bm, const SkSurfaceProps* props)
211 : INHERITED(subset, bm.getGenerationID(), props)
reedbd2bd5c2016-07-25 14:26:02 -0700212 , fBitmap(bm)
213 {
214 SkASSERT(bm.pixelRef());
215
216 // We have to lock now, while bm is still in scope, since it may have come from our
217 // cache, which means we need to keep it locked until we (the special) are done, since
218 // we cannot re-generate the cache entry (if bm came from a generator).
219 fBitmap.lockPixels();
220 SkASSERT(fBitmap.getPixels());
robertphillipsb6c65e92016-02-04 10:52:42 -0800221 }
222
robertphillips3b087f42016-02-18 08:48:03 -0800223 bool isOpaque() const override { return fBitmap.isOpaque(); }
224
225 size_t getSize() const override { return fBitmap.getSize(); }
226
robertphillipse8c34972016-02-16 12:09:36 -0800227 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800228 SkRect dst = SkRect::MakeXYWH(x, y,
229 this->subset().width(), this->subset().height());
230
231 canvas->drawBitmapRect(fBitmap, this->subset(),
232 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
233 }
234
robertphillips64612512016-04-08 12:10:42 -0700235 bool onGetROPixels(SkBitmap* bm) const override {
236 *bm = fBitmap;
robertphillips3b087f42016-02-18 08:48:03 -0800237 return true;
238 }
239
brianosmanafbf71d2016-07-21 07:15:37 -0700240 SkColorSpace* onGetColorSpace() const override {
241 return fBitmap.colorSpace();
242 }
243
robertphillips64612512016-04-08 12:10:42 -0700244#if SK_SUPPORT_GPU
robertphillipsc91fd342016-04-25 12:32:54 -0700245 sk_sp<GrTexture> onAsTextureRef(GrContext* context) const override {
robertphillips64612512016-04-08 12:10:42 -0700246 if (context) {
robertphillipsc91fd342016-04-25 12:32:54 -0700247 return sk_ref_sp(GrRefCachedBitmapTexture(context,
248 fBitmap,
brianosman982eb7f2016-06-06 13:10:58 -0700249 GrTextureParams::ClampNoFilter(),
250 SkSourceGammaTreatment::kRespect));
robertphillips64612512016-04-08 12:10:42 -0700251 }
robertphillips64612512016-04-08 12:10:42 -0700252
253 return nullptr;
254 }
robertphillipsc91fd342016-04-25 12:32:54 -0700255#endif
robertphillips64612512016-04-08 12:10:42 -0700256
robertphillips37bd7c32016-03-17 14:31:39 -0700257 sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const override {
robertphillips3e302272016-04-20 11:48:36 -0700258 return SkSpecialSurface::MakeRaster(info, nullptr);
robertphillipsb6c65e92016-02-04 10:52:42 -0800259 }
260
robertphillips37bd7c32016-03-17 14:31:39 -0700261 sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
robertphillipsc5035e72016-03-17 06:58:39 -0700262 SkBitmap subsetBM;
halcanary9d524f22016-03-29 09:03:52 -0700263
robertphillipsc5035e72016-03-17 06:58:39 -0700264 if (!fBitmap.extractSubset(&subsetBM, subset)) {
265 return nullptr;
266 }
267
robertphillips3e302272016-04-20 11:48:36 -0700268 return SkSpecialImage::MakeFromRaster(SkIRect::MakeWH(subset.width(), subset.height()),
brianosman898235c2016-04-06 07:38:23 -0700269 subsetBM,
270 &this->props());
robertphillipsc5035e72016-03-17 06:58:39 -0700271 }
272
robertphillipsb4bd11e2016-03-21 13:44:18 -0700273 sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const override {
274 SkBitmap subsetBM;
275
276 if (!fBitmap.extractSubset(&subsetBM, subset)) {
277 return nullptr;
278 }
279
280 return SkImage::MakeFromBitmap(subsetBM);
281 }
282
reede8f30622016-03-23 18:59:25 -0700283 sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const override {
284 return SkSurface::MakeRaster(info);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700285 }
286
robertphillipsb6c65e92016-02-04 10:52:42 -0800287private:
288 SkBitmap fBitmap;
289
290 typedef SkSpecialImage_Base INHERITED;
291};
292
robertphillips3e302272016-04-20 11:48:36 -0700293sk_sp<SkSpecialImage> SkSpecialImage::MakeFromRaster(const SkIRect& subset,
brianosman898235c2016-04-06 07:38:23 -0700294 const SkBitmap& bm,
295 const SkSurfaceProps* props) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800296 SkASSERT(rect_fits(subset, bm.width(), bm.height()));
robertphillips37bd7c32016-03-17 14:31:39 -0700297
reedbd2bd5c2016-07-25 14:26:02 -0700298 if (!bm.pixelRef()) {
299 return nullptr;
300 }
301
reeda2217ef2016-07-20 06:04:34 -0700302 const SkBitmap* srcBM = &bm;
303 SkBitmap tmpStorage;
304 // ImageFilters only handle N32 at the moment, so force our src to be that
305 if (!valid_for_imagefilters(bm.info())) {
306 if (!bm.copyTo(&tmpStorage, kN32_SkColorType)) {
307 return nullptr;
308 }
309 srcBM = &tmpStorage;
310 }
311 return sk_make_sp<SkSpecialImage_Raster>(subset, *srcBM, props);
robertphillipsb6c65e92016-02-04 10:52:42 -0800312}
313
314#if SK_SUPPORT_GPU
315///////////////////////////////////////////////////////////////////////////////
robertphillipsed086ca2016-04-26 15:02:25 -0700316#include "GrTexture.h"
robertphillipsb4bd11e2016-03-21 13:44:18 -0700317#include "SkImage_Gpu.h"
robertphillipsb6c65e92016-02-04 10:52:42 -0800318
robertphillipsed086ca2016-04-26 15:02:25 -0700319class SkSpecialImage_Gpu : public SkSpecialImage_Base {
320public:
321 SkSpecialImage_Gpu(const SkIRect& subset,
322 uint32_t uniqueID, sk_sp<GrTexture> tex, SkAlphaType at,
brianosmanafbf71d2016-07-21 07:15:37 -0700323 sk_sp<SkColorSpace> colorSpace, const SkSurfaceProps* props)
robertphillipsed086ca2016-04-26 15:02:25 -0700324 : INHERITED(subset, uniqueID, props)
325 , fTexture(std::move(tex))
326 , fAlphaType(at)
brianosmanafbf71d2016-07-21 07:15:37 -0700327 , fColorSpace(std::move(colorSpace))
robertphillipsed086ca2016-04-26 15:02:25 -0700328 , fAddedRasterVersionToCache(false) {
329 }
330
331 ~SkSpecialImage_Gpu() override {
332 if (fAddedRasterVersionToCache.load()) {
333 SkNotifyBitmapGenIDIsStale(this->uniqueID());
334 }
335 }
336
337 bool isOpaque() const override {
338 return GrPixelConfigIsOpaque(fTexture->config()) || fAlphaType == kOpaque_SkAlphaType;
339 }
340
341 size_t getSize() const override { return fTexture->gpuMemorySize(); }
342
343 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
344 SkRect dst = SkRect::MakeXYWH(x, y,
345 this->subset().width(), this->subset().height());
346
reed77d6f7d2016-07-13 12:24:48 -0700347 auto img = sk_sp<SkImage>(new SkImage_Gpu(fTexture->width(), fTexture->height(),
348 this->uniqueID(), fAlphaType, fTexture.get(),
brianosmanafbf71d2016-07-21 07:15:37 -0700349 fColorSpace, SkBudgeted::kNo));
robertphillipsed086ca2016-04-26 15:02:25 -0700350
reed77d6f7d2016-07-13 12:24:48 -0700351 canvas->drawImageRect(img, this->subset(),
robertphillipsed086ca2016-04-26 15:02:25 -0700352 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
353 }
354
355 GrTexture* onPeekTexture() const override { return fTexture.get(); }
356
357 sk_sp<GrTexture> onAsTextureRef(GrContext*) const override { return fTexture; }
358
359 bool onGetROPixels(SkBitmap* dst) const override {
360 if (SkBitmapCache::Find(this->uniqueID(), dst)) {
361 SkASSERT(dst->getGenerationID() == this->uniqueID());
362 SkASSERT(dst->isImmutable());
363 SkASSERT(dst->getPixels());
364 return true;
365 }
366
367 SkImageInfo info = SkImageInfo::MakeN32(this->width(), this->height(),
368 this->isOpaque() ? kOpaque_SkAlphaType
brianosmanafbf71d2016-07-21 07:15:37 -0700369 : kPremul_SkAlphaType,
370 fColorSpace);
robertphillipsed086ca2016-04-26 15:02:25 -0700371
372 if (!dst->tryAllocPixels(info)) {
373 return false;
374 }
375
376 if (!fTexture->readPixels(0, 0, dst->width(), dst->height(), kSkia8888_GrPixelConfig,
377 dst->getPixels(), dst->rowBytes())) {
378 return false;
379 }
380
381 dst->pixelRef()->setImmutableWithID(this->uniqueID());
382 SkBitmapCache::Add(this->uniqueID(), *dst);
383 fAddedRasterVersionToCache.store(true);
384 return true;
385 }
386
brianosmanafbf71d2016-07-21 07:15:37 -0700387 SkColorSpace* onGetColorSpace() const override {
388 return fColorSpace.get();
389 }
390
robertphillipsed086ca2016-04-26 15:02:25 -0700391 sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const override {
392 if (!fTexture->getContext()) {
393 return nullptr;
394 }
395
robertphillips4df16562016-04-28 15:09:34 -0700396 GrPixelConfig config = SkImageInfo2GrPixelConfig(info, *fTexture->getContext()->caps());
robertphillipsed086ca2016-04-26 15:02:25 -0700397
robertphillips4df16562016-04-28 15:09:34 -0700398 return SkSpecialSurface::MakeRenderTarget(fTexture->getContext(),
399 info.width(), info.height(),
brianosmandfe4f2e2016-07-21 13:28:36 -0700400 config, sk_ref_sp(info.colorSpace()));
robertphillipsed086ca2016-04-26 15:02:25 -0700401 }
402
403 sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
404 return SkSpecialImage::MakeFromGpu(subset,
405 this->uniqueID(),
406 fTexture,
brianosmanafbf71d2016-07-21 07:15:37 -0700407 fColorSpace,
robertphillipsed086ca2016-04-26 15:02:25 -0700408 &this->props(),
409 fAlphaType);
410 }
411
412 sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const override {
413 if (0 == subset.fLeft && 0 == subset.fTop &&
414 fTexture->width() == subset.width() &&
415 fTexture->height() == subset.height()) {
416 // The existing GrTexture is already tight so reuse it in the SkImage
417 return sk_make_sp<SkImage_Gpu>(fTexture->width(), fTexture->height(),
418 kNeedNewImageUniqueID,
brianosmanafbf71d2016-07-21 07:15:37 -0700419 fAlphaType, fTexture.get(), fColorSpace,
420 SkBudgeted::kYes);
robertphillipsed086ca2016-04-26 15:02:25 -0700421 }
422
423 GrContext* ctx = fTexture->getContext();
424 GrSurfaceDesc desc = fTexture->desc();
425 desc.fWidth = subset.width();
426 desc.fHeight = subset.height();
427
428 sk_sp<GrTexture> subTx(ctx->textureProvider()->createTexture(desc, SkBudgeted::kYes));
429 if (!subTx) {
430 return nullptr;
431 }
432 ctx->copySurface(subTx.get(), fTexture.get(), subset, SkIPoint::Make(0, 0));
433 return sk_make_sp<SkImage_Gpu>(desc.fWidth, desc.fHeight, kNeedNewImageUniqueID,
brianosmanafbf71d2016-07-21 07:15:37 -0700434 fAlphaType, subTx.get(), fColorSpace, SkBudgeted::kYes);
robertphillipsed086ca2016-04-26 15:02:25 -0700435 }
436
437 sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const override {
438 return SkSurface::MakeRenderTarget(fTexture->getContext(), SkBudgeted::kYes, info);
439 }
440
441private:
442 sk_sp<GrTexture> fTexture;
443 const SkAlphaType fAlphaType;
brianosmanafbf71d2016-07-21 07:15:37 -0700444 sk_sp<SkColorSpace> fColorSpace;
robertphillipsed086ca2016-04-26 15:02:25 -0700445 mutable SkAtomic<bool> fAddedRasterVersionToCache;
446
447 typedef SkSpecialImage_Base INHERITED;
448};
449
robertphillips3e302272016-04-20 11:48:36 -0700450sk_sp<SkSpecialImage> SkSpecialImage::MakeFromGpu(const SkIRect& subset,
robertphillips37bd7c32016-03-17 14:31:39 -0700451 uint32_t uniqueID,
robertphillipsc91fd342016-04-25 12:32:54 -0700452 sk_sp<GrTexture> tex,
brianosmanafbf71d2016-07-21 07:15:37 -0700453 sk_sp<SkColorSpace> colorSpace,
brianosman898235c2016-04-06 07:38:23 -0700454 const SkSurfaceProps* props,
robertphillips37bd7c32016-03-17 14:31:39 -0700455 SkAlphaType at) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800456 SkASSERT(rect_fits(subset, tex->width(), tex->height()));
brianosmanafbf71d2016-07-21 07:15:37 -0700457 return sk_make_sp<SkSpecialImage_Gpu>(subset, uniqueID, std::move(tex), at,
458 std::move(colorSpace), props);
robertphillipsb6c65e92016-02-04 10:52:42 -0800459}
460
461#endif