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
118c874eee943bdea0fab5b4d2707083c863e37c55senorblanco#include "SkFilterQuality.h"
12894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com#include "SkFlattenable.h"
134cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org#include "SkMatrix.h"
14194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org#include "SkRect.h"
15b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed#include "SkTemplates.h"
16894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com
1715356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.comclass SkBitmap;
188d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.orgclass SkColorFilter;
191f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comclass SkBaseDevice;
202d97bc139a7de5813468bd3dbfd0037351ae5606fmalitaclass SkSurfaceProps;
21c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.comstruct SkIPoint;
22b0a8a377f832c59cee939ad721e1f87d378b7142joshualittclass GrFragmentProcessor;
23d0c1a06cb98dd4a009dfa79e37ba6ca23a8c180btomhudson@google.comclass GrTexture;
2415356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com
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 */
3254e01b2ab985e7a7d38109812069d056d128bfa1senorblanco@chromium.orgclass SK_API SkImageFilter : public SkFlattenable {
33894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.compublic:
340456e0b7b85060e9b9597ce414c4c2b19aff4f58robertphillips@google.com    SK_DECLARE_INST_COUNT(SkImageFilter)
350456e0b7b85060e9b9597ce414c4c2b19aff4f58robertphillips@google.com
363f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org    class CropRect {
373f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org    public:
38b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org        enum CropEdge {
39b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org            kHasLeft_CropEdge   = 0x01,
40b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org            kHasTop_CropEdge    = 0x02,
41b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org            kHasRight_CropEdge  = 0x04,
42b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org            kHasBottom_CropEdge = 0x08,
43b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org            kHasAll_CropEdge    = 0x0F,
44b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org        };
45b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org        CropRect() {}
46b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org        explicit CropRect(const SkRect& rect, uint32_t flags = kHasAll_CropEdge) : fRect(rect), fFlags(flags) {}
473f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org        uint32_t flags() const { return fFlags; }
483f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org        const SkRect& rect() const { return fRect; }
493f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org    private:
503f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org        SkRect fRect;
513f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org        uint32_t fFlags;
52b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org    };
53b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org
5455b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    // This cache maps from (filter's unique ID + CTM + clipBounds + src bitmap generation ID) to
5555b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    // (result, offset).
56be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco    class Cache : public SkRefCnt {
5755b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    public:
5855b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        struct Key;
59be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco        virtual ~Cache() {}
60be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco        static Cache* Create(size_t maxBytes);
61be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco        static Cache* Get();
6255b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        virtual bool get(const Key& key, SkBitmap* result, SkIPoint* offset) const = 0;
6355b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        virtual void set(const Key& key, const SkBitmap& result, const SkIPoint& offset) = 0;
6455b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    };
6555b6d8be997a447ef9ce0f029697677a940bfc24senorblanco
664cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    class Context {
674cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    public:
68be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco        Context(const SkMatrix& ctm, const SkIRect& clipBounds, Cache* cache) :
69f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org            fCTM(ctm), fClipBounds(clipBounds), fCache(cache) {
704cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org        }
714cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org        const SkMatrix& ctm() const { return fCTM; }
724cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org        const SkIRect& clipBounds() const { return fClipBounds; }
73be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco        Cache* cache() const { return fCache; }
744cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    private:
754cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org        SkMatrix fCTM;
764cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org        SkIRect  fClipBounds;
77be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco        Cache* fCache;
784cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    };
794cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org
8076dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com    class Proxy {
8176dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com    public:
828926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        virtual ~Proxy() {};
838926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
841f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com        virtual SkBaseDevice* createDevice(int width, int height) = 0;
858926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        // returns true if the proxy can handle this filter natively
86ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org        virtual bool canHandleImageFilter(const SkImageFilter*) = 0;
8776dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        // returns true if the proxy handled the filter itself. if this returns
8876dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        // false then the filter's code will be called.
89ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org        virtual bool filterImage(const SkImageFilter*, const SkBitmap& src,
904cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org                                 const Context&,
9176dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com                                 SkBitmap* result, SkIPoint* offset) = 0;
922d97bc139a7de5813468bd3dbfd0037351ae5606fmalita        virtual const SkSurfaceProps* surfaceProps() const = 0;
9376dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com    };
94894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com
95894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com    /**
96894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     *  Request a new (result) image to be created from the src image.
97894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     *  If the src has no pixels (isNull()) then the request just wants to
98894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     *  receive the config and width/height of the result.
99894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     *
100894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     *  The matrix is the current matrix on the canvas.
101894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     *
102894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     *  Offset is the amount to translate the resulting image relative to the
1036776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  src when it is drawn. This is an out-param.
104894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     *
105894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     *  If the result image cannot be created, return false, in which case both
106894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     *  the result and offset parameters will be ignored by the caller.
107894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     */
1084cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    bool filterImage(Proxy*, const SkBitmap& src, const Context&,
109ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org                     SkBitmap* result, SkIPoint* offset) const;
11015356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com
11115356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com    /**
11232d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com     *  Given the src bounds of an image, this returns the bounds of the result
11332d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com     *  image after the filter has been applied.
11432d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com     */
115c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    bool filterBounds(const SkIRect& src, const SkMatrix& ctm, SkIRect* dst) const;
11632d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com
11732d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com    /**
118302cffba86a188373c99833d83392f33e6014542senorblanco@chromium.org     *  Returns true if the filter can be processed on the GPU.  This is most
119302cffba86a188373c99833d83392f33e6014542senorblanco@chromium.org     *  often used for multi-pass effects, where intermediate results must be
120b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt     *  rendered to textures.  For single-pass effects, use asFragmentProcessor().
121b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt     *  The default implementation returns asFragmentProcessor(NULL, NULL, SkMatrix::I(),
1227938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org     *  SkIRect()).
12305054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org     */
124302cffba86a188373c99833d83392f33e6014542senorblanco@chromium.org    virtual bool canFilterImageGPU() const;
12505054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org
12605054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org    /**
1273284017a60ea4fc3dc5b95838ba0c301ee1e4e8dskia.committer@gmail.com     *  Process this image filter on the GPU.  This is most often used for
128d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org     *  multi-pass effects, where intermediate results must be rendered to
129b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt     *  textures.  For single-pass effects, use asFragmentProcessor().  src is the
130d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org     *  source image for processing, as a texture-backed bitmap.  result is
131d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org     *  the destination bitmap, which should contain a texture-backed pixelref
132de2e4e8a6422c7d8b5847f038f5c6360b187f7a2skia.committer@gmail.com     *  on success.  offset is the amount to translate the resulting image
1337b320703d47ff2b242ae74faba5e4b0af3560d71commit-bot@chromium.org     *  relative to the src when it is drawn. The default implementation does
134b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt     *  single-pass processing using asFragmentProcessor().
13505054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org     */
1364cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    virtual bool filterImageGPU(Proxy*, const SkBitmap& src, const Context&,
137ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org                                SkBitmap* result, SkIPoint* offset) const;
13805054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org
1398d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    /**
140a1c511b8704c6c266b90860a4c68f30ca7514f9bsugoi@google.com     *  Returns whether this image filter is a color filter and puts the color filter into the
1414b6d432f1e4ea0a6556dfff1b4d19b69ca005c27sugoi@google.com     *  "filterPtr" parameter if it can. Does nothing otherwise.
1424b6d432f1e4ea0a6556dfff1b4d19b69ca005c27sugoi@google.com     *  If this returns false, then the filterPtr is unchanged.
1434b6d432f1e4ea0a6556dfff1b4d19b69ca005c27sugoi@google.com     *  If this returns true, then if filterPtr is not null, it must be set to a ref'd colorfitler
1444b6d432f1e4ea0a6556dfff1b4d19b69ca005c27sugoi@google.com     *  (i.e. it may not be set to NULL).
1458d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org     */
146cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    bool isColorFilterNode(SkColorFilter** filterPtr) const {
147cedc36f18b2254c5ee21f6348124886b6db4f4c2reed        return this->onIsColorFilterNode(filterPtr);
148cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    }
149cedc36f18b2254c5ee21f6348124886b6db4f4c2reed
150cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    // DEPRECATED : use isColorFilterNode() instead
151cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    bool asColorFilter(SkColorFilter** filterPtr) const {
152cedc36f18b2254c5ee21f6348124886b6db4f4c2reed        return this->isColorFilterNode(filterPtr);
153cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    }
154cedc36f18b2254c5ee21f6348124886b6db4f4c2reed
155cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    /**
156cedc36f18b2254c5ee21f6348124886b6db4f4c2reed     *  Returns true (and optionally returns a ref'd filter) if this imagefilter can be completely
157cedc36f18b2254c5ee21f6348124886b6db4f4c2reed     *  replaced by the returned colorfilter. i.e. the two effects will affect drawing in the
158cedc36f18b2254c5ee21f6348124886b6db4f4c2reed     *  same way.
159cedc36f18b2254c5ee21f6348124886b6db4f4c2reed     */
160cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    bool asAColorFilter(SkColorFilter** filterPtr) const {
161cedc36f18b2254c5ee21f6348124886b6db4f4c2reed        return this->countInputs() > 0 &&
162cedc36f18b2254c5ee21f6348124886b6db4f4c2reed               NULL == this->getInput(0) &&
163cedc36f18b2254c5ee21f6348124886b6db4f4c2reed               this->isColorFilterNode(filterPtr);
164cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    }
1658d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org
1668d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    /**
1678d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org     *  Returns the number of inputs this filter will accept (some inputs can
1688d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org     *  be NULL).
1698d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org     */
1708d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    int countInputs() const { return fInputCount; }
1718d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org
1728d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    /**
1738d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org     *  Returns the input filter at a given index, or NULL if no input is
1748d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org     *  connected.  The indices used are filter-specific.
1758d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org     */
1768d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    SkImageFilter* getInput(int i) const {
1778d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org        SkASSERT(i < fInputCount);
1788d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org        return fInputs[i];
1798d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    }
1808d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org
181194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org    /**
1823f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org     *  Returns whether any edges of the crop rect have been set. The crop
1833f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org     *  rect is set at construction time, and determines which pixels from the
1843f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org     *  input image will be processed. The size of the crop rect should be
1853f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org     *  used as the size of the destination image. The origin of this rect
1863f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org     *  should be used to offset access to the input images, and should also
1873f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org     *  be added to the "offset" parameter in onFilterImage and
1883f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org     *  filterImageGPU(). (The latter ensures that the resulting buffer is
1893f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org     *  drawn in the correct location.)
190194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org     */
1913f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org    bool cropRectIsSet() const { return fCropRect.flags() != 0x0; }
192194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org
193336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    // Default impl returns union of all input bounds.
194336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    virtual void computeFastBounds(const SkRect&, SkRect*) const;
195336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org
1968c874eee943bdea0fab5b4d2707083c863e37c55senorblanco    /**
1978c874eee943bdea0fab5b4d2707083c863e37c55senorblanco     * Create an SkMatrixImageFilter, which transforms its input by the given matrix.
1988c874eee943bdea0fab5b4d2707083c863e37c55senorblanco     */
1998c874eee943bdea0fab5b4d2707083c863e37c55senorblanco    static SkImageFilter* CreateMatrixFilter(const SkMatrix& matrix,
2008c874eee943bdea0fab5b4d2707083c863e37c55senorblanco                                             SkFilterQuality,
2018c874eee943bdea0fab5b4d2707083c863e37c55senorblanco                                             SkImageFilter* input = NULL);
2028c874eee943bdea0fab5b4d2707083c863e37c55senorblanco
2034509517e03fd245298d4059f4568435d640a1758kkinnunen#if SK_SUPPORT_GPU
2046aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    /**
2056aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org     * Wrap the given texture in a texture-backed SkBitmap.
2066aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org     */
2076aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    static void WrapTexture(GrTexture* texture, int width, int height, SkBitmap* result);
2086aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org
2096aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    /**
2106aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org     * Recursively evaluate this filter on the GPU. If the filter has no GPU
2116aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org     * implementation, it will be processed in software and uploaded to the GPU.
2126aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org     */
2134cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    bool getInputResultGPU(SkImageFilter::Proxy* proxy, const SkBitmap& src, const Context&,
2146aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org                           SkBitmap* result, SkIPoint* offset) const;
2156aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org#endif
2166aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org
217f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips    SK_TO_STRING_PUREVIRT()
218c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    SK_DEFINE_FLATTENABLE_TYPE(SkImageFilter)
219c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
220894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.comprotected:
221b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    class Common {
222b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    public:
223b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        Common() {}
224b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        ~Common();
225b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed
2269fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        /**
2279fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed         *  Attempt to unflatten the cropRect and the expected number of input filters.
2289fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed         *  If any number of input filters is valid, pass -1.
2299fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed         *  If this fails (i.e. corrupt buffer or contents) then return false and common will
2309fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed         *  be left uninitialized.
2319fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed         *  If this returns true, then inputCount() is the number of found input filters, each
2329fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed         *  of which may be NULL or a valid imagefilter.
2339fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed         */
2349fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        bool unflatten(SkReadBuffer&, int expectedInputs);
2359fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
2369fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        const CropRect& cropRect() const { return fCropRect; }
237b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        int             inputCount() const { return fInputs.count(); }
238b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        SkImageFilter** inputs() const { return fInputs.get(); }
239b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed
2409fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        SkImageFilter*  getInput(int index) const { return fInputs[index]; }
2419fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
242b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        // If the caller wants a copy of the inputs, call this and it will transfer ownership
243b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        // of the unflattened input filters to the caller. This is just a short-cut for copying
244b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        // the inputs, calling ref() on each, and then waiting for Common's destructor to call
245b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        // unref() on each.
246b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        void detachInputs(SkImageFilter** inputs);
247b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed
248b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    private:
249b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        CropRect fCropRect;
250b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        // most filters accept at most 2 input-filters
251b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        SkAutoSTArray<2, SkImageFilter*> fInputs;
252b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed
253b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        void allocInputs(int count);
254b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    };
255b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed
25624e06d5244ae96e440410e1d76e039983b2efac9senorblanco    SkImageFilter(int inputCount, SkImageFilter** inputs, const CropRect* cropRect = NULL);
2579f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org
2589f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org    virtual ~SkImageFilter();
2599f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org
260c84728d72a47415929464c5cf062300d86a91246commit-bot@chromium.org    /**
2618b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org     *  Constructs a new SkImageFilter read from an SkReadBuffer object.
262c84728d72a47415929464c5cf062300d86a91246commit-bot@chromium.org     *
263c84728d72a47415929464c5cf062300d86a91246commit-bot@chromium.org     *  @param inputCount    The exact number of inputs expected for this SkImageFilter object.
264c84728d72a47415929464c5cf062300d86a91246commit-bot@chromium.org     *                       -1 can be used if the filter accepts any number of inputs.
2658b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org     *  @param rb            SkReadBuffer object from which the SkImageFilter is read.
266c84728d72a47415929464c5cf062300d86a91246commit-bot@chromium.org     */
2678b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    explicit SkImageFilter(int inputCount, SkReadBuffer& rb);
2689f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org
26936352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void flatten(SkWriteBuffer&) const override;
27032d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com
2716776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    /**
2726776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  This is the virtual which should be overridden by the derived class
2736776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  to perform image filtering.
2746776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *
2756776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  src is the original primitive bitmap. If the filter has a connected
2766776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  input, it should recurse on that input and use that in place of src.
2776776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *
2786776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  The matrix is the current matrix on the canvas.
2796776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *
2806776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  Offset is the amount to translate the resulting image relative to the
2816776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  src when it is drawn. This is an out-param.
2826776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *
2836776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  If the result image cannot be created, this should false, in which
2846776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  case both the result and offset parameters will be ignored by the
2856776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  caller.
2866776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     */
2874cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    virtual bool onFilterImage(Proxy*, const SkBitmap& src, const Context&,
288ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org                               SkBitmap* result, SkIPoint* offset) const;
289c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    // Given the bounds of the destination rect to be filled in device
290c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    // coordinates (first parameter), and the CTM, compute (conservatively)
291c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    // which rect of the source image would be required (third parameter).
292c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    // Used for clipping and temp-buffer allocations, so the result need not
293c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    // be exact, but should never be smaller than the real answer. The default
294c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    // implementation recursively unions all input bounds, or returns false if
295c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    // no inputs.
296c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    virtual bool onFilterBounds(const SkIRect&, const SkMatrix&, SkIRect*) const;
297894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com
298cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    /**
299cedc36f18b2254c5ee21f6348124886b6db4f4c2reed     *  Return true (and return a ref'd colorfilter) if this node in the DAG is just a
300cedc36f18b2254c5ee21f6348124886b6db4f4c2reed     *  colorfilter w/o CropRect constraints.
301cedc36f18b2254c5ee21f6348124886b6db4f4c2reed     */
302cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    virtual bool onIsColorFilterNode(SkColorFilter** /*filterPtr*/) const {
303cedc36f18b2254c5ee21f6348124886b6db4f4c2reed        return false;
304cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    }
305cedc36f18b2254c5ee21f6348124886b6db4f4c2reed
306118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    /** Computes source bounds as the src bitmap bounds offset by srcOffset.
307118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org     *  Apply the transformed crop rect to the bounds if any of the
308118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org     *  corresponding edge flags are set. Intersects the result against the
309118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org     *  context's clipBounds, and returns the result in "bounds". If there is
310118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org     *  no intersection, returns false and leaves "bounds" unchanged.
311118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org     */
312118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    bool applyCropRect(const Context&, const SkBitmap& src, const SkIPoint& srcOffset,
313118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org                       SkIRect* bounds) const;
314118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org
315118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    /** Same as the above call, except that if the resulting crop rect is not
316118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org     *  entirely contained by the source bitmap's bounds, it creates a new
317118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org     *  bitmap in "result" and pads the edges with transparent black. In that
318118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org     *  case, the srcOffset is modified to be the same as the bounds, since no
319118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org     *  further adjustment is needed by the caller. This version should only
320118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org     *  be used by filters which are not capable of processing a smaller
321118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org     *  source bitmap into a larger destination.
322118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org     */
323118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    bool applyCropRect(const Context&, Proxy* proxy, const SkBitmap& src, SkIPoint* srcOffset,
324118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org                       SkIRect* bounds, SkBitmap* result) const;
325194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org
3261aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org    /**
3271aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org     *  Returns true if the filter can be expressed a single-pass
328b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt     *  GrProcessor, used to process this filter on the GPU, or false if
3291aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org     *  not.
3301aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org     *
331b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt     *  If effect is non-NULL, a new GrProcessor instance is stored
3321aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org     *  in it.  The caller assumes ownership of the stage, and it is up to the
3331aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org     *  caller to unref it.
3341aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org     *
3351aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org     *  The effect can assume its vertexCoords space maps 1-to-1 with texels
3361aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org     *  in the texture.  "matrix" is a transformation to apply to filter
3371aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org     *  parameters before they are used in the effect. Note that this function
3381aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org     *  will be called with (NULL, NULL, SkMatrix::I()) to query for support,
3391aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org     *  so returning "true" indicates support for all possible matrices.
3401aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org     */
341b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    virtual bool asFragmentProcessor(GrFragmentProcessor**, GrTexture*, const SkMatrix&,
342b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                     const SkIRect& bounds) const;
3431aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org
344894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.comprivate:
34555b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    bool usesSrcInput() const { return fUsesSrcInput; }
34655b6d8be997a447ef9ce0f029697677a940bfc24senorblanco
34754e01b2ab985e7a7d38109812069d056d128bfa1senorblanco@chromium.org    typedef SkFlattenable INHERITED;
3488d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    int fInputCount;
3499f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org    SkImageFilter** fInputs;
35055b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    bool fUsesSrcInput;
351b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org    CropRect fCropRect;
35255b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    uint32_t fUniqueID; // Globally unique
353894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com};
354894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com
3559fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed/**
3569fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed *  Helper to unflatten the common data, and return NULL if we fail.
3579fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed */
3589fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#define SK_IMAGEFILTER_UNFLATTEN_COMMON(localVar, expectedCount)    \
3599fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    Common localVar;                                                \
3609fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    do {                                                            \
3619fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        if (!localVar.unflatten(buffer, expectedCount)) {           \
3629fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed            return NULL;                                            \
3639fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        }                                                           \
3649fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    } while (0)
3659fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
366894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com#endif
367