blob: 240d46921947e450a8f6592ac75c060e6fffb340 [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
robertphillips3e302272016-04-20 11:48:36 -0700108 return SkSpecialImage::MakeFromGpu(SkIRect::MakeWH(resultTex->width(), resultTex->height()),
robertphillips83c17fa2016-03-18 08:14:27 -0700109 this->uniqueID(),
brianosmanafbf71d2016-07-21 07:15:37 -0700110 resultTex, sk_ref_sp(this->getColorSpace()), &this->props(),
brianosman80e96082016-08-16 07:09:47 -0700111 this->alphaType());
robertphillips83c17fa2016-03-18 08:14:27 -0700112#else
113 return nullptr;
114#endif
115}
116
robertphillipse8c34972016-02-16 12:09:36 -0800117void SkSpecialImage::draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const {
bsalomon84a4e5a2016-02-29 11:41:52 -0800118 return as_SIB(this)->onDraw(canvas, x, y, paint);
robertphillipsb6c65e92016-02-04 10:52:42 -0800119}
120
robertphillips64612512016-04-08 12:10:42 -0700121bool SkSpecialImage::getROPixels(SkBitmap* bm) const {
122 return as_SIB(this)->onGetROPixels(bm);
robertphillipsb6c65e92016-02-04 10:52:42 -0800123}
124
robertphillips64612512016-04-08 12:10:42 -0700125bool SkSpecialImage::isTextureBacked() const {
126#if SK_SUPPORT_GPU
127 return as_SIB(this)->onPeekTexture() && as_SIB(this)->onPeekTexture()->getContext();
128#else
129 return false;
130#endif
robertphillipsb6c65e92016-02-04 10:52:42 -0800131}
132
robertphillips64612512016-04-08 12:10:42 -0700133GrContext* SkSpecialImage::getContext() const {
134#if SK_SUPPORT_GPU
135 GrTexture* texture = as_SIB(this)->onPeekTexture();
136
137 if (texture) {
138 return texture->getContext();
139 }
140#endif
141 return nullptr;
142}
143
brianosmanafbf71d2016-07-21 07:15:37 -0700144SkColorSpace* SkSpecialImage::getColorSpace() const {
145 return as_SIB(this)->onGetColorSpace();
146}
147
robertphillipsc91fd342016-04-25 12:32:54 -0700148#if SK_SUPPORT_GPU
149sk_sp<GrTexture> SkSpecialImage::asTextureRef(GrContext* context) const {
robertphillips64612512016-04-08 12:10:42 -0700150 return as_SIB(this)->onAsTextureRef(context);
robertphillips4418dba2016-03-07 12:45:14 -0800151}
robertphillipsc91fd342016-04-25 12:32:54 -0700152#endif
robertphillips4418dba2016-03-07 12:45:14 -0800153
robertphillips37bd7c32016-03-17 14:31:39 -0700154sk_sp<SkSpecialSurface> SkSpecialImage::makeSurface(const SkImageInfo& info) const {
155 return as_SIB(this)->onMakeSurface(info);
robertphillipsb6c65e92016-02-04 10:52:42 -0800156}
157
robertphillipsb4bd11e2016-03-21 13:44:18 -0700158sk_sp<SkSurface> SkSpecialImage::makeTightSurface(const SkImageInfo& info) const {
reede8f30622016-03-23 18:59:25 -0700159 return as_SIB(this)->onMakeTightSurface(info);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700160}
161
robertphillips37bd7c32016-03-17 14:31:39 -0700162sk_sp<SkSpecialImage> SkSpecialImage::makeSubset(const SkIRect& subset) const {
163 return as_SIB(this)->onMakeSubset(subset);
robertphillipsc5035e72016-03-17 06:58:39 -0700164}
165
robertphillipsb4bd11e2016-03-21 13:44:18 -0700166sk_sp<SkImage> SkSpecialImage::makeTightSubset(const SkIRect& subset) const {
167 return as_SIB(this)->onMakeTightSubset(subset);
168}
169
robertphillipsb6c65e92016-02-04 10:52:42 -0800170#ifdef SK_DEBUG
171static bool rect_fits(const SkIRect& rect, int width, int height) {
robertphillips4418dba2016-03-07 12:45:14 -0800172 if (0 == width && 0 == height) {
173 SkASSERT(0 == rect.fLeft && 0 == rect.fRight && 0 == rect.fTop && 0 == rect.fBottom);
174 return true;
175 }
176
robertphillipsb6c65e92016-02-04 10:52:42 -0800177 return rect.fLeft >= 0 && rect.fLeft < width && rect.fLeft < rect.fRight &&
178 rect.fRight >= 0 && rect.fRight <= width &&
179 rect.fTop >= 0 && rect.fTop < height && rect.fTop < rect.fBottom &&
180 rect.fBottom >= 0 && rect.fBottom <= height;
181}
182#endif
183
robertphillips3e302272016-04-20 11:48:36 -0700184sk_sp<SkSpecialImage> SkSpecialImage::MakeFromImage(const SkIRect& subset,
brianosman898235c2016-04-06 07:38:23 -0700185 sk_sp<SkImage> image,
186 const SkSurfaceProps* props) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800187 SkASSERT(rect_fits(subset, image->width(), image->height()));
robertphillips37bd7c32016-03-17 14:31:39 -0700188
reedad7604b2016-07-20 16:13:32 -0700189#if SK_SUPPORT_GPU
190 if (GrTexture* texture = as_IB(image)->peekTexture()) {
brianosmanafbf71d2016-07-21 07:15:37 -0700191 return MakeFromGpu(subset, image->uniqueID(), sk_ref_sp(texture),
192 sk_ref_sp(as_IB(image)->onImageInfo().colorSpace()), props);
reedad7604b2016-07-20 16:13:32 -0700193 } else
194#endif
195 {
196 SkBitmap bm;
197 if (as_IB(image)->getROPixels(&bm)) {
198 return MakeFromRaster(subset, bm, props);
199 }
reeda2217ef2016-07-20 06:04:34 -0700200 }
reedad7604b2016-07-20 16:13:32 -0700201 return nullptr;
robertphillipsb6c65e92016-02-04 10:52:42 -0800202}
203
204///////////////////////////////////////////////////////////////////////////////
robertphillipsb6c65e92016-02-04 10:52:42 -0800205
206class SkSpecialImage_Raster : public SkSpecialImage_Base {
207public:
robertphillips3e302272016-04-20 11:48:36 -0700208 SkSpecialImage_Raster(const SkIRect& subset, const SkBitmap& bm, const SkSurfaceProps* props)
209 : INHERITED(subset, bm.getGenerationID(), props)
reedbd2bd5c2016-07-25 14:26:02 -0700210 , fBitmap(bm)
211 {
212 SkASSERT(bm.pixelRef());
213
214 // We have to lock now, while bm is still in scope, since it may have come from our
215 // cache, which means we need to keep it locked until we (the special) are done, since
216 // we cannot re-generate the cache entry (if bm came from a generator).
217 fBitmap.lockPixels();
218 SkASSERT(fBitmap.getPixels());
robertphillipsb6c65e92016-02-04 10:52:42 -0800219 }
220
brianosman80e96082016-08-16 07:09:47 -0700221 SkAlphaType alphaType() const override { return fBitmap.alphaType(); }
robertphillips3b087f42016-02-18 08:48:03 -0800222
223 size_t getSize() const override { return fBitmap.getSize(); }
224
robertphillipse8c34972016-02-16 12:09:36 -0800225 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800226 SkRect dst = SkRect::MakeXYWH(x, y,
227 this->subset().width(), this->subset().height());
228
229 canvas->drawBitmapRect(fBitmap, this->subset(),
230 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
231 }
232
robertphillips64612512016-04-08 12:10:42 -0700233 bool onGetROPixels(SkBitmap* bm) const override {
234 *bm = fBitmap;
robertphillips3b087f42016-02-18 08:48:03 -0800235 return true;
236 }
237
brianosmanafbf71d2016-07-21 07:15:37 -0700238 SkColorSpace* onGetColorSpace() const override {
239 return fBitmap.colorSpace();
240 }
241
robertphillips64612512016-04-08 12:10:42 -0700242#if SK_SUPPORT_GPU
robertphillipsc91fd342016-04-25 12:32:54 -0700243 sk_sp<GrTexture> onAsTextureRef(GrContext* context) const override {
robertphillips64612512016-04-08 12:10:42 -0700244 if (context) {
robertphillipsc91fd342016-04-25 12:32:54 -0700245 return sk_ref_sp(GrRefCachedBitmapTexture(context,
246 fBitmap,
brianosman982eb7f2016-06-06 13:10:58 -0700247 GrTextureParams::ClampNoFilter(),
248 SkSourceGammaTreatment::kRespect));
robertphillips64612512016-04-08 12:10:42 -0700249 }
robertphillips64612512016-04-08 12:10:42 -0700250
251 return nullptr;
252 }
robertphillipsc91fd342016-04-25 12:32:54 -0700253#endif
robertphillips64612512016-04-08 12:10:42 -0700254
robertphillips37bd7c32016-03-17 14:31:39 -0700255 sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const override {
robertphillips3e302272016-04-20 11:48:36 -0700256 return SkSpecialSurface::MakeRaster(info, nullptr);
robertphillipsb6c65e92016-02-04 10:52:42 -0800257 }
258
robertphillips37bd7c32016-03-17 14:31:39 -0700259 sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
robertphillipsc5035e72016-03-17 06:58:39 -0700260 SkBitmap subsetBM;
halcanary9d524f22016-03-29 09:03:52 -0700261
robertphillipsc5035e72016-03-17 06:58:39 -0700262 if (!fBitmap.extractSubset(&subsetBM, subset)) {
263 return nullptr;
264 }
265
robertphillips3e302272016-04-20 11:48:36 -0700266 return SkSpecialImage::MakeFromRaster(SkIRect::MakeWH(subset.width(), subset.height()),
brianosman898235c2016-04-06 07:38:23 -0700267 subsetBM,
268 &this->props());
robertphillipsc5035e72016-03-17 06:58:39 -0700269 }
270
robertphillipsb4bd11e2016-03-21 13:44:18 -0700271 sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const override {
272 SkBitmap subsetBM;
273
274 if (!fBitmap.extractSubset(&subsetBM, subset)) {
275 return nullptr;
276 }
277
278 return SkImage::MakeFromBitmap(subsetBM);
279 }
280
reede8f30622016-03-23 18:59:25 -0700281 sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const override {
282 return SkSurface::MakeRaster(info);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700283 }
284
robertphillipsb6c65e92016-02-04 10:52:42 -0800285private:
286 SkBitmap fBitmap;
287
288 typedef SkSpecialImage_Base INHERITED;
289};
290
robertphillips3e302272016-04-20 11:48:36 -0700291sk_sp<SkSpecialImage> SkSpecialImage::MakeFromRaster(const SkIRect& subset,
brianosman898235c2016-04-06 07:38:23 -0700292 const SkBitmap& bm,
293 const SkSurfaceProps* props) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800294 SkASSERT(rect_fits(subset, bm.width(), bm.height()));
robertphillips37bd7c32016-03-17 14:31:39 -0700295
reedbd2bd5c2016-07-25 14:26:02 -0700296 if (!bm.pixelRef()) {
297 return nullptr;
298 }
299
reeda2217ef2016-07-20 06:04:34 -0700300 const SkBitmap* srcBM = &bm;
301 SkBitmap tmpStorage;
302 // ImageFilters only handle N32 at the moment, so force our src to be that
303 if (!valid_for_imagefilters(bm.info())) {
304 if (!bm.copyTo(&tmpStorage, kN32_SkColorType)) {
305 return nullptr;
306 }
307 srcBM = &tmpStorage;
308 }
309 return sk_make_sp<SkSpecialImage_Raster>(subset, *srcBM, props);
robertphillipsb6c65e92016-02-04 10:52:42 -0800310}
311
312#if SK_SUPPORT_GPU
313///////////////////////////////////////////////////////////////////////////////
robertphillipsed086ca2016-04-26 15:02:25 -0700314#include "GrTexture.h"
robertphillipsb4bd11e2016-03-21 13:44:18 -0700315#include "SkImage_Gpu.h"
robertphillipsb6c65e92016-02-04 10:52:42 -0800316
robertphillipsed086ca2016-04-26 15:02:25 -0700317class SkSpecialImage_Gpu : public SkSpecialImage_Base {
318public:
319 SkSpecialImage_Gpu(const SkIRect& subset,
320 uint32_t uniqueID, sk_sp<GrTexture> tex, SkAlphaType at,
brianosmanafbf71d2016-07-21 07:15:37 -0700321 sk_sp<SkColorSpace> colorSpace, const SkSurfaceProps* props)
robertphillipsed086ca2016-04-26 15:02:25 -0700322 : INHERITED(subset, uniqueID, props)
323 , fTexture(std::move(tex))
324 , fAlphaType(at)
brianosmanafbf71d2016-07-21 07:15:37 -0700325 , fColorSpace(std::move(colorSpace))
robertphillipsed086ca2016-04-26 15:02:25 -0700326 , fAddedRasterVersionToCache(false) {
327 }
328
329 ~SkSpecialImage_Gpu() override {
330 if (fAddedRasterVersionToCache.load()) {
331 SkNotifyBitmapGenIDIsStale(this->uniqueID());
332 }
333 }
334
brianosman80e96082016-08-16 07:09:47 -0700335 SkAlphaType alphaType() const override { return fAlphaType; }
robertphillipsed086ca2016-04-26 15:02:25 -0700336
337 size_t getSize() const override { return fTexture->gpuMemorySize(); }
338
339 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
340 SkRect dst = SkRect::MakeXYWH(x, y,
341 this->subset().width(), this->subset().height());
342
reed77d6f7d2016-07-13 12:24:48 -0700343 auto img = sk_sp<SkImage>(new SkImage_Gpu(fTexture->width(), fTexture->height(),
344 this->uniqueID(), fAlphaType, fTexture.get(),
brianosmanafbf71d2016-07-21 07:15:37 -0700345 fColorSpace, SkBudgeted::kNo));
robertphillipsed086ca2016-04-26 15:02:25 -0700346
reed77d6f7d2016-07-13 12:24:48 -0700347 canvas->drawImageRect(img, this->subset(),
robertphillipsed086ca2016-04-26 15:02:25 -0700348 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
349 }
350
351 GrTexture* onPeekTexture() const override { return fTexture.get(); }
352
353 sk_sp<GrTexture> onAsTextureRef(GrContext*) const override { return fTexture; }
354
355 bool onGetROPixels(SkBitmap* dst) const override {
356 if (SkBitmapCache::Find(this->uniqueID(), dst)) {
357 SkASSERT(dst->getGenerationID() == this->uniqueID());
358 SkASSERT(dst->isImmutable());
359 SkASSERT(dst->getPixels());
360 return true;
361 }
362
363 SkImageInfo info = SkImageInfo::MakeN32(this->width(), this->height(),
brianosman80e96082016-08-16 07:09:47 -0700364 this->alphaType(), fColorSpace);
robertphillipsed086ca2016-04-26 15:02:25 -0700365
366 if (!dst->tryAllocPixels(info)) {
367 return false;
368 }
369
370 if (!fTexture->readPixels(0, 0, dst->width(), dst->height(), kSkia8888_GrPixelConfig,
371 dst->getPixels(), dst->rowBytes())) {
372 return false;
373 }
374
375 dst->pixelRef()->setImmutableWithID(this->uniqueID());
376 SkBitmapCache::Add(this->uniqueID(), *dst);
377 fAddedRasterVersionToCache.store(true);
378 return true;
379 }
380
brianosmanafbf71d2016-07-21 07:15:37 -0700381 SkColorSpace* onGetColorSpace() const override {
382 return fColorSpace.get();
383 }
384
robertphillipsed086ca2016-04-26 15:02:25 -0700385 sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const override {
386 if (!fTexture->getContext()) {
387 return nullptr;
388 }
389
robertphillips4df16562016-04-28 15:09:34 -0700390 GrPixelConfig config = SkImageInfo2GrPixelConfig(info, *fTexture->getContext()->caps());
robertphillipsed086ca2016-04-26 15:02:25 -0700391
robertphillips4df16562016-04-28 15:09:34 -0700392 return SkSpecialSurface::MakeRenderTarget(fTexture->getContext(),
393 info.width(), info.height(),
brianosmandfe4f2e2016-07-21 13:28:36 -0700394 config, sk_ref_sp(info.colorSpace()));
robertphillipsed086ca2016-04-26 15:02:25 -0700395 }
396
397 sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
398 return SkSpecialImage::MakeFromGpu(subset,
399 this->uniqueID(),
400 fTexture,
brianosmanafbf71d2016-07-21 07:15:37 -0700401 fColorSpace,
robertphillipsed086ca2016-04-26 15:02:25 -0700402 &this->props(),
403 fAlphaType);
404 }
405
406 sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const override {
407 if (0 == subset.fLeft && 0 == subset.fTop &&
408 fTexture->width() == subset.width() &&
409 fTexture->height() == subset.height()) {
410 // The existing GrTexture is already tight so reuse it in the SkImage
411 return sk_make_sp<SkImage_Gpu>(fTexture->width(), fTexture->height(),
412 kNeedNewImageUniqueID,
brianosmanafbf71d2016-07-21 07:15:37 -0700413 fAlphaType, fTexture.get(), fColorSpace,
414 SkBudgeted::kYes);
robertphillipsed086ca2016-04-26 15:02:25 -0700415 }
416
417 GrContext* ctx = fTexture->getContext();
418 GrSurfaceDesc desc = fTexture->desc();
419 desc.fWidth = subset.width();
420 desc.fHeight = subset.height();
421
422 sk_sp<GrTexture> subTx(ctx->textureProvider()->createTexture(desc, SkBudgeted::kYes));
423 if (!subTx) {
424 return nullptr;
425 }
426 ctx->copySurface(subTx.get(), fTexture.get(), subset, SkIPoint::Make(0, 0));
427 return sk_make_sp<SkImage_Gpu>(desc.fWidth, desc.fHeight, kNeedNewImageUniqueID,
brianosmanafbf71d2016-07-21 07:15:37 -0700428 fAlphaType, subTx.get(), fColorSpace, SkBudgeted::kYes);
robertphillipsed086ca2016-04-26 15:02:25 -0700429 }
430
431 sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const override {
432 return SkSurface::MakeRenderTarget(fTexture->getContext(), SkBudgeted::kYes, info);
433 }
434
435private:
436 sk_sp<GrTexture> fTexture;
437 const SkAlphaType fAlphaType;
brianosmanafbf71d2016-07-21 07:15:37 -0700438 sk_sp<SkColorSpace> fColorSpace;
robertphillipsed086ca2016-04-26 15:02:25 -0700439 mutable SkAtomic<bool> fAddedRasterVersionToCache;
440
441 typedef SkSpecialImage_Base INHERITED;
442};
443
robertphillips3e302272016-04-20 11:48:36 -0700444sk_sp<SkSpecialImage> SkSpecialImage::MakeFromGpu(const SkIRect& subset,
robertphillips37bd7c32016-03-17 14:31:39 -0700445 uint32_t uniqueID,
robertphillipsc91fd342016-04-25 12:32:54 -0700446 sk_sp<GrTexture> tex,
brianosmanafbf71d2016-07-21 07:15:37 -0700447 sk_sp<SkColorSpace> colorSpace,
brianosman898235c2016-04-06 07:38:23 -0700448 const SkSurfaceProps* props,
robertphillips37bd7c32016-03-17 14:31:39 -0700449 SkAlphaType at) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800450 SkASSERT(rect_fits(subset, tex->width(), tex->height()));
brianosmanafbf71d2016-07-21 07:15:37 -0700451 return sk_make_sp<SkSpecialImage_Gpu>(subset, uniqueID, std::move(tex), at,
452 std::move(colorSpace), props);
robertphillipsb6c65e92016-02-04 10:52:42 -0800453}
454
455#endif