blob: f18e6a7c7c109bf33552bbca2917c4bdc20bcb58 [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,
87 GrTextureParams::ClampNoFilter()));
robertphillips83c17fa2016-03-18 08:14:27 -070088 if (!resultTex) {
89 return nullptr;
90 }
91
92 SkAlphaType at = this->isOpaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
93
robertphillips3e302272016-04-20 11:48:36 -070094 return SkSpecialImage::MakeFromGpu(SkIRect::MakeWH(resultTex->width(), resultTex->height()),
robertphillips83c17fa2016-03-18 08:14:27 -070095 this->uniqueID(),
brianosman898235c2016-04-06 07:38:23 -070096 resultTex, &this->props(), at);
robertphillips83c17fa2016-03-18 08:14:27 -070097#else
98 return nullptr;
99#endif
100}
101
robertphillipse8c34972016-02-16 12:09:36 -0800102void SkSpecialImage::draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const {
bsalomon84a4e5a2016-02-29 11:41:52 -0800103 return as_SIB(this)->onDraw(canvas, x, y, paint);
robertphillipsb6c65e92016-02-04 10:52:42 -0800104}
105
robertphillips64612512016-04-08 12:10:42 -0700106bool SkSpecialImage::getROPixels(SkBitmap* bm) const {
107 return as_SIB(this)->onGetROPixels(bm);
robertphillipsb6c65e92016-02-04 10:52:42 -0800108}
109
robertphillips64612512016-04-08 12:10:42 -0700110bool SkSpecialImage::isTextureBacked() const {
111#if SK_SUPPORT_GPU
112 return as_SIB(this)->onPeekTexture() && as_SIB(this)->onPeekTexture()->getContext();
113#else
114 return false;
115#endif
robertphillipsb6c65e92016-02-04 10:52:42 -0800116}
117
robertphillips64612512016-04-08 12:10:42 -0700118GrContext* SkSpecialImage::getContext() const {
119#if SK_SUPPORT_GPU
120 GrTexture* texture = as_SIB(this)->onPeekTexture();
121
122 if (texture) {
123 return texture->getContext();
124 }
125#endif
126 return nullptr;
127}
128
robertphillipsc91fd342016-04-25 12:32:54 -0700129#if SK_SUPPORT_GPU
130sk_sp<GrTexture> SkSpecialImage::asTextureRef(GrContext* context) const {
robertphillips64612512016-04-08 12:10:42 -0700131 return as_SIB(this)->onAsTextureRef(context);
robertphillips4418dba2016-03-07 12:45:14 -0800132}
robertphillipsc91fd342016-04-25 12:32:54 -0700133#endif
robertphillips4418dba2016-03-07 12:45:14 -0800134
robertphillips37bd7c32016-03-17 14:31:39 -0700135sk_sp<SkSpecialSurface> SkSpecialImage::makeSurface(const SkImageInfo& info) const {
136 return as_SIB(this)->onMakeSurface(info);
robertphillipsb6c65e92016-02-04 10:52:42 -0800137}
138
robertphillipsb4bd11e2016-03-21 13:44:18 -0700139sk_sp<SkSurface> SkSpecialImage::makeTightSurface(const SkImageInfo& info) const {
reede8f30622016-03-23 18:59:25 -0700140 return as_SIB(this)->onMakeTightSurface(info);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700141}
142
robertphillips37bd7c32016-03-17 14:31:39 -0700143sk_sp<SkSpecialImage> SkSpecialImage::makeSubset(const SkIRect& subset) const {
144 return as_SIB(this)->onMakeSubset(subset);
robertphillipsc5035e72016-03-17 06:58:39 -0700145}
146
robertphillipsb4bd11e2016-03-21 13:44:18 -0700147sk_sp<SkImage> SkSpecialImage::makeTightSubset(const SkIRect& subset) const {
148 return as_SIB(this)->onMakeTightSubset(subset);
149}
150
robertphillips3b087f42016-02-18 08:48:03 -0800151#if SK_SUPPORT_GPU
152#include "SkGr.h"
153#include "SkGrPixelRef.h"
154#endif
155
robertphillips3e302272016-04-20 11:48:36 -0700156sk_sp<SkSpecialImage> SkSpecialImage::internal_fromBM(const SkBitmap& src,
brianosman898235c2016-04-06 07:38:23 -0700157 const SkSurfaceProps* props) {
robertphillipsc91fd342016-04-25 12:32:54 -0700158#if SK_SUPPORT_GPU
robertphillips3b087f42016-02-18 08:48:03 -0800159 // Need to test offset case! (see skbug.com/4967)
160 if (src.getTexture()) {
robertphillips3e302272016-04-20 11:48:36 -0700161 return SkSpecialImage::MakeFromGpu(src.bounds(),
robertphillips37bd7c32016-03-17 14:31:39 -0700162 src.getGenerationID(),
robertphillipsc91fd342016-04-25 12:32:54 -0700163 sk_ref_sp(src.getTexture()),
brianosman898235c2016-04-06 07:38:23 -0700164 props);
robertphillips3b087f42016-02-18 08:48:03 -0800165 }
robertphillipsc91fd342016-04-25 12:32:54 -0700166#endif
robertphillips3b087f42016-02-18 08:48:03 -0800167
robertphillips3e302272016-04-20 11:48:36 -0700168 return SkSpecialImage::MakeFromRaster(src.bounds(), src, props);
robertphillips3b087f42016-02-18 08:48:03 -0800169}
170
171bool SkSpecialImage::internal_getBM(SkBitmap* result) {
bsalomon84a4e5a2016-02-29 11:41:52 -0800172 const SkSpecialImage_Base* ib = as_SIB(this);
robertphillips3b087f42016-02-18 08:48:03 -0800173
174 // TODO: need to test offset case! (see skbug.com/4967)
robertphillipsab01ccd2016-03-08 10:45:32 -0800175 return ib->getBitmapDeprecated(result);
robertphillips3b087f42016-02-18 08:48:03 -0800176}
177
robertphillipsb6c65e92016-02-04 10:52:42 -0800178///////////////////////////////////////////////////////////////////////////////
179#include "SkImage.h"
180#if SK_SUPPORT_GPU
brianosmana6359362016-03-21 06:55:37 -0700181#include "GrContext.h"
robertphillipsb6c65e92016-02-04 10:52:42 -0800182#include "SkGrPriv.h"
183#endif
184
185class SkSpecialImage_Image : public SkSpecialImage_Base {
186public:
robertphillips3e302272016-04-20 11:48:36 -0700187 SkSpecialImage_Image(const SkIRect& subset,
brianosman898235c2016-04-06 07:38:23 -0700188 sk_sp<SkImage> image,
189 const SkSurfaceProps* props)
robertphillips3e302272016-04-20 11:48:36 -0700190 : INHERITED(subset, image->uniqueID(), props)
robertphillips37bd7c32016-03-17 14:31:39 -0700191 , fImage(image) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800192 }
193
194 ~SkSpecialImage_Image() override { }
halcanary9d524f22016-03-29 09:03:52 -0700195
robertphillips3b087f42016-02-18 08:48:03 -0800196 bool isOpaque() const override { return fImage->isOpaque(); }
197
198 size_t getSize() const override {
199#if SK_SUPPORT_GPU
bsalomon84a4e5a2016-02-29 11:41:52 -0800200 if (GrTexture* texture = as_IB(fImage.get())->peekTexture()) {
201 return texture->gpuMemorySize();
robertphillips3b087f42016-02-18 08:48:03 -0800202 } else
203#endif
204 {
reed6ceeebd2016-03-09 14:26:26 -0800205 SkPixmap pm;
206 if (fImage->peekPixels(&pm)) {
207 return pm.height() * pm.rowBytes();
robertphillips3b087f42016-02-18 08:48:03 -0800208 }
209 }
210 return 0;
211 }
212
robertphillipse8c34972016-02-16 12:09:36 -0800213 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800214 SkRect dst = SkRect::MakeXYWH(x, y, this->subset().width(), this->subset().height());
215
robertphillips37bd7c32016-03-17 14:31:39 -0700216 canvas->drawImageRect(fImage.get(), this->subset(),
robertphillipsb6c65e92016-02-04 10:52:42 -0800217 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
218 }
219
robertphillips64612512016-04-08 12:10:42 -0700220 bool onGetROPixels(SkBitmap* bm) const override {
221 return as_IB(fImage)->getROPixels(bm);
robertphillipsb6c65e92016-02-04 10:52:42 -0800222 }
223
robertphillips64612512016-04-08 12:10:42 -0700224 GrTexture* onPeekTexture() const override { return as_IB(fImage)->peekTexture(); }
225
robertphillips64612512016-04-08 12:10:42 -0700226#if SK_SUPPORT_GPU
robertphillipsc91fd342016-04-25 12:32:54 -0700227 sk_sp<GrTexture> onAsTextureRef(GrContext* context) const override {
228 return sk_sp<GrTexture>(as_IB(fImage)->asTextureRef(context,
229 GrTextureParams::ClampNoFilter()));
robertphillips64612512016-04-08 12:10:42 -0700230 }
robertphillipsc91fd342016-04-25 12:32:54 -0700231#endif
robertphillipsb6c65e92016-02-04 10:52:42 -0800232
robertphillipsab01ccd2016-03-08 10:45:32 -0800233 bool getBitmapDeprecated(SkBitmap* result) const override {
robertphillips6ac97b72016-03-09 05:17:10 -0800234#if SK_SUPPORT_GPU
235 if (GrTexture* texture = as_IB(fImage.get())->peekTexture()) {
halcanary9d524f22016-03-29 09:03:52 -0700236 const SkImageInfo info = GrMakeInfoFromTexture(texture,
robertphillips6ac97b72016-03-09 05:17:10 -0800237 fImage->width(), fImage->height(),
238 fImage->isOpaque());
239 if (!result->setInfo(info)) {
240 return false;
241 }
242
243 result->setPixelRef(new SkGrPixelRef(info, texture))->unref();
244 return true;
245 }
246#endif
247
248 return as_IB(fImage.get())->asBitmapForImageFilters(result);
robertphillips3b087f42016-02-18 08:48:03 -0800249 }
250
robertphillips37bd7c32016-03-17 14:31:39 -0700251 sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800252#if SK_SUPPORT_GPU
bsalomon84a4e5a2016-02-29 11:41:52 -0800253 GrTexture* texture = as_IB(fImage.get())->peekTexture();
robertphillipsb6c65e92016-02-04 10:52:42 -0800254 if (texture) {
brianosmana6359362016-03-21 06:55:37 -0700255 GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(info, *texture->getContext()->caps());
robertphillipsb6c65e92016-02-04 10:52:42 -0800256 desc.fFlags = kRenderTarget_GrSurfaceFlag;
257
robertphillips3e302272016-04-20 11:48:36 -0700258 return SkSpecialSurface::MakeRenderTarget(texture->getContext(), desc);
robertphillipsb6c65e92016-02-04 10:52:42 -0800259 }
260#endif
robertphillips3e302272016-04-20 11:48:36 -0700261 return SkSpecialSurface::MakeRaster(info, nullptr);
robertphillipsb6c65e92016-02-04 10:52:42 -0800262 }
263
robertphillips37bd7c32016-03-17 14:31:39 -0700264 sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
265 sk_sp<SkImage> subsetImg(fImage->makeSubset(subset));
robertphillipsc5035e72016-03-17 06:58:39 -0700266 if (!subsetImg) {
267 return nullptr;
268 }
269
robertphillips3e302272016-04-20 11:48:36 -0700270 return SkSpecialImage::MakeFromImage(SkIRect::MakeWH(subset.width(), subset.height()),
brianosman898235c2016-04-06 07:38:23 -0700271 subsetImg,
272 &this->props());
robertphillipsc5035e72016-03-17 06:58:39 -0700273 }
274
robertphillipsb4bd11e2016-03-21 13:44:18 -0700275 sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const override {
276 return fImage->makeSubset(subset);
277 }
278
reede8f30622016-03-23 18:59:25 -0700279 sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const override {
robertphillipsb4bd11e2016-03-21 13:44:18 -0700280#if SK_SUPPORT_GPU
281 GrTexture* texture = as_IB(fImage.get())->peekTexture();
282 if (texture) {
reede8f30622016-03-23 18:59:25 -0700283 return SkSurface::MakeRenderTarget(texture->getContext(), SkBudgeted::kYes, info);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700284 }
285#endif
reede8f30622016-03-23 18:59:25 -0700286 return SkSurface::MakeRaster(info, nullptr);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700287 }
288
robertphillipsb6c65e92016-02-04 10:52:42 -0800289private:
robertphillips37bd7c32016-03-17 14:31:39 -0700290 sk_sp<SkImage> fImage;
robertphillipsb6c65e92016-02-04 10:52:42 -0800291
292 typedef SkSpecialImage_Base INHERITED;
293};
294
295#ifdef SK_DEBUG
296static bool rect_fits(const SkIRect& rect, int width, int height) {
robertphillips4418dba2016-03-07 12:45:14 -0800297 if (0 == width && 0 == height) {
298 SkASSERT(0 == rect.fLeft && 0 == rect.fRight && 0 == rect.fTop && 0 == rect.fBottom);
299 return true;
300 }
301
robertphillipsb6c65e92016-02-04 10:52:42 -0800302 return rect.fLeft >= 0 && rect.fLeft < width && rect.fLeft < rect.fRight &&
303 rect.fRight >= 0 && rect.fRight <= width &&
304 rect.fTop >= 0 && rect.fTop < height && rect.fTop < rect.fBottom &&
305 rect.fBottom >= 0 && rect.fBottom <= height;
306}
307#endif
308
robertphillips3e302272016-04-20 11:48:36 -0700309sk_sp<SkSpecialImage> SkSpecialImage::MakeFromImage(const SkIRect& subset,
brianosman898235c2016-04-06 07:38:23 -0700310 sk_sp<SkImage> image,
311 const SkSurfaceProps* props) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800312 SkASSERT(rect_fits(subset, image->width(), image->height()));
robertphillips37bd7c32016-03-17 14:31:39 -0700313
robertphillips3e302272016-04-20 11:48:36 -0700314 return sk_make_sp<SkSpecialImage_Image>(subset, image, props);
robertphillipsb6c65e92016-02-04 10:52:42 -0800315}
316
317///////////////////////////////////////////////////////////////////////////////
318#include "SkBitmap.h"
319#include "SkImageInfo.h"
320#include "SkPixelRef.h"
321
322class SkSpecialImage_Raster : public SkSpecialImage_Base {
323public:
robertphillips3e302272016-04-20 11:48:36 -0700324 SkSpecialImage_Raster(const SkIRect& subset, const SkBitmap& bm, const SkSurfaceProps* props)
325 : INHERITED(subset, bm.getGenerationID(), props)
robertphillipsb6c65e92016-02-04 10:52:42 -0800326 , fBitmap(bm) {
robertphillips4418dba2016-03-07 12:45:14 -0800327 if (bm.pixelRef() && bm.pixelRef()->isPreLocked()) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800328 // we only preemptively lock if there is no chance of triggering something expensive
329 // like a lazy decode or imagegenerator. PreLocked means it is flat pixels already.
330 fBitmap.lockPixels();
331 }
332 }
333
robertphillips3e302272016-04-20 11:48:36 -0700334 SkSpecialImage_Raster(const SkIRect& subset,
robertphillipsc5035e72016-03-17 06:58:39 -0700335 const SkPixmap& pixmap,
robertphillips37bd7c32016-03-17 14:31:39 -0700336 RasterReleaseProc releaseProc,
brianosman898235c2016-04-06 07:38:23 -0700337 ReleaseContext context,
338 const SkSurfaceProps* props)
robertphillips3e302272016-04-20 11:48:36 -0700339 : INHERITED(subset, kNeedNewImageUniqueID_SpecialImage, props) {
robertphillipsc5035e72016-03-17 06:58:39 -0700340 fBitmap.installPixels(pixmap.info(), pixmap.writable_addr(),
341 pixmap.rowBytes(), pixmap.ctable(),
342 releaseProc, context);
343 }
344
robertphillipsb6c65e92016-02-04 10:52:42 -0800345 ~SkSpecialImage_Raster() override { }
346
robertphillips3b087f42016-02-18 08:48:03 -0800347 bool isOpaque() const override { return fBitmap.isOpaque(); }
348
349 size_t getSize() const override { return fBitmap.getSize(); }
350
robertphillipse8c34972016-02-16 12:09:36 -0800351 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800352 SkRect dst = SkRect::MakeXYWH(x, y,
353 this->subset().width(), this->subset().height());
354
355 canvas->drawBitmapRect(fBitmap, this->subset(),
356 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
357 }
358
robertphillips64612512016-04-08 12:10:42 -0700359 bool onGetROPixels(SkBitmap* bm) const override {
360 *bm = fBitmap;
robertphillips3b087f42016-02-18 08:48:03 -0800361 return true;
362 }
363
robertphillips64612512016-04-08 12:10:42 -0700364#if SK_SUPPORT_GPU
robertphillipsc91fd342016-04-25 12:32:54 -0700365 sk_sp<GrTexture> onAsTextureRef(GrContext* context) const override {
robertphillips64612512016-04-08 12:10:42 -0700366 if (context) {
robertphillipsc91fd342016-04-25 12:32:54 -0700367 return sk_ref_sp(GrRefCachedBitmapTexture(context,
368 fBitmap,
369 GrTextureParams::ClampNoFilter()));
robertphillips64612512016-04-08 12:10:42 -0700370 }
robertphillips64612512016-04-08 12:10:42 -0700371
372 return nullptr;
373 }
robertphillipsc91fd342016-04-25 12:32:54 -0700374#endif
robertphillips64612512016-04-08 12:10:42 -0700375
376 bool getBitmapDeprecated(SkBitmap* result) const override {
robertphillips4418dba2016-03-07 12:45:14 -0800377 *result = fBitmap;
378 return true;
379 }
380
robertphillips37bd7c32016-03-17 14:31:39 -0700381 sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const override {
robertphillips3e302272016-04-20 11:48:36 -0700382 return SkSpecialSurface::MakeRaster(info, nullptr);
robertphillipsb6c65e92016-02-04 10:52:42 -0800383 }
384
robertphillips37bd7c32016-03-17 14:31:39 -0700385 sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
robertphillipsc5035e72016-03-17 06:58:39 -0700386 SkBitmap subsetBM;
halcanary9d524f22016-03-29 09:03:52 -0700387
robertphillipsc5035e72016-03-17 06:58:39 -0700388 if (!fBitmap.extractSubset(&subsetBM, subset)) {
389 return nullptr;
390 }
391
robertphillips3e302272016-04-20 11:48:36 -0700392 return SkSpecialImage::MakeFromRaster(SkIRect::MakeWH(subset.width(), subset.height()),
brianosman898235c2016-04-06 07:38:23 -0700393 subsetBM,
394 &this->props());
robertphillipsc5035e72016-03-17 06:58:39 -0700395 }
396
robertphillipsb4bd11e2016-03-21 13:44:18 -0700397 sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const override {
398 SkBitmap subsetBM;
399
400 if (!fBitmap.extractSubset(&subsetBM, subset)) {
401 return nullptr;
402 }
403
404 return SkImage::MakeFromBitmap(subsetBM);
405 }
406
reede8f30622016-03-23 18:59:25 -0700407 sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const override {
408 return SkSurface::MakeRaster(info);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700409 }
410
robertphillipsb6c65e92016-02-04 10:52:42 -0800411private:
412 SkBitmap fBitmap;
413
414 typedef SkSpecialImage_Base INHERITED;
415};
416
robertphillips3e302272016-04-20 11:48:36 -0700417sk_sp<SkSpecialImage> SkSpecialImage::MakeFromRaster(const SkIRect& subset,
brianosman898235c2016-04-06 07:38:23 -0700418 const SkBitmap& bm,
419 const SkSurfaceProps* props) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800420 SkASSERT(nullptr == bm.getTexture());
421 SkASSERT(rect_fits(subset, bm.width(), bm.height()));
robertphillips37bd7c32016-03-17 14:31:39 -0700422
robertphillips3e302272016-04-20 11:48:36 -0700423 return sk_make_sp<SkSpecialImage_Raster>(subset, bm, props);
robertphillipsb6c65e92016-02-04 10:52:42 -0800424}
425
robertphillips3e302272016-04-20 11:48:36 -0700426sk_sp<SkSpecialImage> SkSpecialImage::MakeFromPixmap(const SkIRect& subset,
robertphillips37bd7c32016-03-17 14:31:39 -0700427 const SkPixmap& src,
428 RasterReleaseProc releaseProc,
brianosman898235c2016-04-06 07:38:23 -0700429 ReleaseContext context,
430 const SkSurfaceProps* props) {
robertphillips37bd7c32016-03-17 14:31:39 -0700431 if (!src.addr()) {
432 return nullptr;
433 }
434
robertphillips3e302272016-04-20 11:48:36 -0700435 return sk_make_sp<SkSpecialImage_Raster>(subset, src, releaseProc, context, props);
robertphillipsc5035e72016-03-17 06:58:39 -0700436}
437
438
robertphillipsb6c65e92016-02-04 10:52:42 -0800439#if SK_SUPPORT_GPU
440///////////////////////////////////////////////////////////////////////////////
441#include "GrTexture.h"
robertphillipsb4bd11e2016-03-21 13:44:18 -0700442#include "SkImage_Gpu.h"
robertphillipsb6c65e92016-02-04 10:52:42 -0800443
444class SkSpecialImage_Gpu : public SkSpecialImage_Base {
halcanary9d524f22016-03-29 09:03:52 -0700445public:
robertphillips3e302272016-04-20 11:48:36 -0700446 SkSpecialImage_Gpu(const SkIRect& subset,
robertphillipsc91fd342016-04-25 12:32:54 -0700447 uint32_t uniqueID, sk_sp<GrTexture> tex, SkAlphaType at,
brianosman898235c2016-04-06 07:38:23 -0700448 const SkSurfaceProps* props)
robertphillips3e302272016-04-20 11:48:36 -0700449 : INHERITED(subset, uniqueID, props)
robertphillipsc91fd342016-04-25 12:32:54 -0700450 , fTexture(std::move(tex))
robertphillips64612512016-04-08 12:10:42 -0700451 , fAlphaType(at)
452 , fAddedRasterVersionToCache(false) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800453 }
454
robertphillips64612512016-04-08 12:10:42 -0700455 ~SkSpecialImage_Gpu() override {
456 if (fAddedRasterVersionToCache.load()) {
457 SkNotifyBitmapGenIDIsStale(this->uniqueID());
458 }
459 }
robertphillipsb6c65e92016-02-04 10:52:42 -0800460
robertphillips3b087f42016-02-18 08:48:03 -0800461 bool isOpaque() const override {
462 return GrPixelConfigIsOpaque(fTexture->config()) || fAlphaType == kOpaque_SkAlphaType;
463 }
464
465 size_t getSize() const override { return fTexture->gpuMemorySize(); }
466
robertphillipse8c34972016-02-16 12:09:36 -0800467 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800468 SkRect dst = SkRect::MakeXYWH(x, y,
469 this->subset().width(), this->subset().height());
470
471 SkBitmap bm;
472
robertphillipsc91fd342016-04-25 12:32:54 -0700473 GrWrapTextureInBitmap(fTexture.get(),
robertphillips3b087f42016-02-18 08:48:03 -0800474 fTexture->width(), fTexture->height(), this->isOpaque(), &bm);
robertphillipsb6c65e92016-02-04 10:52:42 -0800475
476 canvas->drawBitmapRect(bm, this->subset(),
477 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
478 }
479
robertphillipsc91fd342016-04-25 12:32:54 -0700480 GrTexture* onPeekTexture() const override { return fTexture.get(); }
robertphillipsb6c65e92016-02-04 10:52:42 -0800481
robertphillipsc91fd342016-04-25 12:32:54 -0700482 sk_sp<GrTexture> onAsTextureRef(GrContext*) const override { return fTexture; }
robertphillips64612512016-04-08 12:10:42 -0700483
484 bool onGetROPixels(SkBitmap* dst) const override {
485 if (SkBitmapCache::Find(this->uniqueID(), dst)) {
486 SkASSERT(dst->getGenerationID() == this->uniqueID());
487 SkASSERT(dst->isImmutable());
488 SkASSERT(dst->getPixels());
489 return true;
490 }
491
492 SkImageInfo info = SkImageInfo::MakeN32(this->width(), this->height(),
493 this->isOpaque() ? kOpaque_SkAlphaType
494 : kPremul_SkAlphaType);
495
496 if (!dst->tryAllocPixels(info)) {
497 return false;
498 }
499
500 if (!fTexture->readPixels(0, 0, dst->width(), dst->height(), kSkia8888_GrPixelConfig,
501 dst->getPixels(), dst->rowBytes())) {
502 return false;
503 }
504
505 dst->pixelRef()->setImmutableWithID(this->uniqueID());
506 SkBitmapCache::Add(this->uniqueID(), *dst);
507 fAddedRasterVersionToCache.store(true);
508 return true;
509 }
510
robertphillipsab01ccd2016-03-08 10:45:32 -0800511 bool getBitmapDeprecated(SkBitmap* result) const override {
robertphillipsc91fd342016-04-25 12:32:54 -0700512 const SkImageInfo info = GrMakeInfoFromTexture(fTexture.get(),
robertphillips3b087f42016-02-18 08:48:03 -0800513 this->width(), this->height(),
514 this->isOpaque());
515 if (!result->setInfo(info)) {
516 return false;
517 }
518
robertphillipsc5035e72016-03-17 06:58:39 -0700519 const SkImageInfo prInfo = info.makeWH(fTexture->width(), fTexture->height());
520
robertphillipsc91fd342016-04-25 12:32:54 -0700521 SkAutoTUnref<SkGrPixelRef> pixelRef(new SkGrPixelRef(prInfo, fTexture.get()));
robertphillipsc5035e72016-03-17 06:58:39 -0700522 result->setPixelRef(pixelRef, this->subset().fLeft, this->subset().fTop);
robertphillips3b087f42016-02-18 08:48:03 -0800523 return true;
524 }
525
robertphillips37bd7c32016-03-17 14:31:39 -0700526 sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const override {
robertphillips090b7622016-03-28 11:07:43 -0700527 if (!fTexture->getContext()) {
528 return nullptr;
529 }
530
brianosmana6359362016-03-21 06:55:37 -0700531 GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(info, *fTexture->getContext()->caps());
robertphillipsb6c65e92016-02-04 10:52:42 -0800532 desc.fFlags = kRenderTarget_GrSurfaceFlag;
533
robertphillips3e302272016-04-20 11:48:36 -0700534 return SkSpecialSurface::MakeRenderTarget(fTexture->getContext(), desc);
robertphillipsb6c65e92016-02-04 10:52:42 -0800535 }
536
robertphillips37bd7c32016-03-17 14:31:39 -0700537 sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
robertphillips3e302272016-04-20 11:48:36 -0700538 return SkSpecialImage::MakeFromGpu(subset,
robertphillips37bd7c32016-03-17 14:31:39 -0700539 this->uniqueID(),
halcanary9d524f22016-03-29 09:03:52 -0700540 fTexture,
brianosman898235c2016-04-06 07:38:23 -0700541 &this->props(),
robertphillips37bd7c32016-03-17 14:31:39 -0700542 fAlphaType);
robertphillipsc5035e72016-03-17 06:58:39 -0700543 }
544
robertphillipsb4bd11e2016-03-21 13:44:18 -0700545 sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const override {
546 if (0 == subset.fLeft && 0 == subset.fTop &&
547 fTexture->width() == subset.width() &&
548 fTexture->height() == subset.height()) {
549 // The existing GrTexture is already tight so reuse it in the SkImage
550 return sk_make_sp<SkImage_Gpu>(fTexture->width(), fTexture->height(),
551 kNeedNewImageUniqueID,
robertphillipsc91fd342016-04-25 12:32:54 -0700552 fAlphaType, fTexture.get(), SkBudgeted::kYes);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700553 }
554
555 GrContext* ctx = fTexture->getContext();
556 GrSurfaceDesc desc = fTexture->desc();
557 desc.fWidth = subset.width();
558 desc.fHeight = subset.height();
559
robertphillipsc91fd342016-04-25 12:32:54 -0700560 sk_sp<GrTexture> subTx(ctx->textureProvider()->createTexture(desc, SkBudgeted::kYes));
robertphillipsb4bd11e2016-03-21 13:44:18 -0700561 if (!subTx) {
562 return nullptr;
563 }
robertphillipsc91fd342016-04-25 12:32:54 -0700564 ctx->copySurface(subTx.get(), fTexture.get(), subset, SkIPoint::Make(0, 0));
robertphillipsb4bd11e2016-03-21 13:44:18 -0700565 return sk_make_sp<SkImage_Gpu>(desc.fWidth, desc.fHeight, kNeedNewImageUniqueID,
robertphillipsc91fd342016-04-25 12:32:54 -0700566 fAlphaType, subTx.get(), SkBudgeted::kYes);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700567 }
568
reede8f30622016-03-23 18:59:25 -0700569 sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const override {
570 return SkSurface::MakeRenderTarget(fTexture->getContext(), SkBudgeted::kYes, info);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700571 }
572
robertphillipsb6c65e92016-02-04 10:52:42 -0800573private:
robertphillipsc91fd342016-04-25 12:32:54 -0700574 sk_sp<GrTexture> fTexture;
robertphillips3b087f42016-02-18 08:48:03 -0800575 const SkAlphaType fAlphaType;
robertphillips64612512016-04-08 12:10:42 -0700576 mutable SkAtomic<bool> fAddedRasterVersionToCache;
robertphillipsb6c65e92016-02-04 10:52:42 -0800577
578 typedef SkSpecialImage_Base INHERITED;
579};
580
robertphillips3e302272016-04-20 11:48:36 -0700581sk_sp<SkSpecialImage> SkSpecialImage::MakeFromGpu(const SkIRect& subset,
robertphillips37bd7c32016-03-17 14:31:39 -0700582 uint32_t uniqueID,
robertphillipsc91fd342016-04-25 12:32:54 -0700583 sk_sp<GrTexture> tex,
brianosman898235c2016-04-06 07:38:23 -0700584 const SkSurfaceProps* props,
robertphillips37bd7c32016-03-17 14:31:39 -0700585 SkAlphaType at) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800586 SkASSERT(rect_fits(subset, tex->width(), tex->height()));
robertphillipsc91fd342016-04-25 12:32:54 -0700587 return sk_make_sp<SkSpecialImage_Gpu>(subset, uniqueID, std::move(tex), at, props);
robertphillipsb6c65e92016-02-04 10:52:42 -0800588}
589
590#endif