blob: 19194bd4054d989f4b77b75fef092ec9a731ecf4 [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
robertphillipsc91fd342016-04-25 12:32:54 -070048#if SK_SUPPORT_GPU
49 virtual sk_sp<GrTexture> onAsTextureRef(GrContext* context) const = 0;
50#endif
robertphillips4418dba2016-03-07 12:45:14 -080051
robertphillips3b087f42016-02-18 08:48:03 -080052 // Delete this entry point ASAP (see skbug.com/4965)
robertphillipsab01ccd2016-03-08 10:45:32 -080053 virtual bool getBitmapDeprecated(SkBitmap* result) const = 0;
robertphillips3b087f42016-02-18 08:48:03 -080054
robertphillipsb4bd11e2016-03-21 13:44:18 -070055 virtual sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const = 0;
56
robertphillips37bd7c32016-03-17 14:31:39 -070057 virtual sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const = 0;
robertphillipsc5035e72016-03-17 06:58:39 -070058
robertphillipsb4bd11e2016-03-21 13:44:18 -070059 virtual sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const = 0;
60
reede8f30622016-03-23 18:59:25 -070061 virtual sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const = 0;
robertphillipsb6c65e92016-02-04 10:52:42 -080062
63private:
64 typedef SkSpecialImage INHERITED;
65};
66
67///////////////////////////////////////////////////////////////////////////////
bsalomon84a4e5a2016-02-29 11:41:52 -080068static inline const SkSpecialImage_Base* as_SIB(const SkSpecialImage* image) {
robertphillipsb6c65e92016-02-04 10:52:42 -080069 return static_cast<const SkSpecialImage_Base*>(image);
70}
71
robertphillips3e302272016-04-20 11:48:36 -070072SkSpecialImage::SkSpecialImage(const SkIRect& subset,
brianosman898235c2016-04-06 07:38:23 -070073 uint32_t uniqueID,
74 const SkSurfaceProps* props)
75 : fProps(SkSurfacePropsCopyOrDefault(props))
76 , fSubset(subset)
robertphillips3e302272016-04-20 11:48:36 -070077 , fUniqueID(kNeedNewImageUniqueID_SpecialImage == uniqueID ? SkNextID::ImageID() : uniqueID) {
brianosman898235c2016-04-06 07:38:23 -070078}
79
robertphillips3e302272016-04-20 11:48:36 -070080sk_sp<SkSpecialImage> SkSpecialImage::makeTextureImage(GrContext* context) {
robertphillips83c17fa2016-03-18 08:14:27 -070081#if SK_SUPPORT_GPU
82 if (!context) {
83 return nullptr;
84 }
robertphillips64612512016-04-08 12:10:42 -070085 if (GrTexture* peek = as_SIB(this)->onPeekTexture()) {
robertphillips83c17fa2016-03-18 08:14:27 -070086 return peek->getContext() == context ? sk_sp<SkSpecialImage>(SkRef(this)) : nullptr;
87 }
88
89 SkBitmap bmp;
reedcf5c8462016-07-20 12:28:40 -070090 // At this point, we are definitely not texture-backed, so we must be raster or generator
91 // backed. If we remove the special-wrapping-an-image subclass, we may be able to assert that
92 // we are strictly raster-backed (i.e. generator images become raster when they are specialized)
93 // in which case getROPixels could turn into peekPixels...
94 if (!this->getROPixels(&bmp)) {
robertphillips83c17fa2016-03-18 08:14:27 -070095 return nullptr;
96 }
97
robertphillips83f2e5a2016-03-24 06:31:25 -070098 if (bmp.empty()) {
robertphillips3e302272016-04-20 11:48:36 -070099 return SkSpecialImage::MakeFromRaster(SkIRect::MakeEmpty(), bmp, &this->props());
robertphillips83f2e5a2016-03-24 06:31:25 -0700100 }
101
robertphillipsc91fd342016-04-25 12:32:54 -0700102 sk_sp<GrTexture> resultTex(GrRefCachedBitmapTexture(context,
103 bmp,
brianosman982eb7f2016-06-06 13:10:58 -0700104 GrTextureParams::ClampNoFilter(),
105 SkSourceGammaTreatment::kRespect));
robertphillips83c17fa2016-03-18 08:14:27 -0700106 if (!resultTex) {
107 return nullptr;
108 }
109
110 SkAlphaType at = this->isOpaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
111
robertphillips3e302272016-04-20 11:48:36 -0700112 return SkSpecialImage::MakeFromGpu(SkIRect::MakeWH(resultTex->width(), resultTex->height()),
robertphillips83c17fa2016-03-18 08:14:27 -0700113 this->uniqueID(),
brianosman898235c2016-04-06 07:38:23 -0700114 resultTex, &this->props(), at);
robertphillips83c17fa2016-03-18 08:14:27 -0700115#else
116 return nullptr;
117#endif
118}
119
robertphillipse8c34972016-02-16 12:09:36 -0800120void SkSpecialImage::draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const {
bsalomon84a4e5a2016-02-29 11:41:52 -0800121 return as_SIB(this)->onDraw(canvas, x, y, paint);
robertphillipsb6c65e92016-02-04 10:52:42 -0800122}
123
robertphillips64612512016-04-08 12:10:42 -0700124bool SkSpecialImage::getROPixels(SkBitmap* bm) const {
125 return as_SIB(this)->onGetROPixels(bm);
robertphillipsb6c65e92016-02-04 10:52:42 -0800126}
127
robertphillips64612512016-04-08 12:10:42 -0700128bool SkSpecialImage::isTextureBacked() const {
129#if SK_SUPPORT_GPU
130 return as_SIB(this)->onPeekTexture() && as_SIB(this)->onPeekTexture()->getContext();
131#else
132 return false;
133#endif
robertphillipsb6c65e92016-02-04 10:52:42 -0800134}
135
robertphillips64612512016-04-08 12:10:42 -0700136GrContext* SkSpecialImage::getContext() const {
137#if SK_SUPPORT_GPU
138 GrTexture* texture = as_SIB(this)->onPeekTexture();
139
140 if (texture) {
141 return texture->getContext();
142 }
143#endif
144 return nullptr;
145}
146
robertphillipsc91fd342016-04-25 12:32:54 -0700147#if SK_SUPPORT_GPU
148sk_sp<GrTexture> SkSpecialImage::asTextureRef(GrContext* context) const {
robertphillips64612512016-04-08 12:10:42 -0700149 return as_SIB(this)->onAsTextureRef(context);
robertphillips4418dba2016-03-07 12:45:14 -0800150}
robertphillipsc91fd342016-04-25 12:32:54 -0700151#endif
robertphillips4418dba2016-03-07 12:45:14 -0800152
robertphillips37bd7c32016-03-17 14:31:39 -0700153sk_sp<SkSpecialSurface> SkSpecialImage::makeSurface(const SkImageInfo& info) const {
154 return as_SIB(this)->onMakeSurface(info);
robertphillipsb6c65e92016-02-04 10:52:42 -0800155}
156
robertphillipsb4bd11e2016-03-21 13:44:18 -0700157sk_sp<SkSurface> SkSpecialImage::makeTightSurface(const SkImageInfo& info) const {
reede8f30622016-03-23 18:59:25 -0700158 return as_SIB(this)->onMakeTightSurface(info);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700159}
160
robertphillips37bd7c32016-03-17 14:31:39 -0700161sk_sp<SkSpecialImage> SkSpecialImage::makeSubset(const SkIRect& subset) const {
162 return as_SIB(this)->onMakeSubset(subset);
robertphillipsc5035e72016-03-17 06:58:39 -0700163}
164
robertphillipsb4bd11e2016-03-21 13:44:18 -0700165sk_sp<SkImage> SkSpecialImage::makeTightSubset(const SkIRect& subset) const {
166 return as_SIB(this)->onMakeTightSubset(subset);
167}
168
robertphillipsb6c65e92016-02-04 10:52:42 -0800169#ifdef SK_DEBUG
170static bool rect_fits(const SkIRect& rect, int width, int height) {
robertphillips4418dba2016-03-07 12:45:14 -0800171 if (0 == width && 0 == height) {
172 SkASSERT(0 == rect.fLeft && 0 == rect.fRight && 0 == rect.fTop && 0 == rect.fBottom);
173 return true;
174 }
175
robertphillipsb6c65e92016-02-04 10:52:42 -0800176 return rect.fLeft >= 0 && rect.fLeft < width && rect.fLeft < rect.fRight &&
177 rect.fRight >= 0 && rect.fRight <= width &&
178 rect.fTop >= 0 && rect.fTop < height && rect.fTop < rect.fBottom &&
179 rect.fBottom >= 0 && rect.fBottom <= height;
180}
181#endif
182
robertphillips3e302272016-04-20 11:48:36 -0700183sk_sp<SkSpecialImage> SkSpecialImage::MakeFromImage(const SkIRect& subset,
brianosman898235c2016-04-06 07:38:23 -0700184 sk_sp<SkImage> image,
185 const SkSurfaceProps* props) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800186 SkASSERT(rect_fits(subset, image->width(), image->height()));
robertphillips37bd7c32016-03-17 14:31:39 -0700187
reedad7604b2016-07-20 16:13:32 -0700188#if SK_SUPPORT_GPU
189 if (GrTexture* texture = as_IB(image)->peekTexture()) {
190 return MakeFromGpu(subset, image->uniqueID(), sk_ref_sp(texture), props);
191 } else
192#endif
193 {
194 SkBitmap bm;
195 if (as_IB(image)->getROPixels(&bm)) {
196 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)
robertphillipsb6c65e92016-02-04 10:52:42 -0800208 , fBitmap(bm) {
robertphillips4418dba2016-03-07 12:45:14 -0800209 if (bm.pixelRef() && bm.pixelRef()->isPreLocked()) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800210 // we only preemptively lock if there is no chance of triggering something expensive
211 // like a lazy decode or imagegenerator. PreLocked means it is flat pixels already.
212 fBitmap.lockPixels();
213 }
214 }
215
robertphillips3b087f42016-02-18 08:48:03 -0800216 bool isOpaque() const override { return fBitmap.isOpaque(); }
217
218 size_t getSize() const override { return fBitmap.getSize(); }
219
robertphillipse8c34972016-02-16 12:09:36 -0800220 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800221 SkRect dst = SkRect::MakeXYWH(x, y,
222 this->subset().width(), this->subset().height());
223
224 canvas->drawBitmapRect(fBitmap, this->subset(),
225 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
226 }
227
robertphillips64612512016-04-08 12:10:42 -0700228 bool onGetROPixels(SkBitmap* bm) const override {
229 *bm = fBitmap;
robertphillips3b087f42016-02-18 08:48:03 -0800230 return true;
231 }
232
robertphillips64612512016-04-08 12:10:42 -0700233#if SK_SUPPORT_GPU
robertphillipsc91fd342016-04-25 12:32:54 -0700234 sk_sp<GrTexture> onAsTextureRef(GrContext* context) const override {
robertphillips64612512016-04-08 12:10:42 -0700235 if (context) {
robertphillipsc91fd342016-04-25 12:32:54 -0700236 return sk_ref_sp(GrRefCachedBitmapTexture(context,
237 fBitmap,
brianosman982eb7f2016-06-06 13:10:58 -0700238 GrTextureParams::ClampNoFilter(),
239 SkSourceGammaTreatment::kRespect));
robertphillips64612512016-04-08 12:10:42 -0700240 }
robertphillips64612512016-04-08 12:10:42 -0700241
242 return nullptr;
243 }
robertphillipsc91fd342016-04-25 12:32:54 -0700244#endif
robertphillips64612512016-04-08 12:10:42 -0700245
246 bool getBitmapDeprecated(SkBitmap* result) const override {
robertphillips4418dba2016-03-07 12:45:14 -0800247 *result = fBitmap;
248 return true;
249 }
250
robertphillips37bd7c32016-03-17 14:31:39 -0700251 sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const override {
robertphillips3e302272016-04-20 11:48:36 -0700252 return SkSpecialSurface::MakeRaster(info, nullptr);
robertphillipsb6c65e92016-02-04 10:52:42 -0800253 }
254
robertphillips37bd7c32016-03-17 14:31:39 -0700255 sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
robertphillipsc5035e72016-03-17 06:58:39 -0700256 SkBitmap subsetBM;
halcanary9d524f22016-03-29 09:03:52 -0700257
robertphillipsc5035e72016-03-17 06:58:39 -0700258 if (!fBitmap.extractSubset(&subsetBM, subset)) {
259 return nullptr;
260 }
261
robertphillips3e302272016-04-20 11:48:36 -0700262 return SkSpecialImage::MakeFromRaster(SkIRect::MakeWH(subset.width(), subset.height()),
brianosman898235c2016-04-06 07:38:23 -0700263 subsetBM,
264 &this->props());
robertphillipsc5035e72016-03-17 06:58:39 -0700265 }
266
robertphillipsb4bd11e2016-03-21 13:44:18 -0700267 sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const override {
268 SkBitmap subsetBM;
269
270 if (!fBitmap.extractSubset(&subsetBM, subset)) {
271 return nullptr;
272 }
273
274 return SkImage::MakeFromBitmap(subsetBM);
275 }
276
reede8f30622016-03-23 18:59:25 -0700277 sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const override {
278 return SkSurface::MakeRaster(info);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700279 }
280
robertphillipsb6c65e92016-02-04 10:52:42 -0800281private:
282 SkBitmap fBitmap;
283
284 typedef SkSpecialImage_Base INHERITED;
285};
286
robertphillips3e302272016-04-20 11:48:36 -0700287sk_sp<SkSpecialImage> SkSpecialImage::MakeFromRaster(const SkIRect& subset,
brianosman898235c2016-04-06 07:38:23 -0700288 const SkBitmap& bm,
289 const SkSurfaceProps* props) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800290 SkASSERT(nullptr == bm.getTexture());
291 SkASSERT(rect_fits(subset, bm.width(), bm.height()));
robertphillips37bd7c32016-03-17 14:31:39 -0700292
reeda2217ef2016-07-20 06:04:34 -0700293 const SkBitmap* srcBM = &bm;
294 SkBitmap tmpStorage;
295 // ImageFilters only handle N32 at the moment, so force our src to be that
296 if (!valid_for_imagefilters(bm.info())) {
297 if (!bm.copyTo(&tmpStorage, kN32_SkColorType)) {
298 return nullptr;
299 }
300 srcBM = &tmpStorage;
301 }
302 return sk_make_sp<SkSpecialImage_Raster>(subset, *srcBM, props);
robertphillipsb6c65e92016-02-04 10:52:42 -0800303}
304
305#if SK_SUPPORT_GPU
306///////////////////////////////////////////////////////////////////////////////
robertphillipsed086ca2016-04-26 15:02:25 -0700307#include "GrTexture.h"
robertphillipsb4bd11e2016-03-21 13:44:18 -0700308#include "SkImage_Gpu.h"
robertphillipsb6c65e92016-02-04 10:52:42 -0800309
robertphillipsed086ca2016-04-26 15:02:25 -0700310class SkSpecialImage_Gpu : public SkSpecialImage_Base {
311public:
312 SkSpecialImage_Gpu(const SkIRect& subset,
313 uint32_t uniqueID, sk_sp<GrTexture> tex, SkAlphaType at,
314 const SkSurfaceProps* props)
315 : INHERITED(subset, uniqueID, props)
316 , fTexture(std::move(tex))
317 , fAlphaType(at)
318 , fAddedRasterVersionToCache(false) {
319 }
320
321 ~SkSpecialImage_Gpu() override {
322 if (fAddedRasterVersionToCache.load()) {
323 SkNotifyBitmapGenIDIsStale(this->uniqueID());
324 }
325 }
326
327 bool isOpaque() const override {
328 return GrPixelConfigIsOpaque(fTexture->config()) || fAlphaType == kOpaque_SkAlphaType;
329 }
330
331 size_t getSize() const override { return fTexture->gpuMemorySize(); }
332
333 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
334 SkRect dst = SkRect::MakeXYWH(x, y,
335 this->subset().width(), this->subset().height());
336
brianosmandddbe382016-07-20 13:55:39 -0700337 // TODO: Supply correct color space after we're storing it here
reed77d6f7d2016-07-13 12:24:48 -0700338 auto img = sk_sp<SkImage>(new SkImage_Gpu(fTexture->width(), fTexture->height(),
339 this->uniqueID(), fAlphaType, fTexture.get(),
brianosmandddbe382016-07-20 13:55:39 -0700340 nullptr, SkBudgeted::kNo));
robertphillipsed086ca2016-04-26 15:02:25 -0700341
reed77d6f7d2016-07-13 12:24:48 -0700342 canvas->drawImageRect(img, this->subset(),
robertphillipsed086ca2016-04-26 15:02:25 -0700343 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
344 }
345
346 GrTexture* onPeekTexture() const override { return fTexture.get(); }
347
348 sk_sp<GrTexture> onAsTextureRef(GrContext*) const override { return fTexture; }
349
350 bool onGetROPixels(SkBitmap* dst) const override {
351 if (SkBitmapCache::Find(this->uniqueID(), dst)) {
352 SkASSERT(dst->getGenerationID() == this->uniqueID());
353 SkASSERT(dst->isImmutable());
354 SkASSERT(dst->getPixels());
355 return true;
356 }
357
358 SkImageInfo info = SkImageInfo::MakeN32(this->width(), this->height(),
359 this->isOpaque() ? kOpaque_SkAlphaType
360 : kPremul_SkAlphaType);
361
362 if (!dst->tryAllocPixels(info)) {
363 return false;
364 }
365
366 if (!fTexture->readPixels(0, 0, dst->width(), dst->height(), kSkia8888_GrPixelConfig,
367 dst->getPixels(), dst->rowBytes())) {
368 return false;
369 }
370
371 dst->pixelRef()->setImmutableWithID(this->uniqueID());
372 SkBitmapCache::Add(this->uniqueID(), *dst);
373 fAddedRasterVersionToCache.store(true);
374 return true;
375 }
376
377 bool getBitmapDeprecated(SkBitmap* result) const override {
378 const SkImageInfo info = GrMakeInfoFromTexture(fTexture.get(),
379 this->width(), this->height(),
380 this->isOpaque());
381 if (!result->setInfo(info)) {
382 return false;
383 }
384
385 const SkImageInfo prInfo = info.makeWH(fTexture->width(), fTexture->height());
386
387 SkAutoTUnref<SkGrPixelRef> pixelRef(new SkGrPixelRef(prInfo, fTexture.get()));
388 result->setPixelRef(pixelRef, this->subset().fLeft, this->subset().fTop);
389 return true;
390 }
391
392 sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const override {
393 if (!fTexture->getContext()) {
394 return nullptr;
395 }
396
robertphillips4df16562016-04-28 15:09:34 -0700397 GrPixelConfig config = SkImageInfo2GrPixelConfig(info, *fTexture->getContext()->caps());
robertphillipsed086ca2016-04-26 15:02:25 -0700398
robertphillips4df16562016-04-28 15:09:34 -0700399 return SkSpecialSurface::MakeRenderTarget(fTexture->getContext(),
400 info.width(), info.height(),
401 config);
robertphillipsed086ca2016-04-26 15:02:25 -0700402 }
403
404 sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
405 return SkSpecialImage::MakeFromGpu(subset,
406 this->uniqueID(),
407 fTexture,
408 &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
brianosmandddbe382016-07-20 13:55:39 -0700417 // TODO: Supply correct color space after we're storing it here
robertphillipsed086ca2016-04-26 15:02:25 -0700418 return sk_make_sp<SkImage_Gpu>(fTexture->width(), fTexture->height(),
419 kNeedNewImageUniqueID,
brianosmandddbe382016-07-20 13:55:39 -0700420 fAlphaType, fTexture.get(), nullptr, 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));
brianosmandddbe382016-07-20 13:55:39 -0700433 // TODO: Supply correct color space after we're storing it here
robertphillipsed086ca2016-04-26 15:02:25 -0700434 return sk_make_sp<SkImage_Gpu>(desc.fWidth, desc.fHeight, kNeedNewImageUniqueID,
brianosmandddbe382016-07-20 13:55:39 -0700435 fAlphaType, subTx.get(), nullptr, SkBudgeted::kYes);
robertphillipsed086ca2016-04-26 15:02:25 -0700436 }
437
438 sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const override {
439 return SkSurface::MakeRenderTarget(fTexture->getContext(), SkBudgeted::kYes, info);
440 }
441
442private:
443 sk_sp<GrTexture> fTexture;
444 const SkAlphaType fAlphaType;
445 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,
brianosman898235c2016-04-06 07:38:23 -0700453 const SkSurfaceProps* props,
robertphillips37bd7c32016-03-17 14:31:39 -0700454 SkAlphaType at) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800455 SkASSERT(rect_fits(subset, tex->width(), tex->height()));
robertphillipsed086ca2016-04-26 15:02:25 -0700456 return sk_make_sp<SkSpecialImage_Gpu>(subset, uniqueID, std::move(tex), at, props);
robertphillipsb6c65e92016-02-04 10:52:42 -0800457}
458
459#endif