Bug 1621454 - implement SWGL shaders for brush_image/solid/opacity. r=jrmuizel

Differential Revision: https://phabricator.services.mozilla.com/D95110
This commit is contained in:
Lee Salzman 2020-10-31 13:30:57 +00:00
Родитель b8fb6a6412
Коммит ee92d8de85
5 изменённых файлов: 184 добавлений и 0 удалений

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

@ -333,4 +333,88 @@ Fragment brush_fs() {
return frag;
}
#if defined(SWGL) && (!defined(WR_FEATURE_ALPHA_PASS) || !defined(WR_FEATURE_DUAL_SOURCE_BLENDING))
void swgl_drawSpanRGBA8() {
if (!swgl_isTextureRGBA8(sColor0) || !swgl_isTextureLinear(sColor0)) {
return;
}
#ifdef WR_FEATURE_ALPHA_PASS
if (v_mask_swizzle != vec2(1.0, 0.0)) {
return;
}
#endif
int layer = swgl_textureLayerOffset(sColor0, v_layer_and_perspective.x);
float perspective_divisor = mix(swgl_forceScalar(gl_FragCoord.w), 1.0, v_layer_and_perspective.y);
#ifndef WR_FEATURE_REPETITION
vec2 uv = swgl_linearQuantize(sColor0, v_uv * perspective_divisor + v_uv_bounds.xy);
vec2 min_uv = swgl_linearQuantize(sColor0, v_uv_sample_bounds.xy);
vec2 max_uv = swgl_linearQuantize(sColor0, v_uv_sample_bounds.zw);
vec2 step_uv = swgl_linearQuantizeStep(sColor0, swgl_interpStep(v_uv)) * perspective_divisor;
#endif
#ifdef WR_FEATURE_ALPHA_PASS
if (needs_clip()) {
while (swgl_SpanLength > 0) {
vec4 color = v_color * do_clip();
#ifdef WR_FEATURE_ANTIALIASING
color *= init_transform_fs(v_local_pos);
v_local_pos += swgl_interpStep(v_local_pos);
#endif
#ifdef WR_FEATURE_REPETITION
vec2 repeated_uv = compute_repeated_uvs(perspective_divisor);
vec2 uv = clamp(repeated_uv, v_uv_sample_bounds.xy, v_uv_sample_bounds.zw);
swgl_commitTextureLinearColorRGBA8(sColor0, swgl_linearQuantize(sColor0, uv), color, layer);
v_uv += swgl_interpStep(v_uv);
#else
swgl_commitTextureLinearColorRGBA8(sColor0, clamp(uv, min_uv, max_uv), color, layer);
uv += step_uv;
#endif
vClipMaskUv += swgl_interpStep(vClipMaskUv);
}
return;
#ifdef WR_FEATURE_ANTIALIASING
} else {
#else
} else if (v_color != vec4(1.0)) {
#endif
while (swgl_SpanLength > 0) {
vec4 color = v_color;
#ifdef WR_FEATURE_ANTIALIASING
color *= init_transform_fs(v_local_pos);
v_local_pos += swgl_interpStep(v_local_pos);
#endif
#ifdef WR_FEATURE_REPETITION
vec2 repeated_uv = compute_repeated_uvs(perspective_divisor);
vec2 uv = clamp(repeated_uv, v_uv_sample_bounds.xy, v_uv_sample_bounds.zw);
swgl_commitTextureLinearColorRGBA8(sColor0, swgl_linearQuantize(sColor0, uv), color, layer);
v_uv += swgl_interpStep(v_uv);
#else
swgl_commitTextureLinearColorRGBA8(sColor0, clamp(uv, min_uv, max_uv), color, layer);
uv += step_uv;
#endif
}
return;
}
// No clip or color scaling required, so just fall through to a normal textured span...
#endif
while (swgl_SpanLength > 0) {
#ifdef WR_FEATURE_REPETITION
vec2 repeated_uv = compute_repeated_uvs(perspective_divisor);
vec2 uv = clamp(repeated_uv, v_uv_sample_bounds.xy, v_uv_sample_bounds.zw);
swgl_commitTextureLinearRGBA8(sColor0, swgl_linearQuantize(sColor0, uv), layer);
v_uv += swgl_interpStep(v_uv);
#else
swgl_commitTextureLinearRGBA8(sColor0, clamp(uv, min_uv, max_uv), layer);
uv += step_uv;
#endif
}
}
#endif
#endif

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

@ -76,4 +76,45 @@ Fragment brush_fs() {
// Pre-multiply the contribution of the opacity factor.
return Fragment(alpha * color);
}
#if defined(SWGL) && !defined(WR_FEATURE_DUAL_SOURCE_BLENDING)
void swgl_drawSpanRGBA8() {
if (!swgl_isTextureRGBA8(sColor0)) {
return;
}
int layer = swgl_textureLayerOffset(sColor0, v_layer_and_perspective.x);
float perspective_divisor = mix(swgl_forceScalar(gl_FragCoord.w), 1.0, v_layer_and_perspective.y);
vec2 uv = swgl_linearQuantize(sColor0, v_uv * perspective_divisor);
vec2 min_uv = swgl_linearQuantize(sColor0, v_uv_sample_bounds.xy);
vec2 max_uv = swgl_linearQuantize(sColor0, v_uv_sample_bounds.zw);
vec2 step_uv = swgl_linearQuantizeStep(sColor0, swgl_interpStep(v_uv)) * perspective_divisor;
if (needs_clip()) {
while (swgl_SpanLength > 0) {
float alpha = v_opacity * do_clip();
#ifdef WR_FEATURE_ANTIALIASING
alpha *= init_transform_fs(v_local_pos);
v_local_pos += swgl_interpStep(v_local_pos);
#endif
swgl_commitTextureLinearColorRGBA8(sColor0, clamp(uv, min_uv, max_uv), alpha, layer);
uv += step_uv;
vClipMaskUv += swgl_interpStep(vClipMaskUv);
}
} else {
while (swgl_SpanLength > 0) {
float alpha = v_opacity;
#ifdef WR_FEATURE_ANTIALIASING
alpha *= init_transform_fs(v_local_pos);
v_local_pos += swgl_interpStep(v_local_pos);
#endif
swgl_commitTextureLinearColorRGBA8(sColor0, clamp(uv, min_uv, max_uv), alpha, layer);
uv += step_uv;
}
}
}
#endif
#endif

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

@ -54,4 +54,55 @@ Fragment brush_fs() {
#endif
return Fragment(color);
}
#if defined(SWGL) && (!defined(WR_FEATURE_ALPHA_PASS) || !defined(WR_FEATURE_DUAL_SOURCE_BLENDING))
void swgl_drawSpanRGBA8() {
#ifdef WR_FEATURE_ALPHA_PASS
if (needs_clip()) {
while (swgl_SpanLength > 0) {
float alpha = init_transform_fs(v_local_pos) * do_clip();
swgl_commitColorRGBA8(v_color, alpha);
v_local_pos += swgl_interpStep(v_local_pos);
vClipMaskUv += swgl_interpStep(vClipMaskUv);
}
return;
} else if (has_valid_transform_bounds()) {
while (swgl_SpanLength > 0) {
float alpha = init_transform_fs(v_local_pos);
swgl_commitColorRGBA8(v_color, alpha);
v_local_pos += swgl_interpStep(v_local_pos);
}
return;
}
// No clip or transform, so just fall through to a solid span...
#endif
swgl_commitSolidRGBA8(v_color);
}
void swgl_drawSpanR8() {
#ifdef WR_FEATURE_ALPHA_PASS
if (needs_clip()) {
while (swgl_SpanLength > 0) {
float alpha = init_transform_fs(v_local_pos) * do_clip();
swgl_commitColorR8(v_color.x, alpha);
v_local_pos += swgl_interpStep(v_local_pos);
vClipMaskUv += swgl_interpStep(vClipMaskUv);
}
return;
} else if (has_valid_transform_bounds()) {
while (swgl_SpanLength > 0) {
float alpha = init_transform_fs(v_local_pos);
swgl_commitColorR8(v_color.x, alpha);
v_local_pos += swgl_interpStep(v_local_pos);
}
return;
}
// No clip or transform, so just fall through to a solid span...
#endif
swgl_commitSolidR8(v_color.x);
}
#endif
#endif

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

@ -248,6 +248,9 @@ struct Fragment {
#endif
};
bool needs_clip() {
return vClipMaskUvBounds.xy != vClipMaskUvBounds.zw;
}
float do_clip() {
// check for the dummy bounds, which are given to the opaque objects

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

@ -93,6 +93,11 @@ vec4 get_node_pos(vec2 pos, Transform transform) {
#ifdef WR_FRAGMENT_SHADER
// Assume transform bounds are set to a large scale to signal they are invalid.
bool has_valid_transform_bounds() {
return vTransformBounds.w < 1.0e15;
}
float signed_distance_rect(vec2 pos, vec2 p0, vec2 p1) {
vec2 d = max(p0 - pos, pos - p1);
return length(max(vec2(0.0), d)) + min(0.0, max(d.x, d.y));