Skip to content

Commit e664737

Browse files
committed
Use CGStyle-based filters for saturate() and hue-rotate() - dropped frames on fakecake.org
https://bugs.webkit.org/show_bug.cgi?id=293212 rdar://148338705 Reviewed by Sam Weinig. The code in `FEColorMatrix::supportedFilterRenderingModes()` caused fallback to `FilterRenderingMode::Software` for `hue-rotate()` and `saturate()` filters, because we didn't have code that converted these to a color matrix. However, that code exists in ColorMatrix, so we can use it. I attempted to have GraphicsColorMatrix own a ColorMatrix<5, 4>, but that isn't easily IPC-encodable. Instead, add a `ColorMatrix` constructors that takes a span, and make the variadic constructor limited to numeric types. * LayoutTests/css3/filters/effect-blur-hw.html: * LayoutTests/css3/filters/effect-brightness-hw.html: * LayoutTests/css3/filters/effect-combined.html: * LayoutTests/css3/filters/effect-grayscale-hw.html: * LayoutTests/css3/filters/effect-hue-rotate-hw.html: * LayoutTests/css3/filters/effect-hue-rotate.html: * LayoutTests/css3/filters/effect-invert-hw.html: * LayoutTests/css3/filters/effect-opacity-hw.html: * LayoutTests/css3/filters/effect-saturate.html: * LayoutTests/css3/filters/effect-sepia-hw.html: * LayoutTests/css3/filters/invalid-reference-filter-in-chain.html: * LayoutTests/css3/filters/resources/filter-helpers.css: Use image-rendering: crisp-edges to reduce noise on iOS where images get scaled. * LayoutTests/fast/filter-image/filter-image.html: * Source/WebCore/Sources.txt: * Source/WebCore/WebCore.xcodeproj/project.pbxproj: * Source/WebCore/platform/graphics/ColorMatrix.h: (WebCore::ColorMatrix::ColorMatrix): (WebCore::ColorMatrix::data const): (WebCore::to5x4Matrix): * Source/WebCore/platform/graphics/GraphicsStyle.h: * Source/WebCore/platform/graphics/filters/FEColorMatrix.cpp: (WebCore::FEColorMatrix::supportedFilterRenderingModes const): (WebCore::FEColorMatrix::createGraphicsStyle const): * Source/WebCore/platform/graphics/filters/FilterRenderingMode.cpp: Copied from Source/WebCore/platform/graphics/filters/FilterRenderingMode.h. (WebCore::operator<<): Make FilterRenderingMode streamable. * Source/WebCore/platform/graphics/filters/FilterRenderingMode.h: * Source/WebCore/rendering/CSSFilter.cpp: (WebCore::CSSFilter::create): Log the rendering mode. Canonical link: https://commits.webkit.org/295269@main
1 parent d61ab0d commit e664737

23 files changed

+110
-20
lines changed

LayoutTests/css3/filters/effect-blur-hw.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<!DOCTYPE html>
22
<html>
33
<head>
4-
<meta name="fuzzy" content="maxDifference=0-54; totalPixels=0-61800">
4+
<meta name="fuzzy" content="maxDifference=0-99; totalPixels=0-61800">
55
<link rel="stylesheet" href="resources/filter-helpers.css">
66
<style>
77
img {

LayoutTests/css3/filters/effect-brightness-hw.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<!DOCTYPE html>
22
<html>
33
<head>
4-
<meta name="fuzzy" content="maxDifference=0-100; totalPixels=0-41000">
4+
<meta name="fuzzy" content="maxDifference=0-186; totalPixels=0-41100">
55
<link rel="stylesheet" href="resources/filter-helpers.css">
66
<style>
77
img {

LayoutTests/css3/filters/effect-combined.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<!DOCTYPE html>
22
<html>
33
<head>
4-
<meta name="fuzzy" content="maxDifference=0-20; totalPixels=0-600" />
4+
<meta name="fuzzy" content="maxDifference=0-20; totalPixels=0-26400" />
55
<link rel="stylesheet" href="resources/filter-helpers.css">
66
<script src="resources/filter-helpers.js"></script>
77
</head>

LayoutTests/css3/filters/effect-grayscale-hw.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<!DOCTYPE html>
22
<html>
33
<head>
4-
<meta name="fuzzy" content="maxDifference=0-54; totalPixels=0-33000">
4+
<meta name="fuzzy" content="maxDifference=0-99; totalPixels=0-33050">
55
<link rel="stylesheet" href="resources/filter-helpers.css">
66
<style>
77
img {

LayoutTests/css3/filters/effect-hue-rotate-hw.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<!DOCTYPE html>
22
<html>
33
<head>
4-
<meta name="fuzzy" content="maxDifference=0-68; totalPixels=0-22400">
4+
<meta name="fuzzy" content="maxDifference=0-123; totalPixels=0-22400">
55
<link rel="stylesheet" href="resources/filter-helpers.css">
66
<style>
77
img {

LayoutTests/css3/filters/effect-hue-rotate.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<!DOCTYPE html>
22
<html>
33
<head>
4-
<meta name="fuzzy" content="maxDifference=0-48; totalPixels=0-2500">
4+
<meta name="fuzzy" content="maxDifference=0-48; totalPixels=0-55700">
55
<link rel="stylesheet" href="resources/filter-helpers.css">
66
<script src="resources/filter-helpers.js"></script>
77
</head>

LayoutTests/css3/filters/effect-invert-hw.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<!DOCTYPE html>
22
<html>
33
<head>
4-
<meta name="fuzzy" content="maxDifference=0-54; totalPixels=0-40300" />
4+
<meta name="fuzzy" content="maxDifference=0-99; totalPixels=0-40410" />
55
<link rel="stylesheet" href="resources/filter-helpers.css">
66
<style>
77
img {

LayoutTests/css3/filters/effect-opacity-hw.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<!DOCTYPE html>
22
<html>
33
<head>
4-
<meta name="fuzzy" content="maxDifference=0-54; totalPixels=0-29200">
4+
<meta name="fuzzy" content="maxDifference=0-99; totalPixels=0-29200">
55
<link rel="stylesheet" href="resources/filter-helpers.css">
66
<style>
77
img {

LayoutTests/css3/filters/effect-saturate.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<!DOCTYPE html>
22
<html>
33
<head>
4-
<meta name="fuzzy" content="maxDifference=0-48; totalPixels=0-2500">
4+
<meta name="fuzzy" content="maxDifference=0-48; totalPixels=0-33200">
55
<link rel="stylesheet" href="resources/filter-helpers.css">
66
<script src="resources/filter-helpers.js"></script>
77
</head>

LayoutTests/css3/filters/effect-sepia-hw.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<!DOCTYPE html>
22
<html>
33
<head>
4-
<meta name="fuzzy" content="maxDifference=0-54; totalPixels=0-36800">
4+
<meta name="fuzzy" content="maxDifference=0-99; totalPixels=0-36800">
55
<link rel="stylesheet" href="resources/filter-helpers.css">
66
<style>
77
img {

LayoutTests/css3/filters/invalid-reference-filter-in-chain.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!DOCTYPE html>
2-
<meta name="fuzzy" content="maxDifference=1; totalPixels=25600" />
2+
<meta name="fuzzy" content="maxDifference=0-1; totalPixels=0-40000" />
33
<html>
44
<head>
55
<style>

LayoutTests/css3/filters/resources/filter-helpers.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
img {
22
margin: 10px;
3+
image-rendering: crisp-edges;
34
}
45

56
svg {

LayoutTests/fast/filter-image/filter-image.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<!DOCTYPE html>
22
<html lang="en">
33
<head>
4-
<meta name="fuzzy" content="maxDifference=0-1; totalPixels=0-5000" />
4+
<meta name="fuzzy" content="maxDifference=0-1; totalPixels=0-7500" />
55
<style>
66
div {
77
width: 50px;

Source/WebCore/Sources.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2611,6 +2611,7 @@ platform/graphics/filters/FilterFunction.cpp
26112611
platform/graphics/filters/FilterImage.cpp
26122612
platform/graphics/filters/FilterOperation.cpp
26132613
platform/graphics/filters/FilterOperations.cpp
2614+
platform/graphics/filters/FilterRenderingMode.cpp
26142615
platform/graphics/filters/FilterResults.cpp
26152616
platform/graphics/filters/PointLightSource.cpp
26162617
platform/graphics/filters/SourceAlpha.cpp

Source/WebCore/WebCore.xcodeproj/project.pbxproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7464,6 +7464,7 @@
74647464
0E7058ED1BC5BC190045A507 /* SearchPopupMenuCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SearchPopupMenuCocoa.mm; sourceTree = "<group>"; };
74657465
0E7058F31BC5CCD70045A507 /* SearchPopupMenuCocoa.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SearchPopupMenuCocoa.h; sourceTree = "<group>"; };
74667466
0E9C1155291BF3CC00A2C2F2 /* ScreenDataOverrides.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ScreenDataOverrides.h; sourceTree = "<group>"; };
7467+
0F0213B92DDA4E9000360760 /* FilterRenderingMode.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FilterRenderingMode.cpp; sourceTree = "<group>"; };
74677468
0F02245026F15D5F000265C3 /* ScrollbarsController.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ScrollbarsController.cpp; sourceTree = "<group>"; };
74687469
0F02245226F15D5F000265C3 /* ScrollbarsController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ScrollbarsController.h; sourceTree = "<group>"; };
74697470
0F02245326F15D75000265C3 /* ScrollbarsControllerMac.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ScrollbarsControllerMac.mm; sourceTree = "<group>"; };
@@ -32140,6 +32141,7 @@
3214032141
49ECEB641499790D00CDD3A4 /* FilterOperation.h */,
3214132142
49ECEB651499790D00CDD3A4 /* FilterOperations.cpp */,
3214232143
49ECEB661499790D00CDD3A4 /* FilterOperations.h */,
32144+
0F0213B92DDA4E9000360760 /* FilterRenderingMode.cpp */,
3214332145
727003E5292F2DBB0094C64B /* FilterRenderingMode.h */,
3214432146
724DCF1D28485C330026ACF4 /* FilterResults.cpp */,
3214532147
7211B5D6276536820076FEF8 /* FilterResults.h */,

Source/WebCore/platform/graphics/ColorMatrix.h

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,21 @@ template<typename, size_t> struct ColorComponents;
3535
template<size_t ColumnCount, size_t RowCount>
3636
class ColorMatrix {
3737
public:
38-
template<typename ...Ts>
38+
explicit constexpr ColorMatrix(std::span<const float, RowCount * ColumnCount> s)
39+
{
40+
std::ranges::copy(s, m_matrix.begin());
41+
}
42+
43+
template<std::convertible_to<float> ...Ts>
3944
explicit constexpr ColorMatrix(Ts ...input)
4045
: m_matrix {{ static_cast<float>(input) ... }}
4146
{
4247
static_assert(sizeof...(Ts) == RowCount * ColumnCount);
4348
}
4449

50+
template<size_t ToColumnCount, size_t ToRowCount>
51+
constexpr operator ColorMatrix<ToColumnCount, ToRowCount>() const;
52+
4553
template<size_t NumberOfComponents>
4654
constexpr ColorComponents<float, NumberOfComponents> transformedColorComponents(const ColorComponents<float, NumberOfComponents>&) const;
4755

@@ -50,12 +58,24 @@ class ColorMatrix {
5058
return m_matrix[(row * ColumnCount) + column];
5159
}
5260

61+
const std::array<float, RowCount * ColumnCount>& data() const { return m_matrix; }
62+
5363
friend bool operator==(const ColorMatrix&, const ColorMatrix&) = default;
5464

5565
private:
5666
std::array<float, RowCount * ColumnCount> m_matrix;
5767
};
5868

69+
template <> template <> constexpr ColorMatrix<3, 3>::operator ColorMatrix<5, 4>() const
70+
{
71+
return ColorMatrix<5, 4> {
72+
at(0, 0), at(0, 1), at(0, 2), 0, 0,
73+
at(1, 0), at(1, 1), at(1, 2), 0, 0,
74+
at(2, 0), at(2, 1), at(2, 2), 0, 0,
75+
0, 0, 0, 1, 0
76+
};
77+
}
78+
5979
constexpr ColorMatrix<3, 3> brightnessColorMatrix(float amount)
6080
{
6181
// Brightness is specified as a component transfer function: https://www.w3.org/TR/filter-effects-1/#brightnessEquivalent

Source/WebCore/platform/graphics/GraphicsStyle.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ struct GraphicsGaussianBlur {
6666
};
6767

6868
struct GraphicsColorMatrix {
69-
std::array<float, 20> values;
69+
std::array<float, 20> values; // Really a ColorMatrix<5, 4>.
7070

7171
friend bool operator==(const GraphicsColorMatrix&, const GraphicsColorMatrix&) = default;
7272
};

Source/WebCore/platform/graphics/filters/FEColorMatrix.cpp

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,9 @@ OptionSet<FilterRenderingMode> FEColorMatrix::supportedFilterRenderingModes() co
132132
modes.add(FilterRenderingMode::Accelerated);
133133
#endif
134134
#if HAVE(CGSTYLE_COLORMATRIX_BLUR)
135-
if (m_type == ColorMatrixType::FECOLORMATRIX_TYPE_MATRIX)
135+
if (m_type == ColorMatrixType::FECOLORMATRIX_TYPE_MATRIX
136+
|| m_type == ColorMatrixType::FECOLORMATRIX_TYPE_SATURATE
137+
|| m_type == ColorMatrixType::FECOLORMATRIX_TYPE_HUEROTATE)
136138
modes.add(FilterRenderingMode::GraphicsContext);
137139
#endif
138140
return modes;
@@ -160,9 +162,25 @@ std::unique_ptr<FilterEffectApplier> FEColorMatrix::createSoftwareApplier() cons
160162

161163
std::optional<GraphicsStyle> FEColorMatrix::createGraphicsStyle(GraphicsContext&, const Filter&) const
162164
{
163-
std::array<float, 20> values;
164-
std::copy_n(m_values.begin(), std::min<size_t>(m_values.size(), 20), values.begin());
165-
return GraphicsColorMatrix { values };
165+
switch (m_type) {
166+
case ColorMatrixType::FECOLORMATRIX_TYPE_MATRIX: {
167+
RELEASE_ASSERT(m_values.size() == 20);
168+
GraphicsColorMatrix result;
169+
std::copy_n(m_values.begin(), std::min<size_t>(m_values.size(), 20), result.values.begin());
170+
return result;
171+
}
172+
case ColorMatrixType::FECOLORMATRIX_TYPE_SATURATE:
173+
return GraphicsColorMatrix { ColorMatrix<5, 4>(saturationColorMatrix(m_values[0])).data() };
174+
175+
case ColorMatrixType::FECOLORMATRIX_TYPE_HUEROTATE:
176+
return GraphicsColorMatrix { ColorMatrix<5, 4>(hueRotateColorMatrix(m_values[0])).data() };
177+
178+
default:
179+
ASSERT_NOT_REACHED();
180+
break;
181+
}
182+
183+
return { };
166184
}
167185

168186
static TextStream& operator<<(TextStream& ts, const ColorMatrixType& type)
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright (C) 2025 Apple Inc. All rights reserved.
3+
*
4+
* Redistribution and use in source and binary forms, with or without
5+
* modification, are permitted provided that the following conditions
6+
* are met:
7+
* 1. Redistributions of source code must retain the above copyright
8+
* notice, this list of conditions and the following disclaimer.
9+
* 2. Redistributions in binary form must reproduce the above copyright
10+
* notice, this list of conditions and the following disclaimer in the
11+
* documentation and/or other materials provided with the distribution.
12+
*
13+
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14+
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16+
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17+
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18+
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19+
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20+
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21+
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24+
*/
25+
26+
#include "config.h"
27+
#include "FilterRenderingMode.h"
28+
29+
namespace WebCore {
30+
31+
TextStream& operator<<(TextStream& ts, FilterRenderingMode mode)
32+
{
33+
switch (mode) {
34+
case FilterRenderingMode::Software: ts << "Software"; break;
35+
case FilterRenderingMode::Accelerated: ts << "Accelerated"; break;
36+
case FilterRenderingMode::GraphicsContext: ts << "GraphicsContext"; break;
37+
}
38+
39+
return ts;
40+
}
41+
42+
43+
} // namespace WebCore

Source/WebCore/platform/graphics/filters/FilterRenderingMode.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,6 @@ constexpr OptionSet<FilterRenderingMode> allFilterRenderingModes = {
4141
FilterRenderingMode::GraphicsContext
4242
};
4343

44+
WTF::TextStream& operator<<(WTF::TextStream&, FilterRenderingMode);
45+
4446
} // namespace WebCore

Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "GLContext.h"
3636
#include "ImageBuffer.h"
3737
#include "IntRect.h"
38+
#include "NativeImage.h"
3839
#include "NotImplemented.h"
3940
#include "PlatformDisplay.h"
4041
#include "ProcessCapabilities.h"

Source/WebCore/platform/gtk/DragImageGtk.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include "Element.h"
2323
#include "Image.h"
24+
#include "NativeImage.h"
2425
#include "TextFlags.h"
2526
#include "TextIndicator.h"
2627
#include <cairo.h>

Source/WebCore/rendering/CSSFilter.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,10 @@ RefPtr<CSSFilter> CSSFilter::create(RenderElement& renderer, const FilterOperati
5959
return nullptr;
6060
}
6161

62-
LOG_WITH_STREAM(Filters, stream << "CSSFilter::create built filter " << filter.get() << " for " << operations);
63-
6462
filter->setFilterRenderingModes(preferredFilterRenderingModes);
63+
64+
LOG_WITH_STREAM(Filters, stream << "CSSFilter::create built filter " << filter.get() << " for " << operations << " supported rendering mode(s) " << filter->filterRenderingModes());
65+
6566
return filter;
6667
}
6768

0 commit comments

Comments
 (0)