blob: f903270dff72dfd1569cbe9a9c9fe45d1dd0d69d [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
robertphillipsc91fd342016-04-25 12:32:54 -070035#if SK_SUPPORT_GPU
36 virtual sk_sp<GrTexture> onAsTextureRef(GrContext* context) const = 0;
37#endif
robertphillips4418dba2016-03-07 12:45:14 -080038
robertphillips3b087f42016-02-18 08:48:03 -080039 // Delete this entry point ASAP (see skbug.com/4965)
robertphillipsab01ccd2016-03-08 10:45:32 -080040 virtual bool getBitmapDeprecated(SkBitmap* result) const = 0;
robertphillips3b087f42016-02-18 08:48:03 -080041
robertphillipsb4bd11e2016-03-21 13:44:18 -070042 virtual sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const = 0;
43
robertphillips37bd7c32016-03-17 14:31:39 -070044 virtual sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const = 0;
robertphillipsc5035e72016-03-17 06:58:39 -070045
robertphillipsb4bd11e2016-03-21 13:44:18 -070046 virtual sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const = 0;
47
reede8f30622016-03-23 18:59:25 -070048 virtual sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const = 0;
robertphillipsb6c65e92016-02-04 10:52:42 -080049
50private:
51 typedef SkSpecialImage INHERITED;
52};
53
54///////////////////////////////////////////////////////////////////////////////
bsalomon84a4e5a2016-02-29 11:41:52 -080055static inline const SkSpecialImage_Base* as_SIB(const SkSpecialImage* image) {
robertphillipsb6c65e92016-02-04 10:52:42 -080056 return static_cast<const SkSpecialImage_Base*>(image);
57}
58
robertphillips3e302272016-04-20 11:48:36 -070059SkSpecialImage::SkSpecialImage(const SkIRect& subset,
brianosman898235c2016-04-06 07:38:23 -070060 uint32_t uniqueID,
61 const SkSurfaceProps* props)
62 : fProps(SkSurfacePropsCopyOrDefault(props))
63 , fSubset(subset)
robertphillips3e302272016-04-20 11:48:36 -070064 , fUniqueID(kNeedNewImageUniqueID_SpecialImage == uniqueID ? SkNextID::ImageID() : uniqueID) {
brianosman898235c2016-04-06 07:38:23 -070065}
66
robertphillips3e302272016-04-20 11:48:36 -070067sk_sp<SkSpecialImage> SkSpecialImage::makeTextureImage(GrContext* context) {
robertphillips83c17fa2016-03-18 08:14:27 -070068#if SK_SUPPORT_GPU
69 if (!context) {
70 return nullptr;
71 }
robertphillips64612512016-04-08 12:10:42 -070072 if (GrTexture* peek = as_SIB(this)->onPeekTexture()) {
robertphillips83c17fa2016-03-18 08:14:27 -070073 return peek->getContext() == context ? sk_sp<SkSpecialImage>(SkRef(this)) : nullptr;
74 }
75
76 SkBitmap bmp;
77 if (!this->internal_getBM(&bmp)) {
78 return nullptr;
79 }
80
robertphillips83f2e5a2016-03-24 06:31:25 -070081 if (bmp.empty()) {
robertphillips3e302272016-04-20 11:48:36 -070082 return SkSpecialImage::MakeFromRaster(SkIRect::MakeEmpty(), bmp, &this->props());
robertphillips83f2e5a2016-03-24 06:31:25 -070083 }
84
robertphillipsc91fd342016-04-25 12:32:54 -070085 sk_sp<GrTexture> resultTex(GrRefCachedBitmapTexture(context,
86 bmp,
brianosman982eb7f2016-06-06 13:10:58 -070087 GrTextureParams::ClampNoFilter(),
88 SkSourceGammaTreatment::kRespect));
robertphillips83c17fa2016-03-18 08:14:27 -070089 if (!resultTex) {
90 return nullptr;
91 }
92
93 SkAlphaType at = this->isOpaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
94
robertphillips3e302272016-04-20 11:48:36 -070095 return SkSpecialImage::MakeFromGpu(SkIRect::MakeWH(resultTex->width(), resultTex->height()),
robertphillips83c17fa2016-03-18 08:14:27 -070096 this->uniqueID(),
brianosman898235c2016-04-06 07:38:23 -070097 resultTex, &this->props(), at);
robertphillips83c17fa2016-03-18 08:14:27 -070098#else
99 return nullptr;
100#endif
101}
102
robertphillipse8c34972016-02-16 12:09:36 -0800103void SkSpecialImage::draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const {
bsalomon84a4e5a2016-02-29 11:41:52 -0800104 return as_SIB(this)->onDraw(canvas, x, y, paint);
robertphillipsb6c65e92016-02-04 10:52:42 -0800105}
106
robertphillips64612512016-04-08 12:10:42 -0700107bool SkSpecialImage::getROPixels(SkBitmap* bm) const {
108 return as_SIB(this)->onGetROPixels(bm);
robertphillipsb6c65e92016-02-04 10:52:42 -0800109}
110
robertphillips64612512016-04-08 12:10:42 -0700111bool SkSpecialImage::isTextureBacked() const {
112#if SK_SUPPORT_GPU
113 return as_SIB(this)->onPeekTexture() && as_SIB(this)->onPeekTexture()->getContext();
114#else
115 return false;
116#endif
robertphillipsb6c65e92016-02-04 10:52:42 -0800117}
118
robertphillips64612512016-04-08 12:10:42 -0700119GrContext* SkSpecialImage::getContext() const {
120#if SK_SUPPORT_GPU
121 GrTexture* texture = as_SIB(this)->onPeekTexture();
122
123 if (texture) {
124 return texture->getContext();
125 }
126#endif
127 return nullptr;
128}
129
robertphillipsc91fd342016-04-25 12:32:54 -0700130#if SK_SUPPORT_GPU
131sk_sp<GrTexture> SkSpecialImage::asTextureRef(GrContext* context) const {
robertphillips64612512016-04-08 12:10:42 -0700132 return as_SIB(this)->onAsTextureRef(context);
robertphillips4418dba2016-03-07 12:45:14 -0800133}
robertphillipsc91fd342016-04-25 12:32:54 -0700134#endif
robertphillips4418dba2016-03-07 12:45:14 -0800135
robertphillips37bd7c32016-03-17 14:31:39 -0700136sk_sp<SkSpecialSurface> SkSpecialImage::makeSurface(const SkImageInfo& info) const {
137 return as_SIB(this)->onMakeSurface(info);
robertphillipsb6c65e92016-02-04 10:52:42 -0800138}
139
robertphillipsb4bd11e2016-03-21 13:44:18 -0700140sk_sp<SkSurface> SkSpecialImage::makeTightSurface(const SkImageInfo& info) const {
reede8f30622016-03-23 18:59:25 -0700141 return as_SIB(this)->onMakeTightSurface(info);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700142}
143
robertphillips37bd7c32016-03-17 14:31:39 -0700144sk_sp<SkSpecialImage> SkSpecialImage::makeSubset(const SkIRect& subset) const {
145 return as_SIB(this)->onMakeSubset(subset);
robertphillipsc5035e72016-03-17 06:58:39 -0700146}
147
robertphillipsb4bd11e2016-03-21 13:44:18 -0700148sk_sp<SkImage> SkSpecialImage::makeTightSubset(const SkIRect& subset) const {
149 return as_SIB(this)->onMakeTightSubset(subset);
150}
151
robertphillips3b087f42016-02-18 08:48:03 -0800152#if SK_SUPPORT_GPU
153#include "SkGr.h"
154#include "SkGrPixelRef.h"
155#endif
156
robertphillips3e302272016-04-20 11:48:36 -0700157sk_sp<SkSpecialImage> SkSpecialImage::internal_fromBM(const SkBitmap& src,
brianosman898235c2016-04-06 07:38:23 -0700158 const SkSurfaceProps* props) {
robertphillipsc91fd342016-04-25 12:32:54 -0700159#if SK_SUPPORT_GPU
robertphillips3b087f42016-02-18 08:48:03 -0800160 // Need to test offset case! (see skbug.com/4967)
161 if (src.getTexture()) {
robertphillips3e302272016-04-20 11:48:36 -0700162 return SkSpecialImage::MakeFromGpu(src.bounds(),
robertphillips37bd7c32016-03-17 14:31:39 -0700163 src.getGenerationID(),
robertphillipsc91fd342016-04-25 12:32:54 -0700164 sk_ref_sp(src.getTexture()),
brianosman898235c2016-04-06 07:38:23 -0700165 props);
robertphillips3b087f42016-02-18 08:48:03 -0800166 }
robertphillipsc91fd342016-04-25 12:32:54 -0700167#endif
robertphillips3b087f42016-02-18 08:48:03 -0800168
robertphillips3e302272016-04-20 11:48:36 -0700169 return SkSpecialImage::MakeFromRaster(src.bounds(), src, props);
robertphillips3b087f42016-02-18 08:48:03 -0800170}
171
172bool SkSpecialImage::internal_getBM(SkBitmap* result) {
bsalomon84a4e5a2016-02-29 11:41:52 -0800173 const SkSpecialImage_Base* ib = as_SIB(this);
robertphillips3b087f42016-02-18 08:48:03 -0800174
175 // TODO: need to test offset case! (see skbug.com/4967)
robertphillipsab01ccd2016-03-08 10:45:32 -0800176 return ib->getBitmapDeprecated(result);
robertphillips3b087f42016-02-18 08:48:03 -0800177}
178
robertphillipsb6c65e92016-02-04 10:52:42 -0800179///////////////////////////////////////////////////////////////////////////////
180#include "SkImage.h"
181#if SK_SUPPORT_GPU
brianosmana6359362016-03-21 06:55:37 -0700182#include "GrContext.h"
robertphillipsb6c65e92016-02-04 10:52:42 -0800183#include "SkGrPriv.h"
184#endif
185
186class SkSpecialImage_Image : public SkSpecialImage_Base {
187public:
robertphillips3e302272016-04-20 11:48:36 -0700188 SkSpecialImage_Image(const SkIRect& subset,
brianosman898235c2016-04-06 07:38:23 -0700189 sk_sp<SkImage> image,
190 const SkSurfaceProps* props)
robertphillips3e302272016-04-20 11:48:36 -0700191 : INHERITED(subset, image->uniqueID(), props)
robertphillips37bd7c32016-03-17 14:31:39 -0700192 , fImage(image) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800193 }
194
195 ~SkSpecialImage_Image() override { }
halcanary9d524f22016-03-29 09:03:52 -0700196
robertphillips3b087f42016-02-18 08:48:03 -0800197 bool isOpaque() const override { return fImage->isOpaque(); }
198
199 size_t getSize() const override {
200#if SK_SUPPORT_GPU
bsalomon84a4e5a2016-02-29 11:41:52 -0800201 if (GrTexture* texture = as_IB(fImage.get())->peekTexture()) {
202 return texture->gpuMemorySize();
robertphillips3b087f42016-02-18 08:48:03 -0800203 } else
204#endif
205 {
reed6ceeebd2016-03-09 14:26:26 -0800206 SkPixmap pm;
207 if (fImage->peekPixels(&pm)) {
208 return pm.height() * pm.rowBytes();
robertphillips3b087f42016-02-18 08:48:03 -0800209 }
210 }
211 return 0;
212 }
213
robertphillipse8c34972016-02-16 12:09:36 -0800214 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800215 SkRect dst = SkRect::MakeXYWH(x, y, this->subset().width(), this->subset().height());
216
robertphillips37bd7c32016-03-17 14:31:39 -0700217 canvas->drawImageRect(fImage.get(), this->subset(),
robertphillipsb6c65e92016-02-04 10:52:42 -0800218 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
219 }
220
robertphillips64612512016-04-08 12:10:42 -0700221 bool onGetROPixels(SkBitmap* bm) const override {
robertphillipsed086ca2016-04-26 15:02:25 -0700222 return as_IB(fImage)->getROPixels(bm);
robertphillipsb6c65e92016-02-04 10:52:42 -0800223 }
224
robertphillips64612512016-04-08 12:10:42 -0700225 GrTexture* onPeekTexture() const override { return as_IB(fImage)->peekTexture(); }
226
robertphillips64612512016-04-08 12:10:42 -0700227#if SK_SUPPORT_GPU
robertphillipsc91fd342016-04-25 12:32:54 -0700228 sk_sp<GrTexture> onAsTextureRef(GrContext* context) const override {
229 return sk_sp<GrTexture>(as_IB(fImage)->asTextureRef(context,
brianosman982eb7f2016-06-06 13:10:58 -0700230 GrTextureParams::ClampNoFilter(),
231 SkSourceGammaTreatment::kRespect));
robertphillips64612512016-04-08 12:10:42 -0700232 }
robertphillipsc91fd342016-04-25 12:32:54 -0700233#endif
robertphillipsb6c65e92016-02-04 10:52:42 -0800234
robertphillipsab01ccd2016-03-08 10:45:32 -0800235 bool getBitmapDeprecated(SkBitmap* result) const override {
robertphillips6ac97b72016-03-09 05:17:10 -0800236#if SK_SUPPORT_GPU
237 if (GrTexture* texture = as_IB(fImage.get())->peekTexture()) {
halcanary9d524f22016-03-29 09:03:52 -0700238 const SkImageInfo info = GrMakeInfoFromTexture(texture,
robertphillips6ac97b72016-03-09 05:17:10 -0800239 fImage->width(), fImage->height(),
240 fImage->isOpaque());
241 if (!result->setInfo(info)) {
242 return false;
243 }
244
245 result->setPixelRef(new SkGrPixelRef(info, texture))->unref();
246 return true;
247 }
248#endif
249
250 return as_IB(fImage.get())->asBitmapForImageFilters(result);
robertphillips3b087f42016-02-18 08:48:03 -0800251 }
252
robertphillips37bd7c32016-03-17 14:31:39 -0700253 sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800254#if SK_SUPPORT_GPU
bsalomon84a4e5a2016-02-29 11:41:52 -0800255 GrTexture* texture = as_IB(fImage.get())->peekTexture();
robertphillipsb6c65e92016-02-04 10:52:42 -0800256 if (texture) {
robertphillips4df16562016-04-28 15:09:34 -0700257 GrPixelConfig config = SkImageInfo2GrPixelConfig(info, *texture->getContext()->caps());
robertphillipsb6c65e92016-02-04 10:52:42 -0800258
robertphillips4df16562016-04-28 15:09:34 -0700259 return SkSpecialSurface::MakeRenderTarget(texture->getContext(),
260 info.width(),
261 info.height(),
262 config);
robertphillipsb6c65e92016-02-04 10:52:42 -0800263 }
264#endif
robertphillips3e302272016-04-20 11:48:36 -0700265 return SkSpecialSurface::MakeRaster(info, nullptr);
robertphillipsb6c65e92016-02-04 10:52:42 -0800266 }
267
robertphillips37bd7c32016-03-17 14:31:39 -0700268 sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
robertphillipsed086ca2016-04-26 15:02:25 -0700269 sk_sp<SkImage> subsetImg(fImage->makeSubset(subset));
270 if (!subsetImg) {
271 return nullptr;
272 }
273
274 return SkSpecialImage::MakeFromImage(SkIRect::MakeWH(subset.width(), subset.height()),
275 subsetImg,
276 &this->props());
robertphillipsc5035e72016-03-17 06:58:39 -0700277 }
278
robertphillipsb4bd11e2016-03-21 13:44:18 -0700279 sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const override {
280 return fImage->makeSubset(subset);
281 }
282
reede8f30622016-03-23 18:59:25 -0700283 sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const override {
robertphillipsb4bd11e2016-03-21 13:44:18 -0700284#if SK_SUPPORT_GPU
285 GrTexture* texture = as_IB(fImage.get())->peekTexture();
286 if (texture) {
reede8f30622016-03-23 18:59:25 -0700287 return SkSurface::MakeRenderTarget(texture->getContext(), SkBudgeted::kYes, info);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700288 }
289#endif
reede8f30622016-03-23 18:59:25 -0700290 return SkSurface::MakeRaster(info, nullptr);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700291 }
292
robertphillipsb6c65e92016-02-04 10:52:42 -0800293private:
robertphillips37bd7c32016-03-17 14:31:39 -0700294 sk_sp<SkImage> fImage;
robertphillipsb6c65e92016-02-04 10:52:42 -0800295
296 typedef SkSpecialImage_Base INHERITED;
297};
298
299#ifdef SK_DEBUG
300static bool rect_fits(const SkIRect& rect, int width, int height) {
robertphillips4418dba2016-03-07 12:45:14 -0800301 if (0 == width && 0 == height) {
302 SkASSERT(0 == rect.fLeft && 0 == rect.fRight && 0 == rect.fTop && 0 == rect.fBottom);
303 return true;
304 }
305
robertphillipsb6c65e92016-02-04 10:52:42 -0800306 return rect.fLeft >= 0 && rect.fLeft < width && rect.fLeft < rect.fRight &&
307 rect.fRight >= 0 && rect.fRight <= width &&
308 rect.fTop >= 0 && rect.fTop < height && rect.fTop < rect.fBottom &&
309 rect.fBottom >= 0 && rect.fBottom <= height;
310}
311#endif
312
robertphillips3e302272016-04-20 11:48:36 -0700313sk_sp<SkSpecialImage> SkSpecialImage::MakeFromImage(const SkIRect& subset,
brianosman898235c2016-04-06 07:38:23 -0700314 sk_sp<SkImage> image,
315 const SkSurfaceProps* props) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800316 SkASSERT(rect_fits(subset, image->width(), image->height()));
robertphillips37bd7c32016-03-17 14:31:39 -0700317
robertphillips3e302272016-04-20 11:48:36 -0700318 return sk_make_sp<SkSpecialImage_Image>(subset, image, props);
robertphillipsb6c65e92016-02-04 10:52:42 -0800319}
320
321///////////////////////////////////////////////////////////////////////////////
322#include "SkBitmap.h"
323#include "SkImageInfo.h"
324#include "SkPixelRef.h"
325
326class SkSpecialImage_Raster : public SkSpecialImage_Base {
327public:
robertphillips3e302272016-04-20 11:48:36 -0700328 SkSpecialImage_Raster(const SkIRect& subset, const SkBitmap& bm, const SkSurfaceProps* props)
329 : INHERITED(subset, bm.getGenerationID(), props)
robertphillipsb6c65e92016-02-04 10:52:42 -0800330 , fBitmap(bm) {
robertphillips4418dba2016-03-07 12:45:14 -0800331 if (bm.pixelRef() && bm.pixelRef()->isPreLocked()) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800332 // we only preemptively lock if there is no chance of triggering something expensive
333 // like a lazy decode or imagegenerator. PreLocked means it is flat pixels already.
334 fBitmap.lockPixels();
335 }
336 }
337
robertphillips3e302272016-04-20 11:48:36 -0700338 SkSpecialImage_Raster(const SkIRect& subset,
robertphillipsc5035e72016-03-17 06:58:39 -0700339 const SkPixmap& pixmap,
robertphillips37bd7c32016-03-17 14:31:39 -0700340 RasterReleaseProc releaseProc,
brianosman898235c2016-04-06 07:38:23 -0700341 ReleaseContext context,
342 const SkSurfaceProps* props)
robertphillips3e302272016-04-20 11:48:36 -0700343 : INHERITED(subset, kNeedNewImageUniqueID_SpecialImage, props) {
robertphillipsc5035e72016-03-17 06:58:39 -0700344 fBitmap.installPixels(pixmap.info(), pixmap.writable_addr(),
345 pixmap.rowBytes(), pixmap.ctable(),
346 releaseProc, context);
347 }
348
robertphillipsb6c65e92016-02-04 10:52:42 -0800349 ~SkSpecialImage_Raster() override { }
350
robertphillips3b087f42016-02-18 08:48:03 -0800351 bool isOpaque() const override { return fBitmap.isOpaque(); }
352
353 size_t getSize() const override { return fBitmap.getSize(); }
354
robertphillipse8c34972016-02-16 12:09:36 -0800355 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800356 SkRect dst = SkRect::MakeXYWH(x, y,
357 this->subset().width(), this->subset().height());
358
359 canvas->drawBitmapRect(fBitmap, this->subset(),
360 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
361 }
362
robertphillips64612512016-04-08 12:10:42 -0700363 bool onGetROPixels(SkBitmap* bm) const override {
364 *bm = fBitmap;
robertphillips3b087f42016-02-18 08:48:03 -0800365 return true;
366 }
367
robertphillips64612512016-04-08 12:10:42 -0700368#if SK_SUPPORT_GPU
robertphillipsc91fd342016-04-25 12:32:54 -0700369 sk_sp<GrTexture> onAsTextureRef(GrContext* context) const override {
robertphillips64612512016-04-08 12:10:42 -0700370 if (context) {
robertphillipsc91fd342016-04-25 12:32:54 -0700371 return sk_ref_sp(GrRefCachedBitmapTexture(context,
372 fBitmap,
brianosman982eb7f2016-06-06 13:10:58 -0700373 GrTextureParams::ClampNoFilter(),
374 SkSourceGammaTreatment::kRespect));
robertphillips64612512016-04-08 12:10:42 -0700375 }
robertphillips64612512016-04-08 12:10:42 -0700376
377 return nullptr;
378 }
robertphillipsc91fd342016-04-25 12:32:54 -0700379#endif
robertphillips64612512016-04-08 12:10:42 -0700380
381 bool getBitmapDeprecated(SkBitmap* result) const override {
robertphillips4418dba2016-03-07 12:45:14 -0800382 *result = fBitmap;
383 return true;
384 }
385
robertphillips37bd7c32016-03-17 14:31:39 -0700386 sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const override {
robertphillips3e302272016-04-20 11:48:36 -0700387 return SkSpecialSurface::MakeRaster(info, nullptr);
robertphillipsb6c65e92016-02-04 10:52:42 -0800388 }
389
robertphillips37bd7c32016-03-17 14:31:39 -0700390 sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
robertphillipsc5035e72016-03-17 06:58:39 -0700391 SkBitmap subsetBM;
halcanary9d524f22016-03-29 09:03:52 -0700392
robertphillipsc5035e72016-03-17 06:58:39 -0700393 if (!fBitmap.extractSubset(&subsetBM, subset)) {
394 return nullptr;
395 }
396
robertphillips3e302272016-04-20 11:48:36 -0700397 return SkSpecialImage::MakeFromRaster(SkIRect::MakeWH(subset.width(), subset.height()),
brianosman898235c2016-04-06 07:38:23 -0700398 subsetBM,
399 &this->props());
robertphillipsc5035e72016-03-17 06:58:39 -0700400 }
401
robertphillipsb4bd11e2016-03-21 13:44:18 -0700402 sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const override {
403 SkBitmap subsetBM;
404
405 if (!fBitmap.extractSubset(&subsetBM, subset)) {
406 return nullptr;
407 }
408
409 return SkImage::MakeFromBitmap(subsetBM);
410 }
411
reede8f30622016-03-23 18:59:25 -0700412 sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const override {
413 return SkSurface::MakeRaster(info);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700414 }
415
robertphillipsb6c65e92016-02-04 10:52:42 -0800416private:
417 SkBitmap fBitmap;
418
419 typedef SkSpecialImage_Base INHERITED;
420};
421
robertphillips3e302272016-04-20 11:48:36 -0700422sk_sp<SkSpecialImage> SkSpecialImage::MakeFromRaster(const SkIRect& subset,
brianosman898235c2016-04-06 07:38:23 -0700423 const SkBitmap& bm,
424 const SkSurfaceProps* props) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800425 SkASSERT(nullptr == bm.getTexture());
426 SkASSERT(rect_fits(subset, bm.width(), bm.height()));
robertphillips37bd7c32016-03-17 14:31:39 -0700427
robertphillips3e302272016-04-20 11:48:36 -0700428 return sk_make_sp<SkSpecialImage_Raster>(subset, bm, props);
robertphillipsb6c65e92016-02-04 10:52:42 -0800429}
430
robertphillips3e302272016-04-20 11:48:36 -0700431sk_sp<SkSpecialImage> SkSpecialImage::MakeFromPixmap(const SkIRect& subset,
robertphillips37bd7c32016-03-17 14:31:39 -0700432 const SkPixmap& src,
433 RasterReleaseProc releaseProc,
brianosman898235c2016-04-06 07:38:23 -0700434 ReleaseContext context,
435 const SkSurfaceProps* props) {
robertphillips37bd7c32016-03-17 14:31:39 -0700436 if (!src.addr()) {
437 return nullptr;
438 }
439
robertphillips3e302272016-04-20 11:48:36 -0700440 return sk_make_sp<SkSpecialImage_Raster>(subset, src, releaseProc, context, props);
robertphillipsc5035e72016-03-17 06:58:39 -0700441}
442
443
robertphillipsb6c65e92016-02-04 10:52:42 -0800444#if SK_SUPPORT_GPU
445///////////////////////////////////////////////////////////////////////////////
robertphillipsed086ca2016-04-26 15:02:25 -0700446#include "GrTexture.h"
robertphillipsb4bd11e2016-03-21 13:44:18 -0700447#include "SkImage_Gpu.h"
robertphillipsb6c65e92016-02-04 10:52:42 -0800448
robertphillipsed086ca2016-04-26 15:02:25 -0700449class SkSpecialImage_Gpu : public SkSpecialImage_Base {
450public:
451 SkSpecialImage_Gpu(const SkIRect& subset,
452 uint32_t uniqueID, sk_sp<GrTexture> tex, SkAlphaType at,
453 const SkSurfaceProps* props)
454 : INHERITED(subset, uniqueID, props)
455 , fTexture(std::move(tex))
456 , fAlphaType(at)
457 , fAddedRasterVersionToCache(false) {
458 }
459
460 ~SkSpecialImage_Gpu() override {
461 if (fAddedRasterVersionToCache.load()) {
462 SkNotifyBitmapGenIDIsStale(this->uniqueID());
463 }
464 }
465
466 bool isOpaque() const override {
467 return GrPixelConfigIsOpaque(fTexture->config()) || fAlphaType == kOpaque_SkAlphaType;
468 }
469
470 size_t getSize() const override { return fTexture->gpuMemorySize(); }
471
472 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
473 SkRect dst = SkRect::MakeXYWH(x, y,
474 this->subset().width(), this->subset().height());
475
reed77d6f7d2016-07-13 12:24:48 -0700476 auto img = sk_sp<SkImage>(new SkImage_Gpu(fTexture->width(), fTexture->height(),
477 this->uniqueID(), fAlphaType, fTexture.get(),
478 SkBudgeted::kNo));
robertphillipsed086ca2016-04-26 15:02:25 -0700479
reed77d6f7d2016-07-13 12:24:48 -0700480 canvas->drawImageRect(img, this->subset(),
robertphillipsed086ca2016-04-26 15:02:25 -0700481 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
482 }
483
484 GrTexture* onPeekTexture() const override { return fTexture.get(); }
485
486 sk_sp<GrTexture> onAsTextureRef(GrContext*) const override { return fTexture; }
487
488 bool onGetROPixels(SkBitmap* dst) const override {
489 if (SkBitmapCache::Find(this->uniqueID(), dst)) {
490 SkASSERT(dst->getGenerationID() == this->uniqueID());
491 SkASSERT(dst->isImmutable());
492 SkASSERT(dst->getPixels());
493 return true;
494 }
495
496 SkImageInfo info = SkImageInfo::MakeN32(this->width(), this->height(),
497 this->isOpaque() ? kOpaque_SkAlphaType
498 : kPremul_SkAlphaType);
499
500 if (!dst->tryAllocPixels(info)) {
501 return false;
502 }
503
504 if (!fTexture->readPixels(0, 0, dst->width(), dst->height(), kSkia8888_GrPixelConfig,
505 dst->getPixels(), dst->rowBytes())) {
506 return false;
507 }
508
509 dst->pixelRef()->setImmutableWithID(this->uniqueID());
510 SkBitmapCache::Add(this->uniqueID(), *dst);
511 fAddedRasterVersionToCache.store(true);
512 return true;
513 }
514
515 bool getBitmapDeprecated(SkBitmap* result) const override {
516 const SkImageInfo info = GrMakeInfoFromTexture(fTexture.get(),
517 this->width(), this->height(),
518 this->isOpaque());
519 if (!result->setInfo(info)) {
520 return false;
521 }
522
523 const SkImageInfo prInfo = info.makeWH(fTexture->width(), fTexture->height());
524
525 SkAutoTUnref<SkGrPixelRef> pixelRef(new SkGrPixelRef(prInfo, fTexture.get()));
526 result->setPixelRef(pixelRef, this->subset().fLeft, this->subset().fTop);
527 return true;
528 }
529
530 sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const override {
531 if (!fTexture->getContext()) {
532 return nullptr;
533 }
534
robertphillips4df16562016-04-28 15:09:34 -0700535 GrPixelConfig config = SkImageInfo2GrPixelConfig(info, *fTexture->getContext()->caps());
robertphillipsed086ca2016-04-26 15:02:25 -0700536
robertphillips4df16562016-04-28 15:09:34 -0700537 return SkSpecialSurface::MakeRenderTarget(fTexture->getContext(),
538 info.width(), info.height(),
539 config);
robertphillipsed086ca2016-04-26 15:02:25 -0700540 }
541
542 sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
543 return SkSpecialImage::MakeFromGpu(subset,
544 this->uniqueID(),
545 fTexture,
546 &this->props(),
547 fAlphaType);
548 }
549
550 sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const override {
551 if (0 == subset.fLeft && 0 == subset.fTop &&
552 fTexture->width() == subset.width() &&
553 fTexture->height() == subset.height()) {
554 // The existing GrTexture is already tight so reuse it in the SkImage
555 return sk_make_sp<SkImage_Gpu>(fTexture->width(), fTexture->height(),
556 kNeedNewImageUniqueID,
557 fAlphaType, fTexture.get(), SkBudgeted::kYes);
558 }
559
560 GrContext* ctx = fTexture->getContext();
561 GrSurfaceDesc desc = fTexture->desc();
562 desc.fWidth = subset.width();
563 desc.fHeight = subset.height();
564
565 sk_sp<GrTexture> subTx(ctx->textureProvider()->createTexture(desc, SkBudgeted::kYes));
566 if (!subTx) {
567 return nullptr;
568 }
569 ctx->copySurface(subTx.get(), fTexture.get(), subset, SkIPoint::Make(0, 0));
570 return sk_make_sp<SkImage_Gpu>(desc.fWidth, desc.fHeight, kNeedNewImageUniqueID,
571 fAlphaType, subTx.get(), SkBudgeted::kYes);
572 }
573
574 sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const override {
575 return SkSurface::MakeRenderTarget(fTexture->getContext(), SkBudgeted::kYes, info);
576 }
577
578private:
579 sk_sp<GrTexture> fTexture;
580 const SkAlphaType fAlphaType;
581 mutable SkAtomic<bool> fAddedRasterVersionToCache;
582
583 typedef SkSpecialImage_Base INHERITED;
584};
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,
robertphillipsc91fd342016-04-25 12:32:54 -0700588 sk_sp<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 SkASSERT(rect_fits(subset, tex->width(), tex->height()));
robertphillipsed086ca2016-04-26 15:02:25 -0700592 return sk_make_sp<SkSpecialImage_Gpu>(subset, uniqueID, std::move(tex), at, props);
robertphillipsb6c65e92016-02-04 10:52:42 -0800593}
594
595#endif