blob: bbc7635b66bbd96156270ee8a5c1ad4dcbfa4fa4 [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 */
robertphillips83c17fa2016-03-18 08:14:27 -07007#include "SkSpecialImage.h"
8
9#if SK_SUPPORT_GPU
10#include "GrTexture.h"
11#include "GrTextureParams.h"
12#include "SkGr.h"
13#endif
robertphillipsb6c65e92016-02-04 10:52:42 -080014
robertphillips64612512016-04-08 12:10:42 -070015#include "SkBitmapCache.h"
robertphillipsb6c65e92016-02-04 10:52:42 -080016#include "SkCanvas.h"
bsalomon84a4e5a2016-02-29 11:41:52 -080017#include "SkImage_Base.h"
robertphillipsb6c65e92016-02-04 10:52:42 -080018#include "SkSpecialSurface.h"
brianosman898235c2016-04-06 07:38:23 -070019#include "SkSurfacePriv.h"
robertphillipsb6c65e92016-02-04 10:52:42 -080020
21///////////////////////////////////////////////////////////////////////////////
22class SkSpecialImage_Base : public SkSpecialImage {
23public:
robertphillips3e302272016-04-20 11:48:36 -070024 SkSpecialImage_Base(const SkIRect& subset, uint32_t uniqueID, const SkSurfaceProps* props)
25 : INHERITED(subset, uniqueID, props) {
robertphillips3b087f42016-02-18 08:48:03 -080026 }
robertphillips3e302272016-04-20 11:48:36 -070027 ~SkSpecialImage_Base() override { }
robertphillipsb6c65e92016-02-04 10:52:42 -080028
robertphillipse8c34972016-02-16 12:09:36 -080029 virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) const = 0;
robertphillipsb6c65e92016-02-04 10:52:42 -080030
robertphillips64612512016-04-08 12:10:42 -070031 virtual bool onGetROPixels(SkBitmap*) const = 0;
robertphillipsb6c65e92016-02-04 10:52:42 -080032
33 virtual GrTexture* onPeekTexture() const { return nullptr; }
34
robertphillips64612512016-04-08 12:10:42 -070035 virtual GrTexture* onAsTextureRef(GrContext* context) const = 0;
robertphillips4418dba2016-03-07 12:45:14 -080036
robertphillips3b087f42016-02-18 08:48:03 -080037 // Delete this entry point ASAP (see skbug.com/4965)
robertphillipsab01ccd2016-03-08 10:45:32 -080038 virtual bool getBitmapDeprecated(SkBitmap* result) const = 0;
robertphillips3b087f42016-02-18 08:48:03 -080039
robertphillipsb4bd11e2016-03-21 13:44:18 -070040 virtual sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const = 0;
41
robertphillips37bd7c32016-03-17 14:31:39 -070042 virtual sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const = 0;
robertphillipsc5035e72016-03-17 06:58:39 -070043
robertphillipsb4bd11e2016-03-21 13:44:18 -070044 virtual sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const = 0;
45
reede8f30622016-03-23 18:59:25 -070046 virtual sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const = 0;
robertphillipsb6c65e92016-02-04 10:52:42 -080047
48private:
49 typedef SkSpecialImage INHERITED;
50};
51
52///////////////////////////////////////////////////////////////////////////////
bsalomon84a4e5a2016-02-29 11:41:52 -080053static inline const SkSpecialImage_Base* as_SIB(const SkSpecialImage* image) {
robertphillipsb6c65e92016-02-04 10:52:42 -080054 return static_cast<const SkSpecialImage_Base*>(image);
55}
56
robertphillips3e302272016-04-20 11:48:36 -070057SkSpecialImage::SkSpecialImage(const SkIRect& subset,
brianosman898235c2016-04-06 07:38:23 -070058 uint32_t uniqueID,
59 const SkSurfaceProps* props)
60 : fProps(SkSurfacePropsCopyOrDefault(props))
61 , fSubset(subset)
robertphillips3e302272016-04-20 11:48:36 -070062 , fUniqueID(kNeedNewImageUniqueID_SpecialImage == uniqueID ? SkNextID::ImageID() : uniqueID) {
brianosman898235c2016-04-06 07:38:23 -070063}
64
robertphillips3e302272016-04-20 11:48:36 -070065sk_sp<SkSpecialImage> SkSpecialImage::makeTextureImage(GrContext* context) {
robertphillips83c17fa2016-03-18 08:14:27 -070066#if SK_SUPPORT_GPU
67 if (!context) {
68 return nullptr;
69 }
robertphillips64612512016-04-08 12:10:42 -070070 if (GrTexture* peek = as_SIB(this)->onPeekTexture()) {
robertphillips83c17fa2016-03-18 08:14:27 -070071 return peek->getContext() == context ? sk_sp<SkSpecialImage>(SkRef(this)) : nullptr;
72 }
73
74 SkBitmap bmp;
75 if (!this->internal_getBM(&bmp)) {
76 return nullptr;
77 }
78
robertphillips83f2e5a2016-03-24 06:31:25 -070079 if (bmp.empty()) {
robertphillips3e302272016-04-20 11:48:36 -070080 return SkSpecialImage::MakeFromRaster(SkIRect::MakeEmpty(), bmp, &this->props());
robertphillips83f2e5a2016-03-24 06:31:25 -070081 }
82
robertphillips83c17fa2016-03-18 08:14:27 -070083 SkAutoTUnref<GrTexture> resultTex(
84 GrRefCachedBitmapTexture(context, bmp, GrTextureParams::ClampNoFilter()));
85 if (!resultTex) {
86 return nullptr;
87 }
88
89 SkAlphaType at = this->isOpaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
90
robertphillips3e302272016-04-20 11:48:36 -070091 return SkSpecialImage::MakeFromGpu(SkIRect::MakeWH(resultTex->width(), resultTex->height()),
robertphillips83c17fa2016-03-18 08:14:27 -070092 this->uniqueID(),
brianosman898235c2016-04-06 07:38:23 -070093 resultTex, &this->props(), at);
robertphillips83c17fa2016-03-18 08:14:27 -070094#else
95 return nullptr;
96#endif
97}
98
robertphillipse8c34972016-02-16 12:09:36 -080099void SkSpecialImage::draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const {
bsalomon84a4e5a2016-02-29 11:41:52 -0800100 return as_SIB(this)->onDraw(canvas, x, y, paint);
robertphillipsb6c65e92016-02-04 10:52:42 -0800101}
102
robertphillips64612512016-04-08 12:10:42 -0700103bool SkSpecialImage::getROPixels(SkBitmap* bm) const {
104 return as_SIB(this)->onGetROPixels(bm);
robertphillipsb6c65e92016-02-04 10:52:42 -0800105}
106
robertphillips64612512016-04-08 12:10:42 -0700107bool SkSpecialImage::isTextureBacked() const {
108#if SK_SUPPORT_GPU
109 return as_SIB(this)->onPeekTexture() && as_SIB(this)->onPeekTexture()->getContext();
110#else
111 return false;
112#endif
robertphillipsb6c65e92016-02-04 10:52:42 -0800113}
114
robertphillips64612512016-04-08 12:10:42 -0700115GrContext* SkSpecialImage::getContext() const {
116#if SK_SUPPORT_GPU
117 GrTexture* texture = as_SIB(this)->onPeekTexture();
118
119 if (texture) {
120 return texture->getContext();
121 }
122#endif
123 return nullptr;
124}
125
126
127GrTexture* SkSpecialImage::asTextureRef(GrContext* context) const {
128 return as_SIB(this)->onAsTextureRef(context);
robertphillips4418dba2016-03-07 12:45:14 -0800129}
130
robertphillips37bd7c32016-03-17 14:31:39 -0700131sk_sp<SkSpecialSurface> SkSpecialImage::makeSurface(const SkImageInfo& info) const {
132 return as_SIB(this)->onMakeSurface(info);
robertphillipsb6c65e92016-02-04 10:52:42 -0800133}
134
robertphillipsb4bd11e2016-03-21 13:44:18 -0700135sk_sp<SkSurface> SkSpecialImage::makeTightSurface(const SkImageInfo& info) const {
reede8f30622016-03-23 18:59:25 -0700136 return as_SIB(this)->onMakeTightSurface(info);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700137}
138
robertphillips37bd7c32016-03-17 14:31:39 -0700139sk_sp<SkSpecialImage> SkSpecialImage::makeSubset(const SkIRect& subset) const {
140 return as_SIB(this)->onMakeSubset(subset);
robertphillipsc5035e72016-03-17 06:58:39 -0700141}
142
robertphillipsb4bd11e2016-03-21 13:44:18 -0700143sk_sp<SkImage> SkSpecialImage::makeTightSubset(const SkIRect& subset) const {
144 return as_SIB(this)->onMakeTightSubset(subset);
145}
146
robertphillips3b087f42016-02-18 08:48:03 -0800147#if SK_SUPPORT_GPU
148#include "SkGr.h"
149#include "SkGrPixelRef.h"
150#endif
151
robertphillips3e302272016-04-20 11:48:36 -0700152sk_sp<SkSpecialImage> SkSpecialImage::internal_fromBM(const SkBitmap& src,
brianosman898235c2016-04-06 07:38:23 -0700153 const SkSurfaceProps* props) {
robertphillips3b087f42016-02-18 08:48:03 -0800154 // Need to test offset case! (see skbug.com/4967)
155 if (src.getTexture()) {
robertphillips3e302272016-04-20 11:48:36 -0700156 return SkSpecialImage::MakeFromGpu(src.bounds(),
robertphillips37bd7c32016-03-17 14:31:39 -0700157 src.getGenerationID(),
brianosman898235c2016-04-06 07:38:23 -0700158 src.getTexture(),
159 props);
robertphillips3b087f42016-02-18 08:48:03 -0800160 }
161
robertphillips3e302272016-04-20 11:48:36 -0700162 return SkSpecialImage::MakeFromRaster(src.bounds(), src, props);
robertphillips3b087f42016-02-18 08:48:03 -0800163}
164
165bool SkSpecialImage::internal_getBM(SkBitmap* result) {
bsalomon84a4e5a2016-02-29 11:41:52 -0800166 const SkSpecialImage_Base* ib = as_SIB(this);
robertphillips3b087f42016-02-18 08:48:03 -0800167
168 // TODO: need to test offset case! (see skbug.com/4967)
robertphillipsab01ccd2016-03-08 10:45:32 -0800169 return ib->getBitmapDeprecated(result);
robertphillips3b087f42016-02-18 08:48:03 -0800170}
171
robertphillipsb6c65e92016-02-04 10:52:42 -0800172///////////////////////////////////////////////////////////////////////////////
173#include "SkImage.h"
174#if SK_SUPPORT_GPU
brianosmana6359362016-03-21 06:55:37 -0700175#include "GrContext.h"
robertphillipsb6c65e92016-02-04 10:52:42 -0800176#include "SkGrPriv.h"
177#endif
178
179class SkSpecialImage_Image : public SkSpecialImage_Base {
180public:
robertphillips3e302272016-04-20 11:48:36 -0700181 SkSpecialImage_Image(const SkIRect& subset,
brianosman898235c2016-04-06 07:38:23 -0700182 sk_sp<SkImage> image,
183 const SkSurfaceProps* props)
robertphillips3e302272016-04-20 11:48:36 -0700184 : INHERITED(subset, image->uniqueID(), props)
robertphillips37bd7c32016-03-17 14:31:39 -0700185 , fImage(image) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800186 }
187
188 ~SkSpecialImage_Image() override { }
halcanary9d524f22016-03-29 09:03:52 -0700189
robertphillips3b087f42016-02-18 08:48:03 -0800190 bool isOpaque() const override { return fImage->isOpaque(); }
191
192 size_t getSize() const override {
193#if SK_SUPPORT_GPU
bsalomon84a4e5a2016-02-29 11:41:52 -0800194 if (GrTexture* texture = as_IB(fImage.get())->peekTexture()) {
195 return texture->gpuMemorySize();
robertphillips3b087f42016-02-18 08:48:03 -0800196 } else
197#endif
198 {
reed6ceeebd2016-03-09 14:26:26 -0800199 SkPixmap pm;
200 if (fImage->peekPixels(&pm)) {
201 return pm.height() * pm.rowBytes();
robertphillips3b087f42016-02-18 08:48:03 -0800202 }
203 }
204 return 0;
205 }
206
robertphillipse8c34972016-02-16 12:09:36 -0800207 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800208 SkRect dst = SkRect::MakeXYWH(x, y, this->subset().width(), this->subset().height());
209
robertphillips37bd7c32016-03-17 14:31:39 -0700210 canvas->drawImageRect(fImage.get(), this->subset(),
robertphillipsb6c65e92016-02-04 10:52:42 -0800211 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
212 }
213
robertphillips64612512016-04-08 12:10:42 -0700214 bool onGetROPixels(SkBitmap* bm) const override {
215 return as_IB(fImage)->getROPixels(bm);
robertphillipsb6c65e92016-02-04 10:52:42 -0800216 }
217
robertphillips64612512016-04-08 12:10:42 -0700218 GrTexture* onPeekTexture() const override { return as_IB(fImage)->peekTexture(); }
219
220 GrTexture* onAsTextureRef(GrContext* context) const override {
221#if SK_SUPPORT_GPU
222 return as_IB(fImage)->asTextureRef(context, GrTextureParams::ClampNoFilter());
223#else
224 return nullptr;
225#endif
226 }
robertphillipsb6c65e92016-02-04 10:52:42 -0800227
robertphillipsab01ccd2016-03-08 10:45:32 -0800228 bool getBitmapDeprecated(SkBitmap* result) const override {
robertphillips6ac97b72016-03-09 05:17:10 -0800229#if SK_SUPPORT_GPU
230 if (GrTexture* texture = as_IB(fImage.get())->peekTexture()) {
halcanary9d524f22016-03-29 09:03:52 -0700231 const SkImageInfo info = GrMakeInfoFromTexture(texture,
robertphillips6ac97b72016-03-09 05:17:10 -0800232 fImage->width(), fImage->height(),
233 fImage->isOpaque());
234 if (!result->setInfo(info)) {
235 return false;
236 }
237
238 result->setPixelRef(new SkGrPixelRef(info, texture))->unref();
239 return true;
240 }
241#endif
242
243 return as_IB(fImage.get())->asBitmapForImageFilters(result);
robertphillips3b087f42016-02-18 08:48:03 -0800244 }
245
robertphillips37bd7c32016-03-17 14:31:39 -0700246 sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800247#if SK_SUPPORT_GPU
bsalomon84a4e5a2016-02-29 11:41:52 -0800248 GrTexture* texture = as_IB(fImage.get())->peekTexture();
robertphillipsb6c65e92016-02-04 10:52:42 -0800249 if (texture) {
brianosmana6359362016-03-21 06:55:37 -0700250 GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(info, *texture->getContext()->caps());
robertphillipsb6c65e92016-02-04 10:52:42 -0800251 desc.fFlags = kRenderTarget_GrSurfaceFlag;
252
robertphillips3e302272016-04-20 11:48:36 -0700253 return SkSpecialSurface::MakeRenderTarget(texture->getContext(), desc);
robertphillipsb6c65e92016-02-04 10:52:42 -0800254 }
255#endif
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 {
260 sk_sp<SkImage> subsetImg(fImage->makeSubset(subset));
robertphillipsc5035e72016-03-17 06:58:39 -0700261 if (!subsetImg) {
262 return nullptr;
263 }
264
robertphillips3e302272016-04-20 11:48:36 -0700265 return SkSpecialImage::MakeFromImage(SkIRect::MakeWH(subset.width(), subset.height()),
brianosman898235c2016-04-06 07:38:23 -0700266 subsetImg,
267 &this->props());
robertphillipsc5035e72016-03-17 06:58:39 -0700268 }
269
robertphillipsb4bd11e2016-03-21 13:44:18 -0700270 sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const override {
271 return fImage->makeSubset(subset);
272 }
273
reede8f30622016-03-23 18:59:25 -0700274 sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const override {
robertphillipsb4bd11e2016-03-21 13:44:18 -0700275#if SK_SUPPORT_GPU
276 GrTexture* texture = as_IB(fImage.get())->peekTexture();
277 if (texture) {
reede8f30622016-03-23 18:59:25 -0700278 return SkSurface::MakeRenderTarget(texture->getContext(), SkBudgeted::kYes, info);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700279 }
280#endif
reede8f30622016-03-23 18:59:25 -0700281 return SkSurface::MakeRaster(info, nullptr);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700282 }
283
robertphillipsb6c65e92016-02-04 10:52:42 -0800284private:
robertphillips37bd7c32016-03-17 14:31:39 -0700285 sk_sp<SkImage> fImage;
robertphillipsb6c65e92016-02-04 10:52:42 -0800286
287 typedef SkSpecialImage_Base INHERITED;
288};
289
290#ifdef SK_DEBUG
291static bool rect_fits(const SkIRect& rect, int width, int height) {
robertphillips4418dba2016-03-07 12:45:14 -0800292 if (0 == width && 0 == height) {
293 SkASSERT(0 == rect.fLeft && 0 == rect.fRight && 0 == rect.fTop && 0 == rect.fBottom);
294 return true;
295 }
296
robertphillipsb6c65e92016-02-04 10:52:42 -0800297 return rect.fLeft >= 0 && rect.fLeft < width && rect.fLeft < rect.fRight &&
298 rect.fRight >= 0 && rect.fRight <= width &&
299 rect.fTop >= 0 && rect.fTop < height && rect.fTop < rect.fBottom &&
300 rect.fBottom >= 0 && rect.fBottom <= height;
301}
302#endif
303
robertphillips3e302272016-04-20 11:48:36 -0700304sk_sp<SkSpecialImage> SkSpecialImage::MakeFromImage(const SkIRect& subset,
brianosman898235c2016-04-06 07:38:23 -0700305 sk_sp<SkImage> image,
306 const SkSurfaceProps* props) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800307 SkASSERT(rect_fits(subset, image->width(), image->height()));
robertphillips37bd7c32016-03-17 14:31:39 -0700308
robertphillips3e302272016-04-20 11:48:36 -0700309 return sk_make_sp<SkSpecialImage_Image>(subset, image, props);
robertphillipsb6c65e92016-02-04 10:52:42 -0800310}
311
312///////////////////////////////////////////////////////////////////////////////
313#include "SkBitmap.h"
314#include "SkImageInfo.h"
315#include "SkPixelRef.h"
316
317class SkSpecialImage_Raster : public SkSpecialImage_Base {
318public:
robertphillips3e302272016-04-20 11:48:36 -0700319 SkSpecialImage_Raster(const SkIRect& subset, const SkBitmap& bm, const SkSurfaceProps* props)
320 : INHERITED(subset, bm.getGenerationID(), props)
robertphillipsb6c65e92016-02-04 10:52:42 -0800321 , fBitmap(bm) {
robertphillips4418dba2016-03-07 12:45:14 -0800322 if (bm.pixelRef() && bm.pixelRef()->isPreLocked()) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800323 // we only preemptively lock if there is no chance of triggering something expensive
324 // like a lazy decode or imagegenerator. PreLocked means it is flat pixels already.
325 fBitmap.lockPixels();
326 }
327 }
328
robertphillips3e302272016-04-20 11:48:36 -0700329 SkSpecialImage_Raster(const SkIRect& subset,
robertphillipsc5035e72016-03-17 06:58:39 -0700330 const SkPixmap& pixmap,
robertphillips37bd7c32016-03-17 14:31:39 -0700331 RasterReleaseProc releaseProc,
brianosman898235c2016-04-06 07:38:23 -0700332 ReleaseContext context,
333 const SkSurfaceProps* props)
robertphillips3e302272016-04-20 11:48:36 -0700334 : INHERITED(subset, kNeedNewImageUniqueID_SpecialImage, props) {
robertphillipsc5035e72016-03-17 06:58:39 -0700335 fBitmap.installPixels(pixmap.info(), pixmap.writable_addr(),
336 pixmap.rowBytes(), pixmap.ctable(),
337 releaseProc, context);
338 }
339
robertphillipsb6c65e92016-02-04 10:52:42 -0800340 ~SkSpecialImage_Raster() override { }
341
robertphillips3b087f42016-02-18 08:48:03 -0800342 bool isOpaque() const override { return fBitmap.isOpaque(); }
343
344 size_t getSize() const override { return fBitmap.getSize(); }
345
robertphillipse8c34972016-02-16 12:09:36 -0800346 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800347 SkRect dst = SkRect::MakeXYWH(x, y,
348 this->subset().width(), this->subset().height());
349
350 canvas->drawBitmapRect(fBitmap, this->subset(),
351 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
352 }
353
robertphillips64612512016-04-08 12:10:42 -0700354 bool onGetROPixels(SkBitmap* bm) const override {
355 *bm = fBitmap;
robertphillips3b087f42016-02-18 08:48:03 -0800356 return true;
357 }
358
robertphillips64612512016-04-08 12:10:42 -0700359 GrTexture* onAsTextureRef(GrContext* context) const override {
360#if SK_SUPPORT_GPU
361 if (context) {
362 return GrRefCachedBitmapTexture(context, fBitmap, GrTextureParams::ClampNoFilter());
363 }
364#endif
365
366 return nullptr;
367 }
368
369 bool getBitmapDeprecated(SkBitmap* result) const override {
robertphillips4418dba2016-03-07 12:45:14 -0800370 *result = fBitmap;
371 return true;
372 }
373
robertphillips37bd7c32016-03-17 14:31:39 -0700374 sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const override {
robertphillips3e302272016-04-20 11:48:36 -0700375 return SkSpecialSurface::MakeRaster(info, nullptr);
robertphillipsb6c65e92016-02-04 10:52:42 -0800376 }
377
robertphillips37bd7c32016-03-17 14:31:39 -0700378 sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
robertphillipsc5035e72016-03-17 06:58:39 -0700379 SkBitmap subsetBM;
halcanary9d524f22016-03-29 09:03:52 -0700380
robertphillipsc5035e72016-03-17 06:58:39 -0700381 if (!fBitmap.extractSubset(&subsetBM, subset)) {
382 return nullptr;
383 }
384
robertphillips3e302272016-04-20 11:48:36 -0700385 return SkSpecialImage::MakeFromRaster(SkIRect::MakeWH(subset.width(), subset.height()),
brianosman898235c2016-04-06 07:38:23 -0700386 subsetBM,
387 &this->props());
robertphillipsc5035e72016-03-17 06:58:39 -0700388 }
389
robertphillipsb4bd11e2016-03-21 13:44:18 -0700390 sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const override {
391 SkBitmap subsetBM;
392
393 if (!fBitmap.extractSubset(&subsetBM, subset)) {
394 return nullptr;
395 }
396
397 return SkImage::MakeFromBitmap(subsetBM);
398 }
399
reede8f30622016-03-23 18:59:25 -0700400 sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const override {
401 return SkSurface::MakeRaster(info);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700402 }
403
robertphillipsb6c65e92016-02-04 10:52:42 -0800404private:
405 SkBitmap fBitmap;
406
407 typedef SkSpecialImage_Base INHERITED;
408};
409
robertphillips3e302272016-04-20 11:48:36 -0700410sk_sp<SkSpecialImage> SkSpecialImage::MakeFromRaster(const SkIRect& subset,
brianosman898235c2016-04-06 07:38:23 -0700411 const SkBitmap& bm,
412 const SkSurfaceProps* props) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800413 SkASSERT(nullptr == bm.getTexture());
414 SkASSERT(rect_fits(subset, bm.width(), bm.height()));
robertphillips37bd7c32016-03-17 14:31:39 -0700415
robertphillips3e302272016-04-20 11:48:36 -0700416 return sk_make_sp<SkSpecialImage_Raster>(subset, bm, props);
robertphillipsb6c65e92016-02-04 10:52:42 -0800417}
418
robertphillips3e302272016-04-20 11:48:36 -0700419sk_sp<SkSpecialImage> SkSpecialImage::MakeFromPixmap(const SkIRect& subset,
robertphillips37bd7c32016-03-17 14:31:39 -0700420 const SkPixmap& src,
421 RasterReleaseProc releaseProc,
brianosman898235c2016-04-06 07:38:23 -0700422 ReleaseContext context,
423 const SkSurfaceProps* props) {
robertphillips37bd7c32016-03-17 14:31:39 -0700424 if (!src.addr()) {
425 return nullptr;
426 }
427
robertphillips3e302272016-04-20 11:48:36 -0700428 return sk_make_sp<SkSpecialImage_Raster>(subset, src, releaseProc, context, props);
robertphillipsc5035e72016-03-17 06:58:39 -0700429}
430
431
robertphillipsb6c65e92016-02-04 10:52:42 -0800432#if SK_SUPPORT_GPU
433///////////////////////////////////////////////////////////////////////////////
434#include "GrTexture.h"
robertphillipsb4bd11e2016-03-21 13:44:18 -0700435#include "SkImage_Gpu.h"
robertphillipsb6c65e92016-02-04 10:52:42 -0800436
437class SkSpecialImage_Gpu : public SkSpecialImage_Base {
halcanary9d524f22016-03-29 09:03:52 -0700438public:
robertphillips3e302272016-04-20 11:48:36 -0700439 SkSpecialImage_Gpu(const SkIRect& subset,
brianosman898235c2016-04-06 07:38:23 -0700440 uint32_t uniqueID, GrTexture* tex, SkAlphaType at,
441 const SkSurfaceProps* props)
robertphillips3e302272016-04-20 11:48:36 -0700442 : INHERITED(subset, uniqueID, props)
robertphillips3b087f42016-02-18 08:48:03 -0800443 , fTexture(SkRef(tex))
robertphillips64612512016-04-08 12:10:42 -0700444 , fAlphaType(at)
445 , fAddedRasterVersionToCache(false) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800446 }
447
robertphillips64612512016-04-08 12:10:42 -0700448 ~SkSpecialImage_Gpu() override {
449 if (fAddedRasterVersionToCache.load()) {
450 SkNotifyBitmapGenIDIsStale(this->uniqueID());
451 }
452 }
robertphillipsb6c65e92016-02-04 10:52:42 -0800453
robertphillips3b087f42016-02-18 08:48:03 -0800454 bool isOpaque() const override {
455 return GrPixelConfigIsOpaque(fTexture->config()) || fAlphaType == kOpaque_SkAlphaType;
456 }
457
458 size_t getSize() const override { return fTexture->gpuMemorySize(); }
459
robertphillipse8c34972016-02-16 12:09:36 -0800460 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800461 SkRect dst = SkRect::MakeXYWH(x, y,
462 this->subset().width(), this->subset().height());
463
464 SkBitmap bm;
465
robertphillipsb6c65e92016-02-04 10:52:42 -0800466 GrWrapTextureInBitmap(fTexture,
robertphillips3b087f42016-02-18 08:48:03 -0800467 fTexture->width(), fTexture->height(), this->isOpaque(), &bm);
robertphillipsb6c65e92016-02-04 10:52:42 -0800468
469 canvas->drawBitmapRect(bm, this->subset(),
470 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
471 }
472
473 GrTexture* onPeekTexture() const override { return fTexture; }
474
robertphillips64612512016-04-08 12:10:42 -0700475 GrTexture* onAsTextureRef(GrContext*) const override { return SkRef(fTexture.get()); }
476
477 bool onGetROPixels(SkBitmap* dst) const override {
478 if (SkBitmapCache::Find(this->uniqueID(), dst)) {
479 SkASSERT(dst->getGenerationID() == this->uniqueID());
480 SkASSERT(dst->isImmutable());
481 SkASSERT(dst->getPixels());
482 return true;
483 }
484
485 SkImageInfo info = SkImageInfo::MakeN32(this->width(), this->height(),
486 this->isOpaque() ? kOpaque_SkAlphaType
487 : kPremul_SkAlphaType);
488
489 if (!dst->tryAllocPixels(info)) {
490 return false;
491 }
492
493 if (!fTexture->readPixels(0, 0, dst->width(), dst->height(), kSkia8888_GrPixelConfig,
494 dst->getPixels(), dst->rowBytes())) {
495 return false;
496 }
497
498 dst->pixelRef()->setImmutableWithID(this->uniqueID());
499 SkBitmapCache::Add(this->uniqueID(), *dst);
500 fAddedRasterVersionToCache.store(true);
501 return true;
502 }
503
robertphillipsab01ccd2016-03-08 10:45:32 -0800504 bool getBitmapDeprecated(SkBitmap* result) const override {
halcanary9d524f22016-03-29 09:03:52 -0700505 const SkImageInfo info = GrMakeInfoFromTexture(fTexture,
robertphillips3b087f42016-02-18 08:48:03 -0800506 this->width(), this->height(),
507 this->isOpaque());
508 if (!result->setInfo(info)) {
509 return false;
510 }
511
robertphillipsc5035e72016-03-17 06:58:39 -0700512 const SkImageInfo prInfo = info.makeWH(fTexture->width(), fTexture->height());
513
514 SkAutoTUnref<SkGrPixelRef> pixelRef(new SkGrPixelRef(prInfo, fTexture));
515 result->setPixelRef(pixelRef, this->subset().fLeft, this->subset().fTop);
robertphillips3b087f42016-02-18 08:48:03 -0800516 return true;
517 }
518
robertphillips37bd7c32016-03-17 14:31:39 -0700519 sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const override {
robertphillips090b7622016-03-28 11:07:43 -0700520 if (!fTexture->getContext()) {
521 return nullptr;
522 }
523
brianosmana6359362016-03-21 06:55:37 -0700524 GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(info, *fTexture->getContext()->caps());
robertphillipsb6c65e92016-02-04 10:52:42 -0800525 desc.fFlags = kRenderTarget_GrSurfaceFlag;
526
robertphillips3e302272016-04-20 11:48:36 -0700527 return SkSpecialSurface::MakeRenderTarget(fTexture->getContext(), desc);
robertphillipsb6c65e92016-02-04 10:52:42 -0800528 }
529
robertphillips37bd7c32016-03-17 14:31:39 -0700530 sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
robertphillips3e302272016-04-20 11:48:36 -0700531 return SkSpecialImage::MakeFromGpu(subset,
robertphillips37bd7c32016-03-17 14:31:39 -0700532 this->uniqueID(),
halcanary9d524f22016-03-29 09:03:52 -0700533 fTexture,
brianosman898235c2016-04-06 07:38:23 -0700534 &this->props(),
robertphillips37bd7c32016-03-17 14:31:39 -0700535 fAlphaType);
robertphillipsc5035e72016-03-17 06:58:39 -0700536 }
537
robertphillipsb4bd11e2016-03-21 13:44:18 -0700538 sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const override {
539 if (0 == subset.fLeft && 0 == subset.fTop &&
540 fTexture->width() == subset.width() &&
541 fTexture->height() == subset.height()) {
542 // The existing GrTexture is already tight so reuse it in the SkImage
543 return sk_make_sp<SkImage_Gpu>(fTexture->width(), fTexture->height(),
544 kNeedNewImageUniqueID,
545 fAlphaType, fTexture, SkBudgeted::kYes);
546 }
547
548 GrContext* ctx = fTexture->getContext();
549 GrSurfaceDesc desc = fTexture->desc();
550 desc.fWidth = subset.width();
551 desc.fHeight = subset.height();
552
robertphillipsd25d06b2016-03-22 09:56:58 -0700553 SkAutoTUnref<GrTexture> subTx(ctx->textureProvider()->createTexture(desc,
554 SkBudgeted::kYes));
robertphillipsb4bd11e2016-03-21 13:44:18 -0700555 if (!subTx) {
556 return nullptr;
557 }
558 ctx->copySurface(subTx, fTexture, subset, SkIPoint::Make(0, 0));
559 return sk_make_sp<SkImage_Gpu>(desc.fWidth, desc.fHeight, kNeedNewImageUniqueID,
560 fAlphaType, subTx, SkBudgeted::kYes);
561 }
562
reede8f30622016-03-23 18:59:25 -0700563 sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const override {
564 return SkSurface::MakeRenderTarget(fTexture->getContext(), SkBudgeted::kYes, info);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700565 }
566
robertphillipsb6c65e92016-02-04 10:52:42 -0800567private:
568 SkAutoTUnref<GrTexture> fTexture;
robertphillips3b087f42016-02-18 08:48:03 -0800569 const SkAlphaType fAlphaType;
robertphillips64612512016-04-08 12:10:42 -0700570 mutable SkAtomic<bool> fAddedRasterVersionToCache;
robertphillipsb6c65e92016-02-04 10:52:42 -0800571
572 typedef SkSpecialImage_Base INHERITED;
573};
574
robertphillips3e302272016-04-20 11:48:36 -0700575sk_sp<SkSpecialImage> SkSpecialImage::MakeFromGpu(const SkIRect& subset,
robertphillips37bd7c32016-03-17 14:31:39 -0700576 uint32_t uniqueID,
577 GrTexture* tex,
brianosman898235c2016-04-06 07:38:23 -0700578 const SkSurfaceProps* props,
robertphillips37bd7c32016-03-17 14:31:39 -0700579 SkAlphaType at) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800580 SkASSERT(rect_fits(subset, tex->width(), tex->height()));
robertphillips3e302272016-04-20 11:48:36 -0700581 return sk_make_sp<SkSpecialImage_Gpu>(subset, uniqueID, tex, at, props);
robertphillipsb6c65e92016-02-04 10:52:42 -0800582}
583
584#else
585
robertphillips3e302272016-04-20 11:48:36 -0700586sk_sp<SkSpecialImage> SkSpecialImage::MakeFromGpu(const SkIRect& subset,
robertphillips37bd7c32016-03-17 14:31:39 -0700587 uint32_t uniqueID,
588 GrTexture* tex,
brianosman898235c2016-04-06 07:38:23 -0700589 const SkSurfaceProps* props,
robertphillips37bd7c32016-03-17 14:31:39 -0700590 SkAlphaType at) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800591 return nullptr;
592}
593
594#endif