58SkBitmap create_kernel_bitmap(
const SkISize& kernelSize,
const float* kernel,
59 float* innerGain,
float* innerBias);
63 SkMatrixConvolutionImageFilter(
const SkISize& kernelSize,
const SkScalar* kernel,
67 , fKernel(kernel, kernelSize.
width() * kernelSize.
height())
68 , fKernelSize(kernelSize)
69 , fKernelOffset({kernelOffset.
fX, kernelOffset.
fY})
72 , fConvolveAlpha(convolveAlpha) {
75 SkASSERT(kernelSize.fWidth >= 1 && kernelSize.fHeight >= 1);
76 SkASSERT(kernelOffset.fX >= 0 && kernelOffset.fX < kernelSize.fWidth);
77 SkASSERT(kernelOffset.fY >= 0 && kernelOffset.fY < kernelSize.fHeight);
80 fKernelBitmap = create_kernel_bitmap(kernelSize, kernel, &fInnerGain, &fInnerBias);
149 int dl,
int dt,
int dr,
int db) {
155std::pair<int, SkKnownRuntimeEffects::StableKey> quantize_by_kernel_size(
int kernelSize) {
159 return {
kSmallKernelSize, SkKnownRuntimeEffects::StableKey::kMatrixConvTexSm };
162 return {
kLargeKernelSize, SkKnownRuntimeEffects::StableKey::kMatrixConvTexLg };
165SkBitmap create_kernel_bitmap(
const SkISize& kernelSize,
const float* kernel,
166 float* innerGain,
float* innerBias) {
168 auto [quantizedKernelSize,
key] = quantize_by_kernel_size(
length);
169 if (
key == SkKnownRuntimeEffects::StableKey::kMatrixConvUniforms) {
189 float min = kernel[0];
190 float max = kernel[0];
192 if (kernel[
i] <
min) {
195 if (kernel[
i] >
max) {
218 for (
int i =
length;
i < quantizedKernelSize; ++
i) {
237 if (kernelSize.
width() < 1 || kernelSize.
height() < 1) {
246 if ((kernelOffset.
fX < 0) || (kernelOffset.
fX >= kernelSize.
fWidth) ||
247 (kernelOffset.
fY < 0) || (kernelOffset.
fY >= kernelSize.
fHeight)) {
261 kernelSize, kernel, gain, bias, kernelOffset, convolveAlpha, &filter));
273 SkMatrixConvolutionImageFilter::CreateProc);
292 if (!
buffer.readScalarArray(kernel.get(),
count)) {
306 bool convolveAlpha =
buffer.readBool();
315 kernelSize, kernel.get(), gain, bias, kernelOffset, tileMode,
321 buffer.writeInt(fKernelSize.width());
322 buffer.writeInt(fKernelSize.height());
323 buffer.writeScalarArray(fKernel.data(), fKernel.size());
324 buffer.writeScalar(fGain);
325 buffer.writeScalar(fBias);
326 buffer.writeInt(fKernelOffset.x());
327 buffer.writeInt(fKernelOffset.y());
328 buffer.writeBool(fConvolveAlpha);
338 fKernelSize.width() - fKernelOffset.x() - 1,
339 fKernelSize.height() - fKernelOffset.y() - 1);
345 fKernelOffset.x() - fKernelSize.width() + 1,
346 fKernelOffset.y() - fKernelSize.height() + 1,
355 const int kernelLength = fKernelSize.width() * fKernelSize.height();
356 auto [_,
key] = quantize_by_kernel_size(kernelLength);
357 const bool useTextureShader = (
key != SkKnownRuntimeEffects::StableKey::kMatrixConvUniforms);
358 if (useTextureShader && fKernelBitmap.empty()) {
365 builder.child(
"child") = std::move(input);
367 if (useTextureShader) {
373 builder.uniform(
"innerGainAndBias") =
SkV2{fInnerGain, fInnerBias};
376 memcpy(paddedKernel, fKernel.data(), kernelLength*
sizeof(
float));
385 builder.uniform(
"gainAndBias") =
SkV2{fGain, fBias / 255.f};
386 builder.uniform(
"convolveAlpha") = fConvolveAlpha ? 1 : 0;
400 if (fConvolveAlpha && fBias != 0.f) {
406 outputBounds = this->boundsAffectedByKernel(childOutput.
layerBounds());
414 this->boundsSampledByKernel(outputBounds),
415 ShaderFlags::kSampledRepeatedly);
417 return this->createShader(context,
inputs[0]);
428 return this->getChildInputLayerBounds(0, mapping, requiredInput, contentBounds);
431std::optional<skif::LayerSpace<SkIRect>> SkMatrixConvolutionImageFilter::onGetOutputLayerBounds(
434 if (fConvolveAlpha && fBias != 0.f) {
444 auto outputBounds = this->getChildOutputLayerBounds(0, mapping, contentBounds);
446 return this->boundsAffectedByKernel(*outputBounds);
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
@ kAlpha_8_SkColorType
pixel with alpha in 8-bit byte
#define SK_FLATTENABLE_HOOKS(type)
#define SK_REGISTER_FLATTENABLE(type)
#define SK_IMAGEFILTER_UNFLATTEN_COMMON(localVar, expectedCount)
static int64_t sk_64_mul(int64_t a, int64_t b)
void SkRegisterMatrixConvolutionImageFilterFlattenable()
sk_sp< T > sk_ref_sp(T *obj)
static bool SkScalarNearlyZero(SkScalar x, SkScalar tolerance=SK_ScalarNearlyZero)
#define SkScalarRoundToInt(x)
uint8_t * getAddr8(int x, int y) const
bool tryAllocPixels(const SkImageInfo &info, size_t rowBytes)
static void Register(const char name[], Factory)
virtual skif::LayerSpace< SkIRect > onGetInputLayerBounds(const skif::Mapping &mapping, const skif::LayerSpace< SkIRect > &desiredOutput, std::optional< skif::LayerSpace< SkIRect > > contentBounds) const =0
virtual bool onAffectsTransparentBlack() const
void flatten(SkWriteBuffer &) const override
virtual std::optional< skif::LayerSpace< SkIRect > > onGetOutputLayerBounds(const skif::Mapping &mapping, std::optional< skif::LayerSpace< SkIRect > > contentBounds) const =0
virtual skif::FilterResult onFilterImage(const skif::Context &context) const =0
virtual SkRect computeFastBounds(const SkRect &bounds) const
static sk_sp< SkImageFilter > MatrixConvolution(const SkISize &kernelSize, const SkScalar kernel[], SkScalar gain, SkScalar bias, const SkIPoint &kernelOffset, SkTileMode tileMode, bool convolveAlpha, sk_sp< SkImageFilter > input, const CropRect &cropRect={})
static sk_sp< SkImageFilter > Crop(const SkRect &rect, SkTileMode tileMode, sk_sp< SkImageFilter > input)
sk_sp< SkShader > makeRawShader(SkTileMode tmx, SkTileMode tmy, const SkSamplingOptions &, const SkMatrix *localMatrix=nullptr) const
@ kConvolutionImageFilterTilingUpdate
static SkRect MakeLargeS32()
static size_t Mul(size_t x, size_t y)
virtual sk_sp< SkImage > getCachedBitmap(const SkBitmap &data) const =0
const Backend * backend() const
const LayerSpace< SkIRect > & desiredOutput() const
Context withNewDesiredOutput(const LayerSpace< SkIRect > &desiredOutput) const
LayerSpace< SkIRect > layerBounds() const
bool intersect(const LayerSpace< SkIRect > &r)
static float max(float r, float g, float b)
static float min(float r, float g, float b)
static constexpr int kSmallKernelSize
static constexpr int kLargeKernelSize
static constexpr int kMaxUniformKernelSize
const SkRuntimeEffect * GetKnownRuntimeEffect(StableKey stableKey)
Optional< SkRect > bounds
sk_sp< SkBlender > blender SkRect rect
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
void adjust(int32_t dL, int32_t dT, int32_t dR, int32_t dB)
constexpr int32_t width() const
constexpr int32_t height() const
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)