зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset ec84f8196c4c (bug 1689316) for regressing macOS font rendering.
This commit is contained in:
Родитель
f9ad45c76b
Коммит
06dbf167c9
|
@ -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.
|
||||
|
|
Загрузка…
Ссылка в новой задаче