diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 1e5fa58c911ea..dcdaf83c6d8eb 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -570,6 +570,8 @@ FILE: ../../../flutter/impeller/entity/contents/path_contents.cc FILE: ../../../flutter/impeller/entity/contents/path_contents.h FILE: ../../../flutter/impeller/entity/contents/radial_gradient_contents.cc FILE: ../../../flutter/impeller/entity/contents/radial_gradient_contents.h +FILE: ../../../flutter/impeller/entity/contents/rrect_shadow_contents.cc +FILE: ../../../flutter/impeller/entity/contents/rrect_shadow_contents.h FILE: ../../../flutter/impeller/entity/contents/solid_color_contents.cc FILE: ../../../flutter/impeller/entity/contents/solid_color_contents.h FILE: ../../../flutter/impeller/entity/contents/solid_stroke_contents.cc @@ -621,6 +623,8 @@ FILE: ../../../flutter/impeller/entity/shaders/gradient_fill.frag FILE: ../../../flutter/impeller/entity/shaders/gradient_fill.vert FILE: ../../../flutter/impeller/entity/shaders/radial_gradient_fill.frag FILE: ../../../flutter/impeller/entity/shaders/radial_gradient_fill.vert +FILE: ../../../flutter/impeller/entity/shaders/rrect_blur.frag +FILE: ../../../flutter/impeller/entity/shaders/rrect_blur.vert FILE: ../../../flutter/impeller/entity/shaders/solid_fill.frag FILE: ../../../flutter/impeller/entity/shaders/solid_fill.vert FILE: ../../../flutter/impeller/entity/shaders/solid_stroke.frag diff --git a/display_list/display_list_builder_benchmarks.cc b/display_list/display_list_builder_benchmarks.cc index 4ebadb4521bc6..ed1d093de31e0 100644 --- a/display_list/display_list_builder_benchmarks.cc +++ b/display_list/display_list_builder_benchmarks.cc @@ -48,8 +48,8 @@ static void Complete(DisplayListBuilder& builder, } // namespace -static void BM_DisplayListBuiderDefault(benchmark::State& state, - DisplayListBuilderBenchmarkType type) { +static void BM_DisplayListBuilderDefault(benchmark::State& state, + DisplayListBuilderBenchmarkType type) { while (state.KeepRunning()) { DisplayListBuilder builder; InvokeAllRenderingOps(builder); @@ -57,7 +57,7 @@ static void BM_DisplayListBuiderDefault(benchmark::State& state, } } -static void BM_DisplayListBuiderWithScaleAndTranslate( +static void BM_DisplayListBuilderWithScaleAndTranslate( benchmark::State& state, DisplayListBuilderBenchmarkType type) { while (state.KeepRunning()) { @@ -69,7 +69,7 @@ static void BM_DisplayListBuiderWithScaleAndTranslate( } } -static void BM_DisplayListBuiderWithPerspective( +static void BM_DisplayListBuilderWithPerspective( benchmark::State& state, DisplayListBuilderBenchmarkType type) { while (state.KeepRunning()) { @@ -81,7 +81,7 @@ static void BM_DisplayListBuiderWithPerspective( } } -static void BM_DisplayListBuiderWithClipRect( +static void BM_DisplayListBuilderWithClipRect( benchmark::State& state, DisplayListBuilderBenchmarkType type) { SkRect clip_bounds = SkRect::MakeLTRB(6.5, 7.3, 90.2, 85.7); @@ -93,7 +93,7 @@ static void BM_DisplayListBuiderWithClipRect( } } -static void BM_DisplayListBuiderWithSaveLayer( +static void BM_DisplayListBuilderWithSaveLayer( benchmark::State& state, DisplayListBuilderBenchmarkType type) { while (state.KeepRunning()) { @@ -110,7 +110,7 @@ static void BM_DisplayListBuiderWithSaveLayer( } } -static void BM_DisplayListBuiderWithSaveLayerAndImageFilter( +static void BM_DisplayListBuilderWithSaveLayerAndImageFilter( benchmark::State& state, DisplayListBuilderBenchmarkType type) { DlPaint layer_paint; @@ -130,104 +130,104 @@ static void BM_DisplayListBuiderWithSaveLayerAndImageFilter( } } -BENCHMARK_CAPTURE(BM_DisplayListBuiderDefault, +BENCHMARK_CAPTURE(BM_DisplayListBuilderDefault, kDefault, DisplayListBuilderBenchmarkType::kDefault) ->Unit(benchmark::kMillisecond); -BENCHMARK_CAPTURE(BM_DisplayListBuiderDefault, +BENCHMARK_CAPTURE(BM_DisplayListBuilderDefault, kBounds, DisplayListBuilderBenchmarkType::kBounds) ->Unit(benchmark::kMillisecond); -BENCHMARK_CAPTURE(BM_DisplayListBuiderDefault, +BENCHMARK_CAPTURE(BM_DisplayListBuilderDefault, kRtree, DisplayListBuilderBenchmarkType::kRtree) ->Unit(benchmark::kMillisecond); -BENCHMARK_CAPTURE(BM_DisplayListBuiderDefault, +BENCHMARK_CAPTURE(BM_DisplayListBuilderDefault, kBoundsAndRtree, DisplayListBuilderBenchmarkType::kBoundsAndRtree) ->Unit(benchmark::kMillisecond); -BENCHMARK_CAPTURE(BM_DisplayListBuiderWithScaleAndTranslate, +BENCHMARK_CAPTURE(BM_DisplayListBuilderWithScaleAndTranslate, kDefault, DisplayListBuilderBenchmarkType::kDefault) ->Unit(benchmark::kMillisecond); -BENCHMARK_CAPTURE(BM_DisplayListBuiderWithScaleAndTranslate, +BENCHMARK_CAPTURE(BM_DisplayListBuilderWithScaleAndTranslate, kBounds, DisplayListBuilderBenchmarkType::kBounds) ->Unit(benchmark::kMillisecond); -BENCHMARK_CAPTURE(BM_DisplayListBuiderWithScaleAndTranslate, +BENCHMARK_CAPTURE(BM_DisplayListBuilderWithScaleAndTranslate, kRtree, DisplayListBuilderBenchmarkType::kRtree) ->Unit(benchmark::kMillisecond); -BENCHMARK_CAPTURE(BM_DisplayListBuiderWithScaleAndTranslate, +BENCHMARK_CAPTURE(BM_DisplayListBuilderWithScaleAndTranslate, kBoundsAndRtree, DisplayListBuilderBenchmarkType::kBoundsAndRtree) ->Unit(benchmark::kMillisecond); -BENCHMARK_CAPTURE(BM_DisplayListBuiderWithPerspective, +BENCHMARK_CAPTURE(BM_DisplayListBuilderWithPerspective, kDefault, DisplayListBuilderBenchmarkType::kDefault) ->Unit(benchmark::kMillisecond); -BENCHMARK_CAPTURE(BM_DisplayListBuiderWithPerspective, +BENCHMARK_CAPTURE(BM_DisplayListBuilderWithPerspective, kBounds, DisplayListBuilderBenchmarkType::kBounds) ->Unit(benchmark::kMillisecond); -BENCHMARK_CAPTURE(BM_DisplayListBuiderWithPerspective, +BENCHMARK_CAPTURE(BM_DisplayListBuilderWithPerspective, kRtree, DisplayListBuilderBenchmarkType::kRtree) ->Unit(benchmark::kMillisecond); -BENCHMARK_CAPTURE(BM_DisplayListBuiderWithPerspective, +BENCHMARK_CAPTURE(BM_DisplayListBuilderWithPerspective, kBoundsAndRtree, DisplayListBuilderBenchmarkType::kBoundsAndRtree) ->Unit(benchmark::kMillisecond); -BENCHMARK_CAPTURE(BM_DisplayListBuiderWithClipRect, +BENCHMARK_CAPTURE(BM_DisplayListBuilderWithClipRect, kDefault, DisplayListBuilderBenchmarkType::kDefault) ->Unit(benchmark::kMillisecond); -BENCHMARK_CAPTURE(BM_DisplayListBuiderWithClipRect, +BENCHMARK_CAPTURE(BM_DisplayListBuilderWithClipRect, kBounds, DisplayListBuilderBenchmarkType::kBounds) ->Unit(benchmark::kMillisecond); -BENCHMARK_CAPTURE(BM_DisplayListBuiderWithClipRect, +BENCHMARK_CAPTURE(BM_DisplayListBuilderWithClipRect, kRtree, DisplayListBuilderBenchmarkType::kRtree) ->Unit(benchmark::kMillisecond); -BENCHMARK_CAPTURE(BM_DisplayListBuiderWithClipRect, +BENCHMARK_CAPTURE(BM_DisplayListBuilderWithClipRect, kBoundsAndRtree, DisplayListBuilderBenchmarkType::kBoundsAndRtree) ->Unit(benchmark::kMillisecond); -BENCHMARK_CAPTURE(BM_DisplayListBuiderWithSaveLayer, +BENCHMARK_CAPTURE(BM_DisplayListBuilderWithSaveLayer, kDefault, DisplayListBuilderBenchmarkType::kDefault) ->Unit(benchmark::kMillisecond); -BENCHMARK_CAPTURE(BM_DisplayListBuiderWithSaveLayer, +BENCHMARK_CAPTURE(BM_DisplayListBuilderWithSaveLayer, kBounds, DisplayListBuilderBenchmarkType::kBounds) ->Unit(benchmark::kMillisecond); -BENCHMARK_CAPTURE(BM_DisplayListBuiderWithSaveLayer, +BENCHMARK_CAPTURE(BM_DisplayListBuilderWithSaveLayer, kRtree, DisplayListBuilderBenchmarkType::kRtree) ->Unit(benchmark::kMillisecond); -BENCHMARK_CAPTURE(BM_DisplayListBuiderWithSaveLayer, +BENCHMARK_CAPTURE(BM_DisplayListBuilderWithSaveLayer, kBoundsAndRtree, DisplayListBuilderBenchmarkType::kBoundsAndRtree) ->Unit(benchmark::kMillisecond); -BENCHMARK_CAPTURE(BM_DisplayListBuiderWithSaveLayerAndImageFilter, +BENCHMARK_CAPTURE(BM_DisplayListBuilderWithSaveLayerAndImageFilter, kDefault, DisplayListBuilderBenchmarkType::kDefault) ->Unit(benchmark::kMillisecond); -BENCHMARK_CAPTURE(BM_DisplayListBuiderWithSaveLayerAndImageFilter, +BENCHMARK_CAPTURE(BM_DisplayListBuilderWithSaveLayerAndImageFilter, kBounds, DisplayListBuilderBenchmarkType::kBounds) ->Unit(benchmark::kMillisecond); -BENCHMARK_CAPTURE(BM_DisplayListBuiderWithSaveLayerAndImageFilter, +BENCHMARK_CAPTURE(BM_DisplayListBuilderWithSaveLayerAndImageFilter, kRtree, DisplayListBuilderBenchmarkType::kRtree) ->Unit(benchmark::kMillisecond); -BENCHMARK_CAPTURE(BM_DisplayListBuiderWithSaveLayerAndImageFilter, +BENCHMARK_CAPTURE(BM_DisplayListBuilderWithSaveLayerAndImageFilter, kBoundsAndRtree, DisplayListBuilderBenchmarkType::kBoundsAndRtree) ->Unit(benchmark::kMillisecond); diff --git a/impeller/entity/BUILD.gn b/impeller/entity/BUILD.gn index 0c1dfefc6ba6e..4f51f52cbdad0 100644 --- a/impeller/entity/BUILD.gn +++ b/impeller/entity/BUILD.gn @@ -34,6 +34,10 @@ impeller_shaders("entity_shaders") { "shaders/glyph_atlas.vert", "shaders/gradient_fill.frag", "shaders/gradient_fill.vert", + "shaders/radial_gradient_fill.vert", + "shaders/radial_gradient_fill.frag", + "shaders/rrect_blur.vert", + "shaders/rrect_blur.frag", "shaders/solid_fill.frag", "shaders/solid_fill.vert", "shaders/solid_stroke.frag", @@ -42,8 +46,6 @@ impeller_shaders("entity_shaders") { "shaders/texture_fill.vert", "shaders/vertices.vert", "shaders/vertices.frag", - "shaders/radial_gradient_fill.vert", - "shaders/radial_gradient_fill.frag", ] } @@ -77,6 +79,8 @@ impeller_component("entity") { "contents/path_contents.h", "contents/radial_gradient_contents.cc", "contents/radial_gradient_contents.h", + "contents/rrect_shadow_contents.cc", + "contents/rrect_shadow_contents.h", "contents/solid_color_contents.cc", "contents/solid_color_contents.h", "contents/solid_stroke_contents.cc", diff --git a/impeller/entity/contents/content_context.cc b/impeller/entity/contents/content_context.cc index 60c6a062db168..bbc6efdc434d7 100644 --- a/impeller/entity/contents/content_context.cc +++ b/impeller/entity/contents/content_context.cc @@ -155,6 +155,8 @@ ContentContext::ContentContext(std::shared_ptr context) CreateDefaultPipeline(*context_); radial_gradient_fill_pipelines_[{}] = CreateDefaultPipeline(*context_); + rrect_blur_pipelines_[{}] = + CreateDefaultPipeline(*context_); texture_blend_pipelines_[{}] = CreateDefaultPipeline(*context_); blend_color_pipelines_[{}] = diff --git a/impeller/entity/contents/content_context.h b/impeller/entity/contents/content_context.h index fb627bad171d9..0f7c84c827513 100644 --- a/impeller/entity/contents/content_context.h +++ b/impeller/entity/contents/content_context.h @@ -40,6 +40,8 @@ #include "impeller/entity/gradient_fill.vert.h" #include "impeller/entity/radial_gradient_fill.frag.h" #include "impeller/entity/radial_gradient_fill.vert.h" +#include "impeller/entity/rrect_blur.frag.h" +#include "impeller/entity/rrect_blur.vert.h" #include "impeller/entity/solid_fill.frag.h" #include "impeller/entity/solid_fill.vert.h" #include "impeller/entity/solid_stroke.frag.h" @@ -59,6 +61,9 @@ using SolidFillPipeline = using RadialGradientFillPipeline = PipelineT; using BlendPipeline = PipelineT; +using RRectBlurPipeline = + PipelineT; +using BlendPipeline = PipelineT; using BlendColorPipeline = PipelineT; using BlendColorBurnPipeline = @@ -147,6 +152,10 @@ class ContentContext { ContentContextOptions opts) const { return GetPipeline(radial_gradient_fill_pipelines_, opts); } + std::shared_ptr GetRRectBlurPipeline( + ContentContextOptions opts) const { + return GetPipeline(rrect_blur_pipelines_, opts); + } std::shared_ptr GetSolidFillPipeline( ContentContextOptions opts) const { @@ -293,6 +302,7 @@ class ContentContext { mutable Variants gradient_fill_pipelines_; mutable Variants solid_fill_pipelines_; mutable Variants radial_gradient_fill_pipelines_; + mutable Variants rrect_blur_pipelines_; mutable Variants texture_blend_pipelines_; mutable Variants texture_pipelines_; mutable Variants gaussian_blur_pipelines_; diff --git a/impeller/entity/contents/rrect_shadow_contents.cc b/impeller/entity/contents/rrect_shadow_contents.cc new file mode 100644 index 0000000000000..b6371f043e1dc --- /dev/null +++ b/impeller/entity/contents/rrect_shadow_contents.cc @@ -0,0 +1,111 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "impeller/entity/contents/rrect_shadow_contents.h" +#include + +#include "impeller/entity/contents/content_context.h" +#include "impeller/entity/entity.h" +#include "impeller/geometry/path.h" +#include "impeller/geometry/path_builder.h" +#include "impeller/renderer/render_pass.h" +#include "impeller/renderer/vertex_buffer_builder.h" +#include "impeller/tessellator/tessellator.h" + +namespace impeller { + +RRectShadowContents::RRectShadowContents() = default; + +RRectShadowContents::~RRectShadowContents() = default; + +void RRectShadowContents::SetRRect(std::optional rect, + Scalar corner_radius) { + rect_ = rect; + corner_radius_ = corner_radius; +} + +void RRectShadowContents::SetSigma(Sigma sigma) { + sigma_ = sigma; +} + +void RRectShadowContents::SetColor(Color color) { + color_ = color.Premultiply(); +} + +std::optional RRectShadowContents::GetCoverage( + const Entity& entity) const { + if (!rect_.has_value()) { + return std::nullopt; + } + + Scalar radius = Radius{sigma_}.radius; + + auto ltrb = rect_->GetLTRB(); + Rect bounds = Rect::MakeLTRB(ltrb[0] - radius, ltrb[1] - radius, + ltrb[2] + radius, ltrb[3] + radius); + return bounds.TransformBounds(entity.GetTransformation()); +}; + +bool RRectShadowContents::Render(const ContentContext& renderer, + const Entity& entity, + RenderPass& pass) const { + if (!rect_.has_value()) { + return true; + } + + using VS = RRectBlurPipeline::VertexShader; + using FS = RRectBlurPipeline::FragmentShader; + + VertexBufferBuilder vtx_builder; + + auto blur_radius = Radius{sigma_}.radius; + auto positive_rect = rect_->GetPositive(); + { + auto left = -blur_radius; + auto top = -blur_radius; + auto right = positive_rect.size.width + blur_radius; + auto bottom = positive_rect.size.height + blur_radius; + + vtx_builder.AddVertices({ + {Point(left, top)}, + {Point(right, top)}, + {Point(left, bottom)}, + {Point(left, bottom)}, + {Point(right, top)}, + {Point(right, bottom)}, + }); + } + + Command cmd; + cmd.label = "RRect Shadow"; + cmd.pipeline = + renderer.GetRRectBlurPipeline(OptionsFromPassAndEntity(pass, entity)); + cmd.stencil_reference = entity.GetStencilDepth(); + + cmd.primitive_type = PrimitiveType::kTriangle; + cmd.BindVertices(vtx_builder.CreateVertexBuffer(pass.GetTransientsBuffer())); + + VS::VertInfo vert_info; + vert_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * + entity.GetTransformation() * + Matrix::MakeTranslation({positive_rect.origin}); + VS::BindVertInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(vert_info)); + + FS::FragInfo frag_info; + frag_info.color = color_; + frag_info.blur_radius = blur_radius; + frag_info.rect_size = Point(positive_rect.size); + frag_info.corner_radius = + std::min(corner_radius_, std::min(positive_rect.size.width / 2.0f, + positive_rect.size.height / 2.0f)); + FS::BindFragInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frag_info)); + + if (!pass.AddCommand(std::move(cmd))) { + return false; + } + + return true; +} + +} // namespace impeller diff --git a/impeller/entity/contents/rrect_shadow_contents.h b/impeller/entity/contents/rrect_shadow_contents.h new file mode 100644 index 0000000000000..d6d46b7f5223a --- /dev/null +++ b/impeller/entity/contents/rrect_shadow_contents.h @@ -0,0 +1,51 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#pragma once + +#include +#include +#include + +#include "impeller/entity/contents/contents.h" +#include "impeller/entity/contents/filters/filter_contents.h" +#include "impeller/geometry/color.h" + +namespace impeller { + +class Path; +class HostBuffer; +struct VertexBuffer; + +class RRectShadowContents final : public Contents { + public: + RRectShadowContents(); + + ~RRectShadowContents() override; + + void SetRRect(std::optional rect, Scalar corner_radius = 0); + + void SetSigma(Sigma sigma); + + void SetColor(Color color); + + // |Contents| + std::optional GetCoverage(const Entity& entity) const override; + + // |Contents| + bool Render(const ContentContext& renderer, + const Entity& entity, + RenderPass& pass) const override; + + private: + std::optional rect_; + Scalar corner_radius_; + Sigma sigma_; + + Color color_; + + FML_DISALLOW_COPY_AND_ASSIGN(RRectShadowContents); +}; + +} // namespace impeller diff --git a/impeller/entity/entity_unittests.cc b/impeller/entity/entity_unittests.cc index b1f0e0b0c6ab8..37e7eef5010cd 100644 --- a/impeller/entity/entity_unittests.cc +++ b/impeller/entity/entity_unittests.cc @@ -10,6 +10,7 @@ #include "impeller/entity/contents/filters/blend_filter_contents.h" #include "impeller/entity/contents/filters/filter_contents.h" #include "impeller/entity/contents/filters/inputs/filter_input.h" +#include "impeller/entity/contents/rrect_shadow_contents.h" #include "impeller/entity/contents/solid_color_contents.h" #include "impeller/entity/contents/solid_stroke_contents.h" #include "impeller/entity/contents/texture_contents.h" @@ -1174,5 +1175,61 @@ TEST_P(EntityTest, ClipContentsShouldRenderIsCorrect) { } } +TEST_P(EntityTest, RRectShadowTest) { + bool first_frame = true; + auto callback = [&](ContentContext& context, RenderPass& pass) { + if (first_frame) { + first_frame = false; + ImGui::SetNextWindowPos({10, 10}); + } + + static Color color = Color::Red(); + static float corner_radius = 100; + static float blur_radius = 100; + static bool show_coverage = false; + static Color coverage_color = Color::Green().WithAlpha(0.2); + + ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize); + ImGui::SliderFloat("Corner radius", &corner_radius, 0, 300); + ImGui::SliderFloat("Blur radius", &blur_radius, 0, 300); + ImGui::ColorEdit4("Color", reinterpret_cast(&color)); + ImGui::Checkbox("Show coverage", &show_coverage); + if (show_coverage) { + ImGui::ColorEdit4("Coverage color", + reinterpret_cast(&coverage_color)); + } + ImGui::End(); + + auto [top_left, bottom_right] = IMPELLER_PLAYGROUND_LINE( + Point(200, 200), Point(600, 400), 30, Color::White(), Color::White()); + auto rect = + Rect::MakeLTRB(top_left.x, top_left.y, bottom_right.x, bottom_right.y); + + auto contents = std::make_unique(); + contents->SetRRect(rect, corner_radius); + contents->SetColor(color); + contents->SetSigma(Radius(blur_radius)); + + Entity entity; + entity.SetTransformation(Matrix::MakeScale(GetContentScale())); + entity.SetContents(std::move(contents)); + entity.Render(context, pass); + + auto coverage = entity.GetCoverage(); + if (show_coverage && coverage.has_value()) { + auto bounds_contents = std::make_unique(); + bounds_contents->SetPath( + PathBuilder{}.AddRect(entity.GetCoverage().value()).TakePath()); + bounds_contents->SetColor(coverage_color.Premultiply()); + Entity bounds_entity; + bounds_entity.SetContents(std::move(bounds_contents)); + bounds_entity.Render(context, pass); + } + + return true; + }; + ASSERT_TRUE(OpenPlaygroundHere(callback)); +} + } // namespace testing } // namespace impeller diff --git a/impeller/entity/shaders/rrect_blur.frag b/impeller/entity/shaders/rrect_blur.frag new file mode 100644 index 0000000000000..6178b1751bca5 --- /dev/null +++ b/impeller/entity/shaders/rrect_blur.frag @@ -0,0 +1,34 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +uniform FragInfo { + vec4 color; + float blur_radius; + vec2 rect_size; + float corner_radius; +} +frag_info; + +in vec2 v_position; + +out vec4 frag_color; + +// Simple logistic sigmoid with a domain of [-1, 1] and range of [0, 1]. +float Sigmoid(float x) { + return 1.03731472073 / (1 + exp(-4 * x)) - 0.0186573603638; +} + +float RRectDistance(vec2 sample_position, vec2 rect_size, float corner_radius) { + vec2 space = abs(sample_position) - rect_size + corner_radius; + return length(max(space, 0.0)) + min(max(space.x, space.y), 0.0) - + corner_radius; +} + +void main() { + vec2 center = v_position - frag_info.rect_size / 2.0; + float dist = + RRectDistance(center, frag_info.rect_size / 2.0, frag_info.corner_radius); + float shadow_mask = Sigmoid(-dist / frag_info.blur_radius); + frag_color = frag_info.color * shadow_mask; +} diff --git a/impeller/entity/shaders/rrect_blur.vert b/impeller/entity/shaders/rrect_blur.vert new file mode 100644 index 0000000000000..36711c6ede5e0 --- /dev/null +++ b/impeller/entity/shaders/rrect_blur.vert @@ -0,0 +1,18 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +uniform VertInfo { + mat4 mvp; +} +vert_info; + +in vec2 position; + +out vec2 v_position; + +void main() { + gl_Position = vert_info.mvp * vec4(position, 0.0, 1.0); + // The fragment stage uses local coordinates to compute the blur. + v_position = position; +} diff --git a/shell/platform/fuchsia/flutter/platform_view_unittest.cc b/shell/platform/fuchsia/flutter/platform_view_unittest.cc index 3afa8526877f3..a02ebb21f4deb 100644 --- a/shell/platform/fuchsia/flutter/platform_view_unittest.cc +++ b/shell/platform/fuchsia/flutter/platform_view_unittest.cc @@ -316,7 +316,7 @@ class PlatformViewBuilder { // Once Build is called, the instance is no longer usable. GfxPlatformView Build() { EXPECT_FALSE(std::exchange(built_, true)) - << "Build() was already called, this buider is good for one use only."; + << "Build() was already called, this builder is good for one use only."; return GfxPlatformView( delegate_, task_runners_, std::move(view_ref_pair_.view_ref), external_external_view_embedder_, std::move(ime_service_), diff --git a/shell/platform/fuchsia/flutter/tests/flatland_platform_view_unittest.cc b/shell/platform/fuchsia/flutter/tests/flatland_platform_view_unittest.cc index 0e804e1f68890..674030b0fc959 100644 --- a/shell/platform/fuchsia/flutter/tests/flatland_platform_view_unittest.cc +++ b/shell/platform/fuchsia/flutter/tests/flatland_platform_view_unittest.cc @@ -421,7 +421,7 @@ class PlatformViewBuilder { // Once Build is called, the instance is no longer usable. FlatlandPlatformView Build() { EXPECT_FALSE(std::exchange(built_, true)) - << "Build() was already called, this buider is good for one use only."; + << "Build() was already called, this builder is good for one use only."; return FlatlandPlatformView( delegate_, task_runners_, std::move(view_ref_pair_.view_ref), external_external_view_embedder_, std::move(ime_service_),