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

Commit 35e14c5

Browse files
authored
[Impeller] Add CPU implementations for all color filters (#42692)
Part of flutter/flutter#127232. Adds a CPU implementation for ColorMatrix and the color space conversions. Also changes the blend signature for consistency. These will be necessary to make the mask blur fast path continue working in the presence of color filters. In general, we can use these to eliminate a needlessly expensive image-based color filter for the non-image color sources.
1 parent a2f040e commit 35e14c5

File tree

8 files changed

+367
-260
lines changed

8 files changed

+367
-260
lines changed

impeller/aiks/paint.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ std::shared_ptr<Contents> Paint::WithColorFilter(
102102

103103
/// A color matrix which inverts colors.
104104
// clang-format off
105-
constexpr ColorFilterContents::ColorMatrix kColorInversion = {
105+
constexpr ColorMatrix kColorInversion = {
106106
.array = {
107107
-1.0, 0, 0, 1.0, 0, //
108108
0, -1.0, 0, 1.0, 0, //

impeller/display_list/dl_dispatcher.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,7 @@ static std::optional<Paint::ColorFilterProc> ToColorFilterProc(
491491
}
492492
case flutter::DlColorFilterType::kMatrix: {
493493
const flutter::DlMatrixColorFilter* dl_matrix = filter->asMatrix();
494-
impeller::FilterContents::ColorMatrix color_matrix;
494+
impeller::ColorMatrix color_matrix;
495495
dl_matrix->get_matrix(color_matrix.array);
496496
return [color_matrix](FilterInput::Ref input) {
497497
return ColorFilterContents::MakeColorMatrix({std::move(input)},

impeller/entity/contents/filters/filter_contents.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,6 @@ class FilterContents : public Contents {
2929
kInner,
3030
};
3131

32-
// Domain is kRGBA, we may decide to support more color modes later.
33-
struct ColorMatrix {
34-
float array[20];
35-
};
36-
3732
enum class MorphType { kDilate, kErode };
3833

3934
static std::shared_ptr<FilterContents> MakeDirectionalGaussianBlur(

impeller/entity/entity_unittests.cc

Lines changed: 2 additions & 234 deletions
Original file line numberDiff line numberDiff line change
@@ -1748,7 +1748,7 @@ TEST_P(EntityTest, ColorMatrixFilterCoverageIsCorrect) {
17481748
fill->SetColor(Color::Coral());
17491749

17501750
// Set the color matrix filter.
1751-
FilterContents::ColorMatrix matrix = {
1751+
ColorMatrix matrix = {
17521752
1, 1, 1, 1, 1, //
17531753
1, 1, 1, 1, 1, //
17541754
1, 1, 1, 1, 1, //
@@ -1775,7 +1775,7 @@ TEST_P(EntityTest, ColorMatrixFilterEditable) {
17751775

17761776
auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
17771777
// UI state.
1778-
static FilterContents::ColorMatrix color_matrix = {
1778+
static ColorMatrix color_matrix = {
17791779
1, 0, 0, 0, 0, //
17801780
0, 3, 0, 0, 0, //
17811781
0, 0, 1, 0, 0, //
@@ -1931,238 +1931,6 @@ TEST_P(EntityTest, SrgbToLinearFilter) {
19311931
ASSERT_TRUE(OpenPlaygroundHere(callback));
19321932
}
19331933

1934-
TEST_P(EntityTest, TTTBlendColor) {
1935-
{
1936-
Color src = {1, 0, 0, 0.5};
1937-
Color dst = {1, 0, 1, 1};
1938-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kClear),
1939-
Color(0, 0, 0, 0));
1940-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kSource),
1941-
Color(1, 0, 0, 0.5));
1942-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kDestination),
1943-
Color(1, 0, 1, 1));
1944-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kSourceOver),
1945-
Color(1.5, 0, 0.5, 1));
1946-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kDestinationOver),
1947-
Color(1, 0, 1, 1));
1948-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kSourceIn),
1949-
Color(1, 0, 0, 0.5));
1950-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kDestinationIn),
1951-
Color(0.5, 0, 0.5, 0.5));
1952-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kSourceOut),
1953-
Color(0, 0, 0, 0));
1954-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kDestinationOut),
1955-
Color(0.5, 0, 0.5, 0.5));
1956-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kSourceATop),
1957-
Color(1.5, 0, 0.5, 1));
1958-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kDestinationATop),
1959-
Color(0.5, 0, 0.5, 0.5));
1960-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kXor),
1961-
Color(0.5, 0, 0.5, 0.5));
1962-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kPlus), Color(1, 0, 1, 1));
1963-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kModulate),
1964-
Color(1, 0, 0, 0.5));
1965-
}
1966-
1967-
{
1968-
Color src = {1, 1, 0, 1};
1969-
Color dst = {1, 0, 1, 1};
1970-
1971-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kClear),
1972-
Color(0, 0, 0, 0));
1973-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kSource),
1974-
Color(1, 1, 0, 1));
1975-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kDestination),
1976-
Color(1, 0, 1, 1));
1977-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kSourceOver),
1978-
Color(1, 1, 0, 1));
1979-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kDestinationOver),
1980-
Color(1, 0, 1, 1));
1981-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kSourceIn),
1982-
Color(1, 1, 0, 1));
1983-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kDestinationIn),
1984-
Color(1, 0, 1, 1));
1985-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kSourceOut),
1986-
Color(0, 0, 0, 0));
1987-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kDestinationOut),
1988-
Color(0, 0, 0, 0));
1989-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kSourceATop),
1990-
Color(1, 1, 0, 1));
1991-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kDestinationATop),
1992-
Color(1, 0, 1, 1));
1993-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kXor), Color(0, 0, 0, 0));
1994-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kPlus), Color(1, 1, 1, 1));
1995-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kModulate),
1996-
Color(1, 0, 0, 1));
1997-
}
1998-
1999-
{
2000-
Color src = {1, 1, 0, 0.2};
2001-
Color dst = {1, 1, 1, 0.5};
2002-
2003-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kClear),
2004-
Color(0, 0, 0, 0));
2005-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kSource),
2006-
Color(1, 1, 0, 0.2));
2007-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kDestination),
2008-
Color(1, 1, 1, 0.5));
2009-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kSourceOver),
2010-
Color(1.8, 1.8, 0.8, 0.6));
2011-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kDestinationOver),
2012-
Color(1.5, 1.5, 1, 0.6));
2013-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kSourceIn),
2014-
Color(0.5, 0.5, 0, 0.1));
2015-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kDestinationIn),
2016-
Color(0.2, 0.2, 0.2, 0.1));
2017-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kSourceOut),
2018-
Color(0.5, 0.5, 0, 0.1));
2019-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kDestinationOut),
2020-
Color(0.8, 0.8, 0.8, 0.4));
2021-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kSourceATop),
2022-
Color(1.3, 1.3, 0.8, 0.5));
2023-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kDestinationATop),
2024-
Color(0.7, 0.7, 0.2, 0.2));
2025-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kXor),
2026-
Color(1.3, 1.3, 0.8, 0.5));
2027-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kPlus),
2028-
Color(1, 1, 1, 0.7));
2029-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kModulate),
2030-
Color(1, 1, 0, 0.1));
2031-
}
2032-
2033-
{
2034-
Color src = {1, 0.5, 0, 0.2};
2035-
Color dst = {1, 1, 0.5, 0.5};
2036-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kClear),
2037-
Color(0, 0, 0, 0));
2038-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kSource),
2039-
Color(1, 0.5, 0, 0.2));
2040-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kDestination),
2041-
Color(1, 1, 0.5, 0.5));
2042-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kSourceOver),
2043-
Color(1.8, 1.3, 0.4, 0.6));
2044-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kDestinationOver),
2045-
Color(1.5, 1.25, 0.5, 0.6));
2046-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kSourceIn),
2047-
Color(0.5, 0.25, 0, 0.1));
2048-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kDestinationIn),
2049-
Color(0.2, 0.2, 0.1, 0.1));
2050-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kSourceOut),
2051-
Color(0.5, 0.25, 0, 0.1));
2052-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kDestinationOut),
2053-
Color(0.8, 0.8, 0.4, 0.4));
2054-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kSourceATop),
2055-
Color(1.3, 1.05, 0.4, 0.5));
2056-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kDestinationATop),
2057-
Color(0.7, 0.45, 0.1, 0.2));
2058-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kXor),
2059-
Color(1.3, 1.05, 0.4, 0.5));
2060-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kPlus),
2061-
Color(1, 1, 0.5, 0.7));
2062-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kModulate),
2063-
Color(1, 0.5, 0, 0.1));
2064-
}
2065-
2066-
{
2067-
Color src = {0.5, 0.5, 0, 0.2};
2068-
Color dst = {0, 1, 0.5, 0.5};
2069-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kClear),
2070-
Color(0, 0, 0, 0));
2071-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kSource),
2072-
Color(0.5, 0.5, 0, 0.2));
2073-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kDestination),
2074-
Color(0, 1, 0.5, 0.5));
2075-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kSourceOver),
2076-
Color(0.5, 1.3, 0.4, 0.6));
2077-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kDestinationOver),
2078-
Color(0.25, 1.25, 0.5, 0.6));
2079-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kSourceIn),
2080-
Color(0.25, 0.25, 0, 0.1));
2081-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kDestinationIn),
2082-
Color(0, 0.2, 0.1, 0.1));
2083-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kSourceOut),
2084-
Color(0.25, 0.25, 0, 0.1));
2085-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kDestinationOut),
2086-
Color(0, 0.8, 0.4, 0.4));
2087-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kSourceATop),
2088-
Color(0.25, 1.05, 0.4, 0.5));
2089-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kDestinationATop),
2090-
Color(0.25, 0.45, 0.1, 0.2));
2091-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kXor),
2092-
Color(0.25, 1.05, 0.4, 0.5));
2093-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kPlus),
2094-
Color(0.5, 1, 0.5, 0.7));
2095-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kModulate),
2096-
Color(0, 0.5, 0, 0.1));
2097-
}
2098-
2099-
{
2100-
Color src = {0.5, 0.5, 0.2, 0.2};
2101-
Color dst = {0.2, 1, 0.5, 0.5};
2102-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kClear),
2103-
Color(0, 0, 0, 0));
2104-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kSource),
2105-
Color(0.5, 0.5, 0.2, 0.2));
2106-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kDestination),
2107-
Color(0.2, 1, 0.5, 0.5));
2108-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kSourceOver),
2109-
Color(0.66, 1.3, 0.6, 0.6));
2110-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kDestinationOver),
2111-
Color(0.45, 1.25, 0.6, 0.6));
2112-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kSourceIn),
2113-
Color(0.25, 0.25, 0.1, 0.1));
2114-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kDestinationIn),
2115-
Color(0.04, 0.2, 0.1, 0.1));
2116-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kSourceOut),
2117-
Color(0.25, 0.25, 0.1, 0.1));
2118-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kDestinationOut),
2119-
Color(0.16, 0.8, 0.4, 0.4));
2120-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kSourceATop),
2121-
Color(0.41, 1.05, 0.5, 0.5));
2122-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kDestinationATop),
2123-
Color(0.29, 0.45, 0.2, 0.2));
2124-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kXor),
2125-
Color(0.41, 1.05, 0.5, 0.5));
2126-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kPlus),
2127-
Color(0.7, 1, 0.7, 0.7));
2128-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kModulate),
2129-
Color(0.1, 0.5, 0.1, 0.1));
2130-
}
2131-
2132-
{
2133-
Color src = {0.5, 0.5, 0.2, 0.2};
2134-
Color dst = {0.2, 0.2, 0.5, 0.5};
2135-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kClear),
2136-
Color(0, 0, 0, 0));
2137-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kSource),
2138-
Color(0.5, 0.5, 0.2, 0.2));
2139-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kDestination),
2140-
Color(0.2, 0.2, 0.5, 0.5));
2141-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kSourceOver),
2142-
Color(0.66, 0.66, 0.6, 0.6));
2143-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kDestinationOver),
2144-
Color(0.45, 0.45, 0.6, 0.6));
2145-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kSourceIn),
2146-
Color(0.25, 0.25, 0.1, 0.1));
2147-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kDestinationIn),
2148-
Color(0.04, 0.04, 0.1, 0.1));
2149-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kSourceOut),
2150-
Color(0.25, 0.25, 0.1, 0.1));
2151-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kDestinationOut),
2152-
Color(0.16, 0.16, 0.4, 0.4));
2153-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kSourceATop),
2154-
Color(0.41, 0.41, 0.5, 0.5));
2155-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kDestinationATop),
2156-
Color(0.29, 0.29, 0.2, 0.2));
2157-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kXor),
2158-
Color(0.41, 0.41, 0.5, 0.5));
2159-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kPlus),
2160-
Color(0.7, 0.7, 0.7, 0.7));
2161-
ASSERT_EQ(Color::BlendColor(src, dst, BlendMode::kModulate),
2162-
Color(0.1, 0.1, 0.1, 0.1));
2163-
}
2164-
}
2165-
21661934
TEST_P(EntityTest, AtlasContentsSubAtlas) {
21671935
auto boston = CreateTextureForFixture("boston.jpg");
21681936

impeller/geometry/color.cc

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -199,9 +199,9 @@ static constexpr Color FromRGB(Vector3 color, Scalar alpha) {
199199
return {color.x, color.y, color.z, alpha};
200200
}
201201

202-
Color Color::BlendColor(const Color& src,
203-
const Color& dst,
204-
BlendMode blend_mode) {
202+
Color Color::Blend(const Color& src, BlendMode blend_mode) const {
203+
const Color& dst = *this;
204+
205205
static auto apply_rgb_srcover_alpha = [&](auto f) -> Color {
206206
return Color(f(src.red, dst.red), f(src.green, dst.green),
207207
f(src.blue, dst.blue),
@@ -372,6 +372,38 @@ Color Color::BlendColor(const Color& src,
372372
}
373373
}
374374

375+
Color Color::ApplyColorMatrix(const ColorMatrix& color_matrix) const {
376+
auto* c = color_matrix.array;
377+
return Color(
378+
c[0] * red + c[1] * green + c[2] * blue + c[3] * alpha + c[4],
379+
c[5] * red + c[6] * green + c[7] * blue + c[8] * alpha + c[9],
380+
c[10] * red + c[11] * green + c[12] * blue + c[13] * alpha + c[14],
381+
c[15] * red + c[16] * green + c[17] * blue + c[18] * alpha + c[19])
382+
.Clamp01();
383+
}
384+
385+
Color Color::LinearToSRGB() const {
386+
static auto conversion = [](Scalar component) {
387+
if (component <= 0.0031308) {
388+
return component * 12.92;
389+
}
390+
return 1.055 * pow(component, (1.0 / 2.4)) - 0.055;
391+
};
392+
393+
return Color(conversion(red), conversion(green), conversion(blue), alpha);
394+
}
395+
396+
Color Color::SRGBToLinear() const {
397+
static auto conversion = [](Scalar component) {
398+
if (component <= 0.04045) {
399+
return component / 12.92;
400+
}
401+
return pow((component + 0.055) / 1.055, 2.4);
402+
};
403+
404+
return Color(conversion(red), conversion(green), conversion(blue), alpha);
405+
}
406+
375407
std::string ColorToString(const Color& color) {
376408
return SPrintF("R=%.1f,G=%.1f,B=%.1f,A=%.1f", //
377409
color.red, //

0 commit comments

Comments
 (0)