Backed out changeset ec84f8196c4c (bug 1689316) for regressing macOS font rendering.

This commit is contained in:
Ryan VanderMeulen 2021-01-28 20:59:25 -05:00
Родитель f9ad45c76b
Коммит 06dbf167c9
11 изменённых файлов: 748 добавлений и 526 удалений

Просмотреть файл

@ -203,29 +203,41 @@ vec4 ComponentTransfer(vec4 colora) {
// Linear/Gamma are a simple calculation.
int offset = 0;
vec4 texel;
int k;
for (int i = 0; i < 4; i++) {
if (vFuncs[i] == COMPONENT_TRANSFER_IDENTITY) {
} else if (vFuncs[i] == COMPONENT_TRANSFER_TABLE ||
vFuncs[i] == COMPONENT_TRANSFER_DISCRETE) {
// fetch value from lookup table
int k = int(floor(colora[i]*255.0));
texel = fetch_from_gpu_cache_1(v_table_address + offset + k/4);
colora[i] = clamp(texel[k % 4], 0.0, 1.0);
// offset plus 256/4 blocks
offset = offset + 64;
} else if (vFuncs[i] == COMPONENT_TRANSFER_LINEAR) {
// fetch the two values for use in the linear equation
texel = fetch_from_gpu_cache_1(v_table_address + offset);
colora[i] = clamp(texel[0] * colora[i] + texel[1], 0.0, 1.0);
// offset plus 1 block
offset = offset + 1;
} else if (vFuncs[i] == COMPONENT_TRANSFER_GAMMA) {
// fetch the three values for use in the gamma equation
texel = fetch_from_gpu_cache_1(v_table_address + offset);
colora[i] = clamp(texel[0] * pow(colora[i], texel[1]) + texel[2], 0.0, 1.0);
// offset plus 1 block
offset = offset + 1;
switch (vFuncs[i]) {
case COMPONENT_TRANSFER_IDENTITY:
break;
case COMPONENT_TRANSFER_TABLE:
case COMPONENT_TRANSFER_DISCRETE: {
// fetch value from lookup table
k = int(floor(colora[i]*255.0));
texel = fetch_from_gpu_cache_1(v_table_address + offset + k/4);
colora[i] = clamp(texel[k % 4], 0.0, 1.0);
// offset plus 256/4 blocks
offset = offset + 64;
break;
}
case COMPONENT_TRANSFER_LINEAR: {
// fetch the two values for use in the linear equation
texel = fetch_from_gpu_cache_1(v_table_address + offset);
colora[i] = clamp(texel[0] * colora[i] + texel[1], 0.0, 1.0);
// offset plus 1 block
offset = offset + 1;
break;
}
case COMPONENT_TRANSFER_GAMMA: {
// fetch the three values for use in the gamma equation
texel = fetch_from_gpu_cache_1(v_table_address + offset);
colora[i] = clamp(texel[0] * pow(colora[i], texel[1]) + texel[2], 0.0, 1.0);
// offset plus 1 block
offset = offset + 1;
break;
}
default:
// shouldn't happen
break;
}
}
return colora;
@ -243,31 +255,40 @@ Fragment brush_fs() {
float alpha = Cs.a;
vec3 color = alpha != 0.0 ? Cs.rgb / alpha : Cs.rgb;
if (v_op == FILTER_CONTRAST) {
color = Contrast(color, v_amount);
} else if (v_op == FILTER_INVERT) {
color = Invert(color, v_amount);
} else if (v_op == FILTER_BRIGHTNESS) {
color = Brightness(color, v_amount);
} else if (v_op == FILTER_SRGB_TO_LINEAR) {
color = SrgbToLinear(color);
} else if (v_op == FILTER_LINEAR_TO_SRGB) {
color = LinearToSrgb(color);
} else if (v_op == FILTER_COMPONENT_TRANSFER) {
// Get the unpremultiplied color with alpha.
vec4 colora = vec4(color, alpha);
colora = ComponentTransfer(colora);
color = colora.rgb;
alpha = colora.a;
} else if (v_op == FILTER_FLOOD) {
color = v_color_offset.rgb;
alpha = v_color_offset.a;
} else {
// Color matrix type filters (sepia, hue-rotate, etc...)
vec4 result = vColorMat * vec4(color, alpha) + v_color_offset;
result = clamp(result, vec4(0.0), vec4(1.0));
color = result.rgb;
alpha = result.a;
switch (v_op) {
case FILTER_CONTRAST:
color = Contrast(color, v_amount);
break;
case FILTER_INVERT:
color = Invert(color, v_amount);
break;
case FILTER_BRIGHTNESS:
color = Brightness(color, v_amount);
break;
case FILTER_SRGB_TO_LINEAR:
color = SrgbToLinear(color);
break;
case FILTER_LINEAR_TO_SRGB:
color = LinearToSrgb(color);
break;
case FILTER_COMPONENT_TRANSFER: {
// Get the unpremultiplied color with alpha.
vec4 colora = vec4(color, alpha);
colora = ComponentTransfer(colora);
color = colora.rgb;
alpha = colora.a;
break;
}
case FILTER_FLOOD:
color = v_color_offset.rgb;
alpha = v_color_offset.a;
break;
default:
// Color matrix type filters (sepia, hue-rotate, etc...)
vec4 result = vColorMat * vec4(color, alpha) + v_color_offset;
result = clamp(result, vec4(0.0), vec4(1.0));
color = result.rgb;
alpha = result.a;
}
#ifdef WR_FEATURE_ALPHA_PASS

Просмотреть файл

@ -193,11 +193,16 @@ void brush_vs(
// Derive the texture coordinates for this image, based on
// whether the source image is a local-space or screen-space
// image.
if (raster_space == RASTER_SCREEN) {
// Since the screen space UVs specify an arbitrary quad, do
// a bilinear interpolation to get the correct UV for this
// local position.
f = get_image_quad_uv(specific_resource_address, f);
switch (raster_space) {
case RASTER_SCREEN: {
// Since the screen space UVs specify an arbitrary quad, do
// a bilinear interpolation to get the correct UV for this
// local position.
f = get_image_quad_uv(specific_resource_address, f);
break;
}
default:
break;
}
#endif
@ -227,31 +232,41 @@ void brush_vs(
v_tile_repeat = repeat.xy;
float opacity = float(prim_user_data.z) / 65535.0;
if (blend_mode == BLEND_MODE_ALPHA) {
image_data.color.a *= opacity;
} else { // blend_mode == BLEND_MODE_PREMUL_ALPHA
image_data.color *= opacity;
switch (blend_mode) {
case BLEND_MODE_ALPHA:
image_data.color.a *= opacity;
break;
case BLEND_MODE_PREMUL_ALPHA:
default:
image_data.color *= opacity;
break;
}
if (color_mode == COLOR_MODE_ALPHA || color_mode == COLOR_MODE_BITMAP) {
v_mask_swizzle = vec2(0.0, 1.0);
v_color = image_data.color;
} else if (color_mode == COLOR_MODE_SUBPX_BG_PASS2 ||
color_mode == COLOR_MODE_SUBPX_DUAL_SOURCE ||
color_mode == COLOR_MODE_IMAGE) {
v_mask_swizzle = vec2(1.0, 0.0);
v_color = image_data.color;
} else if (color_mode == COLOR_MODE_SUBPX_CONST_COLOR ||
color_mode == COLOR_MODE_SUBPX_BG_PASS0 ||
color_mode == COLOR_MODE_COLOR_BITMAP) {
v_mask_swizzle = vec2(1.0, 0.0);
v_color = vec4(image_data.color.a);
} else if (color_mode == COLOR_MODE_SUBPX_BG_PASS1) {
v_mask_swizzle = vec2(-1.0, 1.0);
v_color = vec4(image_data.color.a) * image_data.background_color;
} else {
v_mask_swizzle = vec2(0.0);
v_color = vec4(1.0);
switch (color_mode) {
case COLOR_MODE_ALPHA:
case COLOR_MODE_BITMAP:
v_mask_swizzle = vec2(0.0, 1.0);
v_color = image_data.color;
break;
case COLOR_MODE_SUBPX_BG_PASS2:
case COLOR_MODE_SUBPX_DUAL_SOURCE:
case COLOR_MODE_IMAGE:
v_mask_swizzle = vec2(1.0, 0.0);
v_color = image_data.color;
break;
case COLOR_MODE_SUBPX_CONST_COLOR:
case COLOR_MODE_SUBPX_BG_PASS0:
case COLOR_MODE_COLOR_BITMAP:
v_mask_swizzle = vec2(1.0, 0.0);
v_color = vec4(image_data.color.a);
break;
case COLOR_MODE_SUBPX_BG_PASS1:
v_mask_swizzle = vec2(-1.0, 1.0);
v_color = vec4(image_data.color.a) * image_data.background_color;
break;
default:
v_mask_swizzle = vec2(0.0);
v_color = vec4(1.0);
}
v_local_pos = vi.local_pos;

Просмотреть файл

@ -225,43 +225,60 @@ Fragment brush_fs() {
// Return yellow if none of the branches match (shouldn't happen).
vec4 result = vec4(1.0, 1.0, 0.0, 1.0);
if (v_op == MixBlendMode_Multiply) {
result.rgb = Multiply(Cb.rgb, Cs.rgb);
} else if (v_op == MixBlendMode_Screen) {
result.rgb = Screen(Cb.rgb, Cs.rgb);
} else if (v_op == MixBlendMode_Overlay) {
// Overlay is inverse of Hardlight
result.rgb = HardLight(Cs.rgb, Cb.rgb);
} else if (v_op == MixBlendMode_Darken) {
result.rgb = min(Cs.rgb, Cb.rgb);
} else if (v_op == MixBlendMode_Lighten) {
result.rgb = max(Cs.rgb, Cb.rgb);
} else if (v_op == MixBlendMode_ColorDodge) {
result.r = ColorDodge(Cb.r, Cs.r);
result.g = ColorDodge(Cb.g, Cs.g);
result.b = ColorDodge(Cb.b, Cs.b);
} else if (v_op == MixBlendMode_ColorBurn) {
result.r = ColorBurn(Cb.r, Cs.r);
result.g = ColorBurn(Cb.g, Cs.g);
result.b = ColorBurn(Cb.b, Cs.b);
} else if (v_op == MixBlendMode_HardLight) {
result.rgb = HardLight(Cb.rgb, Cs.rgb);
} else if (v_op == MixBlendMode_SoftLight) {
result.r = SoftLight(Cb.r, Cs.r);
result.g = SoftLight(Cb.g, Cs.g);
result.b = SoftLight(Cb.b, Cs.b);
} else if (v_op == MixBlendMode_Difference) {
result.rgb = Difference(Cb.rgb, Cs.rgb);
} else if (v_op == MixBlendMode_Exclusion) {
result.rgb = Exclusion(Cb.rgb, Cs.rgb);
} else if (v_op == MixBlendMode_Hue) {
result.rgb = Hue(Cb.rgb, Cs.rgb);
} else if (v_op == MixBlendMode_Saturation) {
result.rgb = Saturation(Cb.rgb, Cs.rgb);
} else if (v_op == MixBlendMode_Color) {
result.rgb = Color(Cb.rgb, Cs.rgb);
} else if (v_op == MixBlendMode_Luminosity) {
result.rgb = Luminosity(Cb.rgb, Cs.rgb);
switch (v_op) {
case MixBlendMode_Multiply:
result.rgb = Multiply(Cb.rgb, Cs.rgb);
break;
case MixBlendMode_Screen:
result.rgb = Screen(Cb.rgb, Cs.rgb);
break;
case MixBlendMode_Overlay:
// Overlay is inverse of Hardlight
result.rgb = HardLight(Cs.rgb, Cb.rgb);
break;
case MixBlendMode_Darken:
result.rgb = min(Cs.rgb, Cb.rgb);
break;
case MixBlendMode_Lighten:
result.rgb = max(Cs.rgb, Cb.rgb);
break;
case MixBlendMode_ColorDodge:
result.r = ColorDodge(Cb.r, Cs.r);
result.g = ColorDodge(Cb.g, Cs.g);
result.b = ColorDodge(Cb.b, Cs.b);
break;
case MixBlendMode_ColorBurn:
result.r = ColorBurn(Cb.r, Cs.r);
result.g = ColorBurn(Cb.g, Cs.g);
result.b = ColorBurn(Cb.b, Cs.b);
break;
case MixBlendMode_HardLight:
result.rgb = HardLight(Cb.rgb, Cs.rgb);
break;
case MixBlendMode_SoftLight:
result.r = SoftLight(Cb.r, Cs.r);
result.g = SoftLight(Cb.g, Cs.g);
result.b = SoftLight(Cb.b, Cs.b);
break;
case MixBlendMode_Difference:
result.rgb = Difference(Cb.rgb, Cs.rgb);
break;
case MixBlendMode_Exclusion:
result.rgb = Exclusion(Cb.rgb, Cs.rgb);
break;
case MixBlendMode_Hue:
result.rgb = Hue(Cb.rgb, Cs.rgb);
break;
case MixBlendMode_Saturation:
result.rgb = Saturation(Cb.rgb, Cs.rgb);
break;
case MixBlendMode_Color:
result.rgb = Color(Cb.rgb, Cs.rgb);
break;
case MixBlendMode_Luminosity:
result.rgb = Luminosity(Cb.rgb, Cs.rgb);
break;
default: break;
}
result.rgb = (1.0 - Cb.a) * Cs.rgb + Cb.a * result.rgb;

Просмотреть файл

@ -89,12 +89,15 @@ void main(void) {
vGaussCoefficients = vec2(1.0, 1.0);
}
if (aBlurDirection == DIR_HORIZONTAL) {
vOffsetScale = vec2(1.0 / texture_size.x, 0.0);
} else if (aBlurDirection == DIR_VERTICAL) {
vOffsetScale = vec2(0.0, 1.0 / texture_size.y);
} else {
vOffsetScale = vec2(0.0);
switch (aBlurDirection) {
case DIR_HORIZONTAL:
vOffsetScale = vec2(1.0 / texture_size.x, 0.0);
break;
case DIR_VERTICAL:
vOffsetScale = vec2(0.0, 1.0 / texture_size.y);
break;
default:
vOffsetScale = vec2(0.0);
}
vUvRect = vec4(src_rect.p0 + vec2(0.5),

Просмотреть файл

@ -85,17 +85,23 @@ PER_INSTANCE in vec4 aClipParams2;
vec2 get_outer_corner_scale(int segment) {
vec2 p;
if (segment == SEGMENT_TOP_LEFT) {
p = vec2(0.0, 0.0);
} else if (segment == SEGMENT_TOP_RIGHT) {
p = vec2(1.0, 0.0);
} else if (segment == SEGMENT_BOTTOM_RIGHT) {
p = vec2(1.0, 1.0);
} else if (segment == SEGMENT_BOTTOM_LEFT) {
p = vec2(0.0, 1.0);
} else {
// The result is only used for non-default segment cases
p = vec2(0.0);
switch (segment) {
case SEGMENT_TOP_LEFT:
p = vec2(0.0, 0.0);
break;
case SEGMENT_TOP_RIGHT:
p = vec2(1.0, 0.0);
break;
case SEGMENT_BOTTOM_RIGHT:
p = vec2(1.0, 1.0);
break;
case SEGMENT_BOTTOM_LEFT:
p = vec2(0.0, 1.0);
break;
default:
// The result is only used for non-default segment cases
p = vec2(0.0);
break;
}
return p;
@ -128,15 +134,19 @@ vec4[2] get_colors_for_side(vec4 color, int style) {
bool is_black = color.rgb == vec3(0.0, 0.0, 0.0);
if (style == BORDER_STYLE_GROOVE) {
result[0] = mod_color(color, is_black, true);
result[1] = mod_color(color, is_black, false);
} else if (style == BORDER_STYLE_RIDGE) {
result[0] = mod_color(color, is_black, false);
result[1] = mod_color(color, is_black, true);
} else {
result[0] = color;
result[1] = color;
switch (style) {
case BORDER_STYLE_GROOVE:
result[0] = mod_color(color, is_black, true);
result[1] = mod_color(color, is_black, false);
break;
case BORDER_STYLE_RIDGE:
result[0] = mod_color(color, is_black, false);
result[1] = mod_color(color, is_black, true);
break;
default:
result[0] = color;
result[1] = color;
break;
}
return result;
@ -158,20 +168,31 @@ void main(void) {
// Derive the positions for the edge clips, which must be handled
// differently between corners and edges.
vec2 edge_reference = vec2(0.0);
if (segment == SEGMENT_TOP_LEFT) {
edge_axis = ivec2(0, 1);
edge_reference = outer;
} else if (segment == SEGMENT_TOP_RIGHT) {
edge_axis = ivec2(1, 0);
edge_reference = vec2(outer.x - aWidths.x, outer.y);
} else if (segment == SEGMENT_BOTTOM_RIGHT) {
edge_axis = ivec2(0, 1);
edge_reference = outer - aWidths;
} else if (segment == SEGMENT_BOTTOM_LEFT) {
edge_axis = ivec2(1, 0);
edge_reference = vec2(outer.x, outer.y - aWidths.y);
} else if (segment == SEGMENT_TOP || segment == SEGMENT_BOTTOM) {
edge_axis = ivec2(1, 1);
switch (segment) {
case SEGMENT_TOP_LEFT:
edge_axis = ivec2(0, 1);
edge_reference = outer;
break;
case SEGMENT_TOP_RIGHT:
edge_axis = ivec2(1, 0);
edge_reference = vec2(outer.x - aWidths.x, outer.y);
break;
case SEGMENT_BOTTOM_RIGHT:
edge_axis = ivec2(0, 1);
edge_reference = outer - aWidths;
break;
case SEGMENT_BOTTOM_LEFT:
edge_axis = ivec2(1, 0);
edge_reference = vec2(outer.x, outer.y - aWidths.y);
break;
case SEGMENT_TOP:
case SEGMENT_BOTTOM:
edge_axis = ivec2(1, 1);
break;
case SEGMENT_LEFT:
case SEGMENT_RIGHT:
default:
break;
}
vConfig = ivec4(
@ -236,42 +257,46 @@ vec4 evaluate_color_for_style_in_corner(
int segment,
float aa_range
) {
if (style == BORDER_STYLE_DOUBLE) {
// Get the distances from 0.33 of the radii, and
// also 0.67 of the radii. Use these to form a
// SDF subtraction which will clip out the inside
// third of the rounded edge.
float d_radii_a = distance_to_ellipse(
clip_relative_pos,
clip_radii.xy - vPartialWidths.xy
);
float d_radii_b = distance_to_ellipse(
clip_relative_pos,
clip_radii.xy - 2.0 * vPartialWidths.xy
);
float d = min(-d_radii_a, d_radii_b);
color0 *= distance_aa(aa_range, d);
} else if (style == BORDER_STYLE_GROOVE || style == BORDER_STYLE_RIDGE) {
float d = distance_to_ellipse(
clip_relative_pos,
clip_radii.xy - vPartialWidths.zw
);
float alpha = distance_aa(aa_range, d);
float swizzled_factor;
if (segment == SEGMENT_TOP_LEFT) {
swizzled_factor = 0.0;
} else if (segment == SEGMENT_TOP_RIGHT) {
swizzled_factor = mix_factor;
} else if (segment == SEGMENT_BOTTOM_RIGHT) {
swizzled_factor = 1.0;
} else if (segment == SEGMENT_BOTTOM_LEFT) {
swizzled_factor = 1.0 - mix_factor;
} else {
swizzled_factor = 0.0;
switch (style) {
case BORDER_STYLE_DOUBLE: {
// Get the distances from 0.33 of the radii, and
// also 0.67 of the radii. Use these to form a
// SDF subtraction which will clip out the inside
// third of the rounded edge.
float d_radii_a = distance_to_ellipse(
clip_relative_pos,
clip_radii.xy - vPartialWidths.xy
);
float d_radii_b = distance_to_ellipse(
clip_relative_pos,
clip_radii.xy - 2.0 * vPartialWidths.xy
);
float d = min(-d_radii_a, d_radii_b);
color0 *= distance_aa(aa_range, d);
break;
}
vec4 c0 = mix(color1, color0, swizzled_factor);
vec4 c1 = mix(color0, color1, swizzled_factor);
color0 = mix(c0, c1, alpha);
case BORDER_STYLE_GROOVE:
case BORDER_STYLE_RIDGE: {
float d = distance_to_ellipse(
clip_relative_pos,
clip_radii.xy - vPartialWidths.zw
);
float alpha = distance_aa(aa_range, d);
float swizzled_factor;
switch (segment) {
case SEGMENT_TOP_LEFT: swizzled_factor = 0.0; break;
case SEGMENT_TOP_RIGHT: swizzled_factor = mix_factor; break;
case SEGMENT_BOTTOM_RIGHT: swizzled_factor = 1.0; break;
case SEGMENT_BOTTOM_LEFT: swizzled_factor = 1.0 - mix_factor; break;
default: swizzled_factor = 0.0; break;
};
vec4 c0 = mix(color1, color0, swizzled_factor);
vec4 c1 = mix(color0, color1, swizzled_factor);
color0 = mix(c0, c1, alpha);
break;
}
default:
break;
}
return color0;
@ -287,22 +312,30 @@ vec4 evaluate_color_for_style_in_edge(
) {
vec2 edge_axis = edge_axis_id != 0 ? vec2(0.0, 1.0) : vec2(1.0, 0.0);
float pos = dot(pos_vec, edge_axis);
if (style == BORDER_STYLE_DOUBLE) {
float d = -1.0;
float partial_width = dot(vPartialWidths.xy, edge_axis);
if (partial_width >= 1.0) {
vec2 ref = vec2(
dot(vEdgeReference.xy, edge_axis) + partial_width,
dot(vEdgeReference.zw, edge_axis) - partial_width
);
d = min(pos - ref.x, ref.y - pos);
switch (style) {
case BORDER_STYLE_DOUBLE: {
float d = -1.0;
float partial_width = dot(vPartialWidths.xy, edge_axis);
if (partial_width >= 1.0) {
vec2 ref = vec2(
dot(vEdgeReference.xy, edge_axis) + partial_width,
dot(vEdgeReference.zw, edge_axis) - partial_width
);
d = min(pos - ref.x, ref.y - pos);
}
color0 *= distance_aa(aa_range, d);
break;
}
color0 *= distance_aa(aa_range, d);
} else if (style == BORDER_STYLE_GROOVE || style == BORDER_STYLE_RIDGE) {
float ref = dot(vEdgeReference.xy + vPartialWidths.zw, edge_axis);
float d = pos - ref;
float alpha = distance_aa(aa_range, d);
color0 = mix(color0, color1, alpha);
case BORDER_STYLE_GROOVE:
case BORDER_STYLE_RIDGE: {
float ref = dot(vEdgeReference.xy + vPartialWidths.zw, edge_axis);
float d = pos - ref;
float alpha = distance_aa(aa_range, d);
color0 = mix(color0, color1, alpha);
break;
}
default:
break;
}
return color0;
@ -328,31 +361,41 @@ void main(void) {
bool in_clip_region = all(lessThan(vClipCenter_Sign.zw * clip_relative_pos, vec2(0.0)));
float d = -1.0;
if (clip_mode == CLIP_DOT) {
// Set clip distance based or dot position and radius.
d = distance(vClipParams1.xy, vPos) - vClipParams1.z;
} else if (clip_mode == CLIP_DASH_EDGE) {
bool is_vertical = vClipParams1.x == 0.;
float half_dash = is_vertical ? vClipParams1.y : vClipParams1.x;
// We want to draw something like:
// +---+---+---+---+
// |xxx| | |xxx|
// +---+---+---+---+
float pos = is_vertical ? vPos.y : vPos.x;
bool in_dash = pos < half_dash || pos > 3.0 * half_dash;
if (!in_dash) {
d = 1.;
switch (clip_mode) {
case CLIP_DOT: {
// Set clip distance based or dot position and radius.
d = distance(vClipParams1.xy, vPos) - vClipParams1.z;
break;
}
} else if (clip_mode == CLIP_DASH_CORNER) {
// Get SDF for the two line/tangent clip lines,
// do SDF subtract to get clip distance.
float d0 = distance_to_line(vClipParams1.xy,
vClipParams1.zw,
vPos);
float d1 = distance_to_line(vClipParams2.xy,
vClipParams2.zw,
vPos);
d = max(d0, -d1);
case CLIP_DASH_EDGE: {
bool is_vertical = vClipParams1.x == 0.;
float half_dash = is_vertical ? vClipParams1.y : vClipParams1.x;
// We want to draw something like:
// +---+---+---+---+
// |xxx| | |xxx|
// +---+---+---+---+
float pos = is_vertical ? vPos.y : vPos.x;
bool in_dash = pos < half_dash || pos > 3.0 * half_dash;
if (!in_dash) {
d = 1.;
}
break;
}
case CLIP_DASH_CORNER: {
// Get SDF for the two line/tangent clip lines,
// do SDF subtract to get clip distance.
float d0 = distance_to_line(vClipParams1.xy,
vClipParams1.zw,
vPos);
float d1 = distance_to_line(vClipParams2.xy,
vClipParams2.zw,
vPos);
d = max(d0, -d1);
break;
}
case CLIP_NONE:
default:
break;
}
if (in_clip_region) {

Просмотреть файл

@ -58,17 +58,23 @@ PER_INSTANCE in vec4 aClipParams2;
vec2 get_outer_corner_scale(int segment) {
vec2 p;
if (segment == SEGMENT_TOP_LEFT) {
p = vec2(0.0, 0.0);
} else if (segment == SEGMENT_TOP_RIGHT) {
p = vec2(1.0, 0.0);
} else if (segment == SEGMENT_BOTTOM_RIGHT) {
p = vec2(1.0, 1.0);
} else if (segment == SEGMENT_BOTTOM_LEFT) {
p = vec2(0.0, 1.0);
} else {
// The result is only used for non-default segment cases
p = vec2(0.0);
switch (segment) {
case SEGMENT_TOP_LEFT:
p = vec2(0.0, 0.0);
break;
case SEGMENT_TOP_RIGHT:
p = vec2(1.0, 0.0);
break;
case SEGMENT_BOTTOM_RIGHT:
p = vec2(1.0, 1.0);
break;
case SEGMENT_BOTTOM_LEFT:
p = vec2(0.0, 1.0);
break;
default:
// The result is only used for non-default segment cases
p = vec2(0.0);
break;
}
return p;
@ -83,14 +89,17 @@ void main(void) {
vec2 clip_sign = 1.0 - 2.0 * outer_scale;
int mix_colors;
if (segment == SEGMENT_TOP_LEFT ||
segment == SEGMENT_TOP_RIGHT ||
segment == SEGMENT_BOTTOM_RIGHT ||
segment == SEGMENT_BOTTOM_LEFT)
{
mix_colors = do_aa ? MIX_AA : MIX_NO_AA;
} else {
mix_colors = DONT_MIX;
switch (segment) {
case SEGMENT_TOP_LEFT:
case SEGMENT_TOP_RIGHT:
case SEGMENT_BOTTOM_RIGHT:
case SEGMENT_BOTTOM_LEFT: {
mix_colors = do_aa ? MIX_AA : MIX_NO_AA;
break;
}
default:
mix_colors = DONT_MIX;
break;
}
vMixColors = mix_colors;

Просмотреть файл

@ -81,22 +81,34 @@ void main(void) {
vec2 local_pos = vi.local_pos.xy / vi.local_pos.w;
vLocalPos = vi.local_pos;
if (bs_data.stretch_mode_x == MODE_STRETCH) {
vEdge.x = 0.5;
vEdge.z = (dest_rect.size.x / bs_data.src_rect_size.x) - 0.5;
vUv.x = (local_pos.x - dest_rect.p0.x) / bs_data.src_rect_size.x;
} else { // bs_data.stretch_mode_x == MODE_SIMPLE
vEdge.xz = vec2(1.0);
vUv.x = (local_pos.x - dest_rect.p0.x) / dest_rect.size.x;
switch (bs_data.stretch_mode_x) {
case MODE_STRETCH: {
vEdge.x = 0.5;
vEdge.z = (dest_rect.size.x / bs_data.src_rect_size.x) - 0.5;
vUv.x = (local_pos.x - dest_rect.p0.x) / bs_data.src_rect_size.x;
break;
}
case MODE_SIMPLE:
default: {
vEdge.xz = vec2(1.0);
vUv.x = (local_pos.x - dest_rect.p0.x) / dest_rect.size.x;
break;
}
}
if (bs_data.stretch_mode_y == MODE_STRETCH) {
vEdge.y = 0.5;
vEdge.w = (dest_rect.size.y / bs_data.src_rect_size.y) - 0.5;
vUv.y = (local_pos.y - dest_rect.p0.y) / bs_data.src_rect_size.y;
} else { // bs_data.stretch_mode_y == MODE_SIMPLE
vEdge.yw = vec2(1.0);
vUv.y = (local_pos.y - dest_rect.p0.y) / dest_rect.size.y;
switch (bs_data.stretch_mode_y) {
case MODE_STRETCH: {
vEdge.y = 0.5;
vEdge.w = (dest_rect.size.y / bs_data.src_rect_size.y) - 0.5;
vUv.y = (local_pos.y - dest_rect.p0.y) / bs_data.src_rect_size.y;
break;
}
case MODE_SIMPLE:
default: {
vEdge.yw = vec2(1.0);
vUv.y = (local_pos.y - dest_rect.p0.y) / dest_rect.size.y;
break;
}
}
vUv *= vi.local_pos.w;

Просмотреть файл

@ -42,35 +42,44 @@ void main(void) {
vec2 size = mix(aLocalSize, aLocalSize.yx, aAxisSelect);
vStyle = aStyle;
if (vStyle == LINE_STYLE_SOLID) {
} else if (vStyle == LINE_STYLE_DASHED) {
vParams = vec4(size.x, // period
0.5 * size.x, // dash length
0.0,
0.0);
} else if (vStyle == LINE_STYLE_DOTTED) {
float diameter = size.y;
float period = diameter * 2.0;
float center_line = 0.5 * size.y;
vParams = vec4(period,
diameter / 2.0, // radius
center_line,
0.0);
} else if (vStyle == LINE_STYLE_WAVY) {
// This logic copied from gecko to get the same results
float line_thickness = max(aWavyLineThickness, 1.0);
// Difference in height between peaks and troughs
// (and since slopes are 45 degrees, the length of each slope)
float slope_length = size.y - line_thickness;
// Length of flat runs
float flat_length = max((line_thickness - 1.0) * 2.0, 1.0);
switch (vStyle) {
case LINE_STYLE_SOLID: {
break;
}
case LINE_STYLE_DASHED: {
vParams = vec4(size.x, // period
0.5 * size.x, // dash length
0.0,
0.0);
break;
}
case LINE_STYLE_DOTTED: {
float diameter = size.y;
float period = diameter * 2.0;
float center_line = 0.5 * size.y;
vParams = vec4(period,
diameter / 2.0, // radius
center_line,
0.0);
break;
}
case LINE_STYLE_WAVY: {
// This logic copied from gecko to get the same results
float line_thickness = max(aWavyLineThickness, 1.0);
// Difference in height between peaks and troughs
// (and since slopes are 45 degrees, the length of each slope)
float slope_length = size.y - line_thickness;
// Length of flat runs
float flat_length = max((line_thickness - 1.0) * 2.0, 1.0);
vParams = vec4(line_thickness / 2.0,
slope_length,
flat_length,
size.y);
} else {
vParams = vec4(0.0);
vParams = vec4(line_thickness / 2.0,
slope_length,
flat_length,
size.y);
break;
}
default:
vParams = vec4(0.0);
}
vLocalPos = mix(aPosition.xy, aPosition.yx, aAxisSelect) * size;
@ -89,53 +98,64 @@ void main(void) {
float aa_range = compute_aa_range(pos);
float alpha = 1.0;
if (vStyle == LINE_STYLE_SOLID) {
} else if (vStyle == LINE_STYLE_DASHED) {
// Calculate dash alpha (on/off) based on dash length
alpha = step(floor(pos.x + 0.5), vParams.y);
} else if (vStyle == LINE_STYLE_DOTTED) {
// Get the dot alpha
vec2 dot_relative_pos = pos - vParams.yz;
float dot_distance = length(dot_relative_pos) - vParams.y;
alpha = distance_aa(aa_range, dot_distance);
} else if (vStyle == LINE_STYLE_WAVY) {
float half_line_thickness = vParams.x;
float slope_length = vParams.y;
float flat_length = vParams.z;
float vertical_bounds = vParams.w;
// Our pattern is just two slopes and two flats
float half_period = slope_length + flat_length;
float mid_height = vertical_bounds / 2.0;
float peak_offset = mid_height - half_line_thickness;
// Flip the wave every half period
float flip = -2.0 * (step(mod(pos.x, 2.0 * half_period), half_period) - 0.5);
// float flip = -1.0;
peak_offset *= flip;
float peak_height = mid_height + peak_offset;
// Convert pos to a local position within one half period
pos.x = mod(pos.x, half_period);
// Compute signed distance to the 3 lines that make up an arc
float dist1 = distance_to_line(vec2(0.0, peak_height),
vec2(1.0, -flip),
pos);
float dist2 = distance_to_line(vec2(0.0, peak_height),
vec2(0, -flip),
pos);
float dist3 = distance_to_line(vec2(flat_length, peak_height),
vec2(-1.0, -flip),
pos);
float dist = abs(max(max(dist1, dist2), dist3));
// Apply AA based on the thickness of the wave
alpha = distance_aa(aa_range, dist - half_line_thickness);
// Disable AA for thin lines
if (half_line_thickness <= 1.0) {
alpha = 1.0 - step(alpha, MAGIC_WAVY_LINE_AA_SNAP);
switch (vStyle) {
case LINE_STYLE_SOLID: {
break;
}
case LINE_STYLE_DASHED: {
// Calculate dash alpha (on/off) based on dash length
alpha = step(floor(pos.x + 0.5), vParams.y);
break;
}
case LINE_STYLE_DOTTED: {
// Get the dot alpha
vec2 dot_relative_pos = pos - vParams.yz;
float dot_distance = length(dot_relative_pos) - vParams.y;
alpha = distance_aa(aa_range, dot_distance);
break;
}
case LINE_STYLE_WAVY: {
float half_line_thickness = vParams.x;
float slope_length = vParams.y;
float flat_length = vParams.z;
float vertical_bounds = vParams.w;
// Our pattern is just two slopes and two flats
float half_period = slope_length + flat_length;
float mid_height = vertical_bounds / 2.0;
float peak_offset = mid_height - half_line_thickness;
// Flip the wave every half period
float flip = -2.0 * (step(mod(pos.x, 2.0 * half_period), half_period) - 0.5);
// float flip = -1.0;
peak_offset *= flip;
float peak_height = mid_height + peak_offset;
// Convert pos to a local position within one half period
pos.x = mod(pos.x, half_period);
// Compute signed distance to the 3 lines that make up an arc
float dist1 = distance_to_line(vec2(0.0, peak_height),
vec2(1.0, -flip),
pos);
float dist2 = distance_to_line(vec2(0.0, peak_height),
vec2(0, -flip),
pos);
float dist3 = distance_to_line(vec2(flat_length, peak_height),
vec2(-1.0, -flip),
pos);
float dist = abs(max(max(dist1, dist2), dist3));
// Apply AA based on the thickness of the wave
alpha = distance_aa(aa_range, dist - half_line_thickness);
// Disable AA for thin lines
if (half_line_thickness <= 1.0) {
alpha = 1.0 - step(alpha, MAGIC_WAVY_LINE_AA_SNAP);
}
break;
}
default: break;
}
oFragColor = vec4(alpha);

Просмотреть файл

@ -119,33 +119,44 @@ void main(void) {
vFuncs[2] = (aFilterGenericInt >> 4) & 0xf; // B
vFuncs[3] = (aFilterGenericInt) & 0xf; // A
if (aFilterKind == FILTER_BLEND) {
vData = ivec4(aFilterGenericInt, 0, 0, 0);
} else if (vFilterKind == FILTER_FLOOD) {
vFilterData0 = fetch_from_gpu_cache_1_direct(aFilterExtraDataAddress);
} else if (vFilterKind == FILTER_OPACITY) {
vFloat0 = filter_task.user_data.x;
} else if (vFilterKind == FILTER_COLOR_MATRIX) {
vec4 mat_data[4] = fetch_from_gpu_cache_4_direct(aFilterExtraDataAddress);
vColorMat = mat4(mat_data[0], mat_data[1], mat_data[2], mat_data[3]);
vFilterData0 = fetch_from_gpu_cache_1_direct(aFilterExtraDataAddress + ivec2(4, 0));
} else if (vFilterKind == FILTER_DROP_SHADOW) {
vFilterData0 = fetch_from_gpu_cache_1_direct(aFilterExtraDataAddress);
} else if (vFilterKind == FILTER_OFFSET) {
vec2 texture_size = vec2(textureSize(sColor0, 0).xy);
vFilterData0 = vec4(-filter_task.user_data.xy / texture_size, vec2(0.0));
RectWithSize task_rect = input_1_task.task_rect;
vec4 clipRect = vec4(task_rect.p0, task_rect.p0 + task_rect.size);
clipRect /= texture_size.xyxy;
vFilterData1 = clipRect;
} else if (vFilterKind == FILTER_COMPONENT_TRANSFER) {
vData = ivec4(aFilterExtraDataAddress, 0, 0);
} else if (vFilterKind == FILTER_COMPOSITE) {
vData = ivec4(aFilterGenericInt, 0, 0, 0);
if (aFilterGenericInt == COMPOSITE_ARITHMETIC) {
switch (aFilterKind) {
case FILTER_BLEND:
vData = ivec4(aFilterGenericInt, 0, 0, 0);
break;
case FILTER_FLOOD:
vFilterData0 = fetch_from_gpu_cache_1_direct(aFilterExtraDataAddress);
}
break;
case FILTER_OPACITY:
vFloat0 = filter_task.user_data.x;
break;
case FILTER_COLOR_MATRIX:
vec4 mat_data[4] = fetch_from_gpu_cache_4_direct(aFilterExtraDataAddress);
vColorMat = mat4(mat_data[0], mat_data[1], mat_data[2], mat_data[3]);
vFilterData0 = fetch_from_gpu_cache_1_direct(aFilterExtraDataAddress + ivec2(4, 0));
break;
case FILTER_DROP_SHADOW:
vFilterData0 = fetch_from_gpu_cache_1_direct(aFilterExtraDataAddress);
break;
case FILTER_OFFSET:
vec2 texture_size = vec2(textureSize(sColor0, 0).xy);
vFilterData0 = vec4(-filter_task.user_data.xy / texture_size, vec2(0.0));
RectWithSize task_rect = input_1_task.task_rect;
vec4 clipRect = vec4(task_rect.p0, task_rect.p0 + task_rect.size);
clipRect /= texture_size.xyxy;
vFilterData1 = clipRect;
break;
case FILTER_COMPONENT_TRANSFER:
vData = ivec4(aFilterExtraDataAddress, 0, 0);
break;
case FILTER_COMPOSITE:
vData = ivec4(aFilterGenericInt, 0, 0, 0);
if (aFilterGenericInt == COMPOSITE_ARITHMETIC) {
vFilterData0 = fetch_from_gpu_cache_1_direct(aFilterExtraDataAddress);
}
break;
default:
break;
}
gl_Position = uTransform * vec4(pos, 0.0, 1.0);
@ -321,45 +332,63 @@ const int BlendMode_Luminosity = 15;
vec4 blend(vec4 Cs, vec4 Cb, int mode) {
vec4 result = vec4(1.0, 0.0, 0.0, 1.0);
if (mode == BlendMode_Normal) {
result.rgb = Cs.rgb;
} else if (mode == BlendMode_Multiply) {
result.rgb = Multiply(Cb.rgb, Cs.rgb);
} else if (mode == BlendMode_Screen) {
result.rgb = Screen(Cb.rgb, Cs.rgb);
} else if (mode == BlendMode_Overlay) {
// Overlay is inverse of Hardlight
result.rgb = HardLight(Cs.rgb, Cb.rgb);
} else if (mode == BlendMode_Darken) {
result.rgb = min(Cs.rgb, Cb.rgb);
} else if (mode == BlendMode_Lighten) {
result.rgb = max(Cs.rgb, Cb.rgb);
} else if (mode == BlendMode_ColorDodge) {
result.r = ColorDodge(Cb.r, Cs.r);
result.g = ColorDodge(Cb.g, Cs.g);
result.b = ColorDodge(Cb.b, Cs.b);
} else if (mode == BlendMode_ColorBurn) {
result.r = ColorBurn(Cb.r, Cs.r);
result.g = ColorBurn(Cb.g, Cs.g);
result.b = ColorBurn(Cb.b, Cs.b);
} else if (mode == BlendMode_HardLight) {
result.rgb = HardLight(Cb.rgb, Cs.rgb);
} else if (mode == BlendMode_SoftLight) {
result.r = SoftLight(Cb.r, Cs.r);
result.g = SoftLight(Cb.g, Cs.g);
result.b = SoftLight(Cb.b, Cs.b);
} else if (mode == BlendMode_Difference) {
result.rgb = Difference(Cb.rgb, Cs.rgb);
} else if (mode == BlendMode_Exclusion) {
result.rgb = Exclusion(Cb.rgb, Cs.rgb);
} else if (mode == BlendMode_Hue) {
result.rgb = Hue(Cb.rgb, Cs.rgb);
} else if (mode == BlendMode_Saturation) {
result.rgb = Saturation(Cb.rgb, Cs.rgb);
} else if (mode == BlendMode_Color) {
result.rgb = Color(Cb.rgb, Cs.rgb);
} else if (mode == BlendMode_Luminosity) {
result.rgb = Luminosity(Cb.rgb, Cs.rgb);
switch (mode) {
case BlendMode_Normal:
result.rgb = Cs.rgb;
break;
case BlendMode_Multiply:
result.rgb = Multiply(Cb.rgb, Cs.rgb);
break;
case BlendMode_Screen:
result.rgb = Screen(Cb.rgb, Cs.rgb);
break;
case BlendMode_Overlay:
// Overlay is inverse of Hardlight
result.rgb = HardLight(Cs.rgb, Cb.rgb);
break;
case BlendMode_Darken:
result.rgb = min(Cs.rgb, Cb.rgb);
break;
case BlendMode_Lighten:
result.rgb = max(Cs.rgb, Cb.rgb);
break;
case BlendMode_ColorDodge:
result.r = ColorDodge(Cb.r, Cs.r);
result.g = ColorDodge(Cb.g, Cs.g);
result.b = ColorDodge(Cb.b, Cs.b);
break;
case BlendMode_ColorBurn:
result.r = ColorBurn(Cb.r, Cs.r);
result.g = ColorBurn(Cb.g, Cs.g);
result.b = ColorBurn(Cb.b, Cs.b);
break;
case BlendMode_HardLight:
result.rgb = HardLight(Cb.rgb, Cs.rgb);
break;
case BlendMode_SoftLight:
result.r = SoftLight(Cb.r, Cs.r);
result.g = SoftLight(Cb.g, Cs.g);
result.b = SoftLight(Cb.b, Cs.b);
break;
case BlendMode_Difference:
result.rgb = Difference(Cb.rgb, Cs.rgb);
break;
case BlendMode_Exclusion:
result.rgb = Exclusion(Cb.rgb, Cs.rgb);
break;
case BlendMode_Hue:
result.rgb = Hue(Cb.rgb, Cs.rgb);
break;
case BlendMode_Saturation:
result.rgb = Saturation(Cb.rgb, Cs.rgb);
break;
case BlendMode_Color:
result.rgb = Color(Cb.rgb, Cs.rgb);
break;
case BlendMode_Luminosity:
result.rgb = Luminosity(Cb.rgb, Cs.rgb);
break;
default: break;
}
vec3 rgb = (1.0 - Cb.a) * Cs.rgb + Cb.a * result.rgb;
result = mix(vec4(Cb.rgb * Cb.a, Cb.a), vec4(rgb, 1.0), Cs.a);
@ -403,27 +432,35 @@ vec4 ComponentTransfer(vec4 colora) {
int k;
for (int i = 0; i < 4; i++) {
if (vFuncs[i] == COMPONENT_TRANSFER_IDENTITY) {
} else if (vFuncs[i] == COMPONENT_TRANSFER_TABLE ||
vFuncs[i] == COMPONENT_TRANSFER_DISCRETE) {
// fetch value from lookup table
k = int(floor(colora[i]*255.0));
texel = fetch_from_gpu_cache_1_direct(vData.xy + ivec2(offset + k/4, 0));
colora[i] = clamp(texel[k % 4], 0.0, 1.0);
// offset plus 256/4 blocks
offset = offset + 64;
} else if (vFuncs[i] == COMPONENT_TRANSFER_LINEAR) {
// fetch the two values for use in the linear equation
texel = fetch_from_gpu_cache_1_direct(vData.xy + ivec2(offset, 0));
colora[i] = clamp(texel[0] * colora[i] + texel[1], 0.0, 1.0);
// offset plus 1 block
offset = offset + 1;
} else if (vFuncs[i] == COMPONENT_TRANSFER_GAMMA) {
// fetch the three values for use in the gamma equation
texel = fetch_from_gpu_cache_1_direct(vData.xy + ivec2(offset, 0));
colora[i] = clamp(texel[0] * pow(colora[i], texel[1]) + texel[2], 0.0, 1.0);
// offset plus 1 block
offset = offset + 1;
switch (vFuncs[i]) {
case COMPONENT_TRANSFER_IDENTITY:
break;
case COMPONENT_TRANSFER_TABLE:
case COMPONENT_TRANSFER_DISCRETE:
// fetch value from lookup table
k = int(floor(colora[i]*255.0));
texel = fetch_from_gpu_cache_1_direct(vData.xy + ivec2(offset + k/4, 0));
colora[i] = clamp(texel[k % 4], 0.0, 1.0);
// offset plus 256/4 blocks
offset = offset + 64;
break;
case COMPONENT_TRANSFER_LINEAR:
// fetch the two values for use in the linear equation
texel = fetch_from_gpu_cache_1_direct(vData.xy + ivec2(offset, 0));
colora[i] = clamp(texel[0] * colora[i] + texel[1], 0.0, 1.0);
// offset plus 1 block
offset = offset + 1;
break;
case COMPONENT_TRANSFER_GAMMA:
// fetch the three values for use in the gamma equation
texel = fetch_from_gpu_cache_1_direct(vData.xy + ivec2(offset, 0));
colora[i] = clamp(texel[0] * pow(colora[i], texel[1]) + texel[2], 0.0, 1.0);
// offset plus 1 block
offset = offset + 1;
break;
default:
// shouldn't happen
break;
}
}
return colora;
@ -433,28 +470,38 @@ vec4 ComponentTransfer(vec4 colora) {
vec4 composite(vec4 Cs, vec4 Cb, int mode) {
vec4 Cr = vec4(0.0, 1.0, 0.0, 1.0);
if (mode == COMPOSITE_OVER) {
Cr.rgb = Cs.a * Cs.rgb + Cb.a * Cb.rgb * (1.0 - Cs.a);
Cr.a = Cs.a + Cb.a * (1.0 - Cs.a);
} else if (mode == COMPOSITE_IN) {
Cr.rgb = Cs.a * Cs.rgb * Cb.a;
Cr.a = Cs.a * Cb.a;
} else if (mode == COMPOSITE_OUT) {
Cr.rgb = Cs.a * Cs.rgb * (1.0 - Cb.a);
Cr.a = Cs.a * (1.0 - Cb.a);
} else if (mode == COMPOSITE_ATOP) {
Cr.rgb = Cs.a * Cs.rgb * Cb.a + Cb.a * Cb.rgb * (1.0 - Cs.a);
Cr.a = Cs.a * Cb.a + Cb.a * (1.0 - Cs.a);
} else if (mode == COMPOSITE_XOR) {
Cr.rgb = Cs.a * Cs.rgb * (1.0 - Cb.a) + Cb.a * Cb.rgb * (1.0 - Cs.a);
Cr.a = Cs.a * (1.0 - Cb.a) + Cb.a * (1.0 - Cs.a);
} else if (mode == COMPOSITE_LIGHTER) {
Cr.rgb = Cs.a * Cs.rgb + Cb.a * Cb.rgb;
Cr.a = Cs.a + Cb.a;
Cr = clamp(Cr, vec4(0.0), vec4(1.0));
} else if (mode == COMPOSITE_ARITHMETIC) {
Cr = vec4(vFilterData0.x) * Cs * Cb + vec4(vFilterData0.y) * Cs + vec4(vFilterData0.z) * Cb + vec4(vFilterData0.w);
Cr = clamp(Cr, vec4(0.0), vec4(1.0));
switch (mode) {
case COMPOSITE_OVER:
Cr.rgb = Cs.a * Cs.rgb + Cb.a * Cb.rgb * (1.0 - Cs.a);
Cr.a = Cs.a + Cb.a * (1.0 - Cs.a);
break;
case COMPOSITE_IN:
Cr.rgb = Cs.a * Cs.rgb * Cb.a;
Cr.a = Cs.a * Cb.a;
break;
case COMPOSITE_OUT:
Cr.rgb = Cs.a * Cs.rgb * (1.0 - Cb.a);
Cr.a = Cs.a * (1.0 - Cb.a);
break;
case COMPOSITE_ATOP:
Cr.rgb = Cs.a * Cs.rgb * Cb.a + Cb.a * Cb.rgb * (1.0 - Cs.a);
Cr.a = Cs.a * Cb.a + Cb.a * (1.0 - Cs.a);
break;
case COMPOSITE_XOR:
Cr.rgb = Cs.a * Cs.rgb * (1.0 - Cb.a) + Cb.a * Cb.rgb * (1.0 - Cs.a);
Cr.a = Cs.a * (1.0 - Cb.a) + Cb.a * (1.0 - Cs.a);
break;
case COMPOSITE_LIGHTER:
Cr.rgb = Cs.a * Cs.rgb + Cb.a * Cb.rgb;
Cr.a = Cs.a + Cb.a;
Cr = clamp(Cr, vec4(0.0), vec4(1.0));
break;
case COMPOSITE_ARITHMETIC:
Cr = vec4(vFilterData0.x) * Cs * Cb + vec4(vFilterData0.y) * Cs + vec4(vFilterData0.z) * Cb + vec4(vFilterData0.w);
Cr = clamp(Cr, vec4(0.0), vec4(1.0));
break;
default:
break;
}
return Cr;
}
@ -484,41 +531,54 @@ void main(void) {
bool needsPremul = true;
if (vFilterKind == FILTER_BLEND) {
result = blend(Ca, Cb, vData.x);
needsPremul = false;
} else if (vFilterKind == FILTER_FLOOD) {
result = vFilterData0;
needsPremul = false;
} else if (vFilterKind == FILTER_LINEAR_TO_SRGB) {
result.rgb = LinearToSrgb(Ca.rgb);
result.a = Ca.a;
} else if (vFilterKind == FILTER_SRGB_TO_LINEAR) {
result.rgb = SrgbToLinear(Ca.rgb);
result.a = Ca.a;
} else if (vFilterKind == FILTER_OPACITY) {
result.rgb = Ca.rgb;
result.a = Ca.a * vFloat0;
} else if (vFilterKind == FILTER_COLOR_MATRIX) {
result = vColorMat * Ca + vFilterData0;
result = clamp(result, vec4(0.0), vec4(1.0));
} else if (vFilterKind == FILTER_DROP_SHADOW) {
vec4 shadow = vec4(vFilterData0.rgb, Cb.a * vFilterData0.a);
// Normal blend + source-over coposite
result = blend(Ca, shadow, BlendMode_Normal);
needsPremul = false;
} else if (vFilterKind == FILTER_OFFSET) {
vec2 offsetUv = vInput1Uv + vFilterData0.xy;
result = sampleInUvRect(sColor0, offsetUv, vInput1UvRect);
result *= point_inside_rect(offsetUv, vFilterData1.xy, vFilterData1.zw);
needsPremul = false;
} else if (vFilterKind == FILTER_COMPONENT_TRANSFER) {
result = ComponentTransfer(Ca);
} else if (vFilterKind == FILTER_IDENTITY) {
result = Ca;
} else if (vFilterKind == FILTER_COMPOSITE) {
result = composite(Ca, Cb, vData.x);
needsPremul = false;
switch (vFilterKind) {
case FILTER_BLEND:
result = blend(Ca, Cb, vData.x);
needsPremul = false;
break;
case FILTER_FLOOD:
result = vFilterData0;
needsPremul = false;
break;
case FILTER_LINEAR_TO_SRGB:
result.rgb = LinearToSrgb(Ca.rgb);
result.a = Ca.a;
break;
case FILTER_SRGB_TO_LINEAR:
result.rgb = SrgbToLinear(Ca.rgb);
result.a = Ca.a;
break;
case FILTER_OPACITY:
result.rgb = Ca.rgb;
result.a = Ca.a * vFloat0;
break;
case FILTER_COLOR_MATRIX:
result = vColorMat * Ca + vFilterData0;
result = clamp(result, vec4(0.0), vec4(1.0));
break;
case FILTER_DROP_SHADOW:
vec4 shadow = vec4(vFilterData0.rgb, Cb.a * vFilterData0.a);
// Normal blend + source-over coposite
result = blend(Ca, shadow, BlendMode_Normal);
needsPremul = false;
break;
case FILTER_OFFSET:
vec2 offsetUv = vInput1Uv + vFilterData0.xy;
result = sampleInUvRect(sColor0, offsetUv, vInput1UvRect);
result *= point_inside_rect(offsetUv, vFilterData1.xy, vFilterData1.zw);
needsPremul = false;
break;
case FILTER_COMPONENT_TRANSFER:
result = ComponentTransfer(Ca);
break;
case FILTER_IDENTITY:
result = Ca;
break;
case FILTER_COMPOSITE:
result = composite(Ca, Cb, vData.x);
needsPremul = false;
default:
break;
}
if (needsPremul) {

Просмотреть файл

@ -82,18 +82,20 @@ vec2 get_snap_bias(int subpx_dir) {
// accounted for while rasterizing the glyph. However, we
// must still round with a subpixel bias rather than rounding
// to the nearest whole pixel, depending on subpixel direciton.
if (subpx_dir == SUBPX_DIR_HORIZONTAL) {
// Glyphs positioned [-0.125, 0.125] get a
// subpx position of zero. So include that
// offset in the glyph position to ensure
// we round to the correct whole position.
return vec2(0.125, 0.5);
} else if (subpx_dir == SUBPX_DIR_VERTICAL) {
return vec2(0.5, 0.125);
} else if (subpx_dir == SUBPX_DIR_MIXED) {
return vec2(0.125);
} else { // subpx_dir == SUBPX_DIR_NONE
return vec2(0.5);
switch (subpx_dir) {
case SUBPX_DIR_NONE:
default:
return vec2(0.5);
case SUBPX_DIR_HORIZONTAL:
// Glyphs positioned [-0.125, 0.125] get a
// subpx position of zero. So include that
// offset in the glyph position to ensure
// we round to the correct whole position.
return vec2(0.125, 0.5);
case SUBPX_DIR_VERTICAL:
return vec2(0.5, 0.125);
case SUBPX_DIR_MIXED:
return vec2(0.125);
}
}
@ -222,24 +224,30 @@ void main() {
write_clip(vi.world_pos, clip_area, task);
if (color_mode == COLOR_MODE_ALPHA || color_mode == COLOR_MODE_BITMAP) {
v_mask_swizzle = vec2(0.0, 1.0);
v_color = text.color;
} else if (color_mode == COLOR_MODE_SUBPX_BG_PASS2 ||
color_mode == COLOR_MODE_SUBPX_DUAL_SOURCE) {
v_mask_swizzle = vec2(1.0, 0.0);
v_color = text.color;
} else if (color_mode == COLOR_MODE_SUBPX_CONST_COLOR ||
color_mode == COLOR_MODE_SUBPX_BG_PASS0 ||
color_mode == COLOR_MODE_COLOR_BITMAP) {
v_mask_swizzle = vec2(1.0, 0.0);
v_color = vec4(text.color.a);
} else if (color_mode == COLOR_MODE_SUBPX_BG_PASS1) {
v_mask_swizzle = vec2(-1.0, 1.0);
v_color = vec4(text.color.a) * text.bg_color;
} else {
v_mask_swizzle = vec2(0.0);
v_color = vec4(1.0);
switch (color_mode) {
case COLOR_MODE_ALPHA:
case COLOR_MODE_BITMAP:
v_mask_swizzle = vec2(0.0, 1.0);
v_color = text.color;
break;
case COLOR_MODE_SUBPX_BG_PASS2:
case COLOR_MODE_SUBPX_DUAL_SOURCE:
v_mask_swizzle = vec2(1.0, 0.0);
v_color = text.color;
break;
case COLOR_MODE_SUBPX_CONST_COLOR:
case COLOR_MODE_SUBPX_BG_PASS0:
case COLOR_MODE_COLOR_BITMAP:
v_mask_swizzle = vec2(1.0, 0.0);
v_color = vec4(text.color.a);
break;
case COLOR_MODE_SUBPX_BG_PASS1:
v_mask_swizzle = vec2(-1.0, 1.0);
v_color = vec4(text.color.a) * text.bg_color;
break;
default:
v_mask_swizzle = vec2(0.0);
v_color = vec4(1.0);
}
vec2 texture_size = vec2(textureSize(sColor0, 0));

Просмотреть файл

@ -130,27 +130,41 @@ vec4 sample_yuv(
) {
vec3 yuv_value;
if (format == YUV_FORMAT_PLANAR) {
// The yuv_planar format should have this third texture coordinate.
vec2 uv_y = clamp(in_uv_y, uv_bounds_y.xy, uv_bounds_y.zw);
vec2 uv_u = clamp(in_uv_u, uv_bounds_u.xy, uv_bounds_u.zw);
vec2 uv_v = clamp(in_uv_v, uv_bounds_v.xy, uv_bounds_v.zw);
yuv_value.x = TEX_SAMPLE(sColor0, vec3(uv_y, yuv_layers.x)).r;
yuv_value.y = TEX_SAMPLE(sColor1, vec3(uv_u, yuv_layers.y)).r;
yuv_value.z = TEX_SAMPLE(sColor2, vec3(uv_v, yuv_layers.z)).r;
} else if (format == YUV_FORMAT_NV12) {
vec2 uv_y = clamp(in_uv_y, uv_bounds_y.xy, uv_bounds_y.zw);
vec2 uv_uv = clamp(in_uv_u, uv_bounds_u.xy, uv_bounds_u.zw);
yuv_value.x = TEX_SAMPLE(sColor0, vec3(uv_y, yuv_layers.x)).r;
yuv_value.yz = TEX_SAMPLE(sColor1, vec3(uv_uv, yuv_layers.y)).rg;
} else if (format == YUV_FORMAT_INTERLEAVED) {
// "The Y, Cb and Cr color channels within the 422 data are mapped into
// the existing green, blue and red color channels."
// https://www.khronos.org/registry/OpenGL/extensions/APPLE/APPLE_rgb_422.txt
vec2 uv_y = clamp(in_uv_y, uv_bounds_y.xy, uv_bounds_y.zw);
yuv_value = TEX_SAMPLE(sColor0, vec3(uv_y, yuv_layers.x)).gbr;
} else {
yuv_value = vec3(0.0);
switch (format) {
case YUV_FORMAT_PLANAR:
{
// The yuv_planar format should have this third texture coordinate.
vec2 uv_y = clamp(in_uv_y, uv_bounds_y.xy, uv_bounds_y.zw);
vec2 uv_u = clamp(in_uv_u, uv_bounds_u.xy, uv_bounds_u.zw);
vec2 uv_v = clamp(in_uv_v, uv_bounds_v.xy, uv_bounds_v.zw);
yuv_value.x = TEX_SAMPLE(sColor0, vec3(uv_y, yuv_layers.x)).r;
yuv_value.y = TEX_SAMPLE(sColor1, vec3(uv_u, yuv_layers.y)).r;
yuv_value.z = TEX_SAMPLE(sColor2, vec3(uv_v, yuv_layers.z)).r;
}
break;
case YUV_FORMAT_NV12:
{
vec2 uv_y = clamp(in_uv_y, uv_bounds_y.xy, uv_bounds_y.zw);
vec2 uv_uv = clamp(in_uv_u, uv_bounds_u.xy, uv_bounds_u.zw);
yuv_value.x = TEX_SAMPLE(sColor0, vec3(uv_y, yuv_layers.x)).r;
yuv_value.yz = TEX_SAMPLE(sColor1, vec3(uv_uv, yuv_layers.y)).rg;
}
break;
case YUV_FORMAT_INTERLEAVED:
{
// "The Y, Cb and Cr color channels within the 422 data are mapped into
// the existing green, blue and red color channels."
// https://www.khronos.org/registry/OpenGL/extensions/APPLE/APPLE_rgb_422.txt
vec2 uv_y = clamp(in_uv_y, uv_bounds_y.xy, uv_bounds_y.zw);
yuv_value = TEX_SAMPLE(sColor0, vec3(uv_y, yuv_layers.x)).gbr;
}
break;
default:
yuv_value = vec3(0.0);
break;
}
// See the YuvColorMatrix definition for an explanation of where the constants come from.