SkImageFilter.h revision 8d21f6c7a9d0cf4f87d77c235c6da7203620c7e5
1894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com/*
2894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com * Copyright 2011 Google Inc.
3894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com *
4894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com * Use of this source code is governed by a BSD-style license that can be
5894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com * found in the LICENSE file.
6894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com */
7894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com
8894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com#ifndef SkImageFilter_DEFINED
9894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com#define SkImageFilter_DEFINED
10894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com
11894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com#include "SkFlattenable.h"
12894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com
1315356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.comclass SkBitmap;
148d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.orgclass SkColorFilter;
1576dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.comclass SkDevice;
1615356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.comclass SkMatrix;
17c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.comstruct SkIPoint;
18c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.comstruct SkIRect;
19c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.comstruct SkRect;
20894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgclass GrCustomStage;
21d0c1a06cb98dd4a009dfa79e37ba6ca23a8c180btomhudson@google.comclass GrTexture;
2215356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com
2315356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com/**
2415356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com *  Experimental.
2515356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com *
2615356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com *  Base class for image filters. If one is installed in the paint, then
2715356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com *  all drawing occurs as usual, but it is as if the drawing happened into an
2815356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com *  offscreen (before the xfermode is applied). This offscreen bitmap will
2915356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com *  then be handed to the imagefilter, who in turn creates a new bitmap which
3015356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com *  is what will finally be drawn to the device (using the original xfermode).
3115356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com *
3232d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com *  THIS SIGNATURE IS TEMPORARY
3332d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com *
3432d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com *  There are several weaknesses in this function signature:
3532d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com *  1. Does not expose the destination/target device, so filters that can draw
3632d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com *     directly to it are unable to take advantage of that optimization.
3732d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com *  2. Does not expose a way to create a "compabitible" image (i.e. gpu -> gpu)
3832d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com *  3. As with #1, the filter is unable to "read" the dest (which would be slow)
3932d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com *
4032d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com *  Therefore, we should not create any real dependencies on this API yet -- it
4132d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com *  is being checked in as a check-point so we can explore these and other
4232d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com *  considerations.
4315356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com */
4454e01b2ab985e7a7d38109812069d056d128bfa1senorblanco@chromium.orgclass SK_API SkImageFilter : public SkFlattenable {
45894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.compublic:
460456e0b7b85060e9b9597ce414c4c2b19aff4f58robertphillips@google.com    SK_DECLARE_INST_COUNT(SkImageFilter)
470456e0b7b85060e9b9597ce414c4c2b19aff4f58robertphillips@google.com
4876dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com    class Proxy {
4976dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com    public:
508926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        virtual ~Proxy() {};
518926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
5276dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        virtual SkDevice* createDevice(int width, int height) = 0;
538926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        // returns true if the proxy can handle this filter natively
548926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        virtual bool canHandleImageFilter(SkImageFilter*) = 0;
5576dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        // returns true if the proxy handled the filter itself. if this returns
5676dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        // false then the filter's code will be called.
5776dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        virtual bool filterImage(SkImageFilter*, const SkBitmap& src,
5876dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com                                 const SkMatrix& ctm,
5976dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com                                 SkBitmap* result, SkIPoint* offset) = 0;
6076dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com    };
61894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com
62894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com    /**
63894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     *  Request a new (result) image to be created from the src image.
64894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     *  If the src has no pixels (isNull()) then the request just wants to
65894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     *  receive the config and width/height of the result.
66894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     *
67894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     *  The matrix is the current matrix on the canvas.
68894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     *
69894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     *  Offset is the amount to translate the resulting image relative to the
70fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com     *  src when it is drawn.
71894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     *
72894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     *  If the result image cannot be created, return false, in which case both
73894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     *  the result and offset parameters will be ignored by the caller.
74894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     */
7576dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com    bool filterImage(Proxy*, const SkBitmap& src, const SkMatrix& ctm,
7615356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com                     SkBitmap* result, SkIPoint* offset);
7715356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com
7815356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com    /**
7932d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com     *  Given the src bounds of an image, this returns the bounds of the result
8032d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com     *  image after the filter has been applied.
8132d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com     */
8232d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com    bool filterBounds(const SkIRect& src, const SkMatrix& ctm, SkIRect* dst);
8332d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com
8432d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com    /**
85894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org     *  Returns true if the filter can be expressed a single-pass
86894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org     *  GrCustomStage, used to process this filter on the GPU, or false if
87894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org     *  not.
88fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com     *
89894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org     *  If stage is non-NULL, a new GrCustomStage instance is stored
90894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org     *  in it.  The caller assumes ownership of the stage, and it is up to the
91894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org     *  caller to unref it.
92894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org     */
93d0c1a06cb98dd4a009dfa79e37ba6ca23a8c180btomhudson@google.com    virtual bool asNewCustomStage(GrCustomStage** stage, GrTexture*) const;
94894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
95894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    /**
96302cffba86a188373c99833d83392f33e6014542senorblanco@chromium.org     *  Returns true if the filter can be processed on the GPU.  This is most
97302cffba86a188373c99833d83392f33e6014542senorblanco@chromium.org     *  often used for multi-pass effects, where intermediate results must be
98302cffba86a188373c99833d83392f33e6014542senorblanco@chromium.org     *  rendered to textures.  For single-pass effects, use asNewCustomStage().
99302cffba86a188373c99833d83392f33e6014542senorblanco@chromium.org     *  The default implementation returns false.
10005054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org     */
101302cffba86a188373c99833d83392f33e6014542senorblanco@chromium.org    virtual bool canFilterImageGPU() const;
10205054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org
10305054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org    /**
104302cffba86a188373c99833d83392f33e6014542senorblanco@chromium.org     *  Process this image filter on the GPU.  texture is the source texture
105302cffba86a188373c99833d83392f33e6014542senorblanco@chromium.org     *  for processing, and rect is the effect region to process.  The
106302cffba86a188373c99833d83392f33e6014542senorblanco@chromium.org     *  function must allocate a new texture of at least rect width/height
107302cffba86a188373c99833d83392f33e6014542senorblanco@chromium.org     *  size, and return it to the caller.  The default implementation returns
108302cffba86a188373c99833d83392f33e6014542senorblanco@chromium.org     *  NULL.
10905054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org     */
1109c39744a00573b7133fc765b0a9d50a0ceace7b8senorblanco@chromium.org    virtual GrTexture* onFilterImageGPU(Proxy*, GrTexture* texture, const SkRect& rect);
11105054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org
1128d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    /**
1138d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org     *  Returns this image filter as a color filter if possible,
1148d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org     *  NULL otherwise.
1158d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org     */
1168d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    virtual SkColorFilter* asColorFilter() const;
1178d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org
1188d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    /**
1198d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org     *  Returns the number of inputs this filter will accept (some inputs can
1208d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org     *  be NULL).
1218d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org     */
1228d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    int countInputs() const { return fInputCount; }
1238d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org
1248d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    /**
1258d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org     *  Returns the input filter at a given index, or NULL if no input is
1268d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org     *  connected.  The indices used are filter-specific.
1278d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org     */
1288d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    SkImageFilter* getInput(int i) const {
1298d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org        SkASSERT(i < fInputCount);
1308d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org        return fInputs[i];
1318d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    }
1328d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org
133894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.comprotected:
1348d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    SkImageFilter(int inputCount, SkImageFilter** inputs);
1359f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org
1368d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    // The ... represents inputCount SkImageFilter pointers, upon which this
1379f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org    // constructor will call SkSafeRef().  This is the same behaviour as
1389f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org    // the SkImageFilter(int, SkImageFilter**) constructor above.
1398d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    explicit SkImageFilter(int inputCount, ...);
1409f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org
1419f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org    virtual ~SkImageFilter();
1429f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org
1439f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org    explicit SkImageFilter(SkFlattenableReadBuffer& rb);
1449f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org
1459f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org    virtual void flatten(SkFlattenableWriteBuffer& wb) const SK_OVERRIDE;
14632d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com
14732d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com    // Default impl returns false
14876dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com    virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
14915356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com                               SkBitmap* result, SkIPoint* offset);
15032d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com    // Default impl copies src into dst and returns true
15132d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com    virtual bool onFilterBounds(const SkIRect&, const SkMatrix&, SkIRect*);
152894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com
1539f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org    // Return the result of processing the given input, or the source bitmap
1549f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org    // if we have no connected input at that index.
1559f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org    SkBitmap getInputResult(int index, Proxy*, const SkBitmap& src, const SkMatrix&,
1569f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org                            SkIPoint*);
1579f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org
158894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.comprivate:
15954e01b2ab985e7a7d38109812069d056d128bfa1senorblanco@chromium.org    typedef SkFlattenable INHERITED;
1608d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    int fInputCount;
1619f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org    SkImageFilter** fInputs;
162894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com};
163894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com
164894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com#endif
165