Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
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
2 changes: 0 additions & 2 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -1218,8 +1218,6 @@ FILE: ../../../flutter/impeller/entity/contents/runtime_effect_contents.cc
FILE: ../../../flutter/impeller/entity/contents/runtime_effect_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
FILE: ../../../flutter/impeller/entity/contents/solid_stroke_contents.h
FILE: ../../../flutter/impeller/entity/contents/sweep_gradient_contents.cc
FILE: ../../../flutter/impeller/entity/contents/sweep_gradient_contents.h
FILE: ../../../flutter/impeller/entity/contents/text_contents.cc
Expand Down
95 changes: 95 additions & 0 deletions impeller/aiks/aiks_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1497,6 +1497,101 @@ TEST_P(AiksTest, SolidStrokesRenderCorrectly) {
ASSERT_TRUE(OpenPlaygroundHere(callback));
}

TEST_P(AiksTest, GradientStrokesRenderCorrectly) {
// Compare with https://fiddle.skia.org/c/027392122bec8ac2b5d5de00a4b9bbe2
bool first_frame = true;
auto callback = [&](AiksContext& renderer, RenderTarget& render_target) {
if (first_frame) {
first_frame = false;
ImGui::SetNextWindowSize({480, 100});
ImGui::SetNextWindowPos({100, 550});
}

static float scale = 3;
static bool add_circle_clip = true;
const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
const Entity::TileMode tile_modes[] = {
Entity::TileMode::kClamp, Entity::TileMode::kRepeat,
Entity::TileMode::kMirror, Entity::TileMode::kDecal};
static int selected_tile_mode = 0;
static float alpha = 1;

ImGui::Begin("Controls");
ImGui::SliderFloat("Scale", &scale, 0, 6);
ImGui::Checkbox("Circle clip", &add_circle_clip);
ImGui::SliderFloat("Alpha", &alpha, 0, 1);
ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
sizeof(tile_mode_names) / sizeof(char*));
ImGui::End();

Canvas canvas;
canvas.Scale(GetContentScale());
Paint paint;
paint.color = Color::White();
canvas.DrawPaint(paint);

paint.style = Paint::Style::kStroke;
paint.color = Color(1.0, 1.0, 1.0, alpha);
paint.stroke_width = 10;
auto tile_mode = tile_modes[selected_tile_mode];
paint.color_source = [tile_mode]() {
std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
Color{0.1294, 0.5882, 0.9529, 1.0}};
std::vector<Scalar> stops = {0.0, 1.0};
Matrix matrix = {
1, 0, 0, 0, //
0, 1, 0, 0, //
0, 0, 1, 0, //
0, 0, 0, 1 //
};
auto contents = std::make_shared<LinearGradientContents>();
contents->SetEndPoints({0, 0}, {50, 50});
contents->SetColors(std::move(colors));
contents->SetStops(std::move(stops));
contents->SetTileMode(tile_mode);
contents->SetMatrix(matrix);
return contents;
};

Path path = PathBuilder{}
.MoveTo({20, 20})
.QuadraticCurveTo({60, 20}, {60, 60})
.Close()
.MoveTo({60, 20})
.QuadraticCurveTo({60, 60}, {20, 60})
.TakePath();

canvas.Scale(Vector2(scale, scale));

if (add_circle_clip) {
auto [handle_a, handle_b] = IMPELLER_PLAYGROUND_LINE(
Point(60, 300), Point(600, 300), 20, Color::Red(), Color::Red());

auto screen_to_canvas = canvas.GetCurrentTransformation().Invert();
Point point_a = screen_to_canvas * handle_a * GetContentScale();
Point point_b = screen_to_canvas * handle_b * GetContentScale();

Point middle = (point_a + point_b) / 2;
auto radius = point_a.GetDistance(middle);
canvas.ClipPath(PathBuilder{}.AddCircle(middle, radius).TakePath());
}

for (auto join : {Join::kBevel, Join::kRound, Join::kMiter}) {
paint.stroke_join = join;
for (auto cap : {Cap::kButt, Cap::kSquare, Cap::kRound}) {
paint.stroke_cap = cap;
canvas.DrawPath(path, paint);
canvas.Translate({80, 0});
}
canvas.Translate({-240, 60});
}

return renderer.Render(canvas.EndRecordingAsPicture(), render_target);
};

ASSERT_TRUE(OpenPlaygroundHere(callback));
}

TEST_P(AiksTest, CoverageOriginShouldBeAccountedForInSubpasses) {
auto callback = [&](AiksContext& renderer, RenderTarget& render_target) {
Canvas canvas;
Expand Down
22 changes: 16 additions & 6 deletions impeller/aiks/canvas.cc
Original file line number Diff line number Diff line change
Expand Up @@ -355,16 +355,26 @@ void Canvas::DrawTextFrame(TextFrame text_frame, Point position, Paint paint) {
void Canvas::DrawVertices(Vertices vertices,
BlendMode blend_mode,
Paint paint) {
std::shared_ptr<VerticesContents> contents =
std::make_shared<VerticesContents>();
contents->SetColor(paint.color);
contents->SetBlendMode(blend_mode);
contents->SetGeometry(Geometry::MakeVertices(std::move(vertices)));
auto geometry = Geometry::MakeVertices(std::move(vertices));

Entity entity;
entity.SetTransformation(GetCurrentTransformation());
entity.SetStencilDepth(GetStencilDepth());
entity.SetBlendMode(paint.blend_mode);
entity.SetContents(paint.WithFilters(std::move(contents), true));

if (paint.color_source.has_value()) {
auto& source = paint.color_source.value();
auto contents = source();
contents->SetGeometry(std::move(geometry));
contents->SetAlpha(paint.color.alpha);
entity.SetContents(paint.WithFilters(std::move(contents), true));
} else {
std::shared_ptr<VerticesContents> contents =
std::make_shared<VerticesContents>();
contents->SetColor(paint.color);
contents->SetBlendMode(blend_mode);
entity.SetContents(paint.WithFilters(std::move(contents), true));
}

GetCurrentPass().AddEntity(std::move(entity));
}
Expand Down
42 changes: 19 additions & 23 deletions impeller/aiks/paint.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,41 +4,37 @@

#include "impeller/aiks/paint.h"
#include "impeller/entity/contents/solid_color_contents.h"
#include "impeller/entity/contents/solid_stroke_contents.h"
#include "impeller/entity/geometry.h"

namespace impeller {

std::shared_ptr<Contents> Paint::CreateContentsForEntity(Path path,
bool cover) const {
std::unique_ptr<Geometry> geometry;
switch (style) {
case Style::kFill:
geometry = cover ? Geometry::MakeCover()
: Geometry::MakeFillPath(std::move(path));
break;
case Style::kStroke:
geometry = cover ? Geometry::MakeCover()
: Geometry::MakeStrokePath(std::move(path), stroke_width,
stroke_miter, stroke_cap,
stroke_join);
break;
}

if (color_source.has_value()) {
auto& source = color_source.value();
auto contents = source();
contents->SetGeometry(cover ? Geometry::MakeCover()
: Geometry::MakeFillPath(std::move(path)));
contents->SetGeometry(std::move(geometry));
contents->SetAlpha(color.alpha);
return contents;
}

switch (style) {
case Style::kFill: {
auto solid_color = std::make_shared<SolidColorContents>();
solid_color->SetGeometry(cover ? Geometry::MakeCover()
: Geometry::MakeFillPath(std::move(path)));
solid_color->SetColor(color);
return solid_color;
}
case Style::kStroke: {
auto solid_stroke = std::make_shared<SolidStrokeContents>();
solid_stroke->SetGeometry(
Geometry::MakeStrokePath(std::move(path), stroke_width, stroke_miter,
stroke_cap, stroke_join));
solid_stroke->SetColor(color);
return solid_stroke;
}
}

return nullptr;
auto solid_color = std::make_shared<SolidColorContents>();
solid_color->SetGeometry(std::move(geometry));
solid_color->SetColor(color);
return solid_color;
}

std::shared_ptr<Contents> Paint::WithFilters(
Expand Down
1 change: 0 additions & 1 deletion impeller/aiks/paint.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
#include "impeller/entity/contents/filters/filter_contents.h"
#include "impeller/entity/contents/linear_gradient_contents.h"
#include "impeller/entity/contents/radial_gradient_contents.h"
#include "impeller/entity/contents/solid_stroke_contents.h"
#include "impeller/entity/contents/sweep_gradient_contents.h"
#include "impeller/entity/entity.h"
#include "impeller/entity/geometry.h"
Expand Down
1 change: 0 additions & 1 deletion impeller/display_list/display_list_dispatcher.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
#include "impeller/entity/contents/linear_gradient_contents.h"
#include "impeller/entity/contents/radial_gradient_contents.h"
#include "impeller/entity/contents/runtime_effect_contents.h"
#include "impeller/entity/contents/solid_stroke_contents.h"
#include "impeller/entity/contents/sweep_gradient_contents.h"
#include "impeller/entity/contents/tiled_texture_contents.h"
#include "impeller/entity/entity.h"
Expand Down
2 changes: 0 additions & 2 deletions impeller/entity/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,6 @@ impeller_component("entity") {
"contents/runtime_effect_contents.h",
"contents/solid_color_contents.cc",
"contents/solid_color_contents.h",
"contents/solid_stroke_contents.cc",
"contents/solid_stroke_contents.h",
"contents/sweep_gradient_contents.cc",
"contents/sweep_gradient_contents.h",
"contents/text_contents.cc",
Expand Down
21 changes: 17 additions & 4 deletions impeller/entity/contents/linear_gradient_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "linear_gradient_contents.h"

#include "flutter/fml/logging.h"
#include "impeller/entity/contents/clip_contents.h"
#include "impeller/entity/contents/content_context.h"
#include "impeller/entity/contents/gradient_generator.h"
#include "impeller/entity/entity.h"
Expand Down Expand Up @@ -72,13 +73,17 @@ bool LinearGradientContents::Render(const ContentContext& renderer,

Command cmd;
cmd.label = "LinearGradientFill";
cmd.pipeline = renderer.GetLinearGradientFillPipeline(
OptionsFromPassAndEntity(pass, entity));
cmd.stencil_reference = entity.GetStencilDepth();

auto allocator = renderer.GetContext()->GetResourceAllocator();
auto geometry_result =
GetGeometry()->GetPositionBuffer(renderer, entity, pass);
auto options = OptionsFromPassAndEntity(pass, entity);
if (geometry_result.prevent_overdraw) {
options.stencil_compare = CompareFunction::kEqual;
options.stencil_operation = StencilOperation::kIncrementClamp;
}
cmd.pipeline = renderer.GetLinearGradientFillPipeline(options);

cmd.BindVertices(geometry_result.vertex_buffer);
cmd.primitive_type = geometry_result.type;
FS::BindGradientInfo(
Expand All @@ -90,7 +95,15 @@ bool LinearGradientContents::Render(const ContentContext& renderer,
cmd, std::move(gradient_texture),
renderer.GetContext()->GetSamplerLibrary()->GetSampler(sampler_desc));
VS::BindFrameInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frame_info));
return pass.AddCommand(std::move(cmd));

if (!pass.AddCommand(std::move(cmd))) {
return false;
}

if (geometry_result.prevent_overdraw) {
return ClipRestoreContents().Render(renderer, entity, pass);
}
return true;
}

} // namespace impeller
21 changes: 17 additions & 4 deletions impeller/entity/contents/radial_gradient_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "radial_gradient_contents.h"

#include "flutter/fml/logging.h"
#include "impeller/entity/contents/clip_contents.h"
#include "impeller/entity/contents/content_context.h"
#include "impeller/entity/contents/gradient_generator.h"
#include "impeller/entity/entity.h"
Expand Down Expand Up @@ -72,13 +73,17 @@ bool RadialGradientContents::Render(const ContentContext& renderer,

Command cmd;
cmd.label = "RadialGradientFill";
cmd.pipeline = renderer.GetRadialGradientFillPipeline(
OptionsFromPassAndEntity(pass, entity));
cmd.stencil_reference = entity.GetStencilDepth();

auto allocator = renderer.GetContext()->GetResourceAllocator();
auto geometry_result =
GetGeometry()->GetPositionBuffer(renderer, entity, pass);
auto options = OptionsFromPassAndEntity(pass, entity);
if (geometry_result.prevent_overdraw) {
options.stencil_compare = CompareFunction::kEqual;
options.stencil_operation = StencilOperation::kIncrementClamp;
}
cmd.pipeline = renderer.GetRadialGradientFillPipeline(options);

cmd.BindVertices(geometry_result.vertex_buffer);
cmd.primitive_type = geometry_result.type;
FS::BindGradientInfo(
Expand All @@ -90,7 +95,15 @@ bool RadialGradientContents::Render(const ContentContext& renderer,
cmd, gradient_texture,
renderer.GetContext()->GetSamplerLibrary()->GetSampler(sampler_desc));
VS::BindFrameInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frame_info));
return pass.AddCommand(std::move(cmd));

if (!pass.AddCommand(std::move(cmd))) {
return false;
}

if (geometry_result.prevent_overdraw) {
return ClipRestoreContents().Render(renderer, entity, pass);
}
return true;
}

} // namespace impeller
14 changes: 12 additions & 2 deletions impeller/entity/contents/solid_color_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include "solid_color_contents.h"

#include "impeller/entity/contents/clip_contents.h"
#include "impeller/entity/contents/content_context.h"
#include "impeller/entity/entity.h"
#include "impeller/geometry/path.h"
Expand Down Expand Up @@ -55,11 +56,17 @@ bool SolidColorContents::Render(const ContentContext& renderer,

Command cmd;
cmd.label = "Solid Fill";
cmd.pipeline =
renderer.GetSolidFillPipeline(OptionsFromPassAndEntity(pass, entity));
cmd.stencil_reference = entity.GetStencilDepth();

auto geometry_result = geometry_->GetPositionBuffer(renderer, entity, pass);

auto options = OptionsFromPassAndEntity(pass, entity);
if (geometry_result.prevent_overdraw) {
options.stencil_compare = CompareFunction::kEqual;
options.stencil_operation = StencilOperation::kIncrementClamp;
}

cmd.pipeline = renderer.GetSolidFillPipeline(options);
cmd.BindVertices(geometry_result.vertex_buffer);
cmd.primitive_type = geometry_result.type;

Expand All @@ -76,6 +83,9 @@ bool SolidColorContents::Render(const ContentContext& renderer,
return false;
}

if (geometry_result.prevent_overdraw) {
return ClipRestoreContents().Render(renderer, entity, pass);
}
return true;
}

Expand Down
Loading