blob: e467761a1f0607e2ce244003be132c295c4f9874 [file] [log] [blame]
reed@google.com894aa9a2011-09-23 14:49:49 +00001/*
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"
senorblanco@chromium.orgccf225c2013-07-22 20:03:22 +000012#include "SkRect.h"
reed@google.com894aa9a2011-09-23 14:49:49 +000013
reed@google.com15356a62011-11-03 19:29:08 +000014class SkBitmap;
senorblanco@chromium.org8d21f6c2012-10-12 19:14:06 +000015class SkColorFilter;
reed@google.com76dd2772012-01-05 21:15:07 +000016class SkDevice;
reed@google.com15356a62011-11-03 19:29:08 +000017class SkMatrix;
djsollen@google.comc73dd5c2012-08-07 15:54:32 +000018struct SkIPoint;
sugoi@google.coma1c511b2013-02-21 15:02:28 +000019class SkShader;
bsalomon@google.com0ac6af42013-01-16 15:16:18 +000020class GrEffectRef;
tomhudson@google.comd0c1a062012-07-12 17:23:52 +000021class GrTexture;
reed@google.com15356a62011-11-03 19:29:08 +000022
23/**
24 * Experimental.
25 *
26 * Base class for image filters. If one is installed in the paint, then
27 * all drawing occurs as usual, but it is as if the drawing happened into an
28 * offscreen (before the xfermode is applied). This offscreen bitmap will
29 * then be handed to the imagefilter, who in turn creates a new bitmap which
30 * is what will finally be drawn to the device (using the original xfermode).
31 *
reed@google.com32d25b62011-12-20 16:19:00 +000032 * THIS SIGNATURE IS TEMPORARY
33 *
34 * There are several weaknesses in this function signature:
35 * 1. Does not expose the destination/target device, so filters that can draw
36 * directly to it are unable to take advantage of that optimization.
37 * 2. Does not expose a way to create a "compabitible" image (i.e. gpu -> gpu)
38 * 3. As with #1, the filter is unable to "read" the dest (which would be slow)
39 *
40 * Therefore, we should not create any real dependencies on this API yet -- it
41 * is being checked in as a check-point so we can explore these and other
42 * considerations.
reed@google.com15356a62011-11-03 19:29:08 +000043 */
senorblanco@chromium.org54e01b22011-11-16 18:20:47 +000044class SK_API SkImageFilter : public SkFlattenable {
reed@google.com894aa9a2011-09-23 14:49:49 +000045public:
robertphillips@google.com0456e0b2012-06-27 14:03:26 +000046 SK_DECLARE_INST_COUNT(SkImageFilter)
47
reed@google.com76dd2772012-01-05 21:15:07 +000048 class Proxy {
49 public:
reed@google.com8926b162012-03-23 15:36:36 +000050 virtual ~Proxy() {};
51
reed@google.com76dd2772012-01-05 21:15:07 +000052 virtual SkDevice* createDevice(int width, int height) = 0;
reed@google.com8926b162012-03-23 15:36:36 +000053 // returns true if the proxy can handle this filter natively
54 virtual bool canHandleImageFilter(SkImageFilter*) = 0;
reed@google.com76dd2772012-01-05 21:15:07 +000055 // returns true if the proxy handled the filter itself. if this returns
56 // false then the filter's code will be called.
57 virtual bool filterImage(SkImageFilter*, const SkBitmap& src,
58 const SkMatrix& ctm,
59 SkBitmap* result, SkIPoint* offset) = 0;
60 };
reed@google.com894aa9a2011-09-23 14:49:49 +000061
62 /**
63 * Request a new (result) image to be created from the src image.
64 * If the src has no pixels (isNull()) then the request just wants to
65 * receive the config and width/height of the result.
66 *
67 * The matrix is the current matrix on the canvas.
68 *
69 * Offset is the amount to translate the resulting image relative to the
rmistry@google.comfbfcd562012-08-23 18:09:54 +000070 * src when it is drawn.
reed@google.com894aa9a2011-09-23 14:49:49 +000071 *
72 * If the result image cannot be created, return false, in which case both
73 * the result and offset parameters will be ignored by the caller.
74 */
reed@google.com76dd2772012-01-05 21:15:07 +000075 bool filterImage(Proxy*, const SkBitmap& src, const SkMatrix& ctm,
reed@google.com15356a62011-11-03 19:29:08 +000076 SkBitmap* result, SkIPoint* offset);
77
78 /**
reed@google.com32d25b62011-12-20 16:19:00 +000079 * Given the src bounds of an image, this returns the bounds of the result
80 * image after the filter has been applied.
81 */
82 bool filterBounds(const SkIRect& src, const SkMatrix& ctm, SkIRect* dst);
83
84 /**
senorblanco@chromium.org894790d2012-07-11 16:01:22 +000085 * Returns true if the filter can be expressed a single-pass
bsalomon@google.coma469c282012-10-24 18:28:34 +000086 * GrEffect, used to process this filter on the GPU, or false if
senorblanco@chromium.org894790d2012-07-11 16:01:22 +000087 * not.
rmistry@google.comfbfcd562012-08-23 18:09:54 +000088 *
bsalomon@google.com021fc732012-10-25 12:47:42 +000089 * If effect is non-NULL, a new GrEffect instance is stored
senorblanco@chromium.org894790d2012-07-11 16:01:22 +000090 * in it. The caller assumes ownership of the stage, and it is up to the
91 * caller to unref it.
bsalomon@google.com17fc6512012-11-02 21:45:01 +000092 *
93 * The effect can assume its vertexCoords space maps 1-to-1 with texels
94 * in the texture.
senorblanco@chromium.org894790d2012-07-11 16:01:22 +000095 */
bsalomon@google.com0ac6af42013-01-16 15:16:18 +000096 virtual bool asNewEffect(GrEffectRef** effect, GrTexture*) const;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +000097
98 /**
senorblanco@chromium.org302cffb2012-08-01 20:16:34 +000099 * Returns true if the filter can be processed on the GPU. This is most
100 * often used for multi-pass effects, where intermediate results must be
bsalomon@google.com8ea78d82012-10-24 20:11:30 +0000101 * rendered to textures. For single-pass effects, use asNewEffect().
senorblanco@chromium.orgd043cce2013-04-08 19:43:22 +0000102 * The default implementation returns asNewEffect(NULL, NULL).
reed@google.com15356a62011-11-03 19:29:08 +0000103 */
senorblanco@chromium.org302cffb2012-08-01 20:16:34 +0000104 virtual bool canFilterImageGPU() const;
reed@google.com894aa9a2011-09-23 14:49:49 +0000105
senorblanco@chromium.org05054f12012-03-02 21:05:45 +0000106 /**
skia.committer@gmail.com32840172013-04-09 07:01:27 +0000107 * Process this image filter on the GPU. This is most often used for
senorblanco@chromium.orgd043cce2013-04-08 19:43:22 +0000108 * multi-pass effects, where intermediate results must be rendered to
109 * textures. For single-pass effects, use asNewEffect(). src is the
110 * source image for processing, as a texture-backed bitmap. result is
111 * the destination bitmap, which should contain a texture-backed pixelref
skia.committer@gmail.comde2e4e82013-07-11 07:01:01 +0000112 * on success. offset is the amount to translate the resulting image
commit-bot@chromium.org7b320702013-07-10 21:22:18 +0000113 * relative to the src when it is drawn. The default implementation does
114 * single-pass processing using asNewEffect().
senorblanco@chromium.org05054f12012-03-02 21:05:45 +0000115 */
commit-bot@chromium.org7b320702013-07-10 21:22:18 +0000116 virtual bool filterImageGPU(Proxy*, const SkBitmap& src, SkBitmap* result, SkIPoint* offset);
senorblanco@chromium.org05054f12012-03-02 21:05:45 +0000117
senorblanco@chromium.org8d21f6c2012-10-12 19:14:06 +0000118 /**
sugoi@google.coma1c511b2013-02-21 15:02:28 +0000119 * Returns whether this image filter is a color filter and puts the color filter into the
sugoi@google.com4b6d4322013-02-21 20:26:50 +0000120 * "filterPtr" parameter if it can. Does nothing otherwise.
121 * If this returns false, then the filterPtr is unchanged.
122 * If this returns true, then if filterPtr is not null, it must be set to a ref'd colorfitler
123 * (i.e. it may not be set to NULL).
senorblanco@chromium.org8d21f6c2012-10-12 19:14:06 +0000124 */
sugoi@google.com4b6d4322013-02-21 20:26:50 +0000125 virtual bool asColorFilter(SkColorFilter** filterPtr) const;
senorblanco@chromium.org9f25de72012-10-10 20:36:13 +0000126
senorblanco@chromium.org8d21f6c2012-10-12 19:14:06 +0000127 /**
128 * Returns the number of inputs this filter will accept (some inputs can
129 * be NULL).
130 */
131 int countInputs() const { return fInputCount; }
132
133 /**
134 * Returns the input filter at a given index, or NULL if no input is
135 * connected. The indices used are filter-specific.
136 */
137 SkImageFilter* getInput(int i) const {
138 SkASSERT(i < fInputCount);
139 return fInputs[i];
140 }
141
senorblanco@chromium.orgccf225c2013-07-22 20:03:22 +0000142 /**
143 * Returns the crop rectangle of this filter. This is set at construction
144 * time, and determines which pixels from the input image will
145 * be processed. The size of this rectangle should be used as the size
146 * of the destination image. The origin of this rect should be used to
147 * offset access to the input images, and should also be added to the
148 * "offset" parameter in onFilterImage and filterImageGPU(). (The latter
149 * ensures that the resulting buffer is drawn in the correct location.)
150 */
151 const SkIRect& cropRect() const { return fCropRect; }
152
senorblanco@chromium.org8d21f6c2012-10-12 19:14:06 +0000153protected:
senorblanco@chromium.orgccf225c2013-07-22 20:03:22 +0000154 SkImageFilter(int inputCount, SkImageFilter** inputs, const SkIRect* cropRect = NULL);
senorblanco@chromium.org8d21f6c2012-10-12 19:14:06 +0000155
senorblanco@chromium.orgc2e8cef2012-10-22 15:07:14 +0000156 // Convenience constructor for 1-input filters.
senorblanco@chromium.orgccf225c2013-07-22 20:03:22 +0000157 explicit SkImageFilter(SkImageFilter* input, const SkIRect* cropRect = NULL);
senorblanco@chromium.orgc2e8cef2012-10-22 15:07:14 +0000158
159 // Convenience constructor for 2-input filters.
senorblanco@chromium.orgccf225c2013-07-22 20:03:22 +0000160 SkImageFilter(SkImageFilter* input1, SkImageFilter* input2, const SkIRect* cropRect = NULL);
senorblanco@chromium.org9f25de72012-10-10 20:36:13 +0000161
162 virtual ~SkImageFilter();
163
164 explicit SkImageFilter(SkFlattenableReadBuffer& rb);
165
166 virtual void flatten(SkFlattenableWriteBuffer& wb) const SK_OVERRIDE;
reed@google.com32d25b62011-12-20 16:19:00 +0000167
168 // Default impl returns false
reed@google.com76dd2772012-01-05 21:15:07 +0000169 virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
reed@google.com15356a62011-11-03 19:29:08 +0000170 SkBitmap* result, SkIPoint* offset);
reed@google.com32d25b62011-12-20 16:19:00 +0000171 // Default impl copies src into dst and returns true
172 virtual bool onFilterBounds(const SkIRect&, const SkMatrix&, SkIRect*);
reed@google.com894aa9a2011-09-23 14:49:49 +0000173
senorblanco@chromium.orgccf225c2013-07-22 20:03:22 +0000174 // Sets rect to the intersection of rect and the crop rect. If there
175 // is no overlap, returns false and leaves rect unchanged.
176 bool applyCropRect(SkIRect* rect) const;
177
reed@google.com894aa9a2011-09-23 14:49:49 +0000178private:
senorblanco@chromium.org54e01b22011-11-16 18:20:47 +0000179 typedef SkFlattenable INHERITED;
senorblanco@chromium.org8d21f6c2012-10-12 19:14:06 +0000180 int fInputCount;
senorblanco@chromium.org9f25de72012-10-10 20:36:13 +0000181 SkImageFilter** fInputs;
senorblanco@chromium.orgccf225c2013-07-22 20:03:22 +0000182 SkIRect fCropRect;
reed@google.com894aa9a2011-09-23 14:49:49 +0000183};
184
185#endif