1/*
2 * Copyright 2010 The Android Open Source Project
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#ifndef SkDevice_DEFINED
9#define SkDevice_DEFINED
10
11#include "SkRefCnt.h"
12#include "SkBitmap.h"
13#include "SkCanvas.h"
14#include "SkColor.h"
15#include "SkDeviceProperties.h"
16#include "SkImageFilter.h"
17
18class SkClipStack;
19class SkDraw;
20struct SkIRect;
21class SkMatrix;
22class SkMetaData;
23class SkRegion;
24
25class GrRenderTarget;
26
27class SK_API SkBaseDevice : public SkRefCnt {
28public:
29    SK_DECLARE_INST_COUNT(SkBaseDevice)
30
31    /**
32     *  Construct a new device.
33    */
34    SkBaseDevice();
35
36    /**
37     *  Construct a new device.
38    */
39    SkBaseDevice(const SkDeviceProperties& deviceProperties);
40
41    virtual ~SkBaseDevice();
42
43    SkBaseDevice* createCompatibleDevice(const SkImageInfo&);
44
45    SkMetaData& getMetaData();
46
47    /** Return the image properties of the device. */
48    virtual const SkDeviceProperties& getDeviceProperties() const {
49        //Currently, all the properties are leaky.
50        return fLeakyProperties;
51    }
52
53    /**
54     *  Return ImageInfo for this device. If the canvas is not backed by pixels
55     *  (cpu or gpu), then the info's ColorType will be kUnknown_SkColorType.
56     */
57    virtual SkImageInfo imageInfo() const;
58
59    /**
60     *  Return the bounds of the device in the coordinate space of the root
61     *  canvas. The root device will have its top-left at 0,0, but other devices
62     *  such as those associated with saveLayer may have a non-zero origin.
63     */
64    void getGlobalBounds(SkIRect* bounds) const {
65        SkASSERT(bounds);
66        const SkIPoint& origin = this->getOrigin();
67        bounds->setXYWH(origin.x(), origin.y(), this->width(), this->height());
68    }
69
70#ifdef SK_SUPPORT_LEGACY_DEVICE_VIRTUAL_ISOPAQUE
71    virtual int width() const {
72        return this->imageInfo().width();
73    }
74    virtual int height() const {
75        return this->imageInfo().height();
76    }
77    virtual bool isOpaque() const {
78        return this->imageInfo().isOpaque();
79    }
80#else
81    int width() const {
82        return this->imageInfo().width();
83    }
84    int height() const {
85        return this->imageInfo().height();
86    }
87    bool isOpaque() const {
88        return this->imageInfo().isOpaque();
89    }
90#endif
91
92    /** Return the bitmap associated with this device. Call this each time you need
93        to access the bitmap, as it notifies the subclass to perform any flushing
94        etc. before you examine the pixels.
95        @param changePixels set to true if the caller plans to change the pixels
96        @return the device's bitmap
97    */
98    const SkBitmap& accessBitmap(bool changePixels);
99
100    bool writePixels(const SkImageInfo&, const void*, size_t rowBytes, int x, int y);
101
102    void* accessPixels(SkImageInfo* info, size_t* rowBytes);
103
104    /**
105     * Return the device's associated gpu render target, or NULL.
106     */
107    virtual GrRenderTarget* accessRenderTarget() = 0;
108
109
110    /**
111     *  Return the device's origin: its offset in device coordinates from
112     *  the default origin in its canvas' matrix/clip
113     */
114    const SkIPoint& getOrigin() const { return fOrigin; }
115
116    /**
117     * onAttachToCanvas is invoked whenever a device is installed in a canvas
118     * (i.e., setDevice, saveLayer (for the new device created by the save),
119     * and SkCanvas' SkBaseDevice & SkBitmap -taking ctors). It allows the
120     * devices to prepare for drawing (e.g., locking their pixels, etc.)
121     */
122    virtual void onAttachToCanvas(SkCanvas*) {
123        SkASSERT(!fAttachedToCanvas);
124        this->lockPixels();
125#ifdef SK_DEBUG
126        fAttachedToCanvas = true;
127#endif
128    };
129
130    /**
131     * onDetachFromCanvas notifies a device that it will no longer be drawn to.
132     * It gives the device a chance to clean up (e.g., unlock its pixels). It
133     * is invoked from setDevice (for the displaced device), restore and
134     * possibly from SkCanvas' dtor.
135     */
136    virtual void onDetachFromCanvas() {
137        SkASSERT(fAttachedToCanvas);
138        this->unlockPixels();
139#ifdef SK_DEBUG
140        fAttachedToCanvas = false;
141#endif
142    };
143
144protected:
145    enum Usage {
146       kGeneral_Usage,
147       kSaveLayer_Usage  // <! internal use only
148    };
149
150    struct TextFlags {
151        uint32_t            fFlags;     // SkPaint::getFlags()
152        SkPaint::Hinting    fHinting;
153    };
154
155    /**
156     *  Device may filter the text flags for drawing text here. If it wants to
157     *  make a change to the specified values, it should write them into the
158     *  textflags parameter (output) and return true. If the paint is fine as
159     *  is, then ignore the textflags parameter and return false.
160     *
161     *  The baseclass SkBaseDevice filters based on its depth and blitters.
162     */
163    virtual bool filterTextFlags(const SkPaint& paint, TextFlags*) = 0;
164
165    /**
166     *
167     *  DEPRECATED: This will be removed in a future change. Device subclasses
168     *  should use the matrix and clip from the SkDraw passed to draw functions.
169     *
170     *  Called with the correct matrix and clip before this device is drawn
171     *  to using those settings. If your subclass overrides this, be sure to
172     *  call through to the base class as well.
173     *
174     *  The clipstack is another view of the clip. It records the actual
175     *  geometry that went into building the region. It is present for devices
176     *  that want to parse it, but is not required: the region is a complete
177     *  picture of the current clip. (i.e. if you regionize all of the geometry
178     *  in the clipstack, you will arrive at an equivalent region to the one
179     *  passed in).
180     */
181     virtual void setMatrixClip(const SkMatrix&, const SkRegion&,
182                                const SkClipStack&) {};
183
184    /** Clears the entire device to the specified color (including alpha).
185     *  Ignores the clip.
186     */
187    virtual void clear(SkColor color) = 0;
188
189    SK_ATTR_DEPRECATED("use clear() instead")
190    void eraseColor(SkColor eraseColor) { this->clear(eraseColor); }
191
192    /** These are called inside the per-device-layer loop for each draw call.
193     When these are called, we have already applied any saveLayer operations,
194     and are handling any looping from the paint, and any effects from the
195     DrawFilter.
196     */
197    virtual void drawPaint(const SkDraw&, const SkPaint& paint) = 0;
198    virtual void drawPoints(const SkDraw&, SkCanvas::PointMode mode, size_t count,
199                            const SkPoint[], const SkPaint& paint) = 0;
200    virtual void drawRect(const SkDraw&, const SkRect& r,
201                          const SkPaint& paint) = 0;
202    virtual void drawOval(const SkDraw&, const SkRect& oval,
203                          const SkPaint& paint) = 0;
204    virtual void drawRRect(const SkDraw&, const SkRRect& rr,
205                           const SkPaint& paint) = 0;
206
207    // Default impl calls drawPath()
208    virtual void drawDRRect(const SkDraw&, const SkRRect& outer,
209                            const SkRRect& inner, const SkPaint&);
210
211    /**
212     *  If pathIsMutable, then the implementation is allowed to cast path to a
213     *  non-const pointer and modify it in place (as an optimization). Canvas
214     *  may do this to implement helpers such as drawOval, by placing a temp
215     *  path on the stack to hold the representation of the oval.
216     *
217     *  If prePathMatrix is not null, it should logically be applied before any
218     *  stroking or other effects. If there are no effects on the paint that
219     *  affect the geometry/rasterization, then the pre matrix can just be
220     *  pre-concated with the current matrix.
221     */
222    virtual void drawPath(const SkDraw&, const SkPath& path,
223                          const SkPaint& paint,
224                          const SkMatrix* prePathMatrix = NULL,
225                          bool pathIsMutable = false) = 0;
226    virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap,
227                            const SkMatrix& matrix, const SkPaint& paint) = 0;
228    virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap,
229                            int x, int y, const SkPaint& paint) = 0;
230
231    /**
232     *  The default impl. will create a bitmap-shader from the bitmap,
233     *  and call drawRect with it.
234     */
235    virtual void drawBitmapRect(const SkDraw&, const SkBitmap&,
236                                const SkRect* srcOrNull, const SkRect& dst,
237                                const SkPaint& paint,
238                                SkCanvas::DrawBitmapRectFlags flags) = 0;
239
240    /**
241     *  Does not handle text decoration.
242     *  Decorations (underline and stike-thru) will be handled by SkCanvas.
243     */
244    virtual void drawText(const SkDraw&, const void* text, size_t len,
245                          SkScalar x, SkScalar y, const SkPaint& paint) = 0;
246    virtual void drawPosText(const SkDraw&, const void* text, size_t len,
247                             const SkScalar pos[], SkScalar constY,
248                             int scalarsPerPos, const SkPaint& paint) = 0;
249    virtual void drawTextOnPath(const SkDraw&, const void* text, size_t len,
250                                const SkPath& path, const SkMatrix* matrix,
251                                const SkPaint& paint) = 0;
252    virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode, int vertexCount,
253                              const SkPoint verts[], const SkPoint texs[],
254                              const SkColor colors[], SkXfermode* xmode,
255                              const uint16_t indices[], int indexCount,
256                              const SkPaint& paint) = 0;
257    /** The SkDevice passed will be an SkDevice which was returned by a call to
258        onCreateDevice on this device with kSaveLayer_Usage.
259     */
260    virtual void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y,
261                            const SkPaint&) = 0;
262
263    bool readPixels(const SkImageInfo&, void* dst, size_t rowBytes, int x, int y);
264
265    ///////////////////////////////////////////////////////////////////////////
266
267    /** Update as needed the pixel value in the bitmap, so that the caller can
268        access the pixels directly.
269        @return The device contents as a bitmap
270    */
271    virtual const SkBitmap& onAccessBitmap() = 0;
272
273    /** Called when this device is installed into a Canvas. Balanced by a call
274        to unlockPixels() when the device is removed from a Canvas.
275    */
276    virtual void lockPixels() = 0;
277    virtual void unlockPixels() = 0;
278
279    /**
280     *  Returns true if the device allows processing of this imagefilter. If
281     *  false is returned, then the filter is ignored. This may happen for
282     *  some subclasses that do not support pixel manipulations after drawing
283     *  has occurred (e.g. printing). The default implementation returns true.
284     */
285    virtual bool allowImageFilter(const SkImageFilter*) = 0;
286
287    /**
288     *  Override and return true for filters that the device can handle
289     *  intrinsically. Doing so means that SkCanvas will pass-through this
290     *  filter to drawSprite and drawDevice (and potentially filterImage).
291     *  Returning false means the SkCanvas will have apply the filter itself,
292     *  and just pass the resulting image to the device.
293     */
294    virtual bool canHandleImageFilter(const SkImageFilter*) = 0;
295
296    /**
297     *  Related (but not required) to canHandleImageFilter, this method returns
298     *  true if the device could apply the filter to the src bitmap and return
299     *  the result (and updates offset as needed).
300     *  If the device does not recognize or support this filter,
301     *  it just returns false and leaves result and offset unchanged.
302     */
303    virtual bool filterImage(const SkImageFilter*, const SkBitmap&,
304                             const SkImageFilter::Context& ctx,
305                             SkBitmap* result, SkIPoint* offset) = 0;
306
307protected:
308    // default impl returns NULL
309    virtual SkSurface* newSurface(const SkImageInfo&);
310
311    // default impl returns NULL
312    virtual const void* peekPixels(SkImageInfo*, size_t* rowBytes);
313
314    /**
315     *  The caller is responsible for "pre-clipping" the dst. The impl can assume that the dst
316     *  image at the specified x,y offset will fit within the device's bounds.
317     *
318     *  This is explicitly asserted in readPixels(), the public way to call this.
319     */
320    virtual bool onReadPixels(const SkImageInfo&, void*, size_t, int x, int y);
321
322    /**
323     *  The caller is responsible for "pre-clipping" the src. The impl can assume that the src
324     *  image at the specified x,y offset will fit within the device's bounds.
325     *
326     *  This is explicitly asserted in writePixelsDirect(), the public way to call this.
327     */
328    virtual bool onWritePixels(const SkImageInfo&, const void*, size_t, int x, int y);
329
330    /**
331     *  Default impl returns NULL.
332     */
333    virtual void* onAccessPixels(SkImageInfo* info, size_t* rowBytes);
334
335    /**
336     *  Leaky properties are those which the device should be applying but it isn't.
337     *  These properties will be applied by the draw, when and as it can.
338     *  If the device does handle a property, that property should be set to the identity value
339     *  for that property, effectively making it non-leaky.
340     */
341    SkDeviceProperties fLeakyProperties;
342
343    /**
344     *  PRIVATE / EXPERIMENTAL -- do not call
345     *  Construct an acceleration object and attach it to 'picture'
346     */
347    virtual void EXPERIMENTAL_optimize(const SkPicture* picture);
348
349    /**
350     *  PRIVATE / EXPERIMENTAL -- do not call
351     *  Purge all discardable optimization information for 'picture'. If
352     *  picture is NULL then purge discardable information for all pictures.
353     */
354    virtual void EXPERIMENTAL_purge(const SkPicture* picture);
355
356    /**
357     *  PRIVATE / EXPERIMENTAL -- do not call
358     *  This entry point gives the backend an opportunity to take over the rendering
359     *  of 'picture'. If optimization data is available (due to an earlier
360     *  'optimize' call) this entry point should make use of it and return true
361     *  if all rendering has been done. If false is returned, SkCanvas will
362     *  perform its own rendering pass. It is acceptable for the backend
363     *  to perform some device-specific warm up tasks and then let SkCanvas
364     *  perform the main rendering loop (by return false from here).
365     */
366    virtual bool EXPERIMENTAL_drawPicture(SkCanvas* canvas, const SkPicture* picture);
367
368private:
369    friend class SkCanvas;
370    friend struct DeviceCM; //for setMatrixClip
371    friend class SkDraw;
372    friend class SkDrawIter;
373    friend class SkDeviceFilteredPaint;
374    friend class SkDeviceImageFilterProxy;
375    friend class SkDeferredDevice;    // for newSurface
376
377    friend class SkSurface_Raster;
378
379    // used to change the backend's pixels (and possibly config/rowbytes)
380    // but cannot change the width/height, so there should be no change to
381    // any clip information.
382    // TODO: move to SkBitmapDevice
383    virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) = 0;
384
385    // just called by SkCanvas when built as a layer
386    void setOrigin(int x, int y) { fOrigin.set(x, y); }
387    // just called by SkCanvas for saveLayer
388    SkBaseDevice* createCompatibleDeviceForSaveLayer(const SkImageInfo&);
389
390    virtual SkBaseDevice* onCreateDevice(const SkImageInfo&, Usage) {
391        return NULL;
392    }
393
394    /** Causes any deferred drawing to the device to be completed.
395     */
396    virtual void flush() = 0;
397
398    SkIPoint    fOrigin;
399    SkMetaData* fMetaData;
400
401#ifdef SK_DEBUG
402    bool        fAttachedToCanvas;
403#endif
404
405    typedef SkRefCnt INHERITED;
406};
407
408#endif
409