Commit fe56adee authored by Timothy Nikkel's avatar Timothy Nikkel
Browse files

Bug 1635658. Fix how CSS filters render with webrender that are represented as...

Bug 1635658. Fix how CSS filters render with webrender that are represented as component transfer when they are required to be represented as SVG filters. r=mstange a=pascalc

The brightness, contrast, and invert css filters are represented as component transfer filters when they required to be represented as an svg filter (ie when an element has a combination of CSS and SVG filters specified).

https://hg.mozilla.org/mozilla-central/rev/4f3360c4f104 (bug 1417699) used the value SVG_FECOMPONENTTRANSFER_TYPE_UNKNOWN for the function type in the G and B channels to specify that the R channel function should be used. As we know from https://hg.mozilla.org/mozilla-central/rev/a1ff0af83ad2 (bug 1605223) SVG_FECOMPONENTTRANSFER_TYPE_UNKNOWN is the value we get if the function is not specified, and by spec that is to be interpreted as the identity function.

To fix this use a special function type that is not exposed to content, SVG_FECOMPONENTTRANSFER_SAME_AS_R, when we want to do this optimization. And then teach the webrender filter code to understand it.

Differential Revision: https://phabricator.services.mozilla.com/D74189
parent 8bfb8026
......@@ -799,14 +799,18 @@ static already_AddRefed<FilterNode> FilterNodeFromPrimitiveDescription(
already_AddRefed<FilterNode> operator()(
const ComponentTransferAttributes& aComponentTransfer) {
RefPtr<FilterNode> filters[4]; // one for each FILTER_*_TRANSFER type
bool useRgb = aComponentTransfer.mTypes[kChannelG] ==
SVG_FECOMPONENTTRANSFER_TYPE_UNKNOWN &&
aComponentTransfer.mTypes[kChannelB] ==
SVG_FECOMPONENTTRANSFER_TYPE_UNKNOWN;
MOZ_ASSERT(aComponentTransfer.mTypes[0] !=
SVG_FECOMPONENTTRANSFER_SAME_AS_R);
MOZ_ASSERT(aComponentTransfer.mTypes[3] !=
SVG_FECOMPONENTTRANSFER_SAME_AS_R);
RefPtr<FilterNode> filters[4]; // one for each FILTER_*_TRANSFER type
for (int32_t i = 0; i < 4; i++) {
int32_t inputIndex = useRgb && i < 3 ? 0 : i;
int32_t inputIndex = (aComponentTransfer.mTypes[i] ==
SVG_FECOMPONENTTRANSFER_SAME_AS_R) &&
(i < 3)
? 0
: i;
ConvertComponentTransferFunctionToFilter(aComponentTransfer, inputIndex,
i, mDT, filters[0], filters[1],
filters[2], filters[3]);
......
......@@ -56,6 +56,7 @@ const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_TABLE = 2;
const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_DISCRETE = 3;
const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_LINEAR = 4;
const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_GAMMA = 5;
const unsigned short SVG_FECOMPONENTTRANSFER_SAME_AS_R = 6;
// Blend Mode Values
const unsigned short SVG_FEBLEND_MODE_UNKNOWN = 0;
......@@ -253,8 +254,8 @@ struct ColorMatrixAttributes {
}
};
// If the types for G and B are SVG_FECOMPONENTTRANSFER_TYPE_UNKNOWN,
// assume the R values are RGB - this lets us avoid copies.
// If the types for G and B are SVG_FECOMPONENTTRANSFER_SAME_AS_R,
// use the R channel values - this lets us avoid copies.
const uint32_t kChannelROrRGB = 0;
const uint32_t kChannelG = 1;
const uint32_t kChannelB = 2;
......
<!DOCTYPE html>
<html>
<body>
<svg class="dark" width="400" height="110">
<rect width="300" height="100" style="fill:rgb(0,0,0);" />
</svg>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<style>
.dark {
filter: invert(1) url("#balance-color") ;
}
</style>
</head>
<body>
<svg class="dark" width="400" height="110">
<rect width="300" height="100" style="fill:rgb(255,255,255);" />
</svg>
<svg width="10" height="10">
<defs>
<filter id="balance-color">
<feColorMatrix type="matrix"
values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0">
</feColorMatrix>
</filter>
</defs>
</svg>
</body>
</html>
......@@ -18,6 +18,7 @@ fuzzy-if(Android,0-255,0-30) == clipPath-html-06-extref.xhtml clipPath-html-06-r
== clipPath-html-zoomed-01.xhtml clipPath-html-01-ref.svg
== clipPath-transformed-html-01.xhtml ../pass.svg
== clipPath-transformed-html-02.xhtml ../pass.svg
== css-and-svg-filter-01.html css-and-svg-filter-01-ref.html
== conditions-outer-svg-01.xhtml ../pass.svg
== conditions-outer-svg-02.xhtml ../pass.svg
== dynamic-conditions-outer-svg-01.xhtml ../pass.svg
......
......@@ -126,8 +126,8 @@ nsresult nsCSSFilterInstance::SetAttributesForBrightness(
// Set transfer functions for RGB.
atts.mTypes[kChannelROrRGB] = (uint8_t)SVG_FECOMPONENTTRANSFER_TYPE_LINEAR;
atts.mTypes[kChannelG] = (uint8_t)SVG_FECOMPONENTTRANSFER_TYPE_UNKNOWN;
atts.mTypes[kChannelB] = (uint8_t)SVG_FECOMPONENTTRANSFER_TYPE_UNKNOWN;
atts.mTypes[kChannelG] = (uint8_t)SVG_FECOMPONENTTRANSFER_SAME_AS_R;
atts.mTypes[kChannelB] = (uint8_t)SVG_FECOMPONENTTRANSFER_SAME_AS_R;
float slopeIntercept[2];
slopeIntercept[kComponentTransferSlopeIndex] = value;
slopeIntercept[kComponentTransferInterceptIndex] = intercept;
......@@ -147,8 +147,8 @@ nsresult nsCSSFilterInstance::SetAttributesForContrast(
// Set transfer functions for RGB.
atts.mTypes[kChannelROrRGB] = (uint8_t)SVG_FECOMPONENTTRANSFER_TYPE_LINEAR;
atts.mTypes[kChannelG] = (uint8_t)SVG_FECOMPONENTTRANSFER_TYPE_UNKNOWN;
atts.mTypes[kChannelB] = (uint8_t)SVG_FECOMPONENTTRANSFER_TYPE_UNKNOWN;
atts.mTypes[kChannelG] = (uint8_t)SVG_FECOMPONENTTRANSFER_SAME_AS_R;
atts.mTypes[kChannelB] = (uint8_t)SVG_FECOMPONENTTRANSFER_SAME_AS_R;
float slopeIntercept[2];
slopeIntercept[kComponentTransferSlopeIndex] = value;
slopeIntercept[kComponentTransferInterceptIndex] = intercept;
......@@ -223,8 +223,8 @@ nsresult nsCSSFilterInstance::SetAttributesForInvert(
// Set transfer functions for RGB.
atts.mTypes[kChannelROrRGB] = (uint8_t)SVG_FECOMPONENTTRANSFER_TYPE_TABLE;
atts.mTypes[kChannelG] = (uint8_t)SVG_FECOMPONENTTRANSFER_TYPE_UNKNOWN;
atts.mTypes[kChannelB] = (uint8_t)SVG_FECOMPONENTTRANSFER_TYPE_UNKNOWN;
atts.mTypes[kChannelG] = (uint8_t)SVG_FECOMPONENTTRANSFER_SAME_AS_R;
atts.mTypes[kChannelB] = (uint8_t)SVG_FECOMPONENTTRANSFER_SAME_AS_R;
atts.mValues[kChannelROrRGB].AppendElements(invertTableValues, 2);
atts.mTypes[kChannelA] = (uint8_t)SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY;
......
......@@ -98,6 +98,7 @@ void nsFilterInstance::PaintFilteredFrame(
}
static mozilla::wr::ComponentTransferFuncType FuncTypeToWr(uint8_t aFuncType) {
MOZ_ASSERT(aFuncType != SVG_FECOMPONENTTRANSFER_SAME_AS_R);
switch (aFuncType) {
case SVG_FECOMPONENTTRANSFER_TYPE_TABLE:
return mozilla::wr::ComponentTransferFuncType::Table;
......@@ -288,15 +289,19 @@ bool nsFilterInstance::BuildWebRenderFilters(nsIFrame* aFilteredFrame,
values->AppendElements(attributes.mValues[0]);
filterData.R_values_count = attributes.mValues[0].Length();
filterData.funcG_type = FuncTypeToWr(attributes.mTypes[1]);
size_t indexToUse =
attributes.mTypes[1] == SVG_FECOMPONENTTRANSFER_SAME_AS_R ? 0 : 1;
filterData.funcG_type = FuncTypeToWr(attributes.mTypes[indexToUse]);
size_t G_startindex = values->Length();
values->AppendElements(attributes.mValues[1]);
filterData.G_values_count = attributes.mValues[1].Length();
values->AppendElements(attributes.mValues[indexToUse]);
filterData.G_values_count = attributes.mValues[indexToUse].Length();
filterData.funcB_type = FuncTypeToWr(attributes.mTypes[2]);
indexToUse =
attributes.mTypes[2] == SVG_FECOMPONENTTRANSFER_SAME_AS_R ? 0 : 2;
filterData.funcB_type = FuncTypeToWr(attributes.mTypes[indexToUse]);
size_t B_startindex = values->Length();
values->AppendElements(attributes.mValues[2]);
filterData.B_values_count = attributes.mValues[2].Length();
values->AppendElements(attributes.mValues[indexToUse]);
filterData.B_values_count = attributes.mValues[indexToUse].Length();
filterData.funcA_type = FuncTypeToWr(attributes.mTypes[3]);
size_t A_startindex = values->Length();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment