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