mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-26 13:41:07 +00:00
gpu: Track position fwidth explicitly
This is relevant went encountering repeat nodes, where the repeat cutoff will make the fwidth of the position go wild otherwise. Gradients require more work now, because we need to compute offsets twice - once for the pixel, once for the offst.
This commit is contained in:
parent
6cbf4667a4
commit
a301f18ebf
@ -24,6 +24,32 @@ stack_pop (void)
|
|||||||
return stack[stack_size];
|
return stack[stack_size];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Position
|
||||||
|
{
|
||||||
|
/* pos.xy is the actual position
|
||||||
|
pos.zw is the fwidth() of it
|
||||||
|
*/
|
||||||
|
vec4 pos;
|
||||||
|
};
|
||||||
|
|
||||||
|
vec2
|
||||||
|
position (Position pos)
|
||||||
|
{
|
||||||
|
return pos.pos.xy;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2
|
||||||
|
position_fwidth (Position pos)
|
||||||
|
{
|
||||||
|
return pos.pos.zw;
|
||||||
|
}
|
||||||
|
|
||||||
|
Position
|
||||||
|
position_new (vec2 pos)
|
||||||
|
{
|
||||||
|
return Position (vec4 (pos, fwidth (pos)));
|
||||||
|
}
|
||||||
|
|
||||||
uint
|
uint
|
||||||
read_uint (inout uint reader)
|
read_uint (inout uint reader)
|
||||||
{
|
{
|
||||||
@ -85,18 +111,17 @@ read_gradient (inout uint reader)
|
|||||||
void
|
void
|
||||||
clip_pattern (inout uint reader,
|
clip_pattern (inout uint reader,
|
||||||
inout vec4 color,
|
inout vec4 color,
|
||||||
vec2 pos)
|
Position pos)
|
||||||
{
|
{
|
||||||
Rect clip = read_rect (reader);
|
Rect clip = read_rect (reader);
|
||||||
float alpha = rect_coverage (clip, pos);
|
float alpha = rect_coverage (clip, position (pos), abs (position_fwidth (pos)));
|
||||||
|
|
||||||
color *= alpha;
|
color *= alpha;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
opacity_pattern (inout uint reader,
|
opacity_pattern (inout uint reader,
|
||||||
inout vec4 color,
|
inout vec4 color)
|
||||||
vec2 pos)
|
|
||||||
{
|
{
|
||||||
float opacity = read_float (reader);
|
float opacity = read_float (reader);
|
||||||
|
|
||||||
@ -105,8 +130,7 @@ opacity_pattern (inout uint reader,
|
|||||||
|
|
||||||
void
|
void
|
||||||
color_matrix_pattern (inout uint reader,
|
color_matrix_pattern (inout uint reader,
|
||||||
inout vec4 color,
|
inout vec4 color)
|
||||||
vec2 pos)
|
|
||||||
{
|
{
|
||||||
mat4 matrix = read_mat4 (reader);
|
mat4 matrix = read_mat4 (reader);
|
||||||
vec4 offset = read_vec4 (reader);
|
vec4 offset = read_vec4 (reader);
|
||||||
@ -120,24 +144,24 @@ color_matrix_pattern (inout uint reader,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
repeat_push_pattern (inout uint reader,
|
repeat_push_pattern (inout uint reader,
|
||||||
inout vec2 pos)
|
inout Position pos)
|
||||||
{
|
{
|
||||||
stack_push (vec4 (pos, 0.0, 0.0));
|
stack_push (pos.pos);
|
||||||
Rect bounds = read_rect (reader);
|
Rect bounds = read_rect (reader);
|
||||||
|
|
||||||
vec2 size = rect_size (bounds);
|
vec2 size = rect_size (bounds);
|
||||||
pos = mod (pos - bounds.bounds.xy, size);
|
pos.pos.xy = mod (pos.pos.xy - bounds.bounds.xy, size);
|
||||||
/* make sure we have a positive result */
|
/* make sure we have a positive result */
|
||||||
pos = mix (pos, pos + size, lessThan (pos, vec2 (0.0)));
|
pos.pos.xy = mix (pos.pos.xy, pos.pos.xy + size, lessThan (pos.pos.xy, vec2 (0.0)));
|
||||||
pos += bounds.bounds.xy;
|
pos.pos.xy += bounds.bounds.xy;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
position_pop_pattern (inout uint reader,
|
position_pop_pattern (inout uint reader,
|
||||||
inout vec2 pos)
|
inout Position pos)
|
||||||
{
|
{
|
||||||
pos = stack_pop ().xy;
|
pos = Position (stack_pop ());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -188,22 +212,24 @@ mask_inverted_luminance_pattern (inout uint reader,
|
|||||||
|
|
||||||
vec4
|
vec4
|
||||||
glyphs_pattern (inout uint reader,
|
glyphs_pattern (inout uint reader,
|
||||||
vec2 pos)
|
Position pos)
|
||||||
{
|
{
|
||||||
float opacity = 0.0;
|
float opacity = 0.0;
|
||||||
vec4 color = color_premultiply (read_vec4 (reader));
|
vec4 color = color_premultiply (read_vec4 (reader));
|
||||||
uint num_glyphs = read_uint (reader);
|
uint num_glyphs = read_uint (reader);
|
||||||
uint i;
|
uint i;
|
||||||
|
|
||||||
|
vec2 p = position (pos);
|
||||||
|
vec2 dFdp = abs (position_fwidth (pos));
|
||||||
for (i = 0u; i < num_glyphs; i++)
|
for (i = 0u; i < num_glyphs; i++)
|
||||||
{
|
{
|
||||||
uint tex_id = read_uint (reader);
|
uint tex_id = read_uint (reader);
|
||||||
Rect glyph_bounds = read_rect (reader);
|
Rect glyph_bounds = read_rect (reader);
|
||||||
vec4 tex_rect = read_vec4 (reader);
|
vec4 tex_rect = read_vec4 (reader);
|
||||||
|
|
||||||
float coverage = rect_coverage (glyph_bounds, pos);
|
float coverage = rect_coverage (glyph_bounds, p, dFdp);
|
||||||
if (coverage > 0.0)
|
if (coverage > 0.0)
|
||||||
opacity += coverage * gsk_texture (tex_id, (pos - GSK_GLOBAL_SCALE * tex_rect.xy) / (GSK_GLOBAL_SCALE * tex_rect.zw)).a;
|
opacity += coverage * gsk_texture (tex_id, (p - GSK_GLOBAL_SCALE * tex_rect.xy) / (GSK_GLOBAL_SCALE * tex_rect.zw)).a;
|
||||||
}
|
}
|
||||||
|
|
||||||
return color * opacity;
|
return color * opacity;
|
||||||
@ -211,27 +237,27 @@ glyphs_pattern (inout uint reader,
|
|||||||
|
|
||||||
vec4
|
vec4
|
||||||
texture_pattern (inout uint reader,
|
texture_pattern (inout uint reader,
|
||||||
vec2 pos)
|
Position pos)
|
||||||
{
|
{
|
||||||
uint tex_id = read_uint (reader);
|
uint tex_id = read_uint (reader);
|
||||||
vec4 tex_rect = read_vec4 (reader);
|
vec4 tex_rect = read_vec4 (reader);
|
||||||
|
|
||||||
return gsk_texture (tex_id, (pos - GSK_GLOBAL_SCALE * tex_rect.xy) / (GSK_GLOBAL_SCALE * tex_rect.zw));
|
return gsk_texture (tex_id, (position (pos) - GSK_GLOBAL_SCALE * tex_rect.xy) / (GSK_GLOBAL_SCALE * tex_rect.zw));
|
||||||
}
|
}
|
||||||
|
|
||||||
vec4
|
vec4
|
||||||
straight_alpha_pattern (inout uint reader,
|
straight_alpha_pattern (inout uint reader,
|
||||||
vec2 pos)
|
Position pos)
|
||||||
{
|
{
|
||||||
uint tex_id = read_uint (reader);
|
uint tex_id = read_uint (reader);
|
||||||
vec4 tex_rect = read_vec4 (reader);
|
vec4 tex_rect = read_vec4 (reader);
|
||||||
|
|
||||||
return gsk_texture_straight_alpha (tex_id, (pos - GSK_GLOBAL_SCALE * tex_rect.xy) / (GSK_GLOBAL_SCALE * tex_rect.zw));
|
return gsk_texture_straight_alpha (tex_id, (position (pos) - GSK_GLOBAL_SCALE * tex_rect.xy) / (GSK_GLOBAL_SCALE * tex_rect.zw));
|
||||||
}
|
}
|
||||||
|
|
||||||
vec4
|
vec4
|
||||||
linear_gradient_pattern (inout uint reader,
|
linear_gradient_pattern (inout uint reader,
|
||||||
vec2 pos,
|
Position pos,
|
||||||
bool repeating)
|
bool repeating)
|
||||||
{
|
{
|
||||||
vec2 start = read_vec2 (reader) * GSK_GLOBAL_SCALE;
|
vec2 start = read_vec2 (reader) * GSK_GLOBAL_SCALE;
|
||||||
@ -240,8 +266,9 @@ linear_gradient_pattern (inout uint reader,
|
|||||||
|
|
||||||
vec2 line = end - start;
|
vec2 line = end - start;
|
||||||
float line_length = dot (line, line);
|
float line_length = dot (line, line);
|
||||||
float offset = dot (pos - start, line) / line_length;
|
float offset = dot (position (pos) - start, line) / line_length;
|
||||||
float d_offset = 0.5 * fwidth (offset);
|
float other_offset = dot (position (pos) + position_fwidth (pos) - start, line) / line_length;
|
||||||
|
float d_offset = 0.5 * abs (offset - other_offset);
|
||||||
|
|
||||||
if (repeating)
|
if (repeating)
|
||||||
return gradient_get_color_repeating (gradient, offset - d_offset, offset + d_offset);
|
return gradient_get_color_repeating (gradient, offset - d_offset, offset + d_offset);
|
||||||
@ -251,7 +278,7 @@ linear_gradient_pattern (inout uint reader,
|
|||||||
|
|
||||||
vec4
|
vec4
|
||||||
radial_gradient_pattern (inout uint reader,
|
radial_gradient_pattern (inout uint reader,
|
||||||
vec2 pos,
|
Position pos,
|
||||||
bool repeating)
|
bool repeating)
|
||||||
{
|
{
|
||||||
vec2 center = read_vec2 (reader) * GSK_GLOBAL_SCALE;
|
vec2 center = read_vec2 (reader) * GSK_GLOBAL_SCALE;
|
||||||
@ -260,9 +287,11 @@ radial_gradient_pattern (inout uint reader,
|
|||||||
float end = read_float (reader);
|
float end = read_float (reader);
|
||||||
Gradient gradient = read_gradient (reader);
|
Gradient gradient = read_gradient (reader);
|
||||||
|
|
||||||
float offset = length ((pos - center) / radius);
|
float offset = length ((position (pos) - center) / radius);
|
||||||
|
float other_offset = length ((position (pos) + position_fwidth (pos) - center) / radius);
|
||||||
offset = (offset - start) / (end - start);
|
offset = (offset - start) / (end - start);
|
||||||
float d_offset = 0.5 * fwidth (offset);
|
other_offset = (other_offset - start) / (end - start);
|
||||||
|
float d_offset = abs (0.5 * (offset - other_offset));
|
||||||
|
|
||||||
if (repeating)
|
if (repeating)
|
||||||
return gradient_get_color_repeating (gradient, offset - d_offset, offset + d_offset);
|
return gradient_get_color_repeating (gradient, offset - d_offset, offset + d_offset);
|
||||||
@ -272,19 +301,24 @@ radial_gradient_pattern (inout uint reader,
|
|||||||
|
|
||||||
vec4
|
vec4
|
||||||
conic_gradient_pattern (inout uint reader,
|
conic_gradient_pattern (inout uint reader,
|
||||||
vec2 pos)
|
Position pos)
|
||||||
{
|
{
|
||||||
vec2 center = read_vec2 (reader);
|
vec2 center = read_vec2 (reader);
|
||||||
float angle = read_float (reader);
|
float angle = read_float (reader);
|
||||||
Gradient gradient = read_gradient (reader);
|
Gradient gradient = read_gradient (reader);
|
||||||
|
|
||||||
/* scaling modifies angles, so be sure to use right coordinate system */
|
/* scaling modifies angles, so be sure to use right coordinate system */
|
||||||
pos = pos / GSK_GLOBAL_SCALE - center;
|
vec2 dpos = position (pos) / GSK_GLOBAL_SCALE - center;
|
||||||
float offset = atan (pos.y, pos.x);
|
vec2 dpos2 = (position (pos) + position_fwidth (pos)) / GSK_GLOBAL_SCALE - center;
|
||||||
|
float offset = atan (dpos.y, dpos.x);
|
||||||
|
float offset2 = atan (dpos2.y, dpos2.x);
|
||||||
offset = degrees (offset + angle) / 360.0;
|
offset = degrees (offset + angle) / 360.0;
|
||||||
|
offset2 = degrees (offset2 + angle) / 360.0;
|
||||||
float overflow = fract (offset + 0.5);
|
float overflow = fract (offset + 0.5);
|
||||||
|
float overflow2 = fract (offset2 + 0.5);
|
||||||
offset = fract (offset);
|
offset = fract (offset);
|
||||||
float d_offset = max (0.00001, 0.5 * min (fwidth (offset), fwidth (overflow)));
|
offset2 = fract (offset2);
|
||||||
|
float d_offset = max (0.00001, 0.5 * min (abs (offset - offset2), abs (overflow - overflow2)));
|
||||||
|
|
||||||
return gradient_get_color_repeating (gradient, offset - d_offset, offset + d_offset);
|
return gradient_get_color_repeating (gradient, offset - d_offset, offset + d_offset);
|
||||||
}
|
}
|
||||||
@ -299,9 +333,10 @@ color_pattern (inout uint reader)
|
|||||||
|
|
||||||
vec4
|
vec4
|
||||||
pattern (uint reader,
|
pattern (uint reader,
|
||||||
vec2 pos)
|
vec2 pos_)
|
||||||
{
|
{
|
||||||
vec4 color = vec4 (1.0, 0.0, 0.8, 1.0); /* pink */
|
vec4 color = vec4 (1.0, 0.0, 0.8, 1.0); /* pink */
|
||||||
|
Position pos = position_new (pos_);
|
||||||
|
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
@ -324,10 +359,10 @@ pattern (uint reader,
|
|||||||
color = glyphs_pattern (reader, pos);
|
color = glyphs_pattern (reader, pos);
|
||||||
break;
|
break;
|
||||||
case GSK_GPU_PATTERN_COLOR_MATRIX:
|
case GSK_GPU_PATTERN_COLOR_MATRIX:
|
||||||
color_matrix_pattern (reader, color, pos);
|
color_matrix_pattern (reader, color);
|
||||||
break;
|
break;
|
||||||
case GSK_GPU_PATTERN_OPACITY:
|
case GSK_GPU_PATTERN_OPACITY:
|
||||||
opacity_pattern (reader, color, pos);
|
opacity_pattern (reader, color);
|
||||||
break;
|
break;
|
||||||
case GSK_GPU_PATTERN_LINEAR_GRADIENT:
|
case GSK_GPU_PATTERN_LINEAR_GRADIENT:
|
||||||
color = linear_gradient_pattern (reader, pos, false);
|
color = linear_gradient_pattern (reader, pos, false);
|
||||||
|
@ -78,15 +78,23 @@ rect_get_coord (Rect r, vec2 pt)
|
|||||||
#ifdef GSK_FRAGMENT_SHADER
|
#ifdef GSK_FRAGMENT_SHADER
|
||||||
|
|
||||||
float
|
float
|
||||||
rect_coverage (Rect r, vec2 p)
|
rect_coverage (Rect r,
|
||||||
|
vec2 p,
|
||||||
|
vec2 dFdp)
|
||||||
{
|
{
|
||||||
vec2 dFdp = abs(fwidth (p));
|
|
||||||
Rect prect = Rect(vec4(p - 0.5 * dFdp, p + 0.5 * dFdp));
|
Rect prect = Rect(vec4(p - 0.5 * dFdp, p + 0.5 * dFdp));
|
||||||
Rect coverect = rect_intersect (r, prect);
|
Rect coverect = rect_intersect (r, prect);
|
||||||
vec2 coverage = rect_size(coverect) / dFdp;
|
vec2 coverage = rect_size(coverect) / dFdp;
|
||||||
return coverage.x * coverage.y;
|
return coverage.x * coverage.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float
|
||||||
|
rect_coverage (Rect r, vec2 p)
|
||||||
|
{
|
||||||
|
return rect_coverage (r, p, abs (fwidth (p)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user