13#include "impeller/entity/texture_downsample.frag.h"
14#include "impeller/entity/texture_downsample_bounded.frag.h"
15#include "impeller/entity/texture_fill.frag.h"
16#include "impeller/entity/texture_fill.vert.h"
28constexpr Scalar kMaxSigma = 500.0f;
66 return Vector2(std::clamp(vec2.
x, min, max),
67 std::clamp(vec2.
y, min, max));
94BlurInfo CalculateBlurInfo(
const Entity& entity,
95 const Matrix& effect_transform,
102 ExtractScale(entity.GetTransform().Basis());
104 Vector2(entity.GetTransform().m[12], entity.GetTransform().m[13]);
129std::optional<Snapshot> GetSnapshot(
const std::shared_ptr<FilterInput>&
input,
130 const ContentContext& renderer,
131 const Entity& entity,
132 const std::optional<Rect>& coverage_hint) {
133 std::optional<Snapshot> input_snapshot =
134 input->GetSnapshot(
"GaussianBlur", renderer, entity,
136 if (!input_snapshot.has_value()) {
140 return input_snapshot;
145Rect MakeReferenceUVs(
const Rect& reference,
const Rect& rect) {
148 return result.Scale(1.0f /
Vector2(reference.GetSize()));
151Quad MakeReferenceUVs(
const Rect& reference,
const Quad& target_quad) {
154 1.0f / reference.GetHeight(), 1.0f)) *
156 Vector3(-reference.GetLeft(), -reference.GetTop(), 0));
160Quad CalculateSnapshotUVs(
161 const Snapshot& input_snapshot,
162 const std::optional<Rect>& source_expanded_coverage_hint) {
163 std::optional<Rect> input_snapshot_coverage = input_snapshot.GetCoverage();
165 FML_DCHECK(input_snapshot.transform.IsTranslationScaleOnly());
166 if (source_expanded_coverage_hint.has_value() &&
167 input_snapshot_coverage.has_value()) {
169 std::optional<Rect>
uvs =
170 MakeReferenceUVs(input_snapshot_coverage.value(),
171 source_expanded_coverage_hint.value())
174 if (
uvs.has_value()) {
175 blur_uvs[0] =
uvs->GetLeftTop();
176 blur_uvs[1] =
uvs->GetRightTop();
177 blur_uvs[2] =
uvs->GetLeftBottom();
178 blur_uvs[3] =
uvs->GetRightBottom();
185 if (divisor == 0.0f) {
189 Scalar remainder = fmod(val, divisor);
190 if (remainder != 0.0f) {
191 return val + (divisor - remainder);
198 if (divisor == 0.0f) {
202 Scalar remainder = fmod(val, divisor);
203 if (remainder != 0.0f) {
204 return val - remainder;
220 if (texture_sampler_y_coord_scale < 0.0f) {
232 auto remap_point = [&](
const Point& p) ->
Point {
233 return Point(p.x, 1.0f - p.y);
236 remap_point(
input[0]), remap_point(
input[1])};
261Matrix PrecomputeQuadLineParameters(
const Quad& bounds) {
262 auto computeLine = [](
const Point& p0,
const Point& p1) -> Vector4 {
276 Scalar C = -(A * p0.x + B * p0.y);
277 return Vector4(A, B, C, 0.0);
280 const Point& topLeft = bounds[0];
281 const Point& topRight = bounds[1];
282 const Point& botLeft = bounds[2];
283 const Point& botRight = bounds[3];
286 result.vec[0] = computeLine(topLeft, topRight);
287 result.vec[1] = computeLine(topRight, botRight);
288 result.vec[2] = computeLine(botRight, botLeft);
289 result.vec[3] = computeLine(botLeft, topLeft);
293struct DownsamplePassArgs {
316DownsamplePassArgs CalculateDownsamplePassArgs(
319 const Snapshot& input_snapshot,
320 const std::optional<Rect>& source_expanded_coverage_hint,
321 const std::optional<Quad>& source_bounds,
322 const std::shared_ptr<FilterInput>&
input,
323 const Entity& snapshot_entity) {
331 Vector2 downsample_scalar(desired_scalar, desired_scalar);
341 std::optional<Rect> snapshot_coverage = input_snapshot.GetCoverage();
342 if (input_snapshot.transform.Equals(snapshot_entity.GetTransform()) &&
343 source_expanded_coverage_hint.has_value() &&
344 snapshot_coverage.has_value() &&
345 snapshot_coverage->Contains(source_expanded_coverage_hint.value())) {
354 int32_t divisor = std::round(1.0f / desired_scalar);
356 FloorToDivisible(source_expanded_coverage_hint->GetLeft(), divisor),
357 FloorToDivisible(source_expanded_coverage_hint->GetTop(), divisor),
358 source_expanded_coverage_hint->GetRight(),
359 source_expanded_coverage_hint->GetBottom());
361 aligned_coverage_hint.GetX(), aligned_coverage_hint.GetY(),
362 CeilToDivisible(aligned_coverage_hint.GetWidth(), divisor),
363 CeilToDivisible(aligned_coverage_hint.GetHeight(), divisor));
364 ISize source_size =
ISize(aligned_coverage_hint.GetSize().width,
365 aligned_coverage_hint.GetSize().height);
366 Vector2 downsampled_size = source_size * downsample_scalar;
368 FML_DCHECK(std::modf(downsampled_size.x, &int_part) == 0.0f);
369 FML_DCHECK(std::modf(downsampled_size.y, &int_part) == 0.0f);
375 Quad uvs = CalculateSnapshotUVs(input_snapshot, aligned_coverage_hint);
377 if (source_bounds.has_value()) {
378 uv_bounds = MakeReferenceUVs(input_snapshot.GetCoverage().value(),
379 source_bounds.value());
387 {aligned_coverage_hint.GetX(), aligned_coverage_hint.GetY(), 0})};
390 auto input_snapshot_size = input_snapshot.texture->GetSize();
393 Vector2 downsampled_size = source_rect_padded.GetSize() * downsample_scalar;
395 ISize(ceil(downsampled_size.x), ceil(downsampled_size.y));
396 Vector2 divisible_size(CeilToDivisible(source_rect_padded.GetSize().width,
397 1.0 / downsample_scalar.x),
398 CeilToDivisible(source_rect_padded.GetSize().height,
399 1.0 / downsample_scalar.y));
405 (divisible_size.x - source_rect_padded.GetSize().width) / 2.0
409 (divisible_size.
y - source_rect_padded.GetSize().
height) / 2.0
411 source_rect_padded = source_rect.Expand(divisible_padding);
416 input, snapshot_entity, source_rect_padded, input_snapshot_size);
418 if (source_bounds.has_value()) {
421 input_snapshot.transform.Invert().Transform(source_bounds.value()));
429 .transform = input_snapshot.transform *
438 const ContentContext& renderer,
439 const std::shared_ptr<CommandBuffer>& command_buffer,
440 const std::shared_ptr<Texture>& input_texture,
441 const SamplerDescriptor& sampler_descriptor,
442 const DownsamplePassArgs& pass_args,
444 using VS = TextureFillVertexShader;
451 bool may_reuse_mipmap =
452 !pass_args.uv_bounds.has_value() &&
453 (pass_args.effective_scalar.x >= 0.5f ||
454 (!input_texture->NeedsMipmapGeneration() &&
455 input_texture->GetTextureDescriptor().mip_count > 1));
456 if (may_reuse_mipmap) {
458 [&](
const ContentContext& renderer, RenderPass& pass) {
459 HostBuffer& data_host_buffer = renderer.GetTransientsDataBuffer();
461 pass.SetCommandLabel(
"Gaussian blur downsample");
464 pass.SetPipeline(renderer.GetTexturePipeline(pipeline_options));
466 TextureFillVertexShader::FrameInfo frame_info;
468 frame_info.texture_sampler_y_coord_scale =
469 input_texture->GetYCoordScale();
471 TextureFillFragmentShader::FragInfo frag_info;
472 frag_info.alpha = 1.0;
474 const Quad&
uvs = pass_args.uvs;
475 std::array<VS::PerVertexData, 4> vertices = {
476 VS::PerVertexData{
Point(0, 0),
uvs[0]},
477 VS::PerVertexData{
Point(1, 0),
uvs[1]},
478 VS::PerVertexData{
Point(0, 1),
uvs[2]},
479 VS::PerVertexData{
Point(1, 1),
uvs[3]},
483 SamplerDescriptor linear_sampler_descriptor = sampler_descriptor;
484 SetTileMode(&linear_sampler_descriptor, renderer, tile_mode);
487 TextureFillVertexShader::BindFrameInfo(
488 pass, data_host_buffer.EmplaceUniform(frame_info));
489 TextureFillFragmentShader::BindFragInfo(
490 pass, data_host_buffer.EmplaceUniform(frag_info));
491 TextureFillFragmentShader::BindTextureSampler(
493 renderer.GetContext()->GetSamplerLibrary()->GetSampler(
494 linear_sampler_descriptor));
496 return pass.Draw().ok();
498 return renderer.MakeSubpass(
"Gaussian Blur Filter", pass_args.subpass_size,
499 command_buffer, subpass_callback,
506 if (pass_args.effective_scalar.x <= 0.0625f) {
508 ratio = 1.0f / 64.0f;
509 }
else if (pass_args.effective_scalar.x <= 0.125f) {
511 ratio = 1.0f / 16.0f;
514 [&](
const ContentContext& renderer, RenderPass& pass) {
515 HostBuffer& data_host_buffer = renderer.GetTransientsDataBuffer();
517 pass.SetCommandLabel(
"Gaussian blur downsample");
520 if (pass_args.uv_bounds.has_value()) {
522 renderer.GetDownsampleBoundedPipeline(pipeline_options));
524 TextureDownsampleBoundedFragmentShader::BoundInfo bound_info;
525 bound_info.quad_line_params = PrecomputeQuadLineParameters(
526 RemapQuadCoords(pass_args.uv_bounds.value(),
527 input_texture->GetYCoordScale()));
528 TextureDownsampleBoundedFragmentShader::BindBoundInfo(
529 pass, data_host_buffer.EmplaceUniform(bound_info));
531#ifdef IMPELLER_ENABLE_OPENGLES
534 if (renderer.GetDeviceCapabilities()
535 .SupportsDecalSamplerAddressMode() ||
538 renderer.GetDownsamplePipeline(pipeline_options));
541 renderer.GetDownsampleTextureGlesPipeline(pipeline_options));
544 pass.SetPipeline(renderer.GetDownsamplePipeline(pipeline_options));
548 TextureFillVertexShader::FrameInfo frame_info;
550 frame_info.texture_sampler_y_coord_scale =
551 input_texture->GetYCoordScale();
553 TextureDownsampleFragmentShader::FragInfo frag_info;
554 frag_info.edge = edge;
555 frag_info.ratio = ratio;
556 frag_info.pixel_size =
Vector2(1.0f /
Size(input_texture->GetSize()));
558 const Quad&
uvs = pass_args.uvs;
559 std::array<VS::PerVertexData, 4> vertices = {
560 VS::PerVertexData{
Point(0, 0),
uvs[0]},
561 VS::PerVertexData{
Point(1, 0),
uvs[1]},
562 VS::PerVertexData{
Point(0, 1),
uvs[2]},
563 VS::PerVertexData{
Point(1, 1),
uvs[3]},
567 SamplerDescriptor linear_sampler_descriptor = sampler_descriptor;
568 SetTileMode(&linear_sampler_descriptor, renderer, tile_mode);
571 TextureFillVertexShader::BindFrameInfo(
572 pass, data_host_buffer.EmplaceUniform(frame_info));
573 TextureDownsampleFragmentShader::BindFragInfo(
574 pass, data_host_buffer.EmplaceUniform(frag_info));
575 TextureDownsampleFragmentShader::BindTextureSampler(
577 renderer.GetContext()->GetSamplerLibrary()->GetSampler(
578 linear_sampler_descriptor));
580 return pass.Draw().ok();
582 return renderer.MakeSubpass(
"Gaussian Blur Filter", pass_args.subpass_size,
583 command_buffer, subpass_callback,
590 const ContentContext& renderer,
591 const std::shared_ptr<CommandBuffer>& command_buffer,
592 const RenderTarget& input_pass,
593 const SamplerDescriptor& sampler_descriptor,
594 const BlurParameters& blur_info,
595 std::optional<RenderTarget> destination_target,
596 const Quad& blur_uvs) {
603 const std::shared_ptr<Texture>& input_texture =
604 input_pass.GetRenderTargetTexture();
610 [&](
const ContentContext& renderer, RenderPass& pass) {
611 GaussianBlurVertexShader::FrameInfo frame_info;
613 frame_info.texture_sampler_y_coord_scale =
614 input_texture->GetYCoordScale();
616 HostBuffer& data_host_buffer = renderer.GetTransientsDataBuffer();
620 pass.SetPipeline(renderer.GetGaussianBlurPipeline(options));
622 GaussianBlurFragmentShader::FragInfo frag_info;
623 frag_info.unpremultiply = blur_info.apply_unpremultiply;
624 GaussianBlurFragmentShader::BindFragInfo(
625 pass, data_host_buffer.EmplaceUniform(frag_info));
627 std::array<VS::PerVertexData, 4> vertices = {
628 VS::PerVertexData{blur_uvs[0], blur_uvs[0]},
629 VS::PerVertexData{blur_uvs[1], blur_uvs[1]},
630 VS::PerVertexData{blur_uvs[2], blur_uvs[2]},
631 VS::PerVertexData{blur_uvs[3], blur_uvs[3]},
635 SamplerDescriptor linear_sampler_descriptor = sampler_descriptor;
638 GaussianBlurFragmentShader::BindTextureSampler(
640 renderer.GetContext()->GetSamplerLibrary()->GetSampler(
641 linear_sampler_descriptor));
642 GaussianBlurVertexShader::BindFrameInfo(
643 pass, data_host_buffer.EmplaceUniform(frame_info));
644 GaussianBlurFragmentShader::BindKernelSamples(
645 pass, data_host_buffer.EmplaceUniform(
647 return pass.Draw().ok();
649 if (destination_target.has_value()) {
650 return renderer.MakeSubpass(
"Gaussian Blur Filter",
651 destination_target.value(), command_buffer,
654 return renderer.MakeSubpass(
655 "Gaussian Blur Filter",
subpass_size, command_buffer, subpass_callback,
661 return static_cast<int>(std::round(radius * scalar));
665 const Entity& entity,
666 const std::shared_ptr<FilterInput>&
input,
667 const Snapshot& input_snapshot,
669 const Geometry* geometry) {
670 Matrix entity_transform = entity.GetTransform();
671 Matrix blur_transform = blur_entity.GetTransform();
675 entity_transform, blur_transform, geometry](
676 const ContentContext& renderer,
677 const Entity& entity, RenderPass& pass)
mutable {
679 clipper.SetClipDepth(entity.GetClipDepth());
680 clipper.SetTransform(entity.GetTransform() * entity_transform);
682 auto geom_result = geometry->GetPositionBuffer(renderer, clipper, pass);
684 ClipContents clip_contents(geometry->GetCoverage(clipper.GetTransform())
685 .value_or(Rect::MakeLTRB(0, 0, 0, 0)),
687 clip_contents.SetClipOperation(clip_operation);
688 clip_contents.SetGeometry(std::move(geom_result));
690 if (!clip_contents.Render(renderer, pass, entity.GetClipDepth())) {
693 blur_entity.SetClipDepth(entity.GetClipDepth());
694 blur_entity.SetTransform(entity.GetTransform() * blur_transform);
696 return blur_entity.Render(renderer, pass);
700 blur_transform](
const Entity& entity)
mutable {
701 blur_entity.SetTransform(entity.GetTransform() * blur_transform);
702 return blur_entity.GetCoverage();
710 const Entity& entity,
711 const std::shared_ptr<FilterInput>&
input,
712 const Snapshot& input_snapshot,
714 const Geometry* geometry,
717 switch (blur_style) {
722 input, input_snapshot,
723 std::move(blur_entity), geometry);
727 input, input_snapshot,
728 std::move(blur_entity), geometry);
730 Entity snapshot_entity =
733 Matrix blurred_transform = blur_entity.GetTransform();
734 Matrix snapshot_transform =
735 entity.GetTransform() *
738 input_snapshot.transform;
741 blurred_transform, snapshot_transform,
742 snapshot_entity = std::move(snapshot_entity)](
743 const ContentContext& renderer,
744 const Entity& entity,
745 RenderPass& pass)
mutable {
746 snapshot_entity.SetTransform(entity.GetTransform() *
748 snapshot_entity.SetClipDepth(entity.GetClipDepth());
749 if (!snapshot_entity.Render(renderer, pass)) {
752 blur_entity.SetClipDepth(entity.GetClipDepth());
753 blur_entity.SetTransform(entity.GetTransform() * blurred_transform);
754 return blur_entity.Render(renderer, pass);
757 blurred_transform](
const Entity& entity)
mutable {
758 blur_entity.SetTransform(entity.GetTransform() * blurred_transform);
759 return blur_entity.GetCoverage();
767GaussianBlurFilterContents::GaussianBlurFilterContents(
771 std::optional<Rect> bounds,
774 : sigma_(sigma_x, sigma_y),
775 tile_mode_(tile_mode),
777 mask_blur_style_(mask_blur_style),
778 mask_geometry_(mask_geometry) {
790 Scalar raw_result = 4.0 / sigma;
792 Scalar exponent = round(log2f(raw_result));
794 exponent = std::max(-4.0f, exponent);
795 Scalar rounded = powf(2.0f, exponent);
799 if (rounded < 0.125f) {
800 Scalar rounded_plus = powf(2.0f, exponent + 1);
802 int kernel_size_plus = (ScaleBlurRadius(
blur_radius, rounded_plus) * 2) + 1;
806 static constexpr int32_t kEighthDownsampleKernalWidthMax = 41;
807 result = kernel_size_plus <= kEighthDownsampleKernalWidthMax ? rounded_plus
814 const Matrix& effect_transform,
815 const Rect& output_limit)
const {
821 return output_limit.
Expand(
Point(blur_radii.
x, blur_radii.
y));
827 const Matrix& effect_transform)
const {
828 if (inputs.empty()) {
831 std::optional<Rect> input_coverage = inputs[0]->GetCoverage(entity);
832 if (!input_coverage.has_value()) {
836 BlurInfo blur_info = CalculateBlurInfo(entity, effect_transform, sigma_);
837 return input_coverage.value().Expand(
838 Point(blur_info.local_padding.x, blur_info.local_padding.y));
841std::optional<Entity> GaussianBlurFilterContents::RenderFilter(
845 const Matrix& effect_transform,
846 const Rect& coverage,
847 const std::optional<Rect>& coverage_hint)
const {
848 if (inputs.empty()) {
852 BlurInfo blur_info = CalculateBlurInfo(entity, effect_transform, sigma_);
857 std::optional<Rect> expanded_coverage_hint;
858 if (coverage_hint.has_value()) {
859 expanded_coverage_hint = coverage_hint->Expand(blur_info.local_padding);
862 Entity snapshot_entity = entity.
Clone();
867 std::optional<Rect> source_expanded_coverage_hint;
868 if (expanded_coverage_hint.has_value()) {
869 source_expanded_coverage_hint = expanded_coverage_hint->TransformBounds(
873 std::optional<Snapshot> input_snapshot = GetSnapshot(
874 inputs[0], renderer, snapshot_entity, source_expanded_coverage_hint);
875 if (!input_snapshot.has_value()) {
879 std::optional<Quad> source_bounds;
880 if (bounds_.has_value()) {
881 Matrix
transform = snapshot_entity.GetTransform() * effect_transform;
882 source_bounds = bounds_->GetTransformedPoints(
transform);
894 input_snapshot->transform);
904 std::shared_ptr<CommandBuffer> command_buffer_1 =
906 if (!command_buffer_1) {
910 DownsamplePassArgs downsample_pass_args = CalculateDownsamplePassArgs(
911 blur_info.scaled_sigma, blur_info.padding, input_snapshot.value(),
912 source_expanded_coverage_hint, source_bounds, inputs[0], snapshot_entity);
915 renderer, command_buffer_1, input_snapshot->texture,
916 input_snapshot->sampler_descriptor, downsample_pass_args, tile_mode_);
918 if (!pass1_out.
ok()) {
923 1.0 /
Vector2(pass1_out.
value().GetRenderTargetTexture()->GetSize());
927 std::shared_ptr<CommandBuffer> command_buffer_2 =
929 if (!command_buffer_2) {
934 renderer, command_buffer_2, pass1_out.
value(),
935 input_snapshot->sampler_descriptor,
937 .blur_uv_offset = Point(0.0, pass1_pixel_size.y),
938 .blur_sigma = blur_info.scaled_sigma.y *
939 downsample_pass_args.effective_scalar.y,
940 .blur_radius = ScaleBlurRadius(
941 blur_info.blur_radius.y, downsample_pass_args.effective_scalar.y),
943 .apply_unpremultiply = false,
945 std::nullopt, blur_uvs);
947 if (!pass2_out.
ok()) {
951 std::shared_ptr<CommandBuffer> command_buffer_3 =
953 if (!command_buffer_3) {
958 auto pass3_destination = pass2_out.
value().GetRenderTargetTexture() !=
959 pass1_out.
value().GetRenderTargetTexture()
960 ? std::optional<RenderTarget>(pass1_out.
value())
961 :
std::optional<RenderTarget>(
std::nullopt);
964 renderer, command_buffer_3, pass2_out.
value(),
965 input_snapshot->sampler_descriptor,
967 .blur_uv_offset = Point(pass1_pixel_size.x, 0.0),
968 .blur_sigma = blur_info.scaled_sigma.x *
969 downsample_pass_args.effective_scalar.x,
970 .blur_radius = ScaleBlurRadius(
971 blur_info.blur_radius.x, downsample_pass_args.effective_scalar.x),
973 .apply_unpremultiply = bounds_.has_value(),
975 pass3_destination, blur_uvs);
977 if (!pass3_out.
ok()) {
981 if (!(renderer.
GetContext()->EnqueueCommandBuffer(
982 std::move(command_buffer_1)) &&
984 std::move(command_buffer_2)) &&
986 std::move(command_buffer_3)))) {
993 pass2_out.
value().GetRenderTargetSize()) &&
994 (pass2_out.
value().GetRenderTargetSize() ==
995 pass3_out.
value().GetRenderTargetSize()));
997 SamplerDescriptor sampler_desc = MakeSamplerDescriptor(
1001 Snapshot{.texture = pass3_out.
value().GetRenderTargetTexture(),
1006 downsample_pass_args.transform *
1008 .sampler_descriptor = sampler_desc,
1009 .opacity = input_snapshot->opacity,
1010 .needs_rasterization_for_runtime_effects =
true},
1013 return ApplyBlurStyle(mask_blur_style_, entity, inputs[0],
1014 input_snapshot.value(), std::move(blur_output_entity),
1015 mask_geometry_, blur_info.source_space_scalar,
1016 blur_info.source_space_offset);
1024 const std::shared_ptr<FilterInput>& filter_input,
1026 const Rect& source_rect,
1027 const ISize& texture_size) {
1028 Matrix input_transform = filter_input->GetLocalTransform(entity);
1032 {1.0f / texture_size.
width, 1.0f / texture_size.
height, 1.0f});
1033 return uv_transform.
Transform(coverage_quad);
1041 Scalar clamped = std::min(sigma, kMaxSigma);
1042 constexpr Scalar a = 3.4e-06;
1043 constexpr Scalar b = -3.4e-3;
1044 constexpr Scalar c = 1.f;
1045 Scalar scalar = c + b * clamped + a * clamped * clamped;
1046 return clamped * scalar;
1079 .coefficient = expf(-0.5f * (
x *
x) /
1081 (sqrtf(2.0f * M_PI) * parameters.
blur_sigma),
1087 for (
auto& sample : result.
samples) {
1088 sample.coefficient /= tally;
1098 GaussianBlurPipeline::FragmentShader::KernelSamples result = {};
1100 int32_t middle = result.sample_count / 2;
1103 static_assert(
sizeof(result.sample_data) ==
1104 sizeof(std::array<Vector4, kGaussianBlurMaxKernelSize>));
1106 for (
int i = 0;
i < result.sample_count;
i++) {
1116 result.sample_data[
i].z = left.coefficient + right.coefficient;
1118 Point uv = (left.uv_offset * left.coefficient +
1119 right.uv_offset * right.coefficient) /
1120 (left.coefficient + right.coefficient);
1121 result.sample_data[
i].
x = uv.
x;
1122 result.sample_data[
i].y = uv.
y;
virtual bool SupportsDecalSamplerAddressMode() const =0
Whether the context backend supports SamplerAddressMode::Decal.
const Capabilities & GetDeviceCapabilities() const
std::function< bool(const ContentContext &, RenderPass &)> SubpassCallback
std::shared_ptr< Context > GetContext() const
static std::shared_ptr< Contents > MakeAnonymous(RenderProc render_proc, CoverageProc coverage_proc)
void SetTransform(const Matrix &transform)
Set the global transform matrix for this Entity.
BlendMode GetBlendMode() const
const Matrix & GetTransform() const
Get the global transform matrix for this Entity.
static Entity FromSnapshot(const Snapshot &snapshot, BlendMode blend_mode=BlendMode::kSrcOver)
Create an entity that can be used to render a given snapshot.
@ kNormal
Blurred inside and outside.
@ kOuter
Nothing inside, blurred outside.
@ kInner
Blurred inside, nothing outside.
@ kSolid
Solid inside, blurred outside.
static Scalar CalculateBlurRadius(Scalar sigma)
static Scalar ScaleSigma(Scalar sigma)
std::optional< Rect > GetFilterSourceCoverage(const Matrix &effect_transform, const Rect &output_limit) const override
Internal utility method for |GetSourceCoverage| that computes the inverse effect of this transform on...
std::optional< Rect > GetFilterCoverage(const FilterInput::Vector &inputs, const Entity &entity, const Matrix &effect_transform) const override
Internal utility method for |GetLocalCoverage| that computes the output coverage of this filter acros...
static Scalar CalculateScale(Scalar sigma)
static Quad CalculateUVs(const std::shared_ptr< FilterInput > &filter_input, const Entity &entity, const Rect &source_rect, const ISize &texture_size)
#define FML_DCHECK(condition)
Vector2 local_padding
Padding in unrotated local space.
Vector2 blur_radius
Blur radius in source pixels based on scaled_sigma.
ISize subpass_size
The output size of the down-sampling pass.
Vector2 source_space_offset
Vector2 source_space_scalar
The scalar that is used to get from source space to unrotated local space.
Vector2 padding
The halo padding in source space.
std::optional< Quad > uv_bounds
Vector2 scaled_sigma
Sigma when considering an entity's scale and the effect transform.
internal::CopyableLambda< T > MakeCopyable(T lambda)
static constexpr int32_t kGaussianBlurMaxKernelSize
@ kDecal
decal sampling mode is only supported on devices that pass the Capabilities.SupportsDecalSamplerAddre...
constexpr float kEhCloseEnough
VertexBuffer CreateVertexBuffer(std::array< VertexType, size > input, HostBuffer &data_host_buffer)
Create an index-less vertex buffer from a fixed size array.
LinePipeline::VertexShader VS
KernelSamples GenerateBlurInfo(BlurParameters parameters)
ContentContextOptions OptionsFromPass(const RenderPass &pass)
MinMagFilter
Describes how the texture should be sampled when the texture is being shrunk (minified) or expanded (...
std::array< Point, 4 > Quad
GaussianBlurPipeline::FragmentShader GaussianBlurFragmentShader
GaussianBlurPipeline::FragmentShader::KernelSamples LerpHackKernelSamples(KernelSamples parameters)
GaussianBlurPipeline::VertexShader GaussianBlurVertexShader
static constexpr int kMaxKernelSize
KernelSample samples[kMaxKernelSize]
A 4x4 matrix using column-major storage.
static constexpr Matrix MakeOrthographic(TSize< T > size)
static constexpr Matrix MakeTranslation(const Vector3 &t)
constexpr Matrix Basis() const
The Matrix without its w components (without translation).
constexpr Quad Transform(const Quad &quad) const
static constexpr Matrix MakeScale(const Vector3 &s)
For convolution filters, the "radius" is the size of the convolution kernel to use on the local space...
SamplerAddressMode width_address_mode
SamplerAddressMode height_address_mode
In filters that use Gaussian distributions, "sigma" is a size of one standard deviation in terms of t...
constexpr Type GetLength() const
static constexpr TRect MakeOriginSize(const TPoint< Type > &origin, const TSize< Type > &size)
static constexpr TRect MakeXYWH(Type x, Type y, Type width, Type height)
constexpr std::array< TPoint< T >, 4 > GetTransformedPoints(const Matrix &transform) const
static constexpr TRect MakeSize(const TSize< U > &size)
constexpr TRect< T > Expand(T left, T top, T right, T bottom) const
Returns a rectangle with expanded edges. Negative expansion results in shrinking.
static constexpr TRect MakeLTRB(Type left, Type top, Type right, Type bottom)