• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2019 Google LLC
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_Base_DEFINED
9 #define SkImageFilter_Base_DEFINED
10 
11 #include "include/core/SkColorSpace.h"
12 #include "include/core/SkImageFilter.h"
13 #include "include/core/SkImageInfo.h"
14 #include "include/private/base/SkTArray.h"
15 #include "include/private/base/SkTemplates.h"
16 
17 #include "src/core/SkImageFilterTypes.h"
18 
19 class GrFragmentProcessor;
20 class GrRecordingContext;
21 
22 // True base class that all SkImageFilter implementations need to extend from. This provides the
23 // actual API surface that Skia will use to compute the filtered images.
24 class SkImageFilter_Base : public SkImageFilter {
25 public:
26     // DEPRECATED - Use skif::Context directly.
27     using Context = skif::Context;
28 
29     /**
30      *  Request a new filtered image to be created from the src image. The returned skif::Image
31      *  provides both the pixel data and the origin point that it should be drawn at, relative to
32      *  the layer space defined by the provided context.
33      *
34      *  If the result image cannot be created, or the result would be transparent black, returns
35      *  a skif::Image that has a null special image, in which its origin should be ignored.
36      *
37      *  TODO: Right now the imagefilters sometimes return empty result bitmaps/
38      *        specialimages. That doesn't seem quite right.
39      */
40     skif::FilterResult filterImage(const skif::Context& context) const;
41 
42     /**
43      *  Calculate the smallest-possible required layer bounds that would provide sufficient
44      *  information to correctly compute the image filter for every pixel in the desired output
45      *  bounds. The 'desiredOutput' is intended to represent either the root render target bounds,
46      *  or the device-space bounds of the current clip. If the bounds of the content that will be
47      *  drawn into the layer is known, 'knownContentBounds' should be provided, since it can be
48      *  used to restrict the size of the layer if the image filter DAG does not affect transparent
49      *  black.
50      *
51      *  The returned rect is in the layer space defined by 'mapping', so it directly represents
52      *  the size and location of the SkDevice created to rasterize the content prior to invoking the
53      *  image filter (assuming its CTM and basis matrix are configured to match 'mapping').
54      *
55      *  While this operation transforms an device-space output bounds to a layer-space input bounds,
56      *  it is not necessarily the inverse of getOutputBounds(). For instance, a blur needs to have
57      *  an outset margin when reading pixels at the edge (to satisfy its kernel), thus it expands
58      *  its required input rect to include every pixel that contributes to the desired output rect.
59 
60      *  @param mapping       The coordinate space mapping that defines both the transformation
61      *                       between local and layer, and layer to root device space, that will be
62      *                       used when the filter is later invoked.
63      *  @param desiredOutput The desired output boundary that needs to be covered by the filter's
64      *                       output (assuming that the filter is then invoked with a suitable input)
65      *  @param knownContentBounds
66      *                       Optional, the known layer-space bounds of the non-transparent content
67      *                       that would be rasterized in the source input image.
68      *
69      * @return The layer-space bounding box to use for an SkDevice when drawing the source image.
70      */
71     skif::LayerSpace<SkIRect> getInputBounds(
72             const skif::Mapping& mapping, const skif::DeviceSpace<SkIRect>& desiredOutput,
73             const skif::ParameterSpace<SkRect>* knownContentBounds) const;
74 
75     /**
76      *  Calculate the device-space bounds of the output of this filter DAG, if it were to process
77      *  an image layer covering the 'contentBounds'. The 'mapping' defines how the content will be
78      *  transformed to layer space when it is drawn, and how the output filter image is then
79      *  transformed to the final device space (i.e. it specifies the mapping between the root device
80      *  space and the parameter space of the initially provided content).
81      *
82      *  While this operation transforms a parameter-space input bounds to an device-space output
83      *  bounds, it is not necessarily the inverse of getInputBounds(). For instance, a blur needs to
84      *  have an outset margin when reading pixels at the edge (to satisfy its kernel), so it will
85      *  generate a result larger than its input (so that the blur is visible) and, thus, expands its
86      *  output to include every pixel that it will touch.
87      *
88      *  @param mapping       The coordinate space mapping that defines both the transformation
89      *                       between local and layer, and layer to root device space, that will be
90      *                       used when the filter is later invoked.
91      *  @param contentBounds The local-space bounds of the non-transparent content that would be
92      *                       drawn into the source image prior to filtering with this DAG,  i.e.
93      *                       the same as 'knownContentBounds' in getInputBounds().
94      *
95      *  @return The root device-space bounding box of the filtered image, were it applied to
96      *          content contained by 'contentBounds' and then drawn with 'mapping' to the root
97      *          device (w/o any additional clipping).
98      */
99     skif::DeviceSpace<SkIRect> getOutputBounds(
100             const skif::Mapping& mapping, const skif::ParameterSpace<SkRect>& contentBounds) const;
101 
102     // Returns true if this image filter graph transforms a source transparent black pixel to a
103     // color other than transparent black.
104     bool affectsTransparentBlack() const;
105 
106     /**
107      *  Most ImageFilters can natively handle scaling and translate components in the CTM. Only
108      *  some of them can handle affine (or more complex) matrices. Some may only handle translation.
109      *  This call returns the maximum "kind" of CTM for a filter and all of its (non-null) inputs.
110      */
111     enum class MatrixCapability {
112         kTranslate,
113         kScaleTranslate,
114         kComplex,
115     };
116     MatrixCapability getCTMCapability() const;
117 
uniqueID()118     uint32_t uniqueID() const { return fUniqueID; }
119 
GetFlattenableType()120     static SkFlattenable::Type GetFlattenableType() {
121         return kSkImageFilter_Type;
122     }
123 
getFlattenableType()124     SkFlattenable::Type getFlattenableType() const override {
125         return kSkImageFilter_Type;
126     }
127 
128 protected:
129     // DEPRECATED: Will be removed once cropping is handled by a standalone image filter
130     class CropRect {
131     public:
132         enum CropEdge {
133             kHasLeft_CropEdge   = 0x01,
134             kHasTop_CropEdge    = 0x02,
135             kHasWidth_CropEdge  = 0x04,
136             kHasHeight_CropEdge = 0x08,
137             kHasAll_CropEdge    = 0x0F,
138         };
CropRect()139         CropRect() : fFlags(0) {}
CropRect(const SkRect * rect)140         explicit CropRect(const SkRect* rect)
141             : fRect(rect ? *rect : SkRect::MakeEmpty()), fFlags(rect ? kHasAll_CropEdge : 0x0) {}
142 
143         // CropRect(const CropRect&) = default;
144 
flags()145         uint32_t flags() const { return fFlags; }
rect()146         const SkRect& rect() const { return fRect; }
147 
148         /**
149          *  Apply this cropRect to the imageBounds. If a given edge of the cropRect is not set, then
150          *  the corresponding edge from imageBounds will be used. If "embiggen" is true, the crop
151          *  rect is allowed to enlarge the size of the rect, otherwise it may only reduce the rect.
152          *  Filters that can affect transparent black should pass "true", while all other filters
153          *  should pass "false".
154          *
155          *  Note: imageBounds is in "device" space, as the output cropped rectangle will be, so the
156          *  matrix is ignored for those. It is only applied to the cropRect's bounds.
157          */
158         void applyTo(const SkIRect& imageBounds, const SkMatrix& matrix, bool embiggen,
159                      SkIRect* cropped) const;
160 
161     private:
162         SkRect fRect;
163         uint32_t fFlags;
164     };
165 
166     class Common {
167     public:
168         /**
169          *  Attempt to unflatten the cropRect and the expected number of input filters.
170          *  If any number of input filters is valid, pass -1.
171          *  If this fails (i.e. corrupt buffer or contents) then return false and common will
172          *  be left uninitialized.
173          *  If this returns true, then inputCount() is the number of found input filters, each
174          *  of which may be NULL or a valid imagefilter.
175          */
176         bool unflatten(SkReadBuffer&, int expectedInputs);
177 
cropRect()178         const SkRect* cropRect() const {
179             return fCropRect.flags() != 0x0 ? &fCropRect.rect() : nullptr;
180         }
inputCount()181         int inputCount() const { return fInputs.size(); }
inputs()182         sk_sp<SkImageFilter>* inputs() { return fInputs.begin(); }
183 
getInput(int index)184         sk_sp<SkImageFilter> getInput(int index) { return fInputs[index]; }
185 
186     private:
187         CropRect fCropRect;
188         // most filters accept at most 2 input-filters
189         SkSTArray<2, sk_sp<SkImageFilter>, true> fInputs;
190     };
191 
192     // Whether or not to recurse to child input filters for certain operations that walk the DAG.
193     enum class VisitChildren : bool {
194         kNo  = false,
195         kYes = true
196     };
197 
198     SkImageFilter_Base(sk_sp<SkImageFilter> const* inputs, int inputCount,
199                        const SkRect* cropRect);
200 
201     ~SkImageFilter_Base() override;
202 
203     void flatten(SkWriteBuffer&) const override;
204 
205     // DEPRECATED - Use the private context-only variant
onFilterImage(const Context &,SkIPoint * offset)206     virtual sk_sp<SkSpecialImage> onFilterImage(const Context&, SkIPoint* offset) const {
207         return nullptr;
208     }
209 
210     // DEPRECATED - Override onGetOutputLayerBounds and onGetInputLayerBounds instead. The
211     // node-specific and aggregation functions are no longer separated in the current API. A helper
212     // function is provided to do the default recursion for the common filter case.
213     virtual SkIRect onFilterBounds(const SkIRect&, const SkMatrix& ctm,
214                                    MapDirection, const SkIRect* inputRect) const;
215     virtual SkIRect onFilterNodeBounds(const SkIRect&, const SkMatrix& ctm,
216                                        MapDirection, const SkIRect* inputRect) const;
217 
218     // DEPRECRATED - Call the Context-only filterInput()
filterInput(int index,const Context & ctx,SkIPoint * offset)219     sk_sp<SkSpecialImage> filterInput(int index, const Context& ctx, SkIPoint* offset) const {
220         return this->filterInput(index, ctx).imageAndOffset(offset);
221     }
222 
223     // Helper function to visit each of this filter's child filters and call their
224     // onGetInputLayerBounds with the provided 'desiredOutput' and 'contentBounds'. Automatically
225     // handles null input filters. Returns the union of all of the children's input bounds.
226     skif::LayerSpace<SkIRect> visitInputLayerBounds(
227             const skif::Mapping& mapping, const skif::LayerSpace<SkIRect>& desiredOutput,
228             const skif::LayerSpace<SkIRect>& contentBounds) const;
229     // Helper function to visit each of this filter's child filters and call their
230     // onGetOutputLayerBounds with the provided 'contentBounds'. Automatically handles null input
231     // filters.
232     skif::LayerSpace<SkIRect> visitOutputLayerBounds(
233             const skif::Mapping& mapping, const skif::LayerSpace<SkIRect>& contentBounds) const;
234 
235     // Helper function for recursing through the filter DAG. It automatically evaluates the input
236     // image filter at 'index' using the given context. If the input image filter is null, it
237     // automatically returns the context's dynamic source image.
238     //
239     // Implementations must handle cases when the input filter was unable to compute an image and
240     // the returned skif::Image has a null SkSpecialImage. If the filter affects transparent black,
241     // it should treat null results or images that do not fully cover the requested output bounds as
242     // being transparent black in those regions. Filters that do not affect transparent black can
243     // exit early since the null image would remain transparent.
244     skif::FilterResult filterInput(int index, const skif::Context& ctx) const;
245 
246     /**
247      *  Returns whether any edges of the crop rect have been set. The crop
248      *  rect is set at construction time, and determines which pixels from the
249      *  input image will be processed, and which pixels in the output image will be allowed.
250      *  The size of the crop rect should be
251      *  used as the size of the destination image. The origin of this rect
252      *  should be used to offset access to the input images, and should also
253      *  be added to the "offset" parameter in onFilterImage.
254      *
255      *  DEPRECATED - Remove once cropping is handled by a separate filter
256      */
cropRectIsSet()257     bool cropRectIsSet() const { return fCropRect.flags() != 0x0; }
258 
259     // DEPRECATED - Remove once cropping is handled by a separate filter
getCropRect()260     CropRect getCropRect() const { return fCropRect; }
261 
262     // DEPRECATED - Remove once cropping is handled by a separate filter
getCropRectIfSet()263     const CropRect* getCropRectIfSet() const {
264         return this->cropRectIsSet() ? &fCropRect : nullptr;
265     }
266 
267     /** Given a "srcBounds" rect, computes destination bounds for this filter.
268      *  "dstBounds" are computed by transforming the crop rect by the context's
269      *  CTM, applying it to the initial bounds, and intersecting the result with
270      *  the context's clip bounds.  "srcBounds" (if non-null) are computed by
271      *  intersecting the initial bounds with "dstBounds", to ensure that we never
272      *  sample outside of the crop rect (this restriction may be relaxed in the
273      *  future).
274      *
275      *  DEPRECATED - Remove once cropping is handled by a separate filter, although it may be
276      *  necessary to provide a similar convenience function to compute the output bounds given the
277      *  images returned by filterInput().
278      */
279     bool applyCropRect(const Context&, const SkIRect& srcBounds, SkIRect* dstBounds) const;
280 
281     /** A variant of the above call which takes the original source bitmap and
282      *  source offset. If the resulting crop rect is not entirely contained by
283      *  the source bitmap's bounds, it creates a new bitmap in "result" and
284      *  pads the edges with transparent black. In that case, the srcOffset is
285      *  modified to be the same as the bounds, since no further adjustment is
286      *  needed by the caller. This version should only be used by filters
287      *  which are not capable of processing a smaller source bitmap into a
288      *  larger destination.
289      *
290      *  DEPRECATED - Remove once cropping is handled by a separate filter.
291      */
292     sk_sp<SkSpecialImage> applyCropRectAndPad(const Context&, SkSpecialImage* src,
293                                               SkIPoint* srcOffset, SkIRect* bounds) const;
294 
295     /**
296      *  Creates a modified Context for use when recursing up the image filter DAG.
297      *  The clip bounds are adjusted to accommodate any margins that this
298      *  filter requires by calling this node's
299      *  onFilterNodeBounds(..., kReverse_MapDirection).
300      */
301     // TODO (michaelludwig) - I don't think this is necessary to keep as protected. Other than the
302     // real use case in recursing through the DAG for filterInput(), it feels wrong for blur and
303     // other filters to need to call it.
304     Context mapContext(const Context& ctx) const;
305 
306 #if defined(SK_GANESH)
307     static sk_sp<SkSpecialImage> DrawWithFP(GrRecordingContext* context,
308                                             std::unique_ptr<GrFragmentProcessor> fp,
309                                             const SkIRect& bounds,
310                                             SkColorType colorType,
311                                             const SkColorSpace* colorSpace,
312                                             const SkSurfaceProps&,
313                                             GrSurfaceOrigin surfaceOrigin,
314                                             GrProtected isProtected = GrProtected::kNo);
315 
316     /**
317      *  Returns a version of the passed-in image (possibly the original), that is in a colorspace
318      *  with the same gamut as the one from the OutputProperties. This allows filters that do many
319      *  texture samples to guarantee that any color space conversion has happened before running.
320      */
321     static sk_sp<SkSpecialImage> ImageToColorSpace(SkSpecialImage* src,
322                                                    SkColorType colorType,
323                                                    SkColorSpace* colorSpace,
324                                                    const SkSurfaceProps&);
325 #endif
326 
327     // If 'srcBounds' will sample outside the border of 'originalSrcBounds' (i.e., the sample
328     // will wrap around to the other side) we must preserve the far side of the src along that
329     // axis (e.g., if we will sample beyond the left edge of the src, the right side must be
330     // preserved for the repeat sampling to work).
331     // DEPRECATED - Remove once cropping is handled by a separate filter, that can also handle all
332     // tile modes (including repeat) properly
333     static SkIRect DetermineRepeatedSrcBound(const SkIRect& srcBounds,
334                                              const SkIVector& filterOffset,
335                                              const SkISize& filterSize,
336                                              const SkIRect& originalSrcBounds);
337 
338 private:
339     friend class SkImageFilter;
340     // For PurgeCache()
341     friend class SkGraphics;
342 
343     static void PurgeCache();
344 
345     // Configuration points for the filter implementation, marked private since they should not
346     // need to be invoked by the subclasses. These refer to the node's specific behavior and are
347     // not responsible for aggregating the behavior of the entire filter DAG.
348 
349     /**
350      *  Return true (and returns a ref'd colorfilter) if this node in the DAG is just a colorfilter
351      *  w/o CropRect constraints.
352      */
onIsColorFilterNode(SkColorFilter **)353     virtual bool onIsColorFilterNode(SkColorFilter** /*filterPtr*/) const { return false; }
354 
355     /**
356      *  Return the most complex matrix type this filter can support (mapping from its parameter
357      *  space to a layer space). If this returns anything less than kComplex, the filter only needs
358      *  to worry about mapping from parameter to layer using a matrix that is constrained in that
359      *  way (eg, scale+translate).
360      */
onGetCTMCapability()361     virtual MatrixCapability onGetCTMCapability() const {
362         return MatrixCapability::kScaleTranslate;
363     }
364 
365     /**
366      *  Return true if this filter would transform transparent black pixels to a color other than
367      *  transparent black. When false, optimizations can be taken to discard regions known to be
368      *  transparent black and thus process fewer pixels.
369      */
onAffectsTransparentBlack()370     virtual bool onAffectsTransparentBlack() const { return false; }
371 
372     /**
373      *  This is the virtual which should be overridden by the derived class to perform image
374      *  filtering. Subclasses are responsible for recursing to their input filters, although the
375      *  filterInput() function is provided to handle all necessary details of this.
376      *
377      *  If the image cannot be created (either because of an error or if the result would be empty
378      *  because it was clipped out), this should return a filtered Image with a null SkSpecialImage.
379      *  In these situations, callers that do not affect transparent black can end early, since the
380      *  "transparent" implicit image would be unchanged. Callers that affect transparent black need
381      *  to safely handle these null and empty images and return an image filling the context's clip
382      *  bounds as if its input filtered image were transparent black.
383      */
384     virtual skif::FilterResult onFilterImage(const skif::Context& context) const;
385 
386     /**
387      *  Calculates the necessary input layer size in order for the final output of the filter to
388      *  cover the desired output bounds. The provided 'desiredOutput' represents the requested
389      *  input bounds for this node's parent filter node, i.e. this function answers "what does this
390      *  node require for input in order to satisfy (as its own output), the input needs of its
391      *  parent?".
392      *
393      *  If 'recurse' is true, this function is responsible for recursing to its child image filters
394      *  and accounting for what they require to meet this filter's input requirements. It is up to
395      *  the filter to determine how to aggregate these inputs, but a helper function is provided for
396      *  the common case where the final required layer size is the union of the child filters'
397      *  required inputs, evaluated on what this filter requires for itself. 'recurse' is kNo
398      *  when mapping Contexts while actually filtering images, since the child recursion is
399      *  happening at a higher level.
400      *
401      *  Unlike the public getInputBounds(), all internal bounds calculations are done in the shared
402      *  layer space defined by 'mapping'.
403      *
404      *  The default implementation assumes that current filter requires an input equal to
405      *  'desiredOutputBounds', and passes this down to its child filters, and returns the union of
406      *  their required inputs.
407      */
408     virtual skif::LayerSpace<SkIRect> onGetInputLayerBounds(
409             const skif::Mapping& mapping, const skif::LayerSpace<SkIRect>& desiredOutput,
410             const skif::LayerSpace<SkIRect>& contentBounds,
411             VisitChildren recurse = VisitChildren::kYes) const;
412 
413     /**
414      *  Calculates the output bounds that this filter node would touch when processing an input
415      *  sized to 'contentBounds'. This function is responsible for recursing to its child image
416      *  filters and accounting for what they output. It is up to the filter to determine how to
417      *  aggregate the outputs of its children, but a helper function is provided for the common
418      *  case where the filter output is the union of its child outputs.
419      *
420      *  Unlike the public getOutputBounds(), all internal bounds calculations are done in the
421      *  shared layer space defined by 'mapping'.
422      *
423      *  The default implementation assumes that the output of this filter is equal to the union of
424      *  the outputs of its child filters evaluated with 'contentBounds'.
425      */
426     // TODO (michaelludwig) - When layerMatrix = I, this function could be used to implement
427     // onComputeFastBounds() instead of making filters implement the essentially the same calcs x2
428     virtual skif::LayerSpace<SkIRect> onGetOutputLayerBounds(
429             const skif::Mapping& mapping, const skif::LayerSpace<SkIRect>& contentBounds) const;
430 
431     skia_private::AutoSTArray<2, sk_sp<SkImageFilter>> fInputs;
432 
433     bool fUsesSrcInput;
434     CropRect fCropRect;
435     uint32_t fUniqueID; // Globally unique
436 
437     using INHERITED = SkImageFilter;
438 };
439 
as_IFB(SkImageFilter * filter)440 static inline SkImageFilter_Base* as_IFB(SkImageFilter* filter) {
441     return static_cast<SkImageFilter_Base*>(filter);
442 }
443 
as_IFB(const sk_sp<SkImageFilter> & filter)444 static inline SkImageFilter_Base* as_IFB(const sk_sp<SkImageFilter>& filter) {
445     return static_cast<SkImageFilter_Base*>(filter.get());
446 }
447 
as_IFB(const SkImageFilter * filter)448 static inline const SkImageFilter_Base* as_IFB(const SkImageFilter* filter) {
449     return static_cast<const SkImageFilter_Base*>(filter);
450 }
451 
452 /**
453  *  Helper to unflatten the common data, and return nullptr if we fail.
454  */
455 #define SK_IMAGEFILTER_UNFLATTEN_COMMON(localVar, expectedCount)    \
456     Common localVar;                                                \
457     do {                                                            \
458         if (!localVar.unflatten(buffer, expectedCount)) {           \
459             return nullptr;                                         \
460         }                                                           \
461     } while (0)
462 
463 
464 /**
465  * All image filter implementations defined for the include/effects/SkImageFilters.h factories
466  * are entirely encapsulated within their own CPP files. SkFlattenable deserialization needs a hook
467  * into these types, so their registration functions are exposed here.
468  */
469 void SkRegisterAlphaThresholdImageFilterFlattenable();
470 void SkRegisterArithmeticImageFilterFlattenable();
471 void SkRegisterBlendImageFilterFlattenable();
472 void SkRegisterBlurImageFilterFlattenable();
473 void SkRegisterColorFilterImageFilterFlattenable();
474 void SkRegisterComposeImageFilterFlattenable();
475 void SkRegisterCropImageFilterFlattenable();
476 void SkRegisterDisplacementMapImageFilterFlattenable();
477 void SkRegisterDropShadowImageFilterFlattenable();
478 void SkRegisterImageImageFilterFlattenable();
479 void SkRegisterLightingImageFilterFlattenables();
480 void SkRegisterMagnifierImageFilterFlattenable();
481 void SkRegisterMatrixConvolutionImageFilterFlattenable();
482 void SkRegisterMatrixTransformImageFilterFlattenable();
483 void SkRegisterMergeImageFilterFlattenable();
484 void SkRegisterMorphologyImageFilterFlattenables();
485 void SkRegisterPictureImageFilterFlattenable();
486 #ifdef SK_ENABLE_SKSL
487 void SkRegisterRuntimeImageFilterFlattenable();
488 #endif
489 void SkRegisterShaderImageFilterFlattenable();
490 void SkRegisterTileImageFilterFlattenable();
491 
492 #endif // SkImageFilter_Base_DEFINED
493