1/*
2 * Copyright 2011 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#ifndef SkImageFilter_DEFINED
9#define SkImageFilter_DEFINED
10
11#include "SkFlattenable.h"
12#include "SkMatrix.h"
13#include "SkRect.h"
14#include "SkTemplates.h"
15
16class SkBitmap;
17class SkColorFilter;
18class SkBaseDevice;
19struct SkIPoint;
20class GrFragmentProcessor;
21class GrTexture;
22
23/**
24 *  Base class for image filters. If one is installed in the paint, then
25 *  all drawing occurs as usual, but it is as if the drawing happened into an
26 *  offscreen (before the xfermode is applied). This offscreen bitmap will
27 *  then be handed to the imagefilter, who in turn creates a new bitmap which
28 *  is what will finally be drawn to the device (using the original xfermode).
29 */
30class SK_API SkImageFilter : public SkFlattenable {
31public:
32    SK_DECLARE_INST_COUNT(SkImageFilter)
33
34    class CropRect {
35    public:
36        enum CropEdge {
37            kHasLeft_CropEdge   = 0x01,
38            kHasTop_CropEdge    = 0x02,
39            kHasRight_CropEdge  = 0x04,
40            kHasBottom_CropEdge = 0x08,
41            kHasAll_CropEdge    = 0x0F,
42        };
43        CropRect() {}
44        explicit CropRect(const SkRect& rect, uint32_t flags = kHasAll_CropEdge) : fRect(rect), fFlags(flags) {}
45        uint32_t flags() const { return fFlags; }
46        const SkRect& rect() const { return fRect; }
47    private:
48        SkRect fRect;
49        uint32_t fFlags;
50    };
51
52    // This cache maps from (filter's unique ID + CTM + clipBounds + src bitmap generation ID) to
53    // (result, offset).
54    class Cache : public SkRefCnt {
55    public:
56        struct Key;
57        virtual ~Cache() {}
58        static Cache* Create(size_t maxBytes);
59        static Cache* Get();
60        virtual bool get(const Key& key, SkBitmap* result, SkIPoint* offset) const = 0;
61        virtual void set(const Key& key, const SkBitmap& result, const SkIPoint& offset) = 0;
62    };
63
64    class Context {
65    public:
66        Context(const SkMatrix& ctm, const SkIRect& clipBounds, Cache* cache) :
67            fCTM(ctm), fClipBounds(clipBounds), fCache(cache) {
68        }
69        const SkMatrix& ctm() const { return fCTM; }
70        const SkIRect& clipBounds() const { return fClipBounds; }
71        Cache* cache() const { return fCache; }
72    private:
73        SkMatrix fCTM;
74        SkIRect  fClipBounds;
75        Cache* fCache;
76    };
77
78    class Proxy {
79    public:
80        virtual ~Proxy() {};
81
82        virtual SkBaseDevice* createDevice(int width, int height) = 0;
83        // returns true if the proxy can handle this filter natively
84        virtual bool canHandleImageFilter(const SkImageFilter*) = 0;
85        // returns true if the proxy handled the filter itself. if this returns
86        // false then the filter's code will be called.
87        virtual bool filterImage(const SkImageFilter*, const SkBitmap& src,
88                                 const Context&,
89                                 SkBitmap* result, SkIPoint* offset) = 0;
90    };
91
92    /**
93     *  Request a new (result) image to be created from the src image.
94     *  If the src has no pixels (isNull()) then the request just wants to
95     *  receive the config and width/height of the result.
96     *
97     *  The matrix is the current matrix on the canvas.
98     *
99     *  Offset is the amount to translate the resulting image relative to the
100     *  src when it is drawn. This is an out-param.
101     *
102     *  If the result image cannot be created, return false, in which case both
103     *  the result and offset parameters will be ignored by the caller.
104     */
105    bool filterImage(Proxy*, const SkBitmap& src, const Context&,
106                     SkBitmap* result, SkIPoint* offset) const;
107
108    /**
109     *  Given the src bounds of an image, this returns the bounds of the result
110     *  image after the filter has been applied.
111     */
112    bool filterBounds(const SkIRect& src, const SkMatrix& ctm, SkIRect* dst) const;
113
114    /**
115     *  Returns true if the filter can be processed on the GPU.  This is most
116     *  often used for multi-pass effects, where intermediate results must be
117     *  rendered to textures.  For single-pass effects, use asFragmentProcessor().
118     *  The default implementation returns asFragmentProcessor(NULL, NULL, SkMatrix::I(),
119     *  SkIRect()).
120     */
121    virtual bool canFilterImageGPU() const;
122
123    /**
124     *  Process this image filter on the GPU.  This is most often used for
125     *  multi-pass effects, where intermediate results must be rendered to
126     *  textures.  For single-pass effects, use asFragmentProcessor().  src is the
127     *  source image for processing, as a texture-backed bitmap.  result is
128     *  the destination bitmap, which should contain a texture-backed pixelref
129     *  on success.  offset is the amount to translate the resulting image
130     *  relative to the src when it is drawn. The default implementation does
131     *  single-pass processing using asFragmentProcessor().
132     */
133    virtual bool filterImageGPU(Proxy*, const SkBitmap& src, const Context&,
134                                SkBitmap* result, SkIPoint* offset) const;
135
136    /**
137     *  Returns whether this image filter is a color filter and puts the color filter into the
138     *  "filterPtr" parameter if it can. Does nothing otherwise.
139     *  If this returns false, then the filterPtr is unchanged.
140     *  If this returns true, then if filterPtr is not null, it must be set to a ref'd colorfitler
141     *  (i.e. it may not be set to NULL).
142     */
143    virtual bool asColorFilter(SkColorFilter** filterPtr) const;
144
145    /**
146     *  Returns the number of inputs this filter will accept (some inputs can
147     *  be NULL).
148     */
149    int countInputs() const { return fInputCount; }
150
151    /**
152     *  Returns the input filter at a given index, or NULL if no input is
153     *  connected.  The indices used are filter-specific.
154     */
155    SkImageFilter* getInput(int i) const {
156        SkASSERT(i < fInputCount);
157        return fInputs[i];
158    }
159
160    /**
161     *  Returns whether any edges of the crop rect have been set. The crop
162     *  rect is set at construction time, and determines which pixels from the
163     *  input image will be processed. The size of the crop rect should be
164     *  used as the size of the destination image. The origin of this rect
165     *  should be used to offset access to the input images, and should also
166     *  be added to the "offset" parameter in onFilterImage and
167     *  filterImageGPU(). (The latter ensures that the resulting buffer is
168     *  drawn in the correct location.)
169     */
170    bool cropRectIsSet() const { return fCropRect.flags() != 0x0; }
171
172    // Default impl returns union of all input bounds.
173    virtual void computeFastBounds(const SkRect&, SkRect*) const;
174
175#if SK_SUPPORT_GPU
176    /**
177     * Wrap the given texture in a texture-backed SkBitmap.
178     */
179    static void WrapTexture(GrTexture* texture, int width, int height, SkBitmap* result);
180
181    /**
182     * Recursively evaluate this filter on the GPU. If the filter has no GPU
183     * implementation, it will be processed in software and uploaded to the GPU.
184     */
185    bool getInputResultGPU(SkImageFilter::Proxy* proxy, const SkBitmap& src, const Context&,
186                           SkBitmap* result, SkIPoint* offset) const;
187#endif
188
189    SK_DEFINE_FLATTENABLE_TYPE(SkImageFilter)
190
191protected:
192    class Common {
193    public:
194        Common() {}
195        ~Common();
196
197        /**
198         *  Attempt to unflatten the cropRect and the expected number of input filters.
199         *  If any number of input filters is valid, pass -1.
200         *  If this fails (i.e. corrupt buffer or contents) then return false and common will
201         *  be left uninitialized.
202         *  If this returns true, then inputCount() is the number of found input filters, each
203         *  of which may be NULL or a valid imagefilter.
204         */
205        bool unflatten(SkReadBuffer&, int expectedInputs);
206
207        const CropRect& cropRect() const { return fCropRect; }
208        int             inputCount() const { return fInputs.count(); }
209        SkImageFilter** inputs() const { return fInputs.get(); }
210        uint32_t        uniqueID() const { return fUniqueID; }
211
212        SkImageFilter*  getInput(int index) const { return fInputs[index]; }
213
214        // If the caller wants a copy of the inputs, call this and it will transfer ownership
215        // of the unflattened input filters to the caller. This is just a short-cut for copying
216        // the inputs, calling ref() on each, and then waiting for Common's destructor to call
217        // unref() on each.
218        void detachInputs(SkImageFilter** inputs);
219
220    private:
221        CropRect fCropRect;
222        // most filters accept at most 2 input-filters
223        SkAutoSTArray<2, SkImageFilter*> fInputs;
224        uint32_t fUniqueID;
225
226        void allocInputs(int count);
227    };
228
229    SkImageFilter(int inputCount, SkImageFilter** inputs, const CropRect* cropRect = NULL, uint32_t uniqueID = 0);
230
231    virtual ~SkImageFilter();
232
233    /**
234     *  Constructs a new SkImageFilter read from an SkReadBuffer object.
235     *
236     *  @param inputCount    The exact number of inputs expected for this SkImageFilter object.
237     *                       -1 can be used if the filter accepts any number of inputs.
238     *  @param rb            SkReadBuffer object from which the SkImageFilter is read.
239     */
240    explicit SkImageFilter(int inputCount, SkReadBuffer& rb);
241
242    virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE;
243
244    /**
245     *  This is the virtual which should be overridden by the derived class
246     *  to perform image filtering.
247     *
248     *  src is the original primitive bitmap. If the filter has a connected
249     *  input, it should recurse on that input and use that in place of src.
250     *
251     *  The matrix is the current matrix on the canvas.
252     *
253     *  Offset is the amount to translate the resulting image relative to the
254     *  src when it is drawn. This is an out-param.
255     *
256     *  If the result image cannot be created, this should false, in which
257     *  case both the result and offset parameters will be ignored by the
258     *  caller.
259     */
260    virtual bool onFilterImage(Proxy*, const SkBitmap& src, const Context&,
261                               SkBitmap* result, SkIPoint* offset) const;
262    // Given the bounds of the destination rect to be filled in device
263    // coordinates (first parameter), and the CTM, compute (conservatively)
264    // which rect of the source image would be required (third parameter).
265    // Used for clipping and temp-buffer allocations, so the result need not
266    // be exact, but should never be smaller than the real answer. The default
267    // implementation recursively unions all input bounds, or returns false if
268    // no inputs.
269    virtual bool onFilterBounds(const SkIRect&, const SkMatrix&, SkIRect*) const;
270
271    /** Computes source bounds as the src bitmap bounds offset by srcOffset.
272     *  Apply the transformed crop rect to the bounds if any of the
273     *  corresponding edge flags are set. Intersects the result against the
274     *  context's clipBounds, and returns the result in "bounds". If there is
275     *  no intersection, returns false and leaves "bounds" unchanged.
276     */
277    bool applyCropRect(const Context&, const SkBitmap& src, const SkIPoint& srcOffset,
278                       SkIRect* bounds) const;
279
280    /** Same as the above call, except that if the resulting crop rect is not
281     *  entirely contained by the source bitmap's bounds, it creates a new
282     *  bitmap in "result" and pads the edges with transparent black. In that
283     *  case, the srcOffset is modified to be the same as the bounds, since no
284     *  further adjustment is needed by the caller. This version should only
285     *  be used by filters which are not capable of processing a smaller
286     *  source bitmap into a larger destination.
287     */
288    bool applyCropRect(const Context&, Proxy* proxy, const SkBitmap& src, SkIPoint* srcOffset,
289                       SkIRect* bounds, SkBitmap* result) const;
290
291    /**
292     *  Returns true if the filter can be expressed a single-pass
293     *  GrProcessor, used to process this filter on the GPU, or false if
294     *  not.
295     *
296     *  If effect is non-NULL, a new GrProcessor instance is stored
297     *  in it.  The caller assumes ownership of the stage, and it is up to the
298     *  caller to unref it.
299     *
300     *  The effect can assume its vertexCoords space maps 1-to-1 with texels
301     *  in the texture.  "matrix" is a transformation to apply to filter
302     *  parameters before they are used in the effect. Note that this function
303     *  will be called with (NULL, NULL, SkMatrix::I()) to query for support,
304     *  so returning "true" indicates support for all possible matrices.
305     */
306    virtual bool asFragmentProcessor(GrFragmentProcessor**, GrTexture*, const SkMatrix&,
307                                     const SkIRect& bounds) const;
308
309private:
310    bool usesSrcInput() const { return fUsesSrcInput; }
311
312    typedef SkFlattenable INHERITED;
313    int fInputCount;
314    SkImageFilter** fInputs;
315    bool fUsesSrcInput;
316    CropRect fCropRect;
317    uint32_t fUniqueID; // Globally unique
318};
319
320/**
321 *  Helper to unflatten the common data, and return NULL if we fail.
322 */
323#define SK_IMAGEFILTER_UNFLATTEN_COMMON(localVar, expectedCount)    \
324    Common localVar;                                                \
325    do {                                                            \
326        if (!localVar.unflatten(buffer, expectedCount)) {           \
327            return NULL;                                            \
328        }                                                           \
329    } while (0)
330
331#endif
332