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/SkTArray.h"
15 #include "include/private/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.count(); }
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 SK_SUPPORT_GPU
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 GrProtected isProtected = GrProtected::kNo);
314
315 /**
316 * Returns a version of the passed-in image (possibly the original), that is in a colorspace
317 * with the same gamut as the one from the OutputProperties. This allows filters that do many
318 * texture samples to guarantee that any color space conversion has happened before running.
319 */
320 static sk_sp<SkSpecialImage> ImageToColorSpace(SkSpecialImage* src,
321 SkColorType colorType,
322 SkColorSpace* colorSpace,
323 const SkSurfaceProps&);
324 #endif
325
326 // If 'srcBounds' will sample outside the border of 'originalSrcBounds' (i.e., the sample
327 // will wrap around to the other side) we must preserve the far side of the src along that
328 // axis (e.g., if we will sample beyond the left edge of the src, the right side must be
329 // preserved for the repeat sampling to work).
330 // DEPRECATED - Remove once cropping is handled by a separate filter, that can also handle all
331 // tile modes (including repeat) properly
332 static SkIRect DetermineRepeatedSrcBound(const SkIRect& srcBounds,
333 const SkIVector& filterOffset,
334 const SkISize& filterSize,
335 const SkIRect& originalSrcBounds);
336
337 private:
338 friend class SkImageFilter;
339 // For PurgeCache()
340 friend class SkGraphics;
341
342 static void PurgeCache();
343
344 // Configuration points for the filter implementation, marked private since they should not
345 // need to be invoked by the subclasses. These refer to the node's specific behavior and are
346 // not responsible for aggregating the behavior of the entire filter DAG.
347
348 /**
349 * Return true (and returns a ref'd colorfilter) if this node in the DAG is just a colorfilter
350 * w/o CropRect constraints.
351 */
onIsColorFilterNode(SkColorFilter **)352 virtual bool onIsColorFilterNode(SkColorFilter** /*filterPtr*/) const { return false; }
353
354 /**
355 * Return the most complex matrix type this filter can support (mapping from its parameter
356 * space to a layer space). If this returns anything less than kComplex, the filter only needs
357 * to worry about mapping from parameter to layer using a matrix that is constrained in that
358 * way (eg, scale+translate).
359 */
onGetCTMCapability()360 virtual MatrixCapability onGetCTMCapability() const {
361 return MatrixCapability::kScaleTranslate;
362 }
363
364 /**
365 * Return true if this filter would transform transparent black pixels to a color other than
366 * transparent black. When false, optimizations can be taken to discard regions known to be
367 * transparent black and thus process fewer pixels.
368 */
onAffectsTransparentBlack()369 virtual bool onAffectsTransparentBlack() const { return false; }
370
371 /**
372 * This is the virtual which should be overridden by the derived class to perform image
373 * filtering. Subclasses are responsible for recursing to their input filters, although the
374 * filterInput() function is provided to handle all necessary details of this.
375 *
376 * If the image cannot be created (either because of an error or if the result would be empty
377 * because it was clipped out), this should return a filtered Image with a null SkSpecialImage.
378 * In these situations, callers that do not affect transparent black can end early, since the
379 * "transparent" implicit image would be unchanged. Callers that affect transparent black need
380 * to safely handle these null and empty images and return an image filling the context's clip
381 * bounds as if its input filtered image were transparent black.
382 */
383 virtual skif::FilterResult onFilterImage(const skif::Context& context) const;
384
385 /**
386 * Calculates the necessary input layer size in order for the final output of the filter to
387 * cover the desired output bounds. The provided 'desiredOutput' represents the requested
388 * input bounds for this node's parent filter node, i.e. this function answers "what does this
389 * node require for input in order to satisfy (as its own output), the input needs of its
390 * parent?".
391 *
392 * If 'recurse' is true, this function is responsible for recursing to its child image filters
393 * and accounting for what they require to meet this filter's input requirements. It is up to
394 * the filter to determine how to aggregate these inputs, but a helper function is provided for
395 * the common case where the final required layer size is the union of the child filters'
396 * required inputs, evaluated on what this filter requires for itself. 'recurse' is kNo
397 * when mapping Contexts while actually filtering images, since the child recursion is
398 * happening at a higher level.
399 *
400 * Unlike the public getInputBounds(), all internal bounds calculations are done in the shared
401 * layer space defined by 'mapping'.
402 *
403 * The default implementation assumes that current filter requires an input equal to
404 * 'desiredOutputBounds', and passes this down to its child filters, and returns the union of
405 * their required inputs.
406 */
407 virtual skif::LayerSpace<SkIRect> onGetInputLayerBounds(
408 const skif::Mapping& mapping, const skif::LayerSpace<SkIRect>& desiredOutput,
409 const skif::LayerSpace<SkIRect>& contentBounds,
410 VisitChildren recurse = VisitChildren::kYes) const;
411
412 /**
413 * Calculates the output bounds that this filter node would touch when processing an input
414 * sized to 'contentBounds'. This function is responsible for recursing to its child image
415 * filters and accounting for what they output. It is up to the filter to determine how to
416 * aggregate the outputs of its children, but a helper function is provided for the common
417 * case where the filter output is the union of its child outputs.
418 *
419 * Unlike the public getOutputBounds(), all internal bounds calculations are done in the
420 * shared layer space defined by 'mapping'.
421 *
422 * The default implementation assumes that the output of this filter is equal to the union of
423 * the outputs of its child filters evaluated with 'contentBounds'.
424 */
425 // TODO (michaelludwig) - When layerMatrix = I, this function could be used to implement
426 // onComputeFastBounds() instead of making filters implement the essentially the same calcs x2
427 virtual skif::LayerSpace<SkIRect> onGetOutputLayerBounds(
428 const skif::Mapping& mapping, const skif::LayerSpace<SkIRect>& contentBounds) const;
429
430 SkAutoSTArray<2, sk_sp<SkImageFilter>> fInputs;
431
432 bool fUsesSrcInput;
433 CropRect fCropRect;
434 uint32_t fUniqueID; // Globally unique
435
436 using INHERITED = SkImageFilter;
437 };
438
as_IFB(SkImageFilter * filter)439 static inline SkImageFilter_Base* as_IFB(SkImageFilter* filter) {
440 return static_cast<SkImageFilter_Base*>(filter);
441 }
442
as_IFB(const sk_sp<SkImageFilter> & filter)443 static inline SkImageFilter_Base* as_IFB(const sk_sp<SkImageFilter>& filter) {
444 return static_cast<SkImageFilter_Base*>(filter.get());
445 }
446
as_IFB(const SkImageFilter * filter)447 static inline const SkImageFilter_Base* as_IFB(const SkImageFilter* filter) {
448 return static_cast<const SkImageFilter_Base*>(filter);
449 }
450
451 /**
452 * Helper to unflatten the common data, and return nullptr if we fail.
453 */
454 #define SK_IMAGEFILTER_UNFLATTEN_COMMON(localVar, expectedCount) \
455 Common localVar; \
456 do { \
457 if (!localVar.unflatten(buffer, expectedCount)) { \
458 return nullptr; \
459 } \
460 } while (0)
461
462
463 /**
464 * All image filter implementations defined for the include/effects/SkImageFilters.h factories
465 * are entirely encapsulated within their own CPP files. SkFlattenable deserialization needs a hook
466 * into these types, so their registration functions are exposed here.
467 */
468 void SkRegisterAlphaThresholdImageFilterFlattenable();
469 void SkRegisterArithmeticImageFilterFlattenable();
470 void SkRegisterBlendImageFilterFlattenable();
471 void SkRegisterBlurImageFilterFlattenable();
472 void SkRegisterColorFilterImageFilterFlattenable();
473 void SkRegisterComposeImageFilterFlattenable();
474 void SkRegisterCropImageFilterFlattenable();
475 void SkRegisterDisplacementMapImageFilterFlattenable();
476 void SkRegisterDropShadowImageFilterFlattenable();
477 void SkRegisterImageImageFilterFlattenable();
478 void SkRegisterLightingImageFilterFlattenables();
479 void SkRegisterMagnifierImageFilterFlattenable();
480 void SkRegisterMatrixConvolutionImageFilterFlattenable();
481 void SkRegisterMergeImageFilterFlattenable();
482 void SkRegisterMorphologyImageFilterFlattenables();
483 void SkRegisterOffsetImageFilterFlattenable();
484 void SkRegisterPictureImageFilterFlattenable();
485 #ifdef SK_ENABLE_SKSL
486 void SkRegisterRuntimeImageFilterFlattenable();
487 #endif
488 void SkRegisterShaderImageFilterFlattenable();
489 void SkRegisterTileImageFilterFlattenable();
490
491 #endif // SkImageFilter_Base_DEFINED
492