1 /*
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 ///////////////////////////////////////////////////////////////////////////////
13 class SkSpecialImage_Base : public SkSpecialImage {
14 public:
SkSpecialImage_Base(SkImageFilter::Proxy * proxy,const SkIRect & subset,uint32_t uniqueID)15     SkSpecialImage_Base(SkImageFilter::Proxy* proxy, const SkIRect& subset, uint32_t uniqueID)
16         : INHERITED(proxy, subset, uniqueID) {
17     }
~SkSpecialImage_Base()18     virtual ~SkSpecialImage_Base() { }
19 
20     virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) const = 0;
21 
onPeekPixels(SkPixmap *) const22     virtual bool onPeekPixels(SkPixmap*) const { return false; }
23 
onPeekTexture() const24     virtual GrTexture* onPeekTexture() const { return nullptr; }
25 
26     // Delete this entry point ASAP (see skbug.com/4965)
27     virtual bool getBitmap(SkBitmap* result) const = 0;
28 
onNewSurface(const SkImageInfo & info) const29     virtual SkSpecialSurface* onNewSurface(const SkImageInfo& info) const { return nullptr; }
30 
31 private:
32     typedef SkSpecialImage INHERITED;
33 };
34 
35 ///////////////////////////////////////////////////////////////////////////////
as_IB(const SkSpecialImage * image)36 static inline const SkSpecialImage_Base* as_IB(const SkSpecialImage* image) {
37     return static_cast<const SkSpecialImage_Base*>(image);
38 }
39 
draw(SkCanvas * canvas,SkScalar x,SkScalar y,const SkPaint * paint) const40 void SkSpecialImage::draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const {
41     return as_IB(this)->onDraw(canvas, x, y, paint);
42 }
43 
peekPixels(SkPixmap * pixmap) const44 bool SkSpecialImage::peekPixels(SkPixmap* pixmap) const {
45     return as_IB(this)->onPeekPixels(pixmap);
46 }
47 
peekTexture() const48 GrTexture* SkSpecialImage::peekTexture() const {
49     return as_IB(this)->onPeekTexture();
50 }
51 
newSurface(const SkImageInfo & info) const52 SkSpecialSurface* SkSpecialImage::newSurface(const SkImageInfo& info) const {
53     return as_IB(this)->onNewSurface(info);
54 }
55 
56 #if SK_SUPPORT_GPU
57 #include "SkGr.h"
58 #include "SkGrPixelRef.h"
59 #endif
60 
internal_fromBM(SkImageFilter::Proxy * proxy,const SkBitmap & src)61 SkSpecialImage* 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 
internal_getBM(SkBitmap * result)74 bool 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 
internal_getProxy()81 SkImageFilter::Proxy* SkSpecialImage::internal_getProxy() {
82     SkASSERT(fProxy);
83     return fProxy;
84 }
85 
86 ///////////////////////////////////////////////////////////////////////////////
87 #include "SkImage.h"
88 #if SK_SUPPORT_GPU
89 #include "SkGrPriv.h"
90 #endif
91 
92 class SkSpecialImage_Image : public SkSpecialImage_Base {
93 public:
SkSpecialImage_Image(SkImageFilter::Proxy * proxy,const SkIRect & subset,const SkImage * image)94     SkSpecialImage_Image(SkImageFilter::Proxy* proxy, const SkIRect& subset, const SkImage* image)
95         : INHERITED(proxy, subset, image->uniqueID())
96         , fImage(SkRef(image)) {
97     }
98 
~SkSpecialImage_Image()99     ~SkSpecialImage_Image() override { }
100 
isOpaque() const101     bool isOpaque() const override { return fImage->isOpaque(); }
102 
getSize() const103     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 
onDraw(SkCanvas * canvas,SkScalar x,SkScalar y,const SkPaint * paint) const120     void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
121         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 
onPeekPixels(SkPixmap * pixmap) const127     bool onPeekPixels(SkPixmap* pixmap) const override {
128         return fImage->peekPixels(pixmap);
129     }
130 
onPeekTexture() const131     GrTexture* onPeekTexture() const override { return fImage->getTexture(); }
132 
getBitmap(SkBitmap * result) const133     bool getBitmap(SkBitmap* result) const override {
134         return false;
135     }
136 
onNewSurface(const SkImageInfo & info) const137     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 
144             return SkSpecialSurface::NewRenderTarget(this->proxy(), texture->getContext(), desc);
145         }
146 #endif
147         return SkSpecialSurface::NewRaster(this->proxy(), info, nullptr);
148     }
149 
150 private:
151     SkAutoTUnref<const SkImage> fImage;
152 
153     typedef SkSpecialImage_Base INHERITED;
154 };
155 
156 #ifdef SK_DEBUG
rect_fits(const SkIRect & rect,int width,int height)157 static 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 
NewFromImage(const SkIRect & subset,const SkImage * image)165 SkSpecialImage* SkSpecialImage::NewFromImage(const SkIRect& subset, const SkImage* image) {
166     SkASSERT(rect_fits(subset, image->width(), image->height()));
167     return new SkSpecialImage_Image(nullptr, subset, image);
168 }
169 
170 ///////////////////////////////////////////////////////////////////////////////
171 #include "SkBitmap.h"
172 #include "SkImageInfo.h"
173 #include "SkPixelRef.h"
174 
175 class SkSpecialImage_Raster : public SkSpecialImage_Base {
176 public:
SkSpecialImage_Raster(SkImageFilter::Proxy * proxy,const SkIRect & subset,const SkBitmap & bm)177     SkSpecialImage_Raster(SkImageFilter::Proxy* proxy, const SkIRect& subset, const SkBitmap& bm)
178         : INHERITED(proxy, subset, bm.getGenerationID())
179         , 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 
~SkSpecialImage_Raster()187     ~SkSpecialImage_Raster() override { }
188 
isOpaque() const189     bool isOpaque() const override { return fBitmap.isOpaque(); }
190 
getSize() const191     size_t getSize() const override { return fBitmap.getSize(); }
192 
onDraw(SkCanvas * canvas,SkScalar x,SkScalar y,const SkPaint * paint) const193     void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
194         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 
onPeekPixels(SkPixmap * pixmap) const201     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 
getBitmap(SkBitmap * result) const216     bool getBitmap(SkBitmap* result) const override {
217         *result = fBitmap;
218         return true;
219     }
220 
onNewSurface(const SkImageInfo & info) const221     SkSpecialSurface* onNewSurface(const SkImageInfo& info) const override {
222         return SkSpecialSurface::NewRaster(this->proxy(), info, nullptr);
223     }
224 
225 private:
226     SkBitmap fBitmap;
227 
228     typedef SkSpecialImage_Base INHERITED;
229 };
230 
NewFromRaster(SkImageFilter::Proxy * proxy,const SkIRect & subset,const SkBitmap & bm)231 SkSpecialImage* SkSpecialImage::NewFromRaster(SkImageFilter::Proxy* proxy,
232                                               const SkIRect& subset,
233                                               const SkBitmap& bm) {
234     SkASSERT(nullptr == bm.getTexture());
235     SkASSERT(rect_fits(subset, bm.width(), bm.height()));
236     return new SkSpecialImage_Raster(proxy, subset, bm);
237 }
238 
239 #if SK_SUPPORT_GPU
240 ///////////////////////////////////////////////////////////////////////////////
241 #include "GrTexture.h"
242 
243 class SkSpecialImage_Gpu : public SkSpecialImage_Base {
244 public:
SkSpecialImage_Gpu(SkImageFilter::Proxy * proxy,const SkIRect & subset,uint32_t uniqueID,GrTexture * tex,SkAlphaType at)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) {
250     }
251 
~SkSpecialImage_Gpu()252     ~SkSpecialImage_Gpu() override { }
253 
isOpaque() const254     bool isOpaque() const override {
255         return GrPixelConfigIsOpaque(fTexture->config()) || fAlphaType == kOpaque_SkAlphaType;
256     }
257 
getSize() const258     size_t getSize() const override { return fTexture->gpuMemorySize(); }
259 
onDraw(SkCanvas * canvas,SkScalar x,SkScalar y,const SkPaint * paint) const260     void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
261         SkRect dst = SkRect::MakeXYWH(x, y,
262                                       this->subset().width(), this->subset().height());
263 
264         SkBitmap bm;
265 
266         GrWrapTextureInBitmap(fTexture,
267                               fTexture->width(), fTexture->height(), this->isOpaque(), &bm);
268 
269         canvas->drawBitmapRect(bm, this->subset(),
270                                dst, paint, SkCanvas::kStrict_SrcRectConstraint);
271     }
272 
onPeekTexture() const273     GrTexture* onPeekTexture() const override { return fTexture; }
274 
getBitmap(SkBitmap * result) const275     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 
onNewSurface(const SkImageInfo & info) const287     SkSpecialSurface* onNewSurface(const SkImageInfo& info) const override {
288         GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(info);
289         desc.fFlags = kRenderTarget_GrSurfaceFlag;
290 
291         return SkSpecialSurface::NewRenderTarget(this->proxy(), fTexture->getContext(), desc);
292     }
293 
294 private:
295     SkAutoTUnref<GrTexture> fTexture;
296     const SkAlphaType       fAlphaType;
297 
298     typedef SkSpecialImage_Base INHERITED;
299 };
300 
NewFromGpu(SkImageFilter::Proxy * proxy,const SkIRect & subset,uint32_t uniqueID,GrTexture * tex,SkAlphaType at)301 SkSpecialImage* SkSpecialImage::NewFromGpu(SkImageFilter::Proxy* proxy,
302                                            const SkIRect& subset,
303                                            uint32_t uniqueID,
304                                            GrTexture* tex,
305                                            SkAlphaType at) {
306     SkASSERT(rect_fits(subset, tex->width(), tex->height()));
307     return new SkSpecialImage_Gpu(proxy, subset, uniqueID, tex, at);
308 }
309 
310 #else
311 
NewFromGpu(SkImageFilter::Proxy * proxy,const SkIRect & subset,uint32_t uniqueID,GrTexture * tex,SkAlphaType at)312 SkSpecialImage* SkSpecialImage::NewFromGpu(SkImageFilter::Proxy* proxy,
313                                            const SkIRect& subset,
314                                            uint32_t uniqueID,
315                                            GrTexture* tex,
316                                            SkAlphaType at) {
317     return nullptr;
318 }
319 
320 #endif
321