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