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 16 class SkBitmap; 17 class SkColorFilter; 18 class SkBaseDevice; 19 struct SkIPoint; 20 class GrFragmentProcessor; 21 class 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 */ 30 class SK_API SkImageFilter : public SkFlattenable { 31 public: 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 191 protected: 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 309 private: 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