blob: f7bbf9ecaa58a732d9547e77f4407672f69320df [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:
brianosman898235c2016-04-06 07:38:23 -070024 SkSpecialImage_Base(SkImageFilter::Proxy* proxy, const SkIRect& subset, uint32_t uniqueID,
25 const SkSurfaceProps* props)
26 : INHERITED(proxy, subset, uniqueID, props) {
robertphillips3b087f42016-02-18 08:48:03 -080027 }
robertphillipsb6c65e92016-02-04 10:52:42 -080028 virtual ~SkSpecialImage_Base() { }
29
robertphillipse8c34972016-02-16 12:09:36 -080030 virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) const = 0;
robertphillipsb6c65e92016-02-04 10:52:42 -080031
robertphillips64612512016-04-08 12:10:42 -070032 virtual bool onGetROPixels(SkBitmap*) const = 0;
robertphillipsb6c65e92016-02-04 10:52:42 -080033
34 virtual GrTexture* onPeekTexture() const { return nullptr; }
35
robertphillips64612512016-04-08 12:10:42 -070036 virtual GrTexture* onAsTextureRef(GrContext* context) const = 0;
robertphillips4418dba2016-03-07 12:45:14 -080037
robertphillips3b087f42016-02-18 08:48:03 -080038 // Delete this entry point ASAP (see skbug.com/4965)
robertphillipsab01ccd2016-03-08 10:45:32 -080039 virtual bool getBitmapDeprecated(SkBitmap* result) const = 0;
robertphillips3b087f42016-02-18 08:48:03 -080040
robertphillipsb4bd11e2016-03-21 13:44:18 -070041 virtual sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const = 0;
42
robertphillips37bd7c32016-03-17 14:31:39 -070043 virtual sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const = 0;
robertphillipsc5035e72016-03-17 06:58:39 -070044
robertphillipsb4bd11e2016-03-21 13:44:18 -070045 virtual sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const = 0;
46
reede8f30622016-03-23 18:59:25 -070047 virtual sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const = 0;
robertphillipsb6c65e92016-02-04 10:52:42 -080048
49private:
50 typedef SkSpecialImage INHERITED;
51};
52
53///////////////////////////////////////////////////////////////////////////////
bsalomon84a4e5a2016-02-29 11:41:52 -080054static inline const SkSpecialImage_Base* as_SIB(const SkSpecialImage* image) {
robertphillipsb6c65e92016-02-04 10:52:42 -080055 return static_cast<const SkSpecialImage_Base*>(image);
56}
57
brianosman898235c2016-04-06 07:38:23 -070058SkSpecialImage::SkSpecialImage(SkImageFilter::Proxy* proxy,
59 const SkIRect& subset,
60 uint32_t uniqueID,
61 const SkSurfaceProps* props)
62 : fProps(SkSurfacePropsCopyOrDefault(props))
63 , fSubset(subset)
64 , fUniqueID(kNeedNewImageUniqueID_SpecialImage == uniqueID ? SkNextID::ImageID() : uniqueID)
65 , fProxy(proxy) {
66}
67
robertphillips83c17fa2016-03-18 08:14:27 -070068sk_sp<SkSpecialImage> SkSpecialImage::makeTextureImage(SkImageFilter::Proxy* proxy,
69 GrContext* context) {
70#if SK_SUPPORT_GPU
71 if (!context) {
72 return nullptr;
73 }
robertphillips64612512016-04-08 12:10:42 -070074 if (GrTexture* peek = as_SIB(this)->onPeekTexture()) {
robertphillips83c17fa2016-03-18 08:14:27 -070075 return peek->getContext() == context ? sk_sp<SkSpecialImage>(SkRef(this)) : nullptr;
76 }
77
78 SkBitmap bmp;
79 if (!this->internal_getBM(&bmp)) {
80 return nullptr;
81 }
82
robertphillips83f2e5a2016-03-24 06:31:25 -070083 if (bmp.empty()) {
brianosman898235c2016-04-06 07:38:23 -070084 return SkSpecialImage::MakeFromRaster(proxy, SkIRect::MakeEmpty(), bmp, &this->props());
robertphillips83f2e5a2016-03-24 06:31:25 -070085 }
86
robertphillips83c17fa2016-03-18 08:14:27 -070087 SkAutoTUnref<GrTexture> resultTex(
88 GrRefCachedBitmapTexture(context, bmp, GrTextureParams::ClampNoFilter()));
89 if (!resultTex) {
90 return nullptr;
91 }
92
93 SkAlphaType at = this->isOpaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
94
95 return SkSpecialImage::MakeFromGpu(proxy,
96 SkIRect::MakeWH(resultTex->width(), resultTex->height()),
97 this->uniqueID(),
brianosman898235c2016-04-06 07:38:23 -070098 resultTex, &this->props(), at);
robertphillips83c17fa2016-03-18 08:14:27 -070099#else
100 return nullptr;
101#endif
102}
103
robertphillipse8c34972016-02-16 12:09:36 -0800104void SkSpecialImage::draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const {
bsalomon84a4e5a2016-02-29 11:41:52 -0800105 return as_SIB(this)->onDraw(canvas, x, y, paint);
robertphillipsb6c65e92016-02-04 10:52:42 -0800106}
107
robertphillips64612512016-04-08 12:10:42 -0700108bool SkSpecialImage::getROPixels(SkBitmap* bm) const {
109 return as_SIB(this)->onGetROPixels(bm);
robertphillipsb6c65e92016-02-04 10:52:42 -0800110}
111
robertphillips64612512016-04-08 12:10:42 -0700112bool SkSpecialImage::isTextureBacked() const {
113#if SK_SUPPORT_GPU
114 return as_SIB(this)->onPeekTexture() && as_SIB(this)->onPeekTexture()->getContext();
115#else
116 return false;
117#endif
robertphillipsb6c65e92016-02-04 10:52:42 -0800118}
119
robertphillips64612512016-04-08 12:10:42 -0700120GrContext* SkSpecialImage::getContext() const {
121#if SK_SUPPORT_GPU
122 GrTexture* texture = as_SIB(this)->onPeekTexture();
123
124 if (texture) {
125 return texture->getContext();
126 }
127#endif
128 return nullptr;
129}
130
131
132GrTexture* SkSpecialImage::asTextureRef(GrContext* context) const {
133 return as_SIB(this)->onAsTextureRef(context);
robertphillips4418dba2016-03-07 12:45:14 -0800134}
135
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
robertphillips37bd7c32016-03-17 14:31:39 -0700157sk_sp<SkSpecialImage> SkSpecialImage::internal_fromBM(SkImageFilter::Proxy* proxy,
brianosman898235c2016-04-06 07:38:23 -0700158 const SkBitmap& src,
159 const SkSurfaceProps* props) {
robertphillips3b087f42016-02-18 08:48:03 -0800160 // Need to test offset case! (see skbug.com/4967)
161 if (src.getTexture()) {
robertphillips37bd7c32016-03-17 14:31:39 -0700162 return SkSpecialImage::MakeFromGpu(proxy,
163 src.bounds(),
164 src.getGenerationID(),
brianosman898235c2016-04-06 07:38:23 -0700165 src.getTexture(),
166 props);
robertphillips3b087f42016-02-18 08:48:03 -0800167 }
168
brianosman898235c2016-04-06 07:38:23 -0700169 return SkSpecialImage::MakeFromRaster(proxy, 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
robertphillipsc5035e72016-03-17 06:58:39 -0700179SkImageFilter::Proxy* SkSpecialImage::internal_getProxy() const {
robertphillips3b087f42016-02-18 08:48:03 -0800180 return fProxy;
181}
182
robertphillipsb6c65e92016-02-04 10:52:42 -0800183///////////////////////////////////////////////////////////////////////////////
184#include "SkImage.h"
185#if SK_SUPPORT_GPU
brianosmana6359362016-03-21 06:55:37 -0700186#include "GrContext.h"
robertphillipsb6c65e92016-02-04 10:52:42 -0800187#include "SkGrPriv.h"
188#endif
189
190class SkSpecialImage_Image : public SkSpecialImage_Base {
191public:
robertphillips37bd7c32016-03-17 14:31:39 -0700192 SkSpecialImage_Image(SkImageFilter::Proxy* proxy,
193 const SkIRect& subset,
brianosman898235c2016-04-06 07:38:23 -0700194 sk_sp<SkImage> image,
195 const SkSurfaceProps* props)
196 : INHERITED(proxy, subset, image->uniqueID(), props)
robertphillips37bd7c32016-03-17 14:31:39 -0700197 , fImage(image) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800198 }
199
200 ~SkSpecialImage_Image() override { }
halcanary9d524f22016-03-29 09:03:52 -0700201
robertphillips3b087f42016-02-18 08:48:03 -0800202 bool isOpaque() const override { return fImage->isOpaque(); }
203
204 size_t getSize() const override {
205#if SK_SUPPORT_GPU
bsalomon84a4e5a2016-02-29 11:41:52 -0800206 if (GrTexture* texture = as_IB(fImage.get())->peekTexture()) {
207 return texture->gpuMemorySize();
robertphillips3b087f42016-02-18 08:48:03 -0800208 } else
209#endif
210 {
reed6ceeebd2016-03-09 14:26:26 -0800211 SkPixmap pm;
212 if (fImage->peekPixels(&pm)) {
213 return pm.height() * pm.rowBytes();
robertphillips3b087f42016-02-18 08:48:03 -0800214 }
215 }
216 return 0;
217 }
218
robertphillipse8c34972016-02-16 12:09:36 -0800219 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800220 SkRect dst = SkRect::MakeXYWH(x, y, this->subset().width(), this->subset().height());
221
robertphillips37bd7c32016-03-17 14:31:39 -0700222 canvas->drawImageRect(fImage.get(), this->subset(),
robertphillipsb6c65e92016-02-04 10:52:42 -0800223 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
224 }
225
robertphillips64612512016-04-08 12:10:42 -0700226 bool onGetROPixels(SkBitmap* bm) const override {
227 return as_IB(fImage)->getROPixels(bm);
robertphillipsb6c65e92016-02-04 10:52:42 -0800228 }
229
robertphillips64612512016-04-08 12:10:42 -0700230 GrTexture* onPeekTexture() const override { return as_IB(fImage)->peekTexture(); }
231
232 GrTexture* onAsTextureRef(GrContext* context) const override {
233#if SK_SUPPORT_GPU
234 return as_IB(fImage)->asTextureRef(context, GrTextureParams::ClampNoFilter());
235#else
236 return nullptr;
237#endif
238 }
robertphillipsb6c65e92016-02-04 10:52:42 -0800239
robertphillipsab01ccd2016-03-08 10:45:32 -0800240 bool getBitmapDeprecated(SkBitmap* result) const override {
robertphillips6ac97b72016-03-09 05:17:10 -0800241#if SK_SUPPORT_GPU
242 if (GrTexture* texture = as_IB(fImage.get())->peekTexture()) {
halcanary9d524f22016-03-29 09:03:52 -0700243 const SkImageInfo info = GrMakeInfoFromTexture(texture,
robertphillips6ac97b72016-03-09 05:17:10 -0800244 fImage->width(), fImage->height(),
245 fImage->isOpaque());
246 if (!result->setInfo(info)) {
247 return false;
248 }
249
250 result->setPixelRef(new SkGrPixelRef(info, texture))->unref();
251 return true;
252 }
253#endif
254
255 return as_IB(fImage.get())->asBitmapForImageFilters(result);
robertphillips3b087f42016-02-18 08:48:03 -0800256 }
257
robertphillips37bd7c32016-03-17 14:31:39 -0700258 sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800259#if SK_SUPPORT_GPU
bsalomon84a4e5a2016-02-29 11:41:52 -0800260 GrTexture* texture = as_IB(fImage.get())->peekTexture();
robertphillipsb6c65e92016-02-04 10:52:42 -0800261 if (texture) {
brianosmana6359362016-03-21 06:55:37 -0700262 GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(info, *texture->getContext()->caps());
robertphillipsb6c65e92016-02-04 10:52:42 -0800263 desc.fFlags = kRenderTarget_GrSurfaceFlag;
264
robertphillips37bd7c32016-03-17 14:31:39 -0700265 return SkSpecialSurface::MakeRenderTarget(this->proxy(), texture->getContext(), desc);
robertphillipsb6c65e92016-02-04 10:52:42 -0800266 }
267#endif
robertphillips37bd7c32016-03-17 14:31:39 -0700268 return SkSpecialSurface::MakeRaster(this->proxy(), info, nullptr);
robertphillipsb6c65e92016-02-04 10:52:42 -0800269 }
270
robertphillips37bd7c32016-03-17 14:31:39 -0700271 sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
272 sk_sp<SkImage> subsetImg(fImage->makeSubset(subset));
robertphillipsc5035e72016-03-17 06:58:39 -0700273 if (!subsetImg) {
274 return nullptr;
275 }
276
robertphillips37bd7c32016-03-17 14:31:39 -0700277 return SkSpecialImage::MakeFromImage(this->internal_getProxy(),
278 SkIRect::MakeWH(subset.width(), subset.height()),
brianosman898235c2016-04-06 07:38:23 -0700279 subsetImg,
280 &this->props());
robertphillipsc5035e72016-03-17 06:58:39 -0700281 }
282
robertphillipsb4bd11e2016-03-21 13:44:18 -0700283 sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const override {
284 return fImage->makeSubset(subset);
285 }
286
reede8f30622016-03-23 18:59:25 -0700287 sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const override {
robertphillipsb4bd11e2016-03-21 13:44:18 -0700288#if SK_SUPPORT_GPU
289 GrTexture* texture = as_IB(fImage.get())->peekTexture();
290 if (texture) {
reede8f30622016-03-23 18:59:25 -0700291 return SkSurface::MakeRenderTarget(texture->getContext(), SkBudgeted::kYes, info);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700292 }
293#endif
reede8f30622016-03-23 18:59:25 -0700294 return SkSurface::MakeRaster(info, nullptr);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700295 }
296
robertphillipsb6c65e92016-02-04 10:52:42 -0800297private:
robertphillips37bd7c32016-03-17 14:31:39 -0700298 sk_sp<SkImage> fImage;
robertphillipsb6c65e92016-02-04 10:52:42 -0800299
300 typedef SkSpecialImage_Base INHERITED;
301};
302
303#ifdef SK_DEBUG
304static bool rect_fits(const SkIRect& rect, int width, int height) {
robertphillips4418dba2016-03-07 12:45:14 -0800305 if (0 == width && 0 == height) {
306 SkASSERT(0 == rect.fLeft && 0 == rect.fRight && 0 == rect.fTop && 0 == rect.fBottom);
307 return true;
308 }
309
robertphillipsb6c65e92016-02-04 10:52:42 -0800310 return rect.fLeft >= 0 && rect.fLeft < width && rect.fLeft < rect.fRight &&
311 rect.fRight >= 0 && rect.fRight <= width &&
312 rect.fTop >= 0 && rect.fTop < height && rect.fTop < rect.fBottom &&
313 rect.fBottom >= 0 && rect.fBottom <= height;
314}
315#endif
316
robertphillips37bd7c32016-03-17 14:31:39 -0700317sk_sp<SkSpecialImage> SkSpecialImage::MakeFromImage(SkImageFilter::Proxy* proxy,
318 const SkIRect& subset,
brianosman898235c2016-04-06 07:38:23 -0700319 sk_sp<SkImage> image,
320 const SkSurfaceProps* props) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800321 SkASSERT(rect_fits(subset, image->width(), image->height()));
robertphillips37bd7c32016-03-17 14:31:39 -0700322
brianosman898235c2016-04-06 07:38:23 -0700323 return sk_make_sp<SkSpecialImage_Image>(proxy, subset, image, props);
robertphillipsb6c65e92016-02-04 10:52:42 -0800324}
325
326///////////////////////////////////////////////////////////////////////////////
327#include "SkBitmap.h"
328#include "SkImageInfo.h"
329#include "SkPixelRef.h"
330
331class SkSpecialImage_Raster : public SkSpecialImage_Base {
332public:
brianosman898235c2016-04-06 07:38:23 -0700333 SkSpecialImage_Raster(SkImageFilter::Proxy* proxy, const SkIRect& subset, const SkBitmap& bm,
334 const SkSurfaceProps* props)
335 : INHERITED(proxy, subset, bm.getGenerationID(), props)
robertphillipsb6c65e92016-02-04 10:52:42 -0800336 , fBitmap(bm) {
robertphillips4418dba2016-03-07 12:45:14 -0800337 if (bm.pixelRef() && bm.pixelRef()->isPreLocked()) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800338 // we only preemptively lock if there is no chance of triggering something expensive
339 // like a lazy decode or imagegenerator. PreLocked means it is flat pixels already.
340 fBitmap.lockPixels();
341 }
342 }
343
robertphillipsc5035e72016-03-17 06:58:39 -0700344 SkSpecialImage_Raster(SkImageFilter::Proxy* proxy,
345 const SkIRect& subset,
346 const SkPixmap& pixmap,
robertphillips37bd7c32016-03-17 14:31:39 -0700347 RasterReleaseProc releaseProc,
brianosman898235c2016-04-06 07:38:23 -0700348 ReleaseContext context,
349 const SkSurfaceProps* props)
350 : INHERITED(proxy, subset, kNeedNewImageUniqueID_SpecialImage, props) {
robertphillipsc5035e72016-03-17 06:58:39 -0700351 fBitmap.installPixels(pixmap.info(), pixmap.writable_addr(),
352 pixmap.rowBytes(), pixmap.ctable(),
353 releaseProc, context);
354 }
355
robertphillipsb6c65e92016-02-04 10:52:42 -0800356 ~SkSpecialImage_Raster() override { }
357
robertphillips3b087f42016-02-18 08:48:03 -0800358 bool isOpaque() const override { return fBitmap.isOpaque(); }
359
360 size_t getSize() const override { return fBitmap.getSize(); }
361
robertphillipse8c34972016-02-16 12:09:36 -0800362 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800363 SkRect dst = SkRect::MakeXYWH(x, y,
364 this->subset().width(), this->subset().height());
365
366 canvas->drawBitmapRect(fBitmap, this->subset(),
367 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
368 }
369
robertphillips64612512016-04-08 12:10:42 -0700370 bool onGetROPixels(SkBitmap* bm) const override {
371 *bm = fBitmap;
robertphillips3b087f42016-02-18 08:48:03 -0800372 return true;
373 }
374
robertphillips64612512016-04-08 12:10:42 -0700375 GrTexture* onAsTextureRef(GrContext* context) const override {
376#if SK_SUPPORT_GPU
377 if (context) {
378 return GrRefCachedBitmapTexture(context, fBitmap, GrTextureParams::ClampNoFilter());
379 }
380#endif
381
382 return nullptr;
383 }
384
385 bool getBitmapDeprecated(SkBitmap* result) const override {
robertphillips4418dba2016-03-07 12:45:14 -0800386 *result = fBitmap;
387 return true;
388 }
389
robertphillips37bd7c32016-03-17 14:31:39 -0700390 sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const override {
391 return SkSpecialSurface::MakeRaster(this->proxy(), info, nullptr);
robertphillipsb6c65e92016-02-04 10:52:42 -0800392 }
393
robertphillips37bd7c32016-03-17 14:31:39 -0700394 sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
robertphillipsc5035e72016-03-17 06:58:39 -0700395 SkBitmap subsetBM;
halcanary9d524f22016-03-29 09:03:52 -0700396
robertphillipsc5035e72016-03-17 06:58:39 -0700397 if (!fBitmap.extractSubset(&subsetBM, subset)) {
398 return nullptr;
399 }
400
robertphillips37bd7c32016-03-17 14:31:39 -0700401 return SkSpecialImage::MakeFromRaster(this->internal_getProxy(),
402 SkIRect::MakeWH(subset.width(), subset.height()),
brianosman898235c2016-04-06 07:38:23 -0700403 subsetBM,
404 &this->props());
robertphillipsc5035e72016-03-17 06:58:39 -0700405 }
406
robertphillipsb4bd11e2016-03-21 13:44:18 -0700407 sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const override {
408 SkBitmap subsetBM;
409
410 if (!fBitmap.extractSubset(&subsetBM, subset)) {
411 return nullptr;
412 }
413
414 return SkImage::MakeFromBitmap(subsetBM);
415 }
416
reede8f30622016-03-23 18:59:25 -0700417 sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const override {
418 return SkSurface::MakeRaster(info);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700419 }
420
robertphillipsb6c65e92016-02-04 10:52:42 -0800421private:
422 SkBitmap fBitmap;
423
424 typedef SkSpecialImage_Base INHERITED;
425};
426
robertphillips37bd7c32016-03-17 14:31:39 -0700427sk_sp<SkSpecialImage> SkSpecialImage::MakeFromRaster(SkImageFilter::Proxy* proxy,
428 const SkIRect& subset,
brianosman898235c2016-04-06 07:38:23 -0700429 const SkBitmap& bm,
430 const SkSurfaceProps* props) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800431 SkASSERT(nullptr == bm.getTexture());
432 SkASSERT(rect_fits(subset, bm.width(), bm.height()));
robertphillips37bd7c32016-03-17 14:31:39 -0700433
brianosman898235c2016-04-06 07:38:23 -0700434 return sk_make_sp<SkSpecialImage_Raster>(proxy, subset, bm, props);
robertphillipsb6c65e92016-02-04 10:52:42 -0800435}
436
robertphillips37bd7c32016-03-17 14:31:39 -0700437sk_sp<SkSpecialImage> SkSpecialImage::MakeFromPixmap(SkImageFilter::Proxy* proxy,
438 const SkIRect& subset,
439 const SkPixmap& src,
440 RasterReleaseProc releaseProc,
brianosman898235c2016-04-06 07:38:23 -0700441 ReleaseContext context,
442 const SkSurfaceProps* props) {
robertphillips37bd7c32016-03-17 14:31:39 -0700443 if (!src.addr()) {
444 return nullptr;
445 }
446
brianosman898235c2016-04-06 07:38:23 -0700447 return sk_make_sp<SkSpecialImage_Raster>(proxy, subset, src, releaseProc, context, props);
robertphillipsc5035e72016-03-17 06:58:39 -0700448}
449
450
robertphillipsb6c65e92016-02-04 10:52:42 -0800451#if SK_SUPPORT_GPU
452///////////////////////////////////////////////////////////////////////////////
453#include "GrTexture.h"
robertphillipsb4bd11e2016-03-21 13:44:18 -0700454#include "SkImage_Gpu.h"
robertphillipsb6c65e92016-02-04 10:52:42 -0800455
456class SkSpecialImage_Gpu : public SkSpecialImage_Base {
halcanary9d524f22016-03-29 09:03:52 -0700457public:
robertphillips3b087f42016-02-18 08:48:03 -0800458 SkSpecialImage_Gpu(SkImageFilter::Proxy* proxy, const SkIRect& subset,
brianosman898235c2016-04-06 07:38:23 -0700459 uint32_t uniqueID, GrTexture* tex, SkAlphaType at,
460 const SkSurfaceProps* props)
461 : INHERITED(proxy, subset, uniqueID, props)
robertphillips3b087f42016-02-18 08:48:03 -0800462 , fTexture(SkRef(tex))
robertphillips64612512016-04-08 12:10:42 -0700463 , fAlphaType(at)
464 , fAddedRasterVersionToCache(false) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800465 }
466
robertphillips64612512016-04-08 12:10:42 -0700467 ~SkSpecialImage_Gpu() override {
468 if (fAddedRasterVersionToCache.load()) {
469 SkNotifyBitmapGenIDIsStale(this->uniqueID());
470 }
471 }
robertphillipsb6c65e92016-02-04 10:52:42 -0800472
robertphillips3b087f42016-02-18 08:48:03 -0800473 bool isOpaque() const override {
474 return GrPixelConfigIsOpaque(fTexture->config()) || fAlphaType == kOpaque_SkAlphaType;
475 }
476
477 size_t getSize() const override { return fTexture->gpuMemorySize(); }
478
robertphillipse8c34972016-02-16 12:09:36 -0800479 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800480 SkRect dst = SkRect::MakeXYWH(x, y,
481 this->subset().width(), this->subset().height());
482
483 SkBitmap bm;
484
robertphillipsb6c65e92016-02-04 10:52:42 -0800485 GrWrapTextureInBitmap(fTexture,
robertphillips3b087f42016-02-18 08:48:03 -0800486 fTexture->width(), fTexture->height(), this->isOpaque(), &bm);
robertphillipsb6c65e92016-02-04 10:52:42 -0800487
488 canvas->drawBitmapRect(bm, this->subset(),
489 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
490 }
491
492 GrTexture* onPeekTexture() const override { return fTexture; }
493
robertphillips64612512016-04-08 12:10:42 -0700494 GrTexture* onAsTextureRef(GrContext*) const override { return SkRef(fTexture.get()); }
495
496 bool onGetROPixels(SkBitmap* dst) const override {
497 if (SkBitmapCache::Find(this->uniqueID(), dst)) {
498 SkASSERT(dst->getGenerationID() == this->uniqueID());
499 SkASSERT(dst->isImmutable());
500 SkASSERT(dst->getPixels());
501 return true;
502 }
503
504 SkImageInfo info = SkImageInfo::MakeN32(this->width(), this->height(),
505 this->isOpaque() ? kOpaque_SkAlphaType
506 : kPremul_SkAlphaType);
507
508 if (!dst->tryAllocPixels(info)) {
509 return false;
510 }
511
512 if (!fTexture->readPixels(0, 0, dst->width(), dst->height(), kSkia8888_GrPixelConfig,
513 dst->getPixels(), dst->rowBytes())) {
514 return false;
515 }
516
517 dst->pixelRef()->setImmutableWithID(this->uniqueID());
518 SkBitmapCache::Add(this->uniqueID(), *dst);
519 fAddedRasterVersionToCache.store(true);
520 return true;
521 }
522
robertphillipsab01ccd2016-03-08 10:45:32 -0800523 bool getBitmapDeprecated(SkBitmap* result) const override {
halcanary9d524f22016-03-29 09:03:52 -0700524 const SkImageInfo info = GrMakeInfoFromTexture(fTexture,
robertphillips3b087f42016-02-18 08:48:03 -0800525 this->width(), this->height(),
526 this->isOpaque());
527 if (!result->setInfo(info)) {
528 return false;
529 }
530
robertphillipsc5035e72016-03-17 06:58:39 -0700531 const SkImageInfo prInfo = info.makeWH(fTexture->width(), fTexture->height());
532
533 SkAutoTUnref<SkGrPixelRef> pixelRef(new SkGrPixelRef(prInfo, fTexture));
534 result->setPixelRef(pixelRef, this->subset().fLeft, this->subset().fTop);
robertphillips3b087f42016-02-18 08:48:03 -0800535 return true;
536 }
537
robertphillips37bd7c32016-03-17 14:31:39 -0700538 sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const override {
robertphillips090b7622016-03-28 11:07:43 -0700539 if (!fTexture->getContext()) {
540 return nullptr;
541 }
542
brianosmana6359362016-03-21 06:55:37 -0700543 GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(info, *fTexture->getContext()->caps());
robertphillipsb6c65e92016-02-04 10:52:42 -0800544 desc.fFlags = kRenderTarget_GrSurfaceFlag;
545
robertphillips37bd7c32016-03-17 14:31:39 -0700546 return SkSpecialSurface::MakeRenderTarget(this->proxy(), fTexture->getContext(), desc);
robertphillipsb6c65e92016-02-04 10:52:42 -0800547 }
548
robertphillips37bd7c32016-03-17 14:31:39 -0700549 sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
550 return SkSpecialImage::MakeFromGpu(this->internal_getProxy(),
551 subset,
552 this->uniqueID(),
halcanary9d524f22016-03-29 09:03:52 -0700553 fTexture,
brianosman898235c2016-04-06 07:38:23 -0700554 &this->props(),
robertphillips37bd7c32016-03-17 14:31:39 -0700555 fAlphaType);
robertphillipsc5035e72016-03-17 06:58:39 -0700556 }
557
robertphillipsb4bd11e2016-03-21 13:44:18 -0700558 sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const override {
559 if (0 == subset.fLeft && 0 == subset.fTop &&
560 fTexture->width() == subset.width() &&
561 fTexture->height() == subset.height()) {
562 // The existing GrTexture is already tight so reuse it in the SkImage
563 return sk_make_sp<SkImage_Gpu>(fTexture->width(), fTexture->height(),
564 kNeedNewImageUniqueID,
565 fAlphaType, fTexture, SkBudgeted::kYes);
566 }
567
568 GrContext* ctx = fTexture->getContext();
569 GrSurfaceDesc desc = fTexture->desc();
570 desc.fWidth = subset.width();
571 desc.fHeight = subset.height();
572
robertphillipsd25d06b2016-03-22 09:56:58 -0700573 SkAutoTUnref<GrTexture> subTx(ctx->textureProvider()->createTexture(desc,
574 SkBudgeted::kYes));
robertphillipsb4bd11e2016-03-21 13:44:18 -0700575 if (!subTx) {
576 return nullptr;
577 }
578 ctx->copySurface(subTx, fTexture, subset, SkIPoint::Make(0, 0));
579 return sk_make_sp<SkImage_Gpu>(desc.fWidth, desc.fHeight, kNeedNewImageUniqueID,
580 fAlphaType, subTx, SkBudgeted::kYes);
581 }
582
reede8f30622016-03-23 18:59:25 -0700583 sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const override {
584 return SkSurface::MakeRenderTarget(fTexture->getContext(), SkBudgeted::kYes, info);
robertphillipsb4bd11e2016-03-21 13:44:18 -0700585 }
586
robertphillipsb6c65e92016-02-04 10:52:42 -0800587private:
588 SkAutoTUnref<GrTexture> fTexture;
robertphillips3b087f42016-02-18 08:48:03 -0800589 const SkAlphaType fAlphaType;
robertphillips64612512016-04-08 12:10:42 -0700590 mutable SkAtomic<bool> fAddedRasterVersionToCache;
robertphillipsb6c65e92016-02-04 10:52:42 -0800591
592 typedef SkSpecialImage_Base INHERITED;
593};
594
robertphillips37bd7c32016-03-17 14:31:39 -0700595sk_sp<SkSpecialImage> SkSpecialImage::MakeFromGpu(SkImageFilter::Proxy* proxy,
halcanary9d524f22016-03-29 09:03:52 -0700596 const SkIRect& subset,
robertphillips37bd7c32016-03-17 14:31:39 -0700597 uint32_t uniqueID,
598 GrTexture* tex,
brianosman898235c2016-04-06 07:38:23 -0700599 const SkSurfaceProps* props,
robertphillips37bd7c32016-03-17 14:31:39 -0700600 SkAlphaType at) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800601 SkASSERT(rect_fits(subset, tex->width(), tex->height()));
brianosman898235c2016-04-06 07:38:23 -0700602 return sk_make_sp<SkSpecialImage_Gpu>(proxy, subset, uniqueID, tex, at, props);
robertphillipsb6c65e92016-02-04 10:52:42 -0800603}
604
605#else
606
robertphillips37bd7c32016-03-17 14:31:39 -0700607sk_sp<SkSpecialImage> SkSpecialImage::MakeFromGpu(SkImageFilter::Proxy* proxy,
608 const SkIRect& subset,
609 uint32_t uniqueID,
610 GrTexture* tex,
brianosman898235c2016-04-06 07:38:23 -0700611 const SkSurfaceProps* props,
robertphillips37bd7c32016-03-17 14:31:39 -0700612 SkAlphaType at) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800613 return nullptr;
614}
615
616#endif