blob: 88d90b860253cb830cdad4595b546a7b09731906 [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 */
7
8#include "SkCanvas.h"
bsalomon84a4e5a2016-02-29 11:41:52 -08009#include "SkImage_Base.h"
robertphillipsb6c65e92016-02-04 10:52:42 -080010#include "SkSpecialImage.h"
11#include "SkSpecialSurface.h"
12
13///////////////////////////////////////////////////////////////////////////////
14class SkSpecialImage_Base : public SkSpecialImage {
15public:
robertphillips3b087f42016-02-18 08:48:03 -080016 SkSpecialImage_Base(SkImageFilter::Proxy* proxy, const SkIRect& subset, uint32_t uniqueID)
17 : INHERITED(proxy, subset, uniqueID) {
18 }
robertphillipsb6c65e92016-02-04 10:52:42 -080019 virtual ~SkSpecialImage_Base() { }
20
robertphillipse8c34972016-02-16 12:09:36 -080021 virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) const = 0;
robertphillipsb6c65e92016-02-04 10:52:42 -080022
23 virtual bool onPeekPixels(SkPixmap*) const { return false; }
24
25 virtual GrTexture* onPeekTexture() const { return nullptr; }
26
robertphillips3b087f42016-02-18 08:48:03 -080027 // Delete this entry point ASAP (see skbug.com/4965)
28 virtual bool getBitmap(SkBitmap* result) const = 0;
29
robertphillipsb6c65e92016-02-04 10:52:42 -080030 virtual SkSpecialSurface* onNewSurface(const SkImageInfo& info) const { return nullptr; }
31
32private:
33 typedef SkSpecialImage INHERITED;
34};
35
36///////////////////////////////////////////////////////////////////////////////
bsalomon84a4e5a2016-02-29 11:41:52 -080037static inline const SkSpecialImage_Base* as_SIB(const SkSpecialImage* image) {
robertphillipsb6c65e92016-02-04 10:52:42 -080038 return static_cast<const SkSpecialImage_Base*>(image);
39}
40
robertphillipse8c34972016-02-16 12:09:36 -080041void SkSpecialImage::draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const {
bsalomon84a4e5a2016-02-29 11:41:52 -080042 return as_SIB(this)->onDraw(canvas, x, y, paint);
robertphillipsb6c65e92016-02-04 10:52:42 -080043}
44
45bool SkSpecialImage::peekPixels(SkPixmap* pixmap) const {
bsalomon84a4e5a2016-02-29 11:41:52 -080046 return as_SIB(this)->onPeekPixels(pixmap);
robertphillipsb6c65e92016-02-04 10:52:42 -080047}
48
49GrTexture* SkSpecialImage::peekTexture() const {
bsalomon84a4e5a2016-02-29 11:41:52 -080050 return as_SIB(this)->onPeekTexture();
robertphillipsb6c65e92016-02-04 10:52:42 -080051}
52
53SkSpecialSurface* SkSpecialImage::newSurface(const SkImageInfo& info) const {
bsalomon84a4e5a2016-02-29 11:41:52 -080054 return as_SIB(this)->onNewSurface(info);
robertphillipsb6c65e92016-02-04 10:52:42 -080055}
56
robertphillips3b087f42016-02-18 08:48:03 -080057#if SK_SUPPORT_GPU
58#include "SkGr.h"
59#include "SkGrPixelRef.h"
60#endif
61
62SkSpecialImage* SkSpecialImage::internal_fromBM(SkImageFilter::Proxy* proxy,
63 const SkBitmap& src) {
64 // Need to test offset case! (see skbug.com/4967)
65 if (src.getTexture()) {
66 return SkSpecialImage::NewFromGpu(proxy,
67 src.bounds(),
68 src.getGenerationID(),
69 src.getTexture());
70 }
71
72 return SkSpecialImage::NewFromRaster(proxy, src.bounds(), src);
73}
74
75bool SkSpecialImage::internal_getBM(SkBitmap* result) {
bsalomon84a4e5a2016-02-29 11:41:52 -080076 const SkSpecialImage_Base* ib = as_SIB(this);
robertphillips3b087f42016-02-18 08:48:03 -080077
78 // TODO: need to test offset case! (see skbug.com/4967)
79 return ib->getBitmap(result);
80}
81
82SkImageFilter::Proxy* SkSpecialImage::internal_getProxy() {
83 SkASSERT(fProxy);
84 return fProxy;
85}
86
robertphillipsb6c65e92016-02-04 10:52:42 -080087///////////////////////////////////////////////////////////////////////////////
88#include "SkImage.h"
89#if SK_SUPPORT_GPU
robertphillipsb6c65e92016-02-04 10:52:42 -080090#include "SkGrPriv.h"
91#endif
92
93class SkSpecialImage_Image : public SkSpecialImage_Base {
94public:
robertphillips3b087f42016-02-18 08:48:03 -080095 SkSpecialImage_Image(SkImageFilter::Proxy* proxy, const SkIRect& subset, const SkImage* image)
96 : INHERITED(proxy, subset, image->uniqueID())
robertphillipsb6c65e92016-02-04 10:52:42 -080097 , fImage(SkRef(image)) {
98 }
99
100 ~SkSpecialImage_Image() override { }
101
robertphillips3b087f42016-02-18 08:48:03 -0800102 bool isOpaque() const override { return fImage->isOpaque(); }
103
104 size_t getSize() const override {
105#if SK_SUPPORT_GPU
bsalomon84a4e5a2016-02-29 11:41:52 -0800106 if (GrTexture* texture = as_IB(fImage.get())->peekTexture()) {
107 return texture->gpuMemorySize();
robertphillips3b087f42016-02-18 08:48:03 -0800108 } else
109#endif
110 {
111 SkImageInfo info;
112 size_t rowBytes;
113
114 if (fImage->peekPixels(&info, &rowBytes)) {
115 return info.height() * rowBytes;
116 }
117 }
118 return 0;
119 }
120
robertphillipse8c34972016-02-16 12:09:36 -0800121 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800122 SkRect dst = SkRect::MakeXYWH(x, y, this->subset().width(), this->subset().height());
123
124 canvas->drawImageRect(fImage, this->subset(),
125 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
126 }
127
128 bool onPeekPixels(SkPixmap* pixmap) const override {
129 return fImage->peekPixels(pixmap);
130 }
131
bsalomon84a4e5a2016-02-29 11:41:52 -0800132 GrTexture* onPeekTexture() const override { return as_IB(fImage.get())->peekTexture(); }
robertphillipsb6c65e92016-02-04 10:52:42 -0800133
robertphillips3b087f42016-02-18 08:48:03 -0800134 bool getBitmap(SkBitmap* result) const override {
135 return false;
136 }
137
robertphillipsb6c65e92016-02-04 10:52:42 -0800138 SkSpecialSurface* onNewSurface(const SkImageInfo& info) const override {
139#if SK_SUPPORT_GPU
bsalomon84a4e5a2016-02-29 11:41:52 -0800140 GrTexture* texture = as_IB(fImage.get())->peekTexture();
robertphillipsb6c65e92016-02-04 10:52:42 -0800141 if (texture) {
142 GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(info);
143 desc.fFlags = kRenderTarget_GrSurfaceFlag;
144
robertphillips3b087f42016-02-18 08:48:03 -0800145 return SkSpecialSurface::NewRenderTarget(this->proxy(), texture->getContext(), desc);
robertphillipsb6c65e92016-02-04 10:52:42 -0800146 }
147#endif
robertphillips3b087f42016-02-18 08:48:03 -0800148 return SkSpecialSurface::NewRaster(this->proxy(), info, nullptr);
robertphillipsb6c65e92016-02-04 10:52:42 -0800149 }
150
151private:
152 SkAutoTUnref<const SkImage> fImage;
153
154 typedef SkSpecialImage_Base INHERITED;
155};
156
157#ifdef SK_DEBUG
158static bool rect_fits(const SkIRect& rect, int width, int height) {
159 return rect.fLeft >= 0 && rect.fLeft < width && rect.fLeft < rect.fRight &&
160 rect.fRight >= 0 && rect.fRight <= width &&
161 rect.fTop >= 0 && rect.fTop < height && rect.fTop < rect.fBottom &&
162 rect.fBottom >= 0 && rect.fBottom <= height;
163}
164#endif
165
166SkSpecialImage* SkSpecialImage::NewFromImage(const SkIRect& subset, const SkImage* image) {
167 SkASSERT(rect_fits(subset, image->width(), image->height()));
robertphillips3b087f42016-02-18 08:48:03 -0800168 return new SkSpecialImage_Image(nullptr, subset, image);
robertphillipsb6c65e92016-02-04 10:52:42 -0800169}
170
171///////////////////////////////////////////////////////////////////////////////
172#include "SkBitmap.h"
173#include "SkImageInfo.h"
174#include "SkPixelRef.h"
175
176class SkSpecialImage_Raster : public SkSpecialImage_Base {
177public:
robertphillips3b087f42016-02-18 08:48:03 -0800178 SkSpecialImage_Raster(SkImageFilter::Proxy* proxy, const SkIRect& subset, const SkBitmap& bm)
179 : INHERITED(proxy, subset, bm.getGenerationID())
robertphillipsb6c65e92016-02-04 10:52:42 -0800180 , fBitmap(bm) {
181 if (bm.pixelRef()->isPreLocked()) {
182 // we only preemptively lock if there is no chance of triggering something expensive
183 // like a lazy decode or imagegenerator. PreLocked means it is flat pixels already.
184 fBitmap.lockPixels();
185 }
186 }
187
188 ~SkSpecialImage_Raster() override { }
189
robertphillips3b087f42016-02-18 08:48:03 -0800190 bool isOpaque() const override { return fBitmap.isOpaque(); }
191
192 size_t getSize() const override { return fBitmap.getSize(); }
193
robertphillipse8c34972016-02-16 12:09:36 -0800194 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800195 SkRect dst = SkRect::MakeXYWH(x, y,
196 this->subset().width(), this->subset().height());
197
198 canvas->drawBitmapRect(fBitmap, this->subset(),
199 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
200 }
201
202 bool onPeekPixels(SkPixmap* pixmap) const override {
203 const SkImageInfo info = fBitmap.info();
204 if ((kUnknown_SkColorType == info.colorType()) || !fBitmap.getPixels()) {
205 return false;
206 }
207 const void* pixels = fBitmap.getPixels();
208 if (pixels) {
209 if (pixmap) {
210 pixmap->reset(info, pixels, fBitmap.rowBytes());
211 }
212 return true;
213 }
214 return false;
215 }
216
robertphillips3b087f42016-02-18 08:48:03 -0800217 bool getBitmap(SkBitmap* result) const override {
218 *result = fBitmap;
219 return true;
220 }
221
robertphillipsb6c65e92016-02-04 10:52:42 -0800222 SkSpecialSurface* onNewSurface(const SkImageInfo& info) const override {
robertphillips3b087f42016-02-18 08:48:03 -0800223 return SkSpecialSurface::NewRaster(this->proxy(), info, nullptr);
robertphillipsb6c65e92016-02-04 10:52:42 -0800224 }
225
226private:
227 SkBitmap fBitmap;
228
229 typedef SkSpecialImage_Base INHERITED;
230};
231
robertphillips3b087f42016-02-18 08:48:03 -0800232SkSpecialImage* SkSpecialImage::NewFromRaster(SkImageFilter::Proxy* proxy,
233 const SkIRect& subset,
234 const SkBitmap& bm) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800235 SkASSERT(nullptr == bm.getTexture());
236 SkASSERT(rect_fits(subset, bm.width(), bm.height()));
robertphillips3b087f42016-02-18 08:48:03 -0800237 return new SkSpecialImage_Raster(proxy, subset, bm);
robertphillipsb6c65e92016-02-04 10:52:42 -0800238}
239
240#if SK_SUPPORT_GPU
241///////////////////////////////////////////////////////////////////////////////
242#include "GrTexture.h"
243
244class SkSpecialImage_Gpu : public SkSpecialImage_Base {
robertphillips3b087f42016-02-18 08:48:03 -0800245public:
246 SkSpecialImage_Gpu(SkImageFilter::Proxy* proxy, const SkIRect& subset,
247 uint32_t uniqueID, GrTexture* tex, SkAlphaType at)
248 : INHERITED(proxy, subset, uniqueID)
249 , fTexture(SkRef(tex))
250 , fAlphaType(at) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800251 }
252
253 ~SkSpecialImage_Gpu() override { }
254
robertphillips3b087f42016-02-18 08:48:03 -0800255 bool isOpaque() const override {
256 return GrPixelConfigIsOpaque(fTexture->config()) || fAlphaType == kOpaque_SkAlphaType;
257 }
258
259 size_t getSize() const override { return fTexture->gpuMemorySize(); }
260
robertphillipse8c34972016-02-16 12:09:36 -0800261 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800262 SkRect dst = SkRect::MakeXYWH(x, y,
263 this->subset().width(), this->subset().height());
264
265 SkBitmap bm;
266
robertphillipsb6c65e92016-02-04 10:52:42 -0800267 GrWrapTextureInBitmap(fTexture,
robertphillips3b087f42016-02-18 08:48:03 -0800268 fTexture->width(), fTexture->height(), this->isOpaque(), &bm);
robertphillipsb6c65e92016-02-04 10:52:42 -0800269
270 canvas->drawBitmapRect(bm, this->subset(),
271 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
272 }
273
274 GrTexture* onPeekTexture() const override { return fTexture; }
275
robertphillips3b087f42016-02-18 08:48:03 -0800276 bool getBitmap(SkBitmap* result) const override {
277 const SkImageInfo info = GrMakeInfoFromTexture(fTexture,
278 this->width(), this->height(),
279 this->isOpaque());
280 if (!result->setInfo(info)) {
281 return false;
282 }
283
284 result->setPixelRef(new SkGrPixelRef(info, fTexture))->unref();
285 return true;
286 }
287
robertphillipsb6c65e92016-02-04 10:52:42 -0800288 SkSpecialSurface* onNewSurface(const SkImageInfo& info) const override {
289 GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(info);
290 desc.fFlags = kRenderTarget_GrSurfaceFlag;
291
robertphillips3b087f42016-02-18 08:48:03 -0800292 return SkSpecialSurface::NewRenderTarget(this->proxy(), fTexture->getContext(), desc);
robertphillipsb6c65e92016-02-04 10:52:42 -0800293 }
294
295private:
296 SkAutoTUnref<GrTexture> fTexture;
robertphillips3b087f42016-02-18 08:48:03 -0800297 const SkAlphaType fAlphaType;
robertphillipsb6c65e92016-02-04 10:52:42 -0800298
299 typedef SkSpecialImage_Base INHERITED;
300};
301
robertphillips3b087f42016-02-18 08:48:03 -0800302SkSpecialImage* SkSpecialImage::NewFromGpu(SkImageFilter::Proxy* proxy,
303 const SkIRect& subset,
304 uint32_t uniqueID,
305 GrTexture* tex,
306 SkAlphaType at) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800307 SkASSERT(rect_fits(subset, tex->width(), tex->height()));
robertphillips3b087f42016-02-18 08:48:03 -0800308 return new SkSpecialImage_Gpu(proxy, subset, uniqueID, tex, at);
robertphillipsb6c65e92016-02-04 10:52:42 -0800309}
310
311#else
312
robertphillips3b087f42016-02-18 08:48:03 -0800313SkSpecialImage* SkSpecialImage::NewFromGpu(SkImageFilter::Proxy* proxy,
314 const SkIRect& subset,
315 uint32_t uniqueID,
316 GrTexture* tex,
317 SkAlphaType at) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800318 return nullptr;
319}
320
321#endif