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 6 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
31 changes: 18 additions & 13 deletions impeller/aiks/canvas.cc
Original file line number Diff line number Diff line change
Expand Up @@ -380,25 +380,30 @@ void Canvas::DrawTextFrame(const TextFrame& text_frame,
void Canvas::DrawVertices(std::unique_ptr<VerticesGeometry> vertices,
BlendMode blend_mode,
Paint paint) {
auto has_colors = vertices->GetVertexType() == GeometryVertexType::kColor;
auto rect = vertices->GetCoverage(GetCurrentTransformation());
if ((has_colors && blend_mode == BlendMode::kClear) || !rect.has_value()) {
return;
}

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 (!has_colors || blend_mode == BlendMode::kSource) {
entity.SetContents(paint.WithFilters(
paint.CreateContentsForGeometry(std::move(vertices))));
GetCurrentPass().AddEntity(entity);
return;
}
auto contents = std::make_shared<VerticesContents>();
contents->SetSrcContents(paint.CreateContentsForGeometry(
Geometry::MakeRect(Rect::MakeSize(rect.value().size))));
contents->SetColor(paint.color);
contents->SetBlendMode(blend_mode);
contents->SetGeometry(std::move(vertices));
entity.SetContents(paint.WithFilters(contents));

GetCurrentPass().AddEntity(entity);
}
Expand Down
51 changes: 51 additions & 0 deletions impeller/compiler/shader_lib/impeller/blending.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -190,4 +190,55 @@ vec3 IPBlendLuminosity(vec3 dst, vec3 src) {
return IPSetLuminosity(dst, IPLuminosity(src));
}

vec4 IPBlendSrcOver(vec4 dst, vec4 src) {
return src + dst * (1 - src.a);
}

vec4 IPBlendSrcIn(vec4 dst, vec4 src) {
// https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_srcin
return src * dst.a;
}

vec4 IPBlendDstOver(vec4 dst, vec4 src) {
// https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_dstout
return dst + src * (1 - dst.a);
}

vec4 IPBlendDstIn(vec4 dst, vec4 src) {
// https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_dstin
return dst * src.a;
}

vec4 IPBlendDstOut(vec4 dst, vec4 src) {
return dst * (1 - src.a);
}

vec4 IPBlendSrcOut(vec4 dst, vec4 src) {
// https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_srcout
return src * (1 - dst.a);
}

vec4 IPBlendSrcATop(vec4 dst, vec4 src) {
// https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_srcatop
return src * dst.a + dst * (1 - src.a);
}

vec4 IPBlendDstATop(vec4 dst, vec4 src) {
// https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_dstatop
return dst * src.a + src * (1 - dst.a);
}

vec4 IPBlendXor(vec4 dst, vec4 src) {
// https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_xor
return src * (1 - dst.a) + dst * (1 - src.a);
}

vec4 IPBlendPlus(vec4 dst, vec4 src) {
return min(src + dst, vec4(1));
}

vec4 IPBlendModulate(vec4 dst, vec4 src) {
return src * dst;
}

#endif
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 @@ -1159,6 +1168,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
80 changes: 69 additions & 11 deletions impeller/display_list/display_list_vertices_geometry.cc
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,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,13 +171,12 @@ 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());
auto sk_point = dl_vertices[i];
vertex_data[i] = {
.position = Point(sk_point.x(), sk_point.y()),
.color = color,
.color = color.Premultiply(),
};
}
}
Expand Down Expand Up @@ -226,10 +223,71 @@ GeometryResult DLVerticesGeometry::GetPositionUVBuffer(
const ContentContext& renderer,
const Entity& entity,
RenderPass& pass) {
// TODO(jonahwilliams): support texture coordinates in vertices
// https://github.com/flutter/flutter/issues/109956
return {};
}
using VS = AtlasBlendSrcOverPipeline::VertexShader;

auto index_count = normalized_indices_.size() == 0
? vertices_->index_count()
: normalized_indices_.size();
auto vertex_count = vertices_->vertex_count();
auto* dl_indices = normalized_indices_.size() == 0
? vertices_->indices()
: normalized_indices_.data();
auto* dl_vertices = vertices_->vertices();
auto* dl_colors = vertices_->colors();

auto coverage_rect = ToRect(vertices_->bounds());
std::vector<VS::PerVertexData> vertex_data(vertex_count);
for (auto i = 0; i < vertex_count; i++) {
auto dl_color = dl_colors[i];
auto color = Color(dl_color.getRedF(), dl_color.getGreenF(),
dl_color.getBlueF(), dl_color.getAlphaF());
auto sk_point = dl_vertices[i];
auto vertex = Point(sk_point.x(), sk_point.y());
auto coverage_coords = (vertex - coverage_rect.origin) / coverage_rect.size;
vertex_data[i] = {
.vertices = vertex,
.dst_color = color,
.src_texture_coords = coverage_coords / coverage_rect.size,
};
}

size_t total_vtx_bytes = vertex_data.size() * sizeof(VS::PerVertexData);
size_t total_idx_bytes = index_count * sizeof(uint16_t);

DeviceBufferDescriptor buffer_desc;
buffer_desc.size = total_vtx_bytes + total_idx_bytes;
buffer_desc.storage_mode = StorageMode::kHostVisible;

auto buffer =
renderer.GetContext()->GetResourceAllocator()->CreateBuffer(buffer_desc);

if (!buffer->CopyHostBuffer(reinterpret_cast<uint8_t*>(vertex_data.data()),
Range{0, total_vtx_bytes}, 0)) {
return {};
}
if (!buffer->CopyHostBuffer(
reinterpret_cast<uint8_t*>(const_cast<uint16_t*>(dl_indices)),
Range{0, total_idx_bytes}, total_vtx_bytes)) {
return {};
}

return GeometryResult{
.type = GetPrimitiveType(vertices_),
.vertex_buffer =
{
.vertex_buffer = {.buffer = buffer,
.range = Range{0, total_vtx_bytes}},
.index_buffer = {.buffer = buffer,
.range =
Range{total_vtx_bytes, total_idx_bytes}},
.index_count = index_count,
.index_type = IndexType::k16bit,
},
.transform = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
entity.GetTransformation(),
.prevent_overdraw = false,
};
} // namespace impeller

GeometryVertexType DLVerticesGeometry::GetVertexType() const {
auto* dl_colors = vertices_->colors();
Expand Down
4 changes: 1 addition & 3 deletions impeller/display_list/display_list_vertices_geometry.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@ class DLVerticesGeometry : public VerticesGeometry {
// |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 Down
29 changes: 27 additions & 2 deletions impeller/entity/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ impeller_shaders("entity_shaders") {
name = "entity"

shaders = [
"shaders/atlas_fill.frag",
"shaders/atlas_fill.vert",
"shaders/blending/advanced_blend.vert",
"shaders/blending/advanced_blend_color.frag",
"shaders/blending/advanced_blend_colorburn.frag",
Expand Down Expand Up @@ -56,6 +54,33 @@ impeller_shaders("entity_shaders") {
"shaders/srgb_to_linear_filter.frag",
"shaders/srgb_to_linear_filter.vert",
"shaders/sweep_gradient_fill.frag",
"shaders/atlas_blending/atlas_blend.vert",
"shaders/atlas_blending/atlas_advanced_blend_color.frag",
"shaders/atlas_blending/atlas_advanced_blend_colorburn.frag",
"shaders/atlas_blending/atlas_advanced_blend_colordodge.frag",
"shaders/atlas_blending/atlas_advanced_blend_darken.frag",
"shaders/atlas_blending/atlas_advanced_blend_difference.frag",
"shaders/atlas_blending/atlas_advanced_blend_exclusion.frag",
"shaders/atlas_blending/atlas_advanced_blend_hardlight.frag",
"shaders/atlas_blending/atlas_advanced_blend_hue.frag",
"shaders/atlas_blending/atlas_advanced_blend_lighten.frag",
"shaders/atlas_blending/atlas_advanced_blend_luminosity.frag",
"shaders/atlas_blending/atlas_advanced_blend_multiply.frag",
"shaders/atlas_blending/atlas_advanced_blend_overlay.frag",
"shaders/atlas_blending/atlas_advanced_blend_saturation.frag",
"shaders/atlas_blending/atlas_advanced_blend_screen.frag",
"shaders/atlas_blending/atlas_advanced_blend_softlight.frag",
"shaders/atlas_blending/atlas_blend_dst_a_top.frag",
"shaders/atlas_blending/atlas_blend_dst_in.frag",
"shaders/atlas_blending/atlas_blend_dst_out.frag",
"shaders/atlas_blending/atlas_blend_dst_over.frag",
"shaders/atlas_blending/atlas_blend_modulate.frag",
"shaders/atlas_blending/atlas_blend_plus.frag",
"shaders/atlas_blending/atlas_blend_src_a_top.frag",
"shaders/atlas_blending/atlas_blend_src_in.frag",
"shaders/atlas_blending/atlas_blend_src_out.frag",
"shaders/atlas_blending/atlas_blend_src_over.frag",
"shaders/atlas_blending/atlas_blend_xor.frag",
"shaders/texture_fill.frag",
"shaders/texture_fill.vert",
"shaders/tiled_texture_fill.frag",
Expand Down
Loading