blob: 38499e90c8d2d2b6d99f96e40d4bf122bbc0f0a2 [file] [log] [blame]
/*
* Copyright 2023 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkBlurEngine_DEFINED
#define SkBlurEngine_DEFINED
#include "include/core/SkRefCnt.h"
class SkSpecialImage;
struct SkIRect;
struct SkSize;
enum class SkTileMode;
enum SkColorType : int;
/**
* SkBlurEngine is a backend-agnostic provider of blur algorithms. Each Skia backend defines a blur
* engine with a set of supported algorithms and/or implementations. A given implementation may be
* optimized for a particular color type, sigma range, or available hardware. Each engine and its
* algorithms are assumed to operate only on SkImages corresponding to its Skia backend, and will
* produce output SkImages of the same type.
*
* Algorithms are allowed to specify a maximum supported sigma. If the desired sigma is higher than
* this, the input image and output region must be downscaled by the caller before invoking the
* algorithm. This is to provide the most flexibility for input representation (e.g. directly
* rasterize at half resolution or apply deferred filter effects during the first downsample pass).
*
* skif::FilterResult::Builder::blur() is a convenient wrapper around the blur engine and
* automatically handles resizing.
*/
class SkBlurEngine {
public:
class Algorithm;
virtual ~SkBlurEngine() = default;
// Returns an Algorithm ideal for the requested 'sigma' that will support sampling an image of
// the given 'colorType'. If the engine does not support the requested configuration, it returns
// null. The engine maintains the lifetime of its algorithms, so the returned non-null
// Algorithms live as long as the engine does.
virtual const Algorithm* findAlgorithm(SkSize sigma,
SkColorType colorType) const = 0;
// TODO: Consolidate common utility functions from SkBlurMask.h, skgpu::BlurUtils, and
// skgpu::ganesh::GrBlurUtils into this header.
};
class SkBlurEngine::Algorithm {
public:
virtual ~Algorithm() = default;
// The maximum sigma that can be passed to blur() in the X and/or Y sigma values. Larger
// requested sigmas must manually downscale the input image and upscale the output image.
virtual float maxSigma() const = 0;
// Whether or not the SkTileMode can be passed to blur() must be SkTileMode::kDecal, or if any
// tile mode is supported. If only kDecal is supported, then callers must manually apply the
// tilemode and account for that in the src and dst bounds passed into blur(). If this returns
// false, then the algorithm supports all SkTileModes.
// TODO: Once CPU blurs support all tile modes, this API can go away.
virtual bool supportsOnlyDecalTiling() const = 0;
// Produce a blurred image that fills 'dstRect' (their dimensions will match). 'dstRect's top
// left corner defines the output's location relative to the 'src' image. 'srcRect' restricts
// the pixels that are included in the blur and is also relative to 'src'. The 'tileMode'
// applies to the boundary of 'srcRect', which must be contained within 'src's dimensions.
//
// 'srcRect' and 'dstRect' may be different sizes and even be disjoint.
//
// The returned SkImage will have the same color type and colorspace as the input image. It will
// be an SkImage type matching the underlying Skia backend. If the 'src' SkImage is not a
// compatible SkImage type, null is returned.
// TODO(b/299474380): This only takes SkSpecialImage to work with skif::FilterResult and
// SkDevice::snapSpecial(); SkImage would be ideal.
virtual sk_sp<SkSpecialImage> blur(SkSize sigma,
sk_sp<SkSpecialImage> src,
const SkIRect& srcRect,
SkTileMode tileMode,
const SkIRect& dstRect) const = 0;
};
#endif // SkBlurEngine_DEFINED