blob: e3a14e57abde5ff8016d98ebbeb41b08d2082f8a [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
reeda2217ef2016-07-20 06:04:34 -070021// Currently the raster imagefilters can only handle certain imageinfos. Call this to know if
22// a given info is supported.
23static bool valid_for_imagefilters(const SkImageInfo& info) {
24 // no support for other swizzles/depths yet
25 return info.colorType() == kN32_SkColorType;
26}
27
robertphillipsb6c65e92016-02-04 10:52:42 -080028///////////////////////////////////////////////////////////////////////////////
29class SkSpecialImage_Base : public SkSpecialImage {
30public:
robertphillips3e302272016-04-20 11:48:36 -070031 SkSpecialImage_Base(const SkIRect& subset, uint32_t uniqueID, const SkSurfaceProps* props)
32 : INHERITED(subset, uniqueID, props) {
robertphillips3b087f42016-02-18 08:48:03 -080033 }
robertphillips3e302272016-04-20 11:48:36 -070034 ~SkSpecialImage_Base() override { }
robertphillipsb6c65e92016-02-04 10:52:42 -080035
robertphillipse8c34972016-02-16 12:09:36 -080036 virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) const = 0;
robertphillipsb6c65e92016-02-04 10:52:42 -080037
robertphillips64612512016-04-08 12:10:42 -070038 virtual bool onGetROPixels(SkBitmap*) const = 0;
robertphillipsb6c65e92016-02-04 10:52:42 -080039
40 virtual GrTexture* onPeekTexture() const { return nullptr; }
41
robertphillipsc91fd342016-04-25 12:32:54 -070042#if SK_SUPPORT_GPU
43 virtual sk_sp<GrTexture> onAsTextureRef(GrContext* context) const = 0;
44#endif
robertphillips4418dba2016-03-07 12:45:14 -080045
robertphillips3b087f42016-02-18 08:48:03 -080046 // Delete this entry point ASAP (see skbug.com/4965)
robertphillipsab01ccd2016-03-08 10:45:32 -080047 virtual bool getBitmapDeprecated(SkBitmap* result) const = 0;
robertphillips3b087f42016-02-18 08:48:03 -080048
robertphillipsb4bd11e2016-03-21 13:44:18 -070049 virtual sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const = 0;
50
robertphillips37bd7c32016-03-17 14:31:39 -070051 virtual sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const = 0;
robertphillipsc5035e72016-03-17 06:58:39 -070052
robertphillipsb4bd11e2016-03-21 13:44:18 -070053 virtual sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const = 0;
54
reede8f30622016-03-23 18:59:25 -070055 virtual sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const = 0;
robertphillipsb6c65e92016-02-04 10:52:42 -080056
57private:
58 typedef SkSpecialImage INHERITED;
59};
60
61///////////////////////////////////////////////////////////////////////////////
bsalomon84a4e5a2016-02-29 11:41:52 -080062static inline const SkSpecialImage_Base* as_SIB(const SkSpecialImage* image) {
robertphillipsb6c65e92016-02-04 10:52:42 -080063 return static_cast<const SkSpecialImage_Base*>(image);
64}
65
robertphillips3e302272016-04-20 11:48:36 -070066SkSpecialImage::SkSpecialImage(const SkIRect& subset,
brianosman898235c2016-04-06 07:38:23 -070067 uint32_t uniqueID,
68 const SkSurfaceProps* props)
69 : fProps(SkSurfacePropsCopyOrDefault(props))
70 , fSubset(subset)
robertphillips3e302272016-04-20 11:48:36 -070071 , fUniqueID(kNeedNewImageUniqueID_SpecialImage == uniqueID ? SkNextID::ImageID() : uniqueID) {
brianosman898235c2016-04-06 07:38:23 -070072}
73
robertphillips3e302272016-04-20 11:48:36 -070074sk_sp<SkSpecialImage> SkSpecialImage::makeTextureImage(GrContext* context) {
robertphillips83c17fa2016-03-18 08:14:27 -070075#if SK_SUPPORT_GPU
76 if (!context) {
77 return nullptr;
78 }
robertphillips64612512016-04-08 12:10:42 -070079 if (GrTexture* peek = as_SIB(this)->onPeekTexture()) {
robertphillips83c17fa2016-03-18 08:14:27 -070080 return peek->getContext() == context ? sk_sp<SkSpecialImage>(SkRef(this)) : nullptr;
81 }
82
83 SkBitmap bmp;
84 if (!this->internal_getBM(&bmp)) {
85 return nullptr;
86 }
87
robertphillips83f2e5a2016-03-24 06:31:25 -070088 if (bmp.empty()) {
robertphillips3e302272016-04-20 11:48:36 -070089 return SkSpecialImage::MakeFromRaster(SkIRect::MakeEmpty(), bmp, &this->props());
robertphillips83f2e5a2016-03-24 06:31:25 -070090 }
91
robertphillipsc91fd342016-04-25 12:32:54 -070092 sk_sp<GrTexture> resultTex(GrRefCachedBitmapTexture(context,
93 bmp,
brianosman982eb7f2016-06-06 13:10:58 -070094 GrTextureParams::ClampNoFilter(),
95 SkSourceGammaTreatment::kRespect));
robertphillips83c17fa2016-03-18 08:14:27 -070096 if (!resultTex) {
97 return nullptr;
98 }
99
100 SkAlphaType at = this->isOpaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
101
robertphillips3e302272016-04-20 11:48:36 -0700102 return SkSpecialImage::MakeFromGpu(SkIRect::MakeWH(resultTex->width(), resultTex->height()),
robertphillips83c17fa2016-03-18 08:14:27 -0700103 this->uniqueID(),
brianosman898235c2016-04-06 07:38:23 -0700104 resultTex, &this->props(), at);
robertphillips83c17fa2016-03-18 08:14:27 -0700105#else
106 return nullptr;
107#endif
108}
109
robertphillipse8c34972016-02-16 12:09:36 -0800110void SkSpecialImage::draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const {
bsalomon84a4e5a2016-02-29 11:41:52 -0800111 return as_SIB(this)->onDraw(canvas, x, y, paint);
robertphillipsb6c65e92016-02-04 10:52:42 -0800112}
113
robertphillips64612512016-04-08 12:10:42 -0700114bool SkSpecialImage::getROPixels(SkBitmap* bm) const {
115 return as_SIB(this)->onGetROPixels(bm);
robertphillipsb6c65e92016-02-04 10:52:42 -0800116}
117
robertphillips64612512016-04-08 12:10:42 -0700118bool SkSpecialImage::isTextureBacked() const {
119#if SK_SUPPORT_GPU
120 return as_SIB(this)->onPeekTexture() && as_SIB(this)->onPeekTexture()->getContext();
121#else
122 return false;
123#endif
robertphillipsb6c65e92016-02-04 10:52:42 -0800124}
125
robertphillips64612512016-04-08 12:10:42 -0700126GrContext* SkSpecialImage::getContext() const {
127#if SK_SUPPORT_GPU
128 GrTexture* texture = as_SIB(this)->onPeekTexture();
129
130 if (texture) {
131 return texture->getContext();
132 }
133#endif
134 return nullptr;
135}
136
robertphillipsc91fd342016-04-25 12:32:54 -0700137#if SK_SUPPORT_GPU
138sk_sp<GrTexture> SkSpecialImage::asTextureRef(GrContext* context) const {
robertphillips64612512016-04-08 12:10:42 -0700139 return as_SIB(this)->onAsTextureRef(context);
robertphillips4418dba2016-03-07 12:45:14 -0800140}
robertphillipsc91fd342016-04-25 12:32:54 -0700141#endif
robertphillips4418dba2016-03-07 12:45:14 -0800142
robertphillips37bd7c32016-03-17 14:31:39 -0700143sk_sp<SkSpecialSurface> SkSpecialImage::makeSurface(const SkImageInfo& info) const {
144 return as_SIB(this)->onMakeSurface(info);
robertphillipsb6c65e92016-02-04 10:52:42 -0800145}
146
robertphillipsb4bd11e2016-03-21 13:44:18 -0700147sk_sp<SkSurface> SkSpecialImage::makeTightSurface(const SkImageInfo& info) const {
reede8f30622016-03-23 18:59:25 -0700148 return as_SIB(this)->onMakeTightSurface(info);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700149}
150
robertphillips37bd7c32016-03-17 14:31:39 -0700151sk_sp<SkSpecialImage> SkSpecialImage::makeSubset(const SkIRect& subset) const {
152 return as_SIB(this)->onMakeSubset(subset);
robertphillipsc5035e72016-03-17 06:58:39 -0700153}
154
robertphillipsb4bd11e2016-03-21 13:44:18 -0700155sk_sp<SkImage> SkSpecialImage::makeTightSubset(const SkIRect& subset) const {
156 return as_SIB(this)->onMakeTightSubset(subset);
157}
158
robertphillips3b087f42016-02-18 08:48:03 -0800159#if SK_SUPPORT_GPU
160#include "SkGr.h"
161#include "SkGrPixelRef.h"
162#endif
163
robertphillips3e302272016-04-20 11:48:36 -0700164sk_sp<SkSpecialImage> SkSpecialImage::internal_fromBM(const SkBitmap& src,
brianosman898235c2016-04-06 07:38:23 -0700165 const SkSurfaceProps* props) {
robertphillipsc91fd342016-04-25 12:32:54 -0700166#if SK_SUPPORT_GPU
robertphillips3b087f42016-02-18 08:48:03 -0800167 // Need to test offset case! (see skbug.com/4967)
168 if (src.getTexture()) {
robertphillips3e302272016-04-20 11:48:36 -0700169 return SkSpecialImage::MakeFromGpu(src.bounds(),
robertphillips37bd7c32016-03-17 14:31:39 -0700170 src.getGenerationID(),
robertphillipsc91fd342016-04-25 12:32:54 -0700171 sk_ref_sp(src.getTexture()),
brianosman898235c2016-04-06 07:38:23 -0700172 props);
robertphillips3b087f42016-02-18 08:48:03 -0800173 }
robertphillipsc91fd342016-04-25 12:32:54 -0700174#endif
robertphillips3b087f42016-02-18 08:48:03 -0800175
robertphillips3e302272016-04-20 11:48:36 -0700176 return SkSpecialImage::MakeFromRaster(src.bounds(), src, props);
robertphillips3b087f42016-02-18 08:48:03 -0800177}
178
179bool SkSpecialImage::internal_getBM(SkBitmap* result) {
bsalomon84a4e5a2016-02-29 11:41:52 -0800180 const SkSpecialImage_Base* ib = as_SIB(this);
robertphillips3b087f42016-02-18 08:48:03 -0800181
182 // TODO: need to test offset case! (see skbug.com/4967)
robertphillipsab01ccd2016-03-08 10:45:32 -0800183 return ib->getBitmapDeprecated(result);
robertphillips3b087f42016-02-18 08:48:03 -0800184}
185
robertphillipsb6c65e92016-02-04 10:52:42 -0800186///////////////////////////////////////////////////////////////////////////////
187#include "SkImage.h"
188#if SK_SUPPORT_GPU
brianosmana6359362016-03-21 06:55:37 -0700189#include "GrContext.h"
robertphillipsb6c65e92016-02-04 10:52:42 -0800190#include "SkGrPriv.h"
191#endif
192
193class SkSpecialImage_Image : public SkSpecialImage_Base {
194public:
robertphillips3e302272016-04-20 11:48:36 -0700195 SkSpecialImage_Image(const SkIRect& subset,
brianosman898235c2016-04-06 07:38:23 -0700196 sk_sp<SkImage> image,
197 const SkSurfaceProps* props)
robertphillips3e302272016-04-20 11:48:36 -0700198 : INHERITED(subset, image->uniqueID(), props)
robertphillips37bd7c32016-03-17 14:31:39 -0700199 , fImage(image) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800200 }
201
202 ~SkSpecialImage_Image() override { }
halcanary9d524f22016-03-29 09:03:52 -0700203
robertphillips3b087f42016-02-18 08:48:03 -0800204 bool isOpaque() const override { return fImage->isOpaque(); }
205
206 size_t getSize() const override {
207#if SK_SUPPORT_GPU
bsalomon84a4e5a2016-02-29 11:41:52 -0800208 if (GrTexture* texture = as_IB(fImage.get())->peekTexture()) {
209 return texture->gpuMemorySize();
robertphillips3b087f42016-02-18 08:48:03 -0800210 } else
211#endif
212 {
reed6ceeebd2016-03-09 14:26:26 -0800213 SkPixmap pm;
214 if (fImage->peekPixels(&pm)) {
215 return pm.height() * pm.rowBytes();
robertphillips3b087f42016-02-18 08:48:03 -0800216 }
217 }
218 return 0;
219 }
220
robertphillipse8c34972016-02-16 12:09:36 -0800221 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800222 SkRect dst = SkRect::MakeXYWH(x, y, this->subset().width(), this->subset().height());
223
robertphillips37bd7c32016-03-17 14:31:39 -0700224 canvas->drawImageRect(fImage.get(), this->subset(),
robertphillipsb6c65e92016-02-04 10:52:42 -0800225 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
226 }
227
robertphillips64612512016-04-08 12:10:42 -0700228 bool onGetROPixels(SkBitmap* bm) const override {
robertphillipsed086ca2016-04-26 15:02:25 -0700229 return as_IB(fImage)->getROPixels(bm);
robertphillipsb6c65e92016-02-04 10:52:42 -0800230 }
231
robertphillips64612512016-04-08 12:10:42 -0700232 GrTexture* onPeekTexture() const override { return as_IB(fImage)->peekTexture(); }
233
robertphillips64612512016-04-08 12:10:42 -0700234#if SK_SUPPORT_GPU
robertphillipsc91fd342016-04-25 12:32:54 -0700235 sk_sp<GrTexture> onAsTextureRef(GrContext* context) const override {
236 return sk_sp<GrTexture>(as_IB(fImage)->asTextureRef(context,
brianosman982eb7f2016-06-06 13:10:58 -0700237 GrTextureParams::ClampNoFilter(),
238 SkSourceGammaTreatment::kRespect));
robertphillips64612512016-04-08 12:10:42 -0700239 }
robertphillipsc91fd342016-04-25 12:32:54 -0700240#endif
robertphillipsb6c65e92016-02-04 10:52:42 -0800241
robertphillipsab01ccd2016-03-08 10:45:32 -0800242 bool getBitmapDeprecated(SkBitmap* result) const override {
robertphillips6ac97b72016-03-09 05:17:10 -0800243#if SK_SUPPORT_GPU
244 if (GrTexture* texture = as_IB(fImage.get())->peekTexture()) {
halcanary9d524f22016-03-29 09:03:52 -0700245 const SkImageInfo info = GrMakeInfoFromTexture(texture,
robertphillips6ac97b72016-03-09 05:17:10 -0800246 fImage->width(), fImage->height(),
247 fImage->isOpaque());
248 if (!result->setInfo(info)) {
249 return false;
250 }
251
252 result->setPixelRef(new SkGrPixelRef(info, texture))->unref();
253 return true;
254 }
255#endif
256
257 return as_IB(fImage.get())->asBitmapForImageFilters(result);
robertphillips3b087f42016-02-18 08:48:03 -0800258 }
259
robertphillips37bd7c32016-03-17 14:31:39 -0700260 sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800261#if SK_SUPPORT_GPU
bsalomon84a4e5a2016-02-29 11:41:52 -0800262 GrTexture* texture = as_IB(fImage.get())->peekTexture();
robertphillipsb6c65e92016-02-04 10:52:42 -0800263 if (texture) {
robertphillips4df16562016-04-28 15:09:34 -0700264 GrPixelConfig config = SkImageInfo2GrPixelConfig(info, *texture->getContext()->caps());
robertphillipsb6c65e92016-02-04 10:52:42 -0800265
robertphillips4df16562016-04-28 15:09:34 -0700266 return SkSpecialSurface::MakeRenderTarget(texture->getContext(),
267 info.width(),
268 info.height(),
269 config);
robertphillipsb6c65e92016-02-04 10:52:42 -0800270 }
271#endif
robertphillips3e302272016-04-20 11:48:36 -0700272 return SkSpecialSurface::MakeRaster(info, nullptr);
robertphillipsb6c65e92016-02-04 10:52:42 -0800273 }
274
robertphillips37bd7c32016-03-17 14:31:39 -0700275 sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
robertphillipsed086ca2016-04-26 15:02:25 -0700276 sk_sp<SkImage> subsetImg(fImage->makeSubset(subset));
277 if (!subsetImg) {
278 return nullptr;
279 }
280
281 return SkSpecialImage::MakeFromImage(SkIRect::MakeWH(subset.width(), subset.height()),
282 subsetImg,
283 &this->props());
robertphillipsc5035e72016-03-17 06:58:39 -0700284 }
285
robertphillipsb4bd11e2016-03-21 13:44:18 -0700286 sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const override {
287 return fImage->makeSubset(subset);
288 }
289
reede8f30622016-03-23 18:59:25 -0700290 sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const override {
robertphillipsb4bd11e2016-03-21 13:44:18 -0700291#if SK_SUPPORT_GPU
292 GrTexture* texture = as_IB(fImage.get())->peekTexture();
293 if (texture) {
reede8f30622016-03-23 18:59:25 -0700294 return SkSurface::MakeRenderTarget(texture->getContext(), SkBudgeted::kYes, info);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700295 }
296#endif
reede8f30622016-03-23 18:59:25 -0700297 return SkSurface::MakeRaster(info, nullptr);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700298 }
299
robertphillipsb6c65e92016-02-04 10:52:42 -0800300private:
robertphillips37bd7c32016-03-17 14:31:39 -0700301 sk_sp<SkImage> fImage;
robertphillipsb6c65e92016-02-04 10:52:42 -0800302
303 typedef SkSpecialImage_Base INHERITED;
304};
305
306#ifdef SK_DEBUG
307static bool rect_fits(const SkIRect& rect, int width, int height) {
robertphillips4418dba2016-03-07 12:45:14 -0800308 if (0 == width && 0 == height) {
309 SkASSERT(0 == rect.fLeft && 0 == rect.fRight && 0 == rect.fTop && 0 == rect.fBottom);
310 return true;
311 }
312
robertphillipsb6c65e92016-02-04 10:52:42 -0800313 return rect.fLeft >= 0 && rect.fLeft < width && rect.fLeft < rect.fRight &&
314 rect.fRight >= 0 && rect.fRight <= width &&
315 rect.fTop >= 0 && rect.fTop < height && rect.fTop < rect.fBottom &&
316 rect.fBottom >= 0 && rect.fBottom <= height;
317}
318#endif
319
robertphillips3e302272016-04-20 11:48:36 -0700320sk_sp<SkSpecialImage> SkSpecialImage::MakeFromImage(const SkIRect& subset,
brianosman898235c2016-04-06 07:38:23 -0700321 sk_sp<SkImage> image,
322 const SkSurfaceProps* props) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800323 SkASSERT(rect_fits(subset, image->width(), image->height()));
robertphillips37bd7c32016-03-17 14:31:39 -0700324
reeda2217ef2016-07-20 06:04:34 -0700325 if (valid_for_imagefilters(as_IB(image.get())->onImageInfo())) {
326 return sk_make_sp<SkSpecialImage_Image>(subset, image, props);
327 } else {
328 return nullptr;
329 }
robertphillipsb6c65e92016-02-04 10:52:42 -0800330}
331
332///////////////////////////////////////////////////////////////////////////////
333#include "SkBitmap.h"
334#include "SkImageInfo.h"
335#include "SkPixelRef.h"
336
337class SkSpecialImage_Raster : public SkSpecialImage_Base {
338public:
robertphillips3e302272016-04-20 11:48:36 -0700339 SkSpecialImage_Raster(const SkIRect& subset, const SkBitmap& bm, const SkSurfaceProps* props)
340 : INHERITED(subset, bm.getGenerationID(), props)
robertphillipsb6c65e92016-02-04 10:52:42 -0800341 , fBitmap(bm) {
robertphillips4418dba2016-03-07 12:45:14 -0800342 if (bm.pixelRef() && bm.pixelRef()->isPreLocked()) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800343 // we only preemptively lock if there is no chance of triggering something expensive
344 // like a lazy decode or imagegenerator. PreLocked means it is flat pixels already.
345 fBitmap.lockPixels();
346 }
347 }
348
robertphillips3b087f42016-02-18 08:48:03 -0800349 bool isOpaque() const override { return fBitmap.isOpaque(); }
350
351 size_t getSize() const override { return fBitmap.getSize(); }
352
robertphillipse8c34972016-02-16 12:09:36 -0800353 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800354 SkRect dst = SkRect::MakeXYWH(x, y,
355 this->subset().width(), this->subset().height());
356
357 canvas->drawBitmapRect(fBitmap, this->subset(),
358 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
359 }
360
robertphillips64612512016-04-08 12:10:42 -0700361 bool onGetROPixels(SkBitmap* bm) const override {
362 *bm = fBitmap;
robertphillips3b087f42016-02-18 08:48:03 -0800363 return true;
364 }
365
robertphillips64612512016-04-08 12:10:42 -0700366#if SK_SUPPORT_GPU
robertphillipsc91fd342016-04-25 12:32:54 -0700367 sk_sp<GrTexture> onAsTextureRef(GrContext* context) const override {
robertphillips64612512016-04-08 12:10:42 -0700368 if (context) {
robertphillipsc91fd342016-04-25 12:32:54 -0700369 return sk_ref_sp(GrRefCachedBitmapTexture(context,
370 fBitmap,
brianosman982eb7f2016-06-06 13:10:58 -0700371 GrTextureParams::ClampNoFilter(),
372 SkSourceGammaTreatment::kRespect));
robertphillips64612512016-04-08 12:10:42 -0700373 }
robertphillips64612512016-04-08 12:10:42 -0700374
375 return nullptr;
376 }
robertphillipsc91fd342016-04-25 12:32:54 -0700377#endif
robertphillips64612512016-04-08 12:10:42 -0700378
379 bool getBitmapDeprecated(SkBitmap* result) const override {
robertphillips4418dba2016-03-07 12:45:14 -0800380 *result = fBitmap;
381 return true;
382 }
383
robertphillips37bd7c32016-03-17 14:31:39 -0700384 sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const override {
robertphillips3e302272016-04-20 11:48:36 -0700385 return SkSpecialSurface::MakeRaster(info, nullptr);
robertphillipsb6c65e92016-02-04 10:52:42 -0800386 }
387
robertphillips37bd7c32016-03-17 14:31:39 -0700388 sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
robertphillipsc5035e72016-03-17 06:58:39 -0700389 SkBitmap subsetBM;
halcanary9d524f22016-03-29 09:03:52 -0700390
robertphillipsc5035e72016-03-17 06:58:39 -0700391 if (!fBitmap.extractSubset(&subsetBM, subset)) {
392 return nullptr;
393 }
394
robertphillips3e302272016-04-20 11:48:36 -0700395 return SkSpecialImage::MakeFromRaster(SkIRect::MakeWH(subset.width(), subset.height()),
brianosman898235c2016-04-06 07:38:23 -0700396 subsetBM,
397 &this->props());
robertphillipsc5035e72016-03-17 06:58:39 -0700398 }
399
robertphillipsb4bd11e2016-03-21 13:44:18 -0700400 sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const override {
401 SkBitmap subsetBM;
402
403 if (!fBitmap.extractSubset(&subsetBM, subset)) {
404 return nullptr;
405 }
406
407 return SkImage::MakeFromBitmap(subsetBM);
408 }
409
reede8f30622016-03-23 18:59:25 -0700410 sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const override {
411 return SkSurface::MakeRaster(info);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700412 }
413
robertphillipsb6c65e92016-02-04 10:52:42 -0800414private:
415 SkBitmap fBitmap;
416
417 typedef SkSpecialImage_Base INHERITED;
418};
419
robertphillips3e302272016-04-20 11:48:36 -0700420sk_sp<SkSpecialImage> SkSpecialImage::MakeFromRaster(const SkIRect& subset,
brianosman898235c2016-04-06 07:38:23 -0700421 const SkBitmap& bm,
422 const SkSurfaceProps* props) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800423 SkASSERT(nullptr == bm.getTexture());
424 SkASSERT(rect_fits(subset, bm.width(), bm.height()));
robertphillips37bd7c32016-03-17 14:31:39 -0700425
reeda2217ef2016-07-20 06:04:34 -0700426 const SkBitmap* srcBM = &bm;
427 SkBitmap tmpStorage;
428 // ImageFilters only handle N32 at the moment, so force our src to be that
429 if (!valid_for_imagefilters(bm.info())) {
430 if (!bm.copyTo(&tmpStorage, kN32_SkColorType)) {
431 return nullptr;
432 }
433 srcBM = &tmpStorage;
434 }
435 return sk_make_sp<SkSpecialImage_Raster>(subset, *srcBM, props);
robertphillipsb6c65e92016-02-04 10:52:42 -0800436}
437
438#if SK_SUPPORT_GPU
439///////////////////////////////////////////////////////////////////////////////
robertphillipsed086ca2016-04-26 15:02:25 -0700440#include "GrTexture.h"
robertphillipsb4bd11e2016-03-21 13:44:18 -0700441#include "SkImage_Gpu.h"
robertphillipsb6c65e92016-02-04 10:52:42 -0800442
robertphillipsed086ca2016-04-26 15:02:25 -0700443class SkSpecialImage_Gpu : public SkSpecialImage_Base {
444public:
445 SkSpecialImage_Gpu(const SkIRect& subset,
446 uint32_t uniqueID, sk_sp<GrTexture> tex, SkAlphaType at,
447 const SkSurfaceProps* props)
448 : INHERITED(subset, uniqueID, props)
449 , fTexture(std::move(tex))
450 , fAlphaType(at)
451 , fAddedRasterVersionToCache(false) {
452 }
453
454 ~SkSpecialImage_Gpu() override {
455 if (fAddedRasterVersionToCache.load()) {
456 SkNotifyBitmapGenIDIsStale(this->uniqueID());
457 }
458 }
459
460 bool isOpaque() const override {
461 return GrPixelConfigIsOpaque(fTexture->config()) || fAlphaType == kOpaque_SkAlphaType;
462 }
463
464 size_t getSize() const override { return fTexture->gpuMemorySize(); }
465
466 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
467 SkRect dst = SkRect::MakeXYWH(x, y,
468 this->subset().width(), this->subset().height());
469
reed77d6f7d2016-07-13 12:24:48 -0700470 auto img = sk_sp<SkImage>(new SkImage_Gpu(fTexture->width(), fTexture->height(),
471 this->uniqueID(), fAlphaType, fTexture.get(),
472 SkBudgeted::kNo));
robertphillipsed086ca2016-04-26 15:02:25 -0700473
reed77d6f7d2016-07-13 12:24:48 -0700474 canvas->drawImageRect(img, this->subset(),
robertphillipsed086ca2016-04-26 15:02:25 -0700475 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
476 }
477
478 GrTexture* onPeekTexture() const override { return fTexture.get(); }
479
480 sk_sp<GrTexture> onAsTextureRef(GrContext*) const override { return fTexture; }
481
482 bool onGetROPixels(SkBitmap* dst) const override {
483 if (SkBitmapCache::Find(this->uniqueID(), dst)) {
484 SkASSERT(dst->getGenerationID() == this->uniqueID());
485 SkASSERT(dst->isImmutable());
486 SkASSERT(dst->getPixels());
487 return true;
488 }
489
490 SkImageInfo info = SkImageInfo::MakeN32(this->width(), this->height(),
491 this->isOpaque() ? kOpaque_SkAlphaType
492 : kPremul_SkAlphaType);
493
494 if (!dst->tryAllocPixels(info)) {
495 return false;
496 }
497
498 if (!fTexture->readPixels(0, 0, dst->width(), dst->height(), kSkia8888_GrPixelConfig,
499 dst->getPixels(), dst->rowBytes())) {
500 return false;
501 }
502
503 dst->pixelRef()->setImmutableWithID(this->uniqueID());
504 SkBitmapCache::Add(this->uniqueID(), *dst);
505 fAddedRasterVersionToCache.store(true);
506 return true;
507 }
508
509 bool getBitmapDeprecated(SkBitmap* result) const override {
510 const SkImageInfo info = GrMakeInfoFromTexture(fTexture.get(),
511 this->width(), this->height(),
512 this->isOpaque());
513 if (!result->setInfo(info)) {
514 return false;
515 }
516
517 const SkImageInfo prInfo = info.makeWH(fTexture->width(), fTexture->height());
518
519 SkAutoTUnref<SkGrPixelRef> pixelRef(new SkGrPixelRef(prInfo, fTexture.get()));
520 result->setPixelRef(pixelRef, this->subset().fLeft, this->subset().fTop);
521 return true;
522 }
523
524 sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const override {
525 if (!fTexture->getContext()) {
526 return nullptr;
527 }
528
robertphillips4df16562016-04-28 15:09:34 -0700529 GrPixelConfig config = SkImageInfo2GrPixelConfig(info, *fTexture->getContext()->caps());
robertphillipsed086ca2016-04-26 15:02:25 -0700530
robertphillips4df16562016-04-28 15:09:34 -0700531 return SkSpecialSurface::MakeRenderTarget(fTexture->getContext(),
532 info.width(), info.height(),
533 config);
robertphillipsed086ca2016-04-26 15:02:25 -0700534 }
535
536 sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
537 return SkSpecialImage::MakeFromGpu(subset,
538 this->uniqueID(),
539 fTexture,
540 &this->props(),
541 fAlphaType);
542 }
543
544 sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const override {
545 if (0 == subset.fLeft && 0 == subset.fTop &&
546 fTexture->width() == subset.width() &&
547 fTexture->height() == subset.height()) {
548 // The existing GrTexture is already tight so reuse it in the SkImage
549 return sk_make_sp<SkImage_Gpu>(fTexture->width(), fTexture->height(),
550 kNeedNewImageUniqueID,
551 fAlphaType, fTexture.get(), SkBudgeted::kYes);
552 }
553
554 GrContext* ctx = fTexture->getContext();
555 GrSurfaceDesc desc = fTexture->desc();
556 desc.fWidth = subset.width();
557 desc.fHeight = subset.height();
558
559 sk_sp<GrTexture> subTx(ctx->textureProvider()->createTexture(desc, SkBudgeted::kYes));
560 if (!subTx) {
561 return nullptr;
562 }
563 ctx->copySurface(subTx.get(), fTexture.get(), subset, SkIPoint::Make(0, 0));
564 return sk_make_sp<SkImage_Gpu>(desc.fWidth, desc.fHeight, kNeedNewImageUniqueID,
565 fAlphaType, subTx.get(), SkBudgeted::kYes);
566 }
567
568 sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const override {
569 return SkSurface::MakeRenderTarget(fTexture->getContext(), SkBudgeted::kYes, info);
570 }
571
572private:
573 sk_sp<GrTexture> fTexture;
574 const SkAlphaType fAlphaType;
575 mutable SkAtomic<bool> fAddedRasterVersionToCache;
576
577 typedef SkSpecialImage_Base INHERITED;
578};
579
robertphillips3e302272016-04-20 11:48:36 -0700580sk_sp<SkSpecialImage> SkSpecialImage::MakeFromGpu(const SkIRect& subset,
robertphillips37bd7c32016-03-17 14:31:39 -0700581 uint32_t uniqueID,
robertphillipsc91fd342016-04-25 12:32:54 -0700582 sk_sp<GrTexture> tex,
brianosman898235c2016-04-06 07:38:23 -0700583 const SkSurfaceProps* props,
robertphillips37bd7c32016-03-17 14:31:39 -0700584 SkAlphaType at) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800585 SkASSERT(rect_fits(subset, tex->width(), tex->height()));
robertphillipsed086ca2016-04-26 15:02:25 -0700586 return sk_make_sp<SkSpecialImage_Gpu>(subset, uniqueID, std::move(tex), at, props);
robertphillipsb6c65e92016-02-04 10:52:42 -0800587}
588
589#endif