Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
36 changes: 17 additions & 19 deletions impeller/aiks/canvas.cc
Original file line number Diff line number Diff line change
Expand Up @@ -378,29 +378,32 @@ void Canvas::DrawTextFrame(const TextFrame& text_frame,
GetCurrentPass().AddEntity(entity);
}

void Canvas::DrawVertices(std::unique_ptr<VerticesGeometry> vertices,
void Canvas::DrawVertices(const std::shared_ptr<VerticesGeometry>& vertices,
BlendMode blend_mode,
const Paint& paint) {
Entity entity;
entity.SetTransformation(GetCurrentTransformation());
entity.SetStencilDepth(GetStencilDepth());
entity.SetBlendMode(paint.blend_mode);

if (paint.color_source.has_value()) {
auto& source = paint.color_source.value();
auto contents = source();
contents->SetGeometry(std::move(vertices));
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);
contents->SetGeometry(std::move(vertices));
entity.SetContents(paint.WithFilters(std::move(contents), true));
if (!vertices->HasVertexColors()) {
auto contents = paint.CreateContentsForGeometry(vertices);
entity.SetContents(paint.WithFilters(std::move(contents)));
GetCurrentPass().AddEntity(entity);
return;
}

auto src_paint = paint;
src_paint.color = paint.color.WithAlpha(1.0);
auto src_contents = src_paint.CreateContentsForGeometry(vertices);

auto contents = std::make_shared<VerticesContents>();
contents->SetAlpha(paint.color.alpha);
contents->SetBlendMode(blend_mode);
contents->SetGeometry(vertices);
contents->SetSourceContents(std::move(src_contents));
entity.SetContents(paint.WithFilters(std::move(contents)));

GetCurrentPass().AddEntity(entity);
}

Expand All @@ -415,11 +418,6 @@ void Canvas::DrawAtlas(const std::shared_ptr<Image>& atlas,
if (!atlas) {
return;
}
auto size = atlas->GetSize();

if (size.IsEmpty()) {
return;
}

std::shared_ptr<AtlasContents> contents = std::make_shared<AtlasContents>();
contents->SetColors(std::move(colors));
Expand Down
2 changes: 1 addition & 1 deletion impeller/aiks/canvas.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ class Canvas {
Point position,
const Paint& paint);

void DrawVertices(std::unique_ptr<VerticesGeometry> vertices,
void DrawVertices(const std::shared_ptr<VerticesGeometry>& vertices,
BlendMode blend_mode,
const Paint& paint);

Expand Down
15 changes: 15 additions & 0 deletions impeller/aiks/paint.cc
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,21 @@ std::shared_ptr<Contents> Paint::CreateContentsForGeometry(
return solid_color;
}

std::shared_ptr<Contents> Paint::CreateContentsForGeometry(
const std::shared_ptr<Geometry>& geometry) const {
if (color_source.has_value()) {
auto& source = color_source.value();
auto contents = source();
contents->SetGeometry(geometry);
contents->SetAlpha(color.alpha);
return contents;
}
auto solid_color = std::make_shared<SolidColorContents>();
solid_color->SetGeometry(geometry);
solid_color->SetColor(color);
return solid_color;
}

std::shared_ptr<Contents> Paint::WithFilters(
std::shared_ptr<Contents> input,
std::optional<bool> is_solid_color,
Expand Down
3 changes: 3 additions & 0 deletions impeller/aiks/paint.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@ struct Paint {
std::shared_ptr<Contents> CreateContentsForGeometry(
std::unique_ptr<Geometry> geometry) const;

std::shared_ptr<Contents> CreateContentsForGeometry(
const std::shared_ptr<Geometry>& geometry) const;

/// @brief Whether this paint has a color filter that can apply opacity
bool HasColorFilter() const;

Expand Down
100 changes: 100 additions & 0 deletions impeller/display_list/display_list_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@
namespace impeller {
namespace testing {

flutter::DlColor toColor(const float* components) {
auto value = (((std::lround(components[3] * 255) & 0xff) << 24) |
((std::lround(components[0] * 255) & 0xff) << 16) |
((std::lround(components[1] * 255) & 0xff) << 8) |
((std::lround(components[2] * 255) & 0xff) << 0)) &
0xFFFFFFFF;
return flutter::DlColor(value);
}

using DisplayListTest = DisplayListPlayground;
INSTANTIATE_PLAYGROUND_SUITE(DisplayListTest);

Expand Down Expand Up @@ -1164,6 +1173,97 @@ TEST_P(DisplayListTest, DrawShapes) {
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}

TEST_P(DisplayListTest, DrawVerticesBlendModes) {
std::vector<const char*> blend_mode_names;
std::vector<flutter::DlBlendMode> blend_mode_values;
{
const std::vector<std::tuple<const char*, flutter::DlBlendMode>> blends = {
// Pipeline blends (Porter-Duff alpha compositing)
{"Clear", flutter::DlBlendMode::kClear},
{"Source", flutter::DlBlendMode::kSrc},
{"Destination", flutter::DlBlendMode::kDst},
{"SourceOver", flutter::DlBlendMode::kSrcOver},
{"DestinationOver", flutter::DlBlendMode::kDstOver},
{"SourceIn", flutter::DlBlendMode::kSrcIn},
{"DestinationIn", flutter::DlBlendMode::kDstIn},
{"SourceOut", flutter::DlBlendMode::kSrcOut},
{"DestinationOut", flutter::DlBlendMode::kDstOut},
{"SourceATop", flutter::DlBlendMode::kSrcATop},
{"DestinationATop", flutter::DlBlendMode::kDstATop},
{"Xor", flutter::DlBlendMode::kXor},
{"Plus", flutter::DlBlendMode::kPlus},
{"Modulate", flutter::DlBlendMode::kModulate},
// Advanced blends (color component blends)
{"Screen", flutter::DlBlendMode::kScreen},
{"Overlay", flutter::DlBlendMode::kOverlay},
{"Darken", flutter::DlBlendMode::kDarken},
{"Lighten", flutter::DlBlendMode::kLighten},
{"ColorDodge", flutter::DlBlendMode::kColorDodge},
{"ColorBurn", flutter::DlBlendMode::kColorBurn},
{"HardLight", flutter::DlBlendMode::kHardLight},
{"SoftLight", flutter::DlBlendMode::kSoftLight},
{"Difference", flutter::DlBlendMode::kDifference},
{"Exclusion", flutter::DlBlendMode::kExclusion},
{"Multiply", flutter::DlBlendMode::kMultiply},
{"Hue", flutter::DlBlendMode::kHue},
{"Saturation", flutter::DlBlendMode::kSaturation},
{"Color", flutter::DlBlendMode::kColor},
{"Luminosity", flutter::DlBlendMode::kLuminosity},
};
assert(blends.size() ==
static_cast<size_t>(flutter::DlBlendMode::kLastMode) + 1);
for (const auto& [name, mode] : blends) {
blend_mode_names.push_back(name);
blend_mode_values.push_back(mode);
}
}

auto callback = [&]() {
static int current_blend_index = 3;
static float dst_alpha = 1;
static float src_alpha = 1;
static float color0[4] = {1.0f, 0.0f, 0.0f, 1.0f};
static float color1[4] = {0.0f, 1.0f, 0.0f, 1.0f};
static float color2[4] = {0.0f, 0.0f, 1.0f, 1.0f};
static float src_color[4] = {1.0f, 1.0f, 1.0f, 1.0f};

ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
{
ImGui::ListBox("Blending mode", &current_blend_index,
blend_mode_names.data(), blend_mode_names.size());
ImGui::SliderFloat("Source alpha", &src_alpha, 0, 1);
ImGui::ColorEdit4("Color A", color0);
ImGui::ColorEdit4("Color B", color1);
ImGui::ColorEdit4("Color C", color2);
ImGui::ColorEdit4("Source Color", src_color);
ImGui::SliderFloat("Destination alpha", &dst_alpha, 0, 1);
}
ImGui::End();

std::vector<SkPoint> positions = {SkPoint::Make(100, 300),
SkPoint::Make(200, 100),
SkPoint::Make(300, 300)};
std::vector<flutter::DlColor> colors = {
toColor(color0).modulateOpacity(dst_alpha),
toColor(color1).modulateOpacity(dst_alpha),
toColor(color2).modulateOpacity(dst_alpha)};

auto vertices = flutter::DlVertices::Make(
flutter::DlVertexMode::kTriangles, 3, positions.data(),
/*texture_coorindates=*/nullptr, colors.data());

flutter::DisplayListBuilder builder;
flutter::DlPaint paint;

paint.setColor(toColor(src_color).modulateOpacity(src_alpha));
builder.drawVertices(vertices, blend_mode_values[current_blend_index],
paint);
return builder.Build();
};

ASSERT_TRUE(OpenPlaygroundHere(callback));
}

#ifdef IMPELLER_ENABLE_3D
TEST_P(DisplayListTest, SceneColorSource) {
// Load up the scene.
Expand Down
18 changes: 10 additions & 8 deletions impeller/display_list/display_list_vertices_geometry.cc
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ static std::vector<uint16_t> fromFanIndices(
/////// Vertices Geometry ///////

// static
std::unique_ptr<VerticesGeometry> DLVerticesGeometry::MakeVertices(
std::shared_ptr<VerticesGeometry> DLVerticesGeometry::MakeVertices(
const flutter::DlVertices* vertices) {
return std::make_unique<DLVerticesGeometry>(vertices);
return std::make_shared<DLVerticesGeometry>(vertices);
}

DLVerticesGeometry::DLVerticesGeometry(const flutter::DlVertices* vertices)
Expand Down Expand Up @@ -100,6 +100,10 @@ static PrimitiveType GetPrimitiveType(const flutter::DlVertices* vertices) {
}
}

bool DLVerticesGeometry::HasVertexColors() const {
return vertices_->colors() != nullptr;
}

GeometryResult DLVerticesGeometry::GetPositionBuffer(
const ContentContext& renderer,
const Entity& entity,
Expand Down Expand Up @@ -154,9 +158,7 @@ GeometryResult DLVerticesGeometry::GetPositionBuffer(
GeometryResult DLVerticesGeometry::GetPositionColorBuffer(
const ContentContext& renderer,
const Entity& entity,
RenderPass& pass,
Color paint_color,
BlendMode blend_mode) {
RenderPass& pass) {
using VS = GeometryColorPipeline::VertexShader;

auto index_count = normalized_indices_.size() == 0
Expand All @@ -173,9 +175,9 @@ GeometryResult DLVerticesGeometry::GetPositionColorBuffer(
{
for (auto i = 0; i < vertex_count; i++) {
auto dl_color = dl_colors[i];
auto pre_color = Color(dl_color.getRedF(), dl_color.getGreenF(),
dl_color.getBlueF(), dl_color.getAlphaF());
auto color = Color::BlendColor(paint_color, pre_color, blend_mode);
auto color = Color(dl_color.getRedF(), dl_color.getGreenF(),
dl_color.getBlueF(), dl_color.getAlphaF())
.Premultiply();
auto sk_point = dl_vertices[i];
vertex_data[i] = {
.position = Point(sk_point.x(), sk_point.y()),
Expand Down
9 changes: 5 additions & 4 deletions impeller/display_list/display_list_vertices_geometry.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,13 @@ class DLVerticesGeometry : public VerticesGeometry {

~DLVerticesGeometry();

static std::unique_ptr<VerticesGeometry> MakeVertices(
static std::shared_ptr<VerticesGeometry> MakeVertices(
const flutter::DlVertices* vertices);

// |VerticesGeometry|
GeometryResult GetPositionColorBuffer(const ContentContext& renderer,
const Entity& entity,
RenderPass& pass,
Color paint_color,
BlendMode blend_mode) override;
RenderPass& pass) override;

// |VerticesGeometry|
GeometryResult GetPositionUVBuffer(const ContentContext& renderer,
Expand All @@ -49,6 +47,9 @@ class DLVerticesGeometry : public VerticesGeometry {
// |Geometry|
GeometryVertexType GetVertexType() const override;

// |VerticesGeometry|
bool HasVertexColors() const override;

private:
void NormalizeIndices();

Expand Down
2 changes: 0 additions & 2 deletions impeller/entity/contents/atlas_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,6 @@ bool AtlasContents::Render(const ContentContext& renderer,
auto dst_contents = std::make_shared<AtlasColorContents>(*this);
dst_contents->SetCoverage(coverage);

// For some reason this looks backwards compared to Skia unless
// we reverse the src/dst.
auto contents = ColorFilterContents::MakeBlend(
blend_mode_,
{FilterInput::Make(dst_contents), FilterInput::Make(src_contents)});
Expand Down
5 changes: 3 additions & 2 deletions impeller/entity/contents/content_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -260,11 +260,12 @@ bool ContentContext::IsValid() const {

std::shared_ptr<Texture> ContentContext::MakeSubpass(
ISize texture_size,
const SubpassCallback& subpass_callback) const {
const SubpassCallback& subpass_callback,
bool msaa_enabled) const {
auto context = GetContext();

RenderTarget subpass_target;
if (context->SupportsOffscreenMSAA()) {
if (context->SupportsOffscreenMSAA() && msaa_enabled) {
subpass_target = RenderTarget::CreateOffscreenMSAA(*context, texture_size);
} else {
subpass_target = RenderTarget::CreateOffscreen(*context, texture_size);
Expand Down
6 changes: 3 additions & 3 deletions impeller/entity/contents/content_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -432,9 +432,9 @@ class ContentContext {

/// @brief Creates a new texture of size `texture_size` and calls
/// `subpass_callback` with a `RenderPass` for drawing to the texture.
std::shared_ptr<Texture> MakeSubpass(
ISize texture_size,
const SubpassCallback& subpass_callback) const;
std::shared_ptr<Texture> MakeSubpass(ISize texture_size,
const SubpassCallback& subpass_callback,
bool msaa_enabled = true) const;

private:
std::shared_ptr<Context> context_;
Expand Down
6 changes: 4 additions & 2 deletions impeller/entity/contents/contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ Contents::StencilCoverage Contents::GetStencilCoverage(

std::optional<Snapshot> Contents::RenderToSnapshot(
const ContentContext& renderer,
const Entity& entity) const {
const Entity& entity,
bool msaa_enabled) const {
auto coverage = GetCoverage(entity);
if (!coverage.has_value()) {
return std::nullopt;
Expand All @@ -56,7 +57,8 @@ std::optional<Snapshot> Contents::RenderToSnapshot(
Matrix::MakeTranslation(Vector3(-coverage->origin)) *
entity.GetTransformation());
return contents.Render(renderer, sub_entity, pass);
});
},
msaa_enabled);

if (!texture) {
return std::nullopt;
Expand Down
3 changes: 2 additions & 1 deletion impeller/entity/contents/contents.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ class Contents {
/// `GetCoverage(entity)`.
virtual std::optional<Snapshot> RenderToSnapshot(
const ContentContext& renderer,
const Entity& entity) const;
const Entity& entity,
bool msaa_enabled = true) const;

virtual bool ShouldRender(const Entity& entity,
const std::optional<Rect>& stencil_coverage) const;
Expand Down
2 changes: 1 addition & 1 deletion impeller/entity/contents/filters/blend_filter_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ static std::optional<Snapshot> PipelineBlend(
FS::FragInfo frag_info;
frag_info.texture_sampler_y_coord_scale =
input->texture->GetYCoordScale();
frag_info.input_alpha = absorb_opacity ? input->opacity : 1.0f;
frag_info.input_alpha = absorb_opacity ? input->opacity : 1.0;
FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info));
VS::BindFrameInfo(cmd, host_buffer.EmplaceUniform(frame_info));

Expand Down
3 changes: 2 additions & 1 deletion impeller/entity/contents/filters/filter_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,8 @@ std::optional<Rect> FilterContents::GetFilterCoverage(

std::optional<Snapshot> FilterContents::RenderToSnapshot(
const ContentContext& renderer,
const Entity& entity) const {
const Entity& entity,
bool msaa_enabled) const {
Entity entity_with_local_transform = entity;
entity_with_local_transform.SetTransformation(
GetTransform(entity.GetTransformation()));
Expand Down
6 changes: 4 additions & 2 deletions impeller/entity/contents/filters/filter_contents.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,10 @@ class FilterContents : public Contents {
std::optional<Rect> GetCoverage(const Entity& entity) const override;

// |Contents|
std::optional<Snapshot> RenderToSnapshot(const ContentContext& renderer,
const Entity& entity) const override;
std::optional<Snapshot> RenderToSnapshot(
const ContentContext& renderer,
const Entity& entity,
bool msaa_enabled = true) const override;

virtual Matrix GetLocalTransform(const Matrix& parent_transform) const;

Expand Down
Loading