forked from AuroraMiddleware/gtk
gl renderer: Transform rounded rect on the GPU
Change the RoundedRect struct we use in our shaders so we can transform it using (affine) matrices.
This commit is contained in:
parent
f9e613f8fd
commit
c8fa1f19db
@ -535,17 +535,16 @@ transform_rect (GskGLRenderer *self,
|
||||
RenderOpBuilder *builder,
|
||||
const GskRoundedRect *rect)
|
||||
{
|
||||
const float scale = ops_get_scale (builder);
|
||||
GskRoundedRect r;
|
||||
int i;
|
||||
|
||||
ops_transform_bounds_modelview (builder, &rect->bounds, &r.bounds);
|
||||
r.bounds.origin.x = builder->dx + rect->bounds.origin.x;
|
||||
r.bounds.origin.y = builder->dy + rect->bounds.origin.y;
|
||||
r.bounds.size = rect->bounds.size;
|
||||
|
||||
for (i = 0; i < 4; i ++)
|
||||
{
|
||||
r.corner[i].width = rect->corner[i].width * scale;
|
||||
r.corner[i].height = rect->corner[i].height * scale;
|
||||
}
|
||||
r.corner[0] = rect->corner[0];
|
||||
r.corner[1] = rect->corner[1];
|
||||
r.corner[2] = rect->corner[2];
|
||||
r.corner[3] = rect->corner[3];
|
||||
|
||||
return r;
|
||||
}
|
||||
@ -745,24 +744,22 @@ render_border_node (GskGLRenderer *self,
|
||||
GskRenderNode *node,
|
||||
RenderOpBuilder *builder)
|
||||
{
|
||||
const float scale = ops_get_scale (builder);
|
||||
const float min_x = builder->dx + node->bounds.origin.x;
|
||||
const float min_y = builder->dy + node->bounds.origin.y;
|
||||
const float max_x = min_x + node->bounds.size.width;
|
||||
const float max_y = min_y + node->bounds.size.height;
|
||||
const GdkRGBA *colors = gsk_border_node_peek_colors (node);
|
||||
const GskRoundedRect *rounded_outline = gsk_border_node_peek_outline (node);
|
||||
const float *og_widths = gsk_border_node_peek_widths (node);
|
||||
float widths[4];
|
||||
const float *widths = gsk_border_node_peek_widths (node);
|
||||
int i;
|
||||
struct {
|
||||
float w;
|
||||
float h;
|
||||
} sizes[4];
|
||||
|
||||
if (og_widths[0] == og_widths[1] &&
|
||||
og_widths[0] == og_widths[2] &&
|
||||
og_widths[0] == og_widths[3] &&
|
||||
if (widths[0] == widths[1] &&
|
||||
widths[0] == widths[2] &&
|
||||
widths[0] == widths[3] &&
|
||||
gdk_rgba_equal (&colors[0], &colors[1]) &&
|
||||
gdk_rgba_equal (&colors[0], &colors[2]) &&
|
||||
gdk_rgba_equal (&colors[0], &colors[3]))
|
||||
@ -773,7 +770,7 @@ render_border_node (GskGLRenderer *self,
|
||||
op = ops_begin (builder, OP_CHANGE_INSET_SHADOW);
|
||||
op->color = &colors[0];
|
||||
op->outline = transform_rect (self, builder, rounded_outline);
|
||||
op->spread = og_widths[0] * scale;
|
||||
op->spread = widths[0];
|
||||
op->offset[0] = 0;
|
||||
op->offset[1] = 0;
|
||||
|
||||
@ -781,9 +778,6 @@ render_border_node (GskGLRenderer *self,
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i ++)
|
||||
widths[i] = og_widths[i];
|
||||
|
||||
/* Top left */
|
||||
if (widths[3] > 0)
|
||||
sizes[0].w = MAX (widths[3], rounded_outline->corner[0].width);
|
||||
@ -829,9 +823,6 @@ render_border_node (GskGLRenderer *self,
|
||||
else
|
||||
sizes[3].h = 0;
|
||||
|
||||
for (i = 0; i < 4; i ++)
|
||||
widths[i] *= scale;
|
||||
|
||||
{
|
||||
const GskQuadVertex side_data[4][6] = {
|
||||
/* Top */
|
||||
@ -1481,7 +1472,6 @@ render_unblurred_inset_shadow_node (GskGLRenderer *self,
|
||||
GskRenderNode *node,
|
||||
RenderOpBuilder *builder)
|
||||
{
|
||||
const float scale = ops_get_scale (builder);
|
||||
const float blur_radius = gsk_inset_shadow_node_get_blur_radius (node);
|
||||
const float dx = gsk_inset_shadow_node_get_dx (node);
|
||||
const float dy = gsk_inset_shadow_node_get_dy (node);
|
||||
@ -1494,9 +1484,9 @@ render_unblurred_inset_shadow_node (GskGLRenderer *self,
|
||||
op = ops_begin (builder, OP_CHANGE_INSET_SHADOW);
|
||||
op->color = gsk_inset_shadow_node_peek_color (node);
|
||||
op->outline = transform_rect (self, builder, gsk_inset_shadow_node_peek_outline (node));
|
||||
op->spread = spread * scale;
|
||||
op->offset[0] = dx * scale;
|
||||
op->offset[1] = dy * scale;
|
||||
op->spread = spread;
|
||||
op->offset[0] = dx;
|
||||
op->offset[1] = dy;
|
||||
|
||||
load_vertex_data (ops_draw (builder, NULL), node, builder);
|
||||
}
|
||||
@ -1647,7 +1637,6 @@ render_unblurred_outset_shadow_node (GskGLRenderer *self,
|
||||
GskRenderNode *node,
|
||||
RenderOpBuilder *builder)
|
||||
{
|
||||
const float scale = ops_get_scale (builder);
|
||||
const GskRoundedRect *outline = gsk_outset_shadow_node_peek_outline (node);
|
||||
const float spread = gsk_outset_shadow_node_get_spread (node);
|
||||
const float dx = gsk_outset_shadow_node_get_dx (node);
|
||||
@ -1658,9 +1647,9 @@ render_unblurred_outset_shadow_node (GskGLRenderer *self,
|
||||
op = ops_begin (builder, OP_CHANGE_UNBLURRED_OUTSET_SHADOW);
|
||||
op->color = gsk_outset_shadow_node_peek_color (node);
|
||||
op->outline = transform_rect (self, builder, outline);
|
||||
op->spread = spread * scale;
|
||||
op->offset[0] = dx * scale;
|
||||
op->offset[1] = dy * scale;
|
||||
op->spread = spread;
|
||||
op->offset[0] = dx;
|
||||
op->offset[1] = dy;
|
||||
|
||||
load_vertex_data (ops_draw (builder, NULL), node, builder);
|
||||
}
|
||||
|
@ -25,6 +25,9 @@ void main() {
|
||||
RoundedRect outside = create_rect(u_outline_rect);
|
||||
RoundedRect inside = rounded_rect_shrink (outside, u_widths);
|
||||
|
||||
rounded_rect_transform(outside, u_modelview);
|
||||
rounded_rect_transform(inside, u_modelview);
|
||||
|
||||
float alpha = clamp (rounded_rect_coverage (outside, f.xy) -
|
||||
rounded_rect_coverage (inside, f.xy),
|
||||
0.0, 1.0);
|
||||
|
@ -20,15 +20,21 @@ _IN_ vec4 final_color;
|
||||
|
||||
void main() {
|
||||
vec4 f = gl_FragCoord;
|
||||
vec4 color;
|
||||
|
||||
f.x += u_viewport.x;
|
||||
f.y = (u_viewport.y + u_viewport.w) - f.y;
|
||||
|
||||
RoundedRect outside = create_rect(u_outline_rect);
|
||||
RoundedRect inside = rounded_rect_shrink(outside, vec4(u_spread));
|
||||
color = final_color * clamp (rounded_rect_coverage (outside, f.xy) -
|
||||
rounded_rect_coverage (inside, f.xy - u_offset),
|
||||
0.0, 1.0);
|
||||
setOutputColor(color);
|
||||
|
||||
rounded_rect_offset(inside, u_offset);
|
||||
|
||||
rounded_rect_transform(outside, u_modelview);
|
||||
rounded_rect_transform(inside, u_modelview);
|
||||
|
||||
float alpha = clamp (rounded_rect_coverage (outside, f.xy) -
|
||||
rounded_rect_coverage (inside, f.xy),
|
||||
0.0, 1.0);
|
||||
|
||||
setOutputColor(final_color * alpha);
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ void main() {
|
||||
f.y = (u_viewport.y + u_viewport.w) - f.y;
|
||||
|
||||
RoundedRect outline = create_rect(u_outline_rect);
|
||||
rounded_rect_transform(outline, u_modelview);
|
||||
|
||||
float alpha = Texture(u_source, vUv).a;
|
||||
alpha *= (1.0 - clamp(rounded_rect_coverage(outline, f.xy), 0.0, 1.0));
|
||||
|
@ -6,7 +6,6 @@ precision highp float;
|
||||
precision highp float;
|
||||
#endif
|
||||
|
||||
|
||||
uniform sampler2D u_source;
|
||||
uniform mat4 u_projection;
|
||||
uniform mat4 u_modelview;
|
||||
@ -33,18 +32,24 @@ _IN_ vec2 vUv;
|
||||
struct RoundedRect
|
||||
{
|
||||
vec4 bounds;
|
||||
vec4 corner_widths;
|
||||
vec4 corner_heights;
|
||||
// Look, arrays can't be in structs if you want to return the struct
|
||||
// from a function in gles or whatever. Just kill me.
|
||||
vec4 corner_points1; // xy = top left, zw = top right
|
||||
vec4 corner_points2; // xy = bottom right, zw = bottom left
|
||||
};
|
||||
|
||||
// Transform from a GskRoundedRect to a RoundedRect as we need it.
|
||||
RoundedRect
|
||||
create_rect(vec4 data[3])
|
||||
create_rect(vec4[3] data)
|
||||
{
|
||||
vec4 bounds = vec4(data[0].xy, data[0].xy + data[0].zw);
|
||||
vec4 widths = vec4(data[1].x, data[1].z, data[2].x, data[2].z);
|
||||
vec4 heights = vec4(data[1].y, data[1].w, data[2].y, data[2].w);
|
||||
return RoundedRect(bounds, widths, heights);
|
||||
|
||||
vec4 corner_points1 = vec4(bounds.xy + data[1].xy,
|
||||
bounds.zy + vec2(data[1].zw * vec2(-1, 1)));
|
||||
vec4 corner_points2 = vec4(bounds.zw + (data[2].xy * vec2(-1, -1)),
|
||||
bounds.xw + vec2(data[2].zw * vec2(1, -1)));
|
||||
|
||||
return RoundedRect(bounds, corner_points1, corner_points2);
|
||||
}
|
||||
|
||||
float
|
||||
@ -73,15 +78,15 @@ rounded_rect_coverage (RoundedRect r, vec2 p)
|
||||
p.x >= r.bounds.z || p.y >= r.bounds.w)
|
||||
return 0.0;
|
||||
|
||||
vec2 rad_tl = vec2(r.corner_widths.x, r.corner_heights.x);
|
||||
vec2 rad_tr = vec2(r.corner_widths.y, r.corner_heights.y);
|
||||
vec2 rad_br = vec2(r.corner_widths.z, r.corner_heights.z);
|
||||
vec2 rad_bl = vec2(r.corner_widths.w, r.corner_heights.w);
|
||||
vec2 rad_tl = r.corner_points1.xy - r.bounds.xy;
|
||||
vec2 rad_tr = r.corner_points1.zw - r.bounds.zy;
|
||||
vec2 rad_br = r.corner_points2.xy - r.bounds.zw;
|
||||
vec2 rad_bl = r.corner_points2.zw - r.bounds.xw;
|
||||
|
||||
vec2 ref_tl = r.bounds.xy + vec2( r.corner_widths.x, r.corner_heights.x);
|
||||
vec2 ref_tr = r.bounds.zy + vec2(-r.corner_widths.y, r.corner_heights.y);
|
||||
vec2 ref_br = r.bounds.zw + vec2(-r.corner_widths.z, -r.corner_heights.z);
|
||||
vec2 ref_bl = r.bounds.xw + vec2( r.corner_widths.w, -r.corner_heights.w);
|
||||
vec2 ref_tl = r.corner_points1.xy;
|
||||
vec2 ref_tr = r.corner_points1.zw;
|
||||
vec2 ref_br = r.corner_points2.xy;
|
||||
vec2 ref_bl = r.corner_points2.zw;
|
||||
|
||||
float d_tl = ellipsis_coverage(p, ref_tl, rad_tl);
|
||||
float d_tr = ellipsis_coverage(p, ref_tr, rad_tr);
|
||||
@ -103,26 +108,38 @@ RoundedRect
|
||||
rounded_rect_shrink (RoundedRect r, vec4 amount)
|
||||
{
|
||||
vec4 new_bounds = r.bounds + vec4(1.0,1.0,-1.0,-1.0) * amount.wxyz;
|
||||
vec4 new_widths = vec4(0);
|
||||
vec4 new_heights = vec4(0);
|
||||
vec4 new_corner_points1 = r.corner_points1;
|
||||
vec4 new_corner_points2 = r.corner_points2;
|
||||
|
||||
// Left top
|
||||
if (r.corner_widths.x > 0.0) new_widths.x = r.corner_widths.x - amount.w;
|
||||
if (r.corner_heights.x > 0.0) new_heights.x = r.corner_heights.x - amount.x;
|
||||
if (r.corner_points1.xy == r.bounds.xy) new_corner_points1.xy = new_bounds.xy;
|
||||
if (r.corner_points1.zw == r.bounds.zy) new_corner_points1.zw = new_bounds.zy;
|
||||
if (r.corner_points2.xy == r.bounds.zw) new_corner_points2.xy = new_bounds.zw;
|
||||
if (r.corner_points2.zw == r.bounds.xw) new_corner_points2.zw = new_bounds.xw;
|
||||
|
||||
// Top right
|
||||
if (r.corner_widths.y > 0.0) new_widths.y = r.corner_widths.y - amount.y;
|
||||
if (r.corner_heights.y > 0.0) new_heights.y = r.corner_heights.y - amount.x;
|
||||
return RoundedRect (new_bounds, new_corner_points1, new_corner_points2);
|
||||
}
|
||||
|
||||
// Bottom right
|
||||
if (r.corner_widths.z > 0.0) new_widths.z = r.corner_widths.z - amount.y;
|
||||
if (r.corner_heights.z > 0.0) new_heights.z = r.corner_heights.z - amount.z;
|
||||
void
|
||||
rounded_rect_offset(inout RoundedRect r, vec2 offset)
|
||||
{
|
||||
r.bounds.xy += offset;
|
||||
r.bounds.zw += offset;
|
||||
r.corner_points1.xy += offset;
|
||||
r.corner_points1.zw += offset;
|
||||
r.corner_points2.xy += offset;
|
||||
r.corner_points2.zw += offset;
|
||||
}
|
||||
|
||||
// Bottom left
|
||||
if (r.corner_widths.w > 0.0) new_widths.w = r.corner_widths.w - amount.w;
|
||||
if (r.corner_heights.w > 0.0) new_heights.w = r.corner_heights.w - amount.z;
|
||||
void rounded_rect_transform(inout RoundedRect r, mat4 mat)
|
||||
{
|
||||
r.bounds.xy = (mat * vec4(r.bounds.xy, 0.0, 1.0)).xy;
|
||||
r.bounds.zw = (mat * vec4(r.bounds.zw, 0.0, 1.0)).xy;
|
||||
|
||||
return RoundedRect (new_bounds, new_widths, new_heights);
|
||||
r.corner_points1.xy = (mat * vec4(r.corner_points1.xy, 0.0, 1.0)).xy;
|
||||
r.corner_points1.zw = (mat * vec4(r.corner_points1.zw, 0.0, 1.0)).xy;
|
||||
|
||||
r.corner_points2.xy = (mat * vec4(r.corner_points2.xy, 0.0, 1.0)).xy;
|
||||
r.corner_points2.zw = (mat * vec4(r.corner_points2.zw, 0.0, 1.0)).xy;
|
||||
}
|
||||
|
||||
vec4 Texture(sampler2D sampler, vec2 texCoords) {
|
||||
@ -141,6 +158,9 @@ void setOutputColor(vec4 color) {
|
||||
f.x += u_viewport.x;
|
||||
f.y = (u_viewport.y + u_viewport.w) - f.y;
|
||||
|
||||
|
||||
// We do *NOT* transform the clip rect here since we already
|
||||
// need to do that on the CPU.
|
||||
#if GSK_GLES
|
||||
gl_FragColor = color * rounded_rect_coverage(create_rect(u_clip_rect), f.xy);
|
||||
#elif GSK_LEGACY
|
||||
|
@ -20,15 +20,21 @@ _IN_ vec4 final_color;
|
||||
|
||||
void main() {
|
||||
vec4 f = gl_FragCoord;
|
||||
vec4 color;
|
||||
|
||||
f.x += u_viewport.x;
|
||||
f.y = (u_viewport.y + u_viewport.w) - f.y;
|
||||
|
||||
RoundedRect inside = create_rect(u_outline_rect);
|
||||
RoundedRect outside = rounded_rect_shrink(inside, vec4(- u_spread));
|
||||
color = final_color * clamp (rounded_rect_coverage (outside, f.xy - u_offset) -
|
||||
rounded_rect_coverage (inside, f.xy),
|
||||
0.0, 1.0);
|
||||
setOutputColor(color);
|
||||
|
||||
rounded_rect_offset(outside, u_offset);
|
||||
|
||||
rounded_rect_transform(outside, u_modelview);
|
||||
rounded_rect_transform(inside, u_modelview);
|
||||
|
||||
float alpha = clamp (rounded_rect_coverage (outside, f.xy) -
|
||||
rounded_rect_coverage (inside, f.xy),
|
||||
0.0, 1.0);
|
||||
|
||||
setOutputColor(final_color * alpha);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user