Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

[Impeller] make strokes < 0.5 physical pixels visually thinner. #53154

Merged
merged 1 commit into from
May 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions impeller/entity/contents/conical_gradient_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,14 @@ bool ConicalGradientContents::RenderSSBO(const ContentContext& renderer,
};
return ColorSourceContents::DrawGeometry<VS>(
renderer, entity, pass, pipeline_callback, frame_info,
[this, &renderer](RenderPass& pass) {
[this, &renderer, &entity](RenderPass& pass) {
FS::FragInfo frag_info;
frag_info.center = center_;
frag_info.radius = radius_;
frag_info.tile_mode = static_cast<Scalar>(tile_mode_);
frag_info.decal_border_color = decal_border_color_;
frag_info.alpha = GetOpacityFactor();
frag_info.alpha =
GetOpacityFactor() * GetGeometry()->ComputeAlphaCoverage(entity);
if (focus_) {
frag_info.focus = focus_.value();
frag_info.focus_radius = focus_radius_;
Expand Down Expand Up @@ -127,15 +128,16 @@ bool ConicalGradientContents::RenderTexture(const ContentContext& renderer,
};
return ColorSourceContents::DrawGeometry<VS>(
renderer, entity, pass, pipeline_callback, frame_info,
[this, &renderer, &gradient_texture](RenderPass& pass) {
[this, &renderer, &gradient_texture, &entity](RenderPass& pass) {
FS::FragInfo frag_info;
frag_info.center = center_;
frag_info.radius = radius_;
frag_info.tile_mode = static_cast<Scalar>(tile_mode_);
frag_info.decal_border_color = decal_border_color_;
frag_info.texture_sampler_y_coord_scale =
gradient_texture->GetYCoordScale();
frag_info.alpha = GetOpacityFactor();
frag_info.alpha =
GetOpacityFactor() * GetGeometry()->ComputeAlphaCoverage(entity);
frag_info.half_texel =
Vector2(0.5 / gradient_texture->GetSize().width,
0.5 / gradient_texture->GetSize().height);
Expand Down
11 changes: 7 additions & 4 deletions impeller/entity/contents/linear_gradient_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ bool LinearGradientContents::RenderTexture(const ContentContext& renderer,
};
return ColorSourceContents::DrawGeometry<VS>(
renderer, entity, pass, pipeline_callback, frame_info,
[this, &renderer](RenderPass& pass) {
[this, &renderer, &entity](RenderPass& pass) {
auto gradient_data = CreateGradientBuffer(colors_, stops_);
auto gradient_texture =
CreateGradientTexture(gradient_data, renderer.GetContext());
Expand All @@ -92,7 +92,9 @@ bool LinearGradientContents::RenderTexture(const ContentContext& renderer,
frag_info.decal_border_color = decal_border_color_;
frag_info.texture_sampler_y_coord_scale =
gradient_texture->GetYCoordScale();
frag_info.alpha = GetOpacityFactor();
frag_info.alpha =
GetOpacityFactor() * GetGeometry()->ComputeAlphaCoverage(entity);
;
frag_info.half_texel =
Vector2(0.5 / gradient_texture->GetSize().width,
0.5 / gradient_texture->GetSize().height);
Expand Down Expand Up @@ -137,13 +139,14 @@ bool LinearGradientContents::RenderSSBO(const ContentContext& renderer,
};
return ColorSourceContents::DrawGeometry<VS>(
renderer, entity, pass, pipeline_callback, frame_info,
[this, &renderer](RenderPass& pass) {
[this, &renderer, &entity](RenderPass& pass) {
FS::FragInfo frag_info;
frag_info.start_point = start_point_;
frag_info.end_point = end_point_;
frag_info.tile_mode = static_cast<Scalar>(tile_mode_);
frag_info.decal_border_color = decal_border_color_;
frag_info.alpha = GetOpacityFactor();
frag_info.alpha =
GetOpacityFactor() * GetGeometry()->ComputeAlphaCoverage(entity);
frag_info.start_to_end = end_point_ - start_point_;
frag_info.inverse_dot_start_to_end =
CalculateInverseDotStartToEnd(start_point_, end_point_);
Expand Down
10 changes: 6 additions & 4 deletions impeller/entity/contents/radial_gradient_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,14 @@ bool RadialGradientContents::RenderSSBO(const ContentContext& renderer,
};
return ColorSourceContents::DrawGeometry<VS>(
renderer, entity, pass, pipeline_callback, frame_info,
[this, &renderer](RenderPass& pass) {
[this, &renderer, &entity](RenderPass& pass) {
FS::FragInfo frag_info;
frag_info.center = center_;
frag_info.radius = radius_;
frag_info.tile_mode = static_cast<Scalar>(tile_mode_);
frag_info.decal_border_color = decal_border_color_;
frag_info.alpha = GetOpacityFactor();
frag_info.alpha =
GetOpacityFactor() * GetGeometry()->ComputeAlphaCoverage(entity);

auto& host_buffer = renderer.GetTransientsBuffer();
auto colors = CreateGradientColors(colors_, stops_);
Expand Down Expand Up @@ -126,15 +127,16 @@ bool RadialGradientContents::RenderTexture(const ContentContext& renderer,
};
return ColorSourceContents::DrawGeometry<VS>(
renderer, entity, pass, pipeline_callback, frame_info,
[this, &renderer, &gradient_texture](RenderPass& pass) {
[this, &renderer, &gradient_texture, &entity](RenderPass& pass) {
FS::FragInfo frag_info;
frag_info.center = center_;
frag_info.radius = radius_;
frag_info.tile_mode = static_cast<Scalar>(tile_mode_);
frag_info.decal_border_color = decal_border_color_;
frag_info.texture_sampler_y_coord_scale =
gradient_texture->GetYCoordScale();
frag_info.alpha = GetOpacityFactor();
frag_info.alpha =
GetOpacityFactor() * GetGeometry()->ComputeAlphaCoverage(entity);
frag_info.half_texel =
Vector2(0.5 / gradient_texture->GetSize().width,
0.5 / gradient_texture->GetSize().height);
Expand Down
3 changes: 2 additions & 1 deletion impeller/entity/contents/solid_color_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ bool SolidColorContents::Render(const ContentContext& renderer,
using VS = SolidFillPipeline::VertexShader;

VS::FrameInfo frame_info;
frame_info.color = GetColor().Premultiply();
frame_info.color =
GetColor().Premultiply() * GetGeometry()->ComputeAlphaCoverage(entity);

PipelineBuilderCallback pipeline_callback =
[&renderer](ContentContextOptions options) {
Expand Down
10 changes: 6 additions & 4 deletions impeller/entity/contents/sweep_gradient_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,15 @@ bool SweepGradientContents::RenderSSBO(const ContentContext& renderer,
};
return ColorSourceContents::DrawGeometry<VS>(
renderer, entity, pass, pipeline_callback, frame_info,
[this, &renderer](RenderPass& pass) {
[this, &renderer, &entity](RenderPass& pass) {
FS::FragInfo frag_info;
frag_info.center = center_;
frag_info.bias = bias_;
frag_info.scale = scale_;
frag_info.tile_mode = static_cast<Scalar>(tile_mode_);
frag_info.decal_border_color = decal_border_color_;
frag_info.alpha = GetOpacityFactor();
frag_info.alpha =
GetOpacityFactor() * GetGeometry()->ComputeAlphaCoverage(entity);

auto& host_buffer = renderer.GetTransientsBuffer();
auto colors = CreateGradientColors(colors_, stops_);
Expand Down Expand Up @@ -136,7 +137,7 @@ bool SweepGradientContents::RenderTexture(const ContentContext& renderer,
};
return ColorSourceContents::DrawGeometry<VS>(
renderer, entity, pass, pipeline_callback, frame_info,
[this, &renderer, &gradient_texture](RenderPass& pass) {
[this, &renderer, &gradient_texture, &entity](RenderPass& pass) {
FS::FragInfo frag_info;
frag_info.center = center_;
frag_info.bias = bias_;
Expand All @@ -145,7 +146,8 @@ bool SweepGradientContents::RenderTexture(const ContentContext& renderer,
gradient_texture->GetYCoordScale();
frag_info.tile_mode = static_cast<Scalar>(tile_mode_);
frag_info.decal_border_color = decal_border_color_;
frag_info.alpha = GetOpacityFactor();
frag_info.alpha =
GetOpacityFactor() * GetGeometry()->ComputeAlphaCoverage(entity);
frag_info.half_texel =
Vector2(0.5 / gradient_texture->GetSize().width,
0.5 / gradient_texture->GetSize().height);
Expand Down
8 changes: 5 additions & 3 deletions impeller/entity/contents/tiled_texture_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ bool TiledTextureContents::Render(const ContentContext& renderer,
};
return ColorSourceContents::DrawGeometry<VS>(
renderer, entity, pass, pipeline_callback, frame_info,
[this, &renderer, &is_external_texture](RenderPass& pass) {
[this, &renderer, &is_external_texture, &entity](RenderPass& pass) {
auto& host_buffer = renderer.GetTransientsBuffer();

pass.SetCommandLabel("TextureFill");
Expand All @@ -159,13 +159,15 @@ bool TiledTextureContents::Render(const ContentContext& renderer,
FSExternal::FragInfo frag_info;
frag_info.x_tile_mode = static_cast<Scalar>(x_tile_mode_);
frag_info.y_tile_mode = static_cast<Scalar>(y_tile_mode_);
frag_info.alpha = GetOpacityFactor();
frag_info.alpha =
GetOpacityFactor() * GetGeometry()->ComputeAlphaCoverage(entity);
FSExternal::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info));
} else {
FS::FragInfo frag_info;
frag_info.x_tile_mode = static_cast<Scalar>(x_tile_mode_);
frag_info.y_tile_mode = static_cast<Scalar>(y_tile_mode_);
frag_info.alpha = GetOpacityFactor();
frag_info.alpha =
GetOpacityFactor() * GetGeometry()->ComputeAlphaCoverage(entity);
FS::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info));
}

Expand Down
4 changes: 4 additions & 0 deletions impeller/entity/geometry/geometry.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ class Geometry {

virtual bool CanApplyMaskFilter() const;

virtual Scalar ComputeAlphaCoverage(const Entity& entitys) const {
return 1.0;
}

protected:
static GeometryResult ComputePositionGeometry(
const ContentContext& renderer,
Expand Down
18 changes: 18 additions & 0 deletions impeller/entity/geometry/geometry_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@

#include <memory>
#include "flutter/testing/testing.h"
#include "gtest/gtest.h"
#include "impeller/entity/contents/content_context.h"
#include "impeller/entity/geometry/geometry.h"
#include "impeller/entity/geometry/stroke_path_geometry.h"
#include "impeller/geometry/constants.h"
#include "impeller/geometry/geometry_asserts.h"
#include "impeller/geometry/path_builder.h"
#include "impeller/renderer/testing/mocks.h"
Expand Down Expand Up @@ -134,5 +136,21 @@ TEST(EntityGeometryTest, GeometryResultHasReasonableDefaults) {
EXPECT_EQ(result.mode, GeometryResult::Mode::kNormal);
}

TEST(EntityGeometryTest, AlphaCoverageStrokePaths) {
Entity entity;
entity.SetTransform(Matrix::MakeScale(Vector2{3.0, 3.0}));
EXPECT_EQ(Geometry::MakeStrokePath({}, 0.5)->ComputeAlphaCoverage(entity), 1);
EXPECT_EQ(Geometry::MakeStrokePath({}, 0.1)->ComputeAlphaCoverage(entity), 1);
EXPECT_EQ(Geometry::MakeStrokePath({}, 0.05)->ComputeAlphaCoverage(entity),
1);
EXPECT_NEAR(Geometry::MakeStrokePath({}, 0.01)->ComputeAlphaCoverage(entity),
0.6, 0.1);
EXPECT_NEAR(
Geometry::MakeStrokePath({}, 0.0000005)->ComputeAlphaCoverage(entity),
1e-05, 0.001);
EXPECT_EQ(Geometry::MakeStrokePath({}, 0)->ComputeAlphaCoverage(entity), 1);
EXPECT_EQ(Geometry::MakeStrokePath({}, 40)->ComputeAlphaCoverage(entity), 1);
}

} // namespace testing
} // namespace impeller
15 changes: 13 additions & 2 deletions impeller/entity/geometry/stroke_path_geometry.cc
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,18 @@ Join StrokePathGeometry::GetStrokeJoin() const {
return stroke_join_;
}

Scalar StrokePathGeometry::ComputeAlphaCoverage(const Entity& entity) const {
Scalar scaled_stroke_width =
entity.GetTransform().GetMaxBasisLengthXY() * stroke_width_;
// If the stroke width is 0 or greater than kMinStrokeSizeMSAA, don't apply
// any additional alpha. This is intended to match Skia behavior.
if (scaled_stroke_width == 0.0 || scaled_stroke_width >= kMinStrokeSizeMSAA) {
return 1.0;
}
// This scalling is eyeballed from Skia.
return std::clamp(scaled_stroke_width * 20.0f, 0.f, 1.f);
}

GeometryResult StrokePathGeometry::GetPositionBuffer(
const ContentContext& renderer,
const Entity& entity,
Expand Down Expand Up @@ -568,8 +580,7 @@ GeometryResult StrokePathGeometry::GetPositionBuffer(
.index_type = IndexType::kNone,
},
.transform = entity.GetShaderTransform(pass),
.mode = GeometryResult::Mode::kPreventOverdraw,
};
.mode = GeometryResult::Mode::kPreventOverdraw};
}

GeometryResult::Mode StrokePathGeometry::GetResultMode() const {
Expand Down
2 changes: 2 additions & 0 deletions impeller/entity/geometry/stroke_path_geometry.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ class StrokePathGeometry final : public Geometry {

Join GetStrokeJoin() const;

Scalar ComputeAlphaCoverage(const Entity& entity) const override;

private:
// |Geometry|
GeometryResult GetPositionBuffer(const ContentContext& renderer,
Expand Down