Bug 1897783 - Fix incorrect rounding in software rendering of feColorMatrix. r=longsonr

This doesn't fix a similar problem in ArithmeticCombineTwoPixels because the fixes there have performance implications, appear wrong, or are wrong for common inputs.

Since hue-rotate is defined in terms of a color matrix, some tests involving hue-rotate behave slightly differently.

Differential Revision: https://phabricator.services.mozilla.com/D211113
This commit is contained in:
Toby
2024-12-12 15:57:56 +00:00
parent 5cff60b98b
commit e8580fa48b
10 changed files with 80 additions and 20 deletions

View File

@@ -623,7 +623,7 @@ static already_AddRefed<DataSourceSurface> ApplyColorMatrix_SIMD(
Float clampedFloatMatrixElement =
std::clamp(floatMatrixElement, -floatElementMax, floatElementMax);
int16_t scaledIntMatrixElement =
int16_t(clampedFloatMatrixElement * factor + 0.5);
int16_t(floorf(clampedFloatMatrixElement * factor + 0.5));
int8_t bg_or_ra = componentOffsets[rowIndex] / 2;
int8_t g_or_a = componentOffsets[rowIndex] % 2;
int8_t B_or_G_or_R_or_A = componentOffsets[colIndex];
@@ -633,14 +633,19 @@ static already_AddRefed<DataSourceSurface> ApplyColorMatrix_SIMD(
}
int32_t rowBias[4];
Float biasMax = (INT32_MAX - 4 * 255 * INT16_MAX) / (factor * 255);
Float biasMax =
(INT32_MAX - 4 * 255 * INT16_MAX - (factor / 2)) / (factor * 255);
for (size_t colIndex = 0; colIndex < 4; colIndex++) {
size_t rowIndex = 4;
const Float& floatMatrixElement = floats[rowIndex * 4 + colIndex];
Float clampedFloatMatrixElement =
std::clamp(floatMatrixElement, -biasMax, biasMax);
// Add 0.5 before multiplying by factor so that the later bitshift dividing
// by factor is rounding to nearest
Float scaledFloatMatrixElement =
(clampedFloatMatrixElement * 255 + 0.5) * factor;
int32_t scaledIntMatrixElement =
int32_t(clampedFloatMatrixElement * factor * 255 + 0.5);
int32_t(floorf(scaledFloatMatrixElement + 0.5));
rowBias[componentOffsets[colIndex]] = scaledIntMatrixElement;
}

View File

@@ -9,8 +9,8 @@
<link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
<style type="text/css">
#target {
/* The first 8 CSS filter functions result in this color. */
background-color: rgba(118, 153, 44, 0.8);
/* The first 8 CSS filter functions should result in this color. */
background-color: rgba(123.1913, 151.0739, 47.3751, 0.8);
/* Use an equivalent SVG filter for the last 2 CSS filter functions. */
filter: url(#blur-and-drop-shadow);
width: 100px;

View File

@@ -2,6 +2,6 @@
# e.g. filter: blur(3px) grayscale(0.5) invert(0.2);
# Some platforms render this complex filter chain a little differently, and that's ok.
fuzzy(4-10,12000-20260) == long-chain.html long-chain-ref.html # Win10: Bug 1258241
fuzzy(0-10,0-20260) == long-chain.html long-chain-ref.html # Win10: Bug 1258241
== moz-element.html moz-element-ref.html
fuzzy(0-15,0-14056) == same-filter.html same-filter-ref.html

View File

@@ -16,13 +16,13 @@
height: 50px;
}
#color-strip-1 {
background-color: rgb(64, 187, 46);
background-color: rgb(64, 186.716, 45.886);
}
#color-strip-2 {
background-color: rgb(64, 250, 255);
background-color: rgb(64, 250.089, 255);
}
#color-strip-3 {
background-color: rgb(255, 14, 109);
background-color: rgb(255.0, 12.307, 109.872);
}
</style>
</head>

View File

@@ -38,7 +38,7 @@ fuzzy(0-1,0-10000) == grayscale-zero.html grayscale-zero-ref.html
== hue-rotate.html hue-rotate-ref.html
== hue-rotate-360.html hue-rotate-360-ref.html
== hue-rotate-grad.html hue-rotate-grad-ref.html
fuzzy-if(!useDrawSnapshot&&!geckoview,2-2,7500-7500) fuzzy-if(winWidget,0-2,0-7500) == hue-rotate-multichannel.html hue-rotate-multichannel-ref.html
fuzzy(0-2,0-15000) == hue-rotate-multichannel.html hue-rotate-multichannel-ref.html
== hue-rotate-negative.html hue-rotate-negative-ref.html
== hue-rotate-over-360.html hue-rotate-over-360-ref.html
== hue-rotate-rad.html hue-rotate-rad-ref.html
@@ -61,7 +61,7 @@ fuzzy-if(!useDrawSnapshot&&!geckoview,1-1,10000-10000) fuzzy-if(winWidget,0-1,0-
== saturate-extreme.html saturate-extreme-ref.html
== saturate-one.html saturate-one-ref.html
== saturate-percent.html saturate-percent-ref.html
fuzzy-if(!useDrawSnapshot&&!geckoview,1-1,10000-10000) fuzzy-if(winWidget,0-1,0-10000) == saturate-zero.html saturate-zero-ref.html
fuzzy(0-1,0-10000) == saturate-zero.html saturate-zero-ref.html
fuzzy(0-1,0-10000) == sepia.html sepia-ref.html
fuzzy(0-1,0-10000) == sepia-one.html sepia-one-ref.html
fuzzy(0-1,0-10000) == sepia-over-one.html sepia-over-one-ref.html

View File

@@ -9,7 +9,7 @@
<link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
<style type="text/css">
#target {
background-color: rgb(53, 53, 53);
background-color: rgb(54.315, 54.315, 54.315);
width: 100px;
height: 100px;
}

View File

@@ -3,14 +3,14 @@
fuzzy-if(!nogpu&&Android13&&aarch64,128-128,10000-10000) == clip-input.svg clip-input-ref.svg # bug 1918599
== clip-original-SourceGraphic.svg clip-original-SourceGraphic-ref.svg
== clip-output.svg clip-output-ref.svg
fuzzy-if(!useDrawSnapshot&&!Android,0-1,0-10000) == clip-output.svg clip-output-ref.svg
fuzzy(0-5,0-20300) fuzzy-if(Android&&device&&!swgl,5-5,21751-21751) fuzzy-if(gfxSVGFE,0-9,0-1000000) == default-subregion.svg default-subregion-ref.svg
== different-FillPaint-filter-regions.svg different-FillPaint-filter-regions-ref.svg
== different-StrokePaint-filter-regions.svg different-StrokePaint-filter-regions-ref.svg
== dont-clip-previous-primitives.svg dont-clip-previous-primitives-ref.svg
== intersecting-filter-regions.svg intersecting-filter-regions-ref.svg
fuzzy-if(!useDrawSnapshot,9-9,5168-5536) fuzzy-if(!useDrawSnapshot&&swgl,7-7,13170-13184) fuzzy-if(Android&&device&&!swgl,8-8,12391-12391) fuzzy-if(gfxSVGFE,0-9,0-1000000) == long-chain.svg simple-chain-ref.svg
fuzzy-if(!useDrawSnapshot,9-9,5168-5536) fuzzy-if(!useDrawSnapshot&&swgl,7-7,13170-13184) fuzzy-if(Android&&device&&!swgl,8-8,12391-12391) fuzzy-if(gfxSVGFE,0-9,0-1000000) == multiple-primitives-per-filter.svg simple-chain-ref.svg
fuzzy-if(!useDrawSnapshot&&!Android,1-1,40000-40000) == different-FillPaint-filter-regions.svg different-FillPaint-filter-regions-ref.svg
fuzzy-if(!useDrawSnapshot&&!Android,1-1,40000-40000) == different-StrokePaint-filter-regions.svg different-StrokePaint-filter-regions-ref.svg
fuzzy-if(!useDrawSnapshot&&!Android,0-1,0-10000) == dont-clip-previous-primitives.svg dont-clip-previous-primitives-ref.svg
fuzzy-if(!useDrawSnapshot&&!Android,0-1,0-10000) == intersecting-filter-regions.svg intersecting-filter-regions-ref.svg
fuzzy(0-9,0-13180) fuzzy-if(gfxSVGFE,0-9,0-1000000) == long-chain.svg simple-chain-ref.svg
fuzzy(0-9,0-13180) fuzzy-if(gfxSVGFE,0-9,0-1000000) == multiple-primitives-per-filter.svg simple-chain-ref.svg
fuzzy-if(winWidget,0-1,0-173) fuzzy-if(!useDrawSnapshot||(winWidget&&isCoverageBuild),9-9,5128-5496) fuzzy-if(!useDrawSnapshot&&swgl,7-7,12820-12830) fuzzy-if(Android&&device&&!swgl,8-8,12355-12355) fuzzy-if(gfxSVGFE,0-9,0-1000000) == second-filter-uses-SourceAlpha.svg second-filter-uses-SourceAlpha-ref.svg
fuzzy-if(!useDrawSnapshot,9-9,5168-5536) fuzzy-if(!useDrawSnapshot&&swgl,7-7,13170-13180) fuzzy-if(Android&&device&&!swgl,8-8,12391-12391) fuzzy-if(gfxSVGFE,0-9,0-1000000) == second-filter-uses-SourceGraphic.svg simple-chain-ref.svg
fuzzy(0-9,0-13180) fuzzy-if(gfxSVGFE,0-9,0-1000000) == second-filter-uses-SourceGraphic.svg simple-chain-ref.svg
== simple-chain.svg simple-chain-ref.svg

View File

@@ -0,0 +1,2 @@
[svg-image-root-filter.html]
fuzzy: maxDifference=0-1;totalPixels=0-400

View File

@@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<head>
<title>Filter Effects: Test feColorMatrix with negative matrix entries</title>
<link rel="author" title="Toby Cathcart Burn" href="mailto:tcathcartburn@gmail.com">
</head>
<body>
<p>You should see a cyan colored rectangle.</p>
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'>
<rect x='0' y='0' width='100' height='100' fill="#00ffff"></rect>
</svg>
</body>
</html>

View File

@@ -0,0 +1,35 @@
<!DOCTYPE html>
<html>
<head>
<title>Filter Effects: Test feColorMatrix with negative matrix entries</title>
<link rel="author" title="Toby Cathcart Burn" href="mailto:tcathcartburn@gmail.com">
<link rel="help" href="http://www.w3.org/TR/filter-effects-1/#feColorMatrixElement">
<link rel="help" href="http://www.w3.org/TR/filter-effects-1/#element-attrdef-fecolormatrix-type">
<link rel="match" href="fecolormatrix-negative-ref.html">
<meta name="assert" content="If the test runs, you should see a cyan(#00ffff) colored rectangle.">
</head>
<body>
<p>You should see a cyan colored rectangle.</p>
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'>
<defs>
<filter id='invert' color-interpolation-filters='sRGB'>
<feColorMatrix in='SourceGraphic'
values='-1 0 0 0 1
0 -1 0 0 1
0 0 -1 0 1
0 0 0 1 0' result='ef0'>
</feColorMatrix>
<feComposite in='ef0' in2='ef0' operator='arithmetic' k2='255'>
</feComposite>
</filter>
</defs>
<rect x='0' y='0' width='100' height='100' fill="#ffaa00" filter="url(#invert)"></rect>
</svg>
</body>
</html>