blob: 50117b2e83556e64a1fe70dd2e218c8b1532a3ea [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"
9#include "SkSpecialImage.h"
10#include "SkSpecialSurface.h"
11
12///////////////////////////////////////////////////////////////////////////////
13class SkSpecialImage_Base : public SkSpecialImage {
14public:
robertphillips3b087f42016-02-18 08:48:03 -080015 SkSpecialImage_Base(SkImageFilter::Proxy* proxy, const SkIRect& subset, uint32_t uniqueID)
16 : INHERITED(proxy, subset, uniqueID) {
17 }
robertphillipsb6c65e92016-02-04 10:52:42 -080018 virtual ~SkSpecialImage_Base() { }
19
robertphillipse8c34972016-02-16 12:09:36 -080020 virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) const = 0;
robertphillipsb6c65e92016-02-04 10:52:42 -080021
22 virtual bool onPeekPixels(SkPixmap*) const { return false; }
23
24 virtual GrTexture* onPeekTexture() const { return nullptr; }
25
robertphillips3b087f42016-02-18 08:48:03 -080026 // Delete this entry point ASAP (see skbug.com/4965)
27 virtual bool getBitmap(SkBitmap* result) const = 0;
28
robertphillipsb6c65e92016-02-04 10:52:42 -080029 virtual SkSpecialSurface* onNewSurface(const SkImageInfo& info) const { return nullptr; }
30
31private:
32 typedef SkSpecialImage INHERITED;
33};
34
35///////////////////////////////////////////////////////////////////////////////
36static inline const SkSpecialImage_Base* as_IB(const SkSpecialImage* image) {
37 return static_cast<const SkSpecialImage_Base*>(image);
38}
39
robertphillipse8c34972016-02-16 12:09:36 -080040void SkSpecialImage::draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const {
robertphillipsb6c65e92016-02-04 10:52:42 -080041 return as_IB(this)->onDraw(canvas, x, y, paint);
42}
43
44bool SkSpecialImage::peekPixels(SkPixmap* pixmap) const {
45 return as_IB(this)->onPeekPixels(pixmap);
46}
47
48GrTexture* SkSpecialImage::peekTexture() const {
49 return as_IB(this)->onPeekTexture();
50}
51
52SkSpecialSurface* SkSpecialImage::newSurface(const SkImageInfo& info) const {
53 return as_IB(this)->onNewSurface(info);
54}
55
robertphillips3b087f42016-02-18 08:48:03 -080056#if SK_SUPPORT_GPU
57#include "SkGr.h"
58#include "SkGrPixelRef.h"
59#endif
60
61SkSpecialImage* SkSpecialImage::internal_fromBM(SkImageFilter::Proxy* proxy,
62 const SkBitmap& src) {
63 // Need to test offset case! (see skbug.com/4967)
64 if (src.getTexture()) {
65 return SkSpecialImage::NewFromGpu(proxy,
66 src.bounds(),
67 src.getGenerationID(),
68 src.getTexture());
69 }
70
71 return SkSpecialImage::NewFromRaster(proxy, src.bounds(), src);
72}
73
74bool SkSpecialImage::internal_getBM(SkBitmap* result) {
75 const SkSpecialImage_Base* ib = as_IB(this);
76
77 // TODO: need to test offset case! (see skbug.com/4967)
78 return ib->getBitmap(result);
79}
80
81SkImageFilter::Proxy* SkSpecialImage::internal_getProxy() {
82 SkASSERT(fProxy);
83 return fProxy;
84}
85
robertphillipsb6c65e92016-02-04 10:52:42 -080086///////////////////////////////////////////////////////////////////////////////
87#include "SkImage.h"
88#if SK_SUPPORT_GPU
robertphillipsb6c65e92016-02-04 10:52:42 -080089#include "SkGrPriv.h"
90#endif
91
92class SkSpecialImage_Image : public SkSpecialImage_Base {
93public:
robertphillips3b087f42016-02-18 08:48:03 -080094 SkSpecialImage_Image(SkImageFilter::Proxy* proxy, const SkIRect& subset, const SkImage* image)
95 : INHERITED(proxy, subset, image->uniqueID())
robertphillipsb6c65e92016-02-04 10:52:42 -080096 , fImage(SkRef(image)) {
97 }
98
99 ~SkSpecialImage_Image() override { }
100
robertphillips3b087f42016-02-18 08:48:03 -0800101 bool isOpaque() const override { return fImage->isOpaque(); }
102
103 size_t getSize() const override {
104#if SK_SUPPORT_GPU
105 if (fImage->getTexture()) {
106 return fImage->getTexture()->gpuMemorySize();
107 } else
108#endif
109 {
110 SkImageInfo info;
111 size_t rowBytes;
112
113 if (fImage->peekPixels(&info, &rowBytes)) {
114 return info.height() * rowBytes;
115 }
116 }
117 return 0;
118 }
119
robertphillipse8c34972016-02-16 12:09:36 -0800120 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800121 SkRect dst = SkRect::MakeXYWH(x, y, this->subset().width(), this->subset().height());
122
123 canvas->drawImageRect(fImage, this->subset(),
124 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
125 }
126
127 bool onPeekPixels(SkPixmap* pixmap) const override {
128 return fImage->peekPixels(pixmap);
129 }
130
131 GrTexture* onPeekTexture() const override { return fImage->getTexture(); }
132
robertphillips3b087f42016-02-18 08:48:03 -0800133 bool getBitmap(SkBitmap* result) const override {
134 return false;
135 }
136
robertphillipsb6c65e92016-02-04 10:52:42 -0800137 SkSpecialSurface* onNewSurface(const SkImageInfo& info) const override {
138#if SK_SUPPORT_GPU
139 GrTexture* texture = fImage->getTexture();
140 if (texture) {
141 GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(info);
142 desc.fFlags = kRenderTarget_GrSurfaceFlag;
143
robertphillips3b087f42016-02-18 08:48:03 -0800144 return SkSpecialSurface::NewRenderTarget(this->proxy(), texture->getContext(), desc);
robertphillipsb6c65e92016-02-04 10:52:42 -0800145 }
146#endif
robertphillips3b087f42016-02-18 08:48:03 -0800147 return SkSpecialSurface::NewRaster(this->proxy(), info, nullptr);
robertphillipsb6c65e92016-02-04 10:52:42 -0800148 }
149
150private:
151 SkAutoTUnref<const SkImage> fImage;
152
153 typedef SkSpecialImage_Base INHERITED;
154};
155
156#ifdef SK_DEBUG
157static bool rect_fits(const SkIRect& rect, int width, int height) {
158 return rect.fLeft >= 0 && rect.fLeft < width && rect.fLeft < rect.fRight &&
159 rect.fRight >= 0 && rect.fRight <= width &&
160 rect.fTop >= 0 && rect.fTop < height && rect.fTop < rect.fBottom &&
161 rect.fBottom >= 0 && rect.fBottom <= height;
162}
163#endif
164
165SkSpecialImage* SkSpecialImage::NewFromImage(const SkIRect& subset, const SkImage* image) {
166 SkASSERT(rect_fits(subset, image->width(), image->height()));
robertphillips3b087f42016-02-18 08:48:03 -0800167 return new SkSpecialImage_Image(nullptr, subset, image);
robertphillipsb6c65e92016-02-04 10:52:42 -0800168}
169
170///////////////////////////////////////////////////////////////////////////////
171#include "SkBitmap.h"
172#include "SkImageInfo.h"
173#include "SkPixelRef.h"
174
175class SkSpecialImage_Raster : public SkSpecialImage_Base {
176public:
robertphillips3b087f42016-02-18 08:48:03 -0800177 SkSpecialImage_Raster(SkImageFilter::Proxy* proxy, const SkIRect& subset, const SkBitmap& bm)
178 : INHERITED(proxy, subset, bm.getGenerationID())
robertphillipsb6c65e92016-02-04 10:52:42 -0800179 , fBitmap(bm) {
180 if (bm.pixelRef()->isPreLocked()) {
181 // we only preemptively lock if there is no chance of triggering something expensive
182 // like a lazy decode or imagegenerator. PreLocked means it is flat pixels already.
183 fBitmap.lockPixels();
184 }
185 }
186
187 ~SkSpecialImage_Raster() override { }
188
robertphillips3b087f42016-02-18 08:48:03 -0800189 bool isOpaque() const override { return fBitmap.isOpaque(); }
190
191 size_t getSize() const override { return fBitmap.getSize(); }
192
robertphillipse8c34972016-02-16 12:09:36 -0800193 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800194 SkRect dst = SkRect::MakeXYWH(x, y,
195 this->subset().width(), this->subset().height());
196
197 canvas->drawBitmapRect(fBitmap, this->subset(),
198 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
199 }
200
201 bool onPeekPixels(SkPixmap* pixmap) const override {
202 const SkImageInfo info = fBitmap.info();
203 if ((kUnknown_SkColorType == info.colorType()) || !fBitmap.getPixels()) {
204 return false;
205 }
206 const void* pixels = fBitmap.getPixels();
207 if (pixels) {
208 if (pixmap) {
209 pixmap->reset(info, pixels, fBitmap.rowBytes());
210 }
211 return true;
212 }
213 return false;
214 }
215
robertphillips3b087f42016-02-18 08:48:03 -0800216 bool getBitmap(SkBitmap* result) const override {
217 *result = fBitmap;
218 return true;
219 }
220
robertphillipsb6c65e92016-02-04 10:52:42 -0800221 SkSpecialSurface* onNewSurface(const SkImageInfo& info) const override {
robertphillips3b087f42016-02-18 08:48:03 -0800222 return SkSpecialSurface::NewRaster(this->proxy(), info, nullptr);
robertphillipsb6c65e92016-02-04 10:52:42 -0800223 }
224
225private:
226 SkBitmap fBitmap;
227
228 typedef SkSpecialImage_Base INHERITED;
229};
230
robertphillips3b087f42016-02-18 08:48:03 -0800231SkSpecialImage* SkSpecialImage::NewFromRaster(SkImageFilter::Proxy* proxy,
232 const SkIRect& subset,
233 const SkBitmap& bm) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800234 SkASSERT(nullptr == bm.getTexture());
235 SkASSERT(rect_fits(subset, bm.width(), bm.height()));
robertphillips3b087f42016-02-18 08:48:03 -0800236 return new SkSpecialImage_Raster(proxy, subset, bm);
robertphillipsb6c65e92016-02-04 10:52:42 -0800237}
238
239#if SK_SUPPORT_GPU
240///////////////////////////////////////////////////////////////////////////////
241#include "GrTexture.h"
242
243class SkSpecialImage_Gpu : public SkSpecialImage_Base {
robertphillips3b087f42016-02-18 08:48:03 -0800244public:
245 SkSpecialImage_Gpu(SkImageFilter::Proxy* proxy, const SkIRect& subset,
246 uint32_t uniqueID, GrTexture* tex, SkAlphaType at)
247 : INHERITED(proxy, subset, uniqueID)
248 , fTexture(SkRef(tex))
249 , fAlphaType(at) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800250 }
251
252 ~SkSpecialImage_Gpu() override { }
253
robertphillips3b087f42016-02-18 08:48:03 -0800254 bool isOpaque() const override {
255 return GrPixelConfigIsOpaque(fTexture->config()) || fAlphaType == kOpaque_SkAlphaType;
256 }
257
258 size_t getSize() const override { return fTexture->gpuMemorySize(); }
259
robertphillipse8c34972016-02-16 12:09:36 -0800260 void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
robertphillipsb6c65e92016-02-04 10:52:42 -0800261 SkRect dst = SkRect::MakeXYWH(x, y,
262 this->subset().width(), this->subset().height());
263
264 SkBitmap bm;
265
robertphillipsb6c65e92016-02-04 10:52:42 -0800266 GrWrapTextureInBitmap(fTexture,
robertphillips3b087f42016-02-18 08:48:03 -0800267 fTexture->width(), fTexture->height(), this->isOpaque(), &bm);
robertphillipsb6c65e92016-02-04 10:52:42 -0800268
269 canvas->drawBitmapRect(bm, this->subset(),
270 dst, paint, SkCanvas::kStrict_SrcRectConstraint);
271 }
272
273 GrTexture* onPeekTexture() const override { return fTexture; }
274
robertphillips3b087f42016-02-18 08:48:03 -0800275 bool getBitmap(SkBitmap* result) const override {
276 const SkImageInfo info = GrMakeInfoFromTexture(fTexture,
277 this->width(), this->height(),
278 this->isOpaque());
279 if (!result->setInfo(info)) {
280 return false;
281 }
282
283 result->setPixelRef(new SkGrPixelRef(info, fTexture))->unref();
284 return true;
285 }
286
robertphillipsb6c65e92016-02-04 10:52:42 -0800287 SkSpecialSurface* onNewSurface(const SkImageInfo& info) const override {
288 GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(info);
289 desc.fFlags = kRenderTarget_GrSurfaceFlag;
290
robertphillips3b087f42016-02-18 08:48:03 -0800291 return SkSpecialSurface::NewRenderTarget(this->proxy(), fTexture->getContext(), desc);
robertphillipsb6c65e92016-02-04 10:52:42 -0800292 }
293
294private:
295 SkAutoTUnref<GrTexture> fTexture;
robertphillips3b087f42016-02-18 08:48:03 -0800296 const SkAlphaType fAlphaType;
robertphillipsb6c65e92016-02-04 10:52:42 -0800297
298 typedef SkSpecialImage_Base INHERITED;
299};
300
robertphillips3b087f42016-02-18 08:48:03 -0800301SkSpecialImage* SkSpecialImage::NewFromGpu(SkImageFilter::Proxy* proxy,
302 const SkIRect& subset,
303 uint32_t uniqueID,
304 GrTexture* tex,
305 SkAlphaType at) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800306 SkASSERT(rect_fits(subset, tex->width(), tex->height()));
robertphillips3b087f42016-02-18 08:48:03 -0800307 return new SkSpecialImage_Gpu(proxy, subset, uniqueID, tex, at);
robertphillipsb6c65e92016-02-04 10:52:42 -0800308}
309
310#else
311
robertphillips3b087f42016-02-18 08:48:03 -0800312SkSpecialImage* SkSpecialImage::NewFromGpu(SkImageFilter::Proxy* proxy,
313 const SkIRect& subset,
314 uint32_t uniqueID,
315 GrTexture* tex,
316 SkAlphaType at) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800317 return nullptr;
318}
319
320#endif