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