gl renderer: Fix clipped borders

Stop abusing the clip rect for borders.
This commit is contained in:
Timm Bäder
2018-03-15 17:27:19 +01:00
parent a475e6671c
commit 0a7880110e
4 changed files with 64 additions and 57 deletions

View File

@@ -242,28 +242,6 @@ struct _GskGLRendererClass
G_DEFINE_TYPE (GskGLRenderer, gsk_gl_renderer, GSK_TYPE_RENDERER)
static inline void
rounded_rect_intersect (GskGLRenderer *self,
RenderOpBuilder *builder,
const GskRoundedRect *rect,
GskRoundedRect *dest)
{
graphene_rect_t transformed_rect;
graphene_rect_t intersection;
int i;
graphene_matrix_transform_bounds (&builder->current_modelview, &rect->bounds, &transformed_rect);
graphene_rect_intersection (&transformed_rect, &builder->current_clip.bounds,
&intersection);
dest->bounds = intersection;
for (i = 0; i < 4; i ++)
{
dest->corner[i].width = rect->corner[i].width * self->scale_factor;
dest->corner[i].height = rect->corner[i].height * self->scale_factor;
}
}
static inline void
rounded_rect_to_floats (GskGLRenderer *self,
RenderOpBuilder *builder,
@@ -429,10 +407,9 @@ render_border_node (GskGLRenderer *self,
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);
GskRoundedRect outline;
float widths[4];
const gboolean needs_clip = TRUE;/*!gsk_rounded_rect_is_rectilinear (rounded_outline);*/
int i;
GskRoundedRect prev_clip;
struct {
float w;
float h;
@@ -490,22 +467,6 @@ render_border_node (GskGLRenderer *self,
for (i = 0; i < 4; i ++)
widths[i] *= self->scale_factor;
if (needs_clip)
{
GskRoundedRect child_clip;
ops_set_program (builder, &self->border_program);
rounded_rect_intersect (self, builder, rounded_outline, &child_clip);
prev_clip = ops_set_clip (builder, &child_clip);
ops_set_border (builder, widths);
}
else
{
ops_set_program (builder, &self->color_program);
}
{
const GskQuadVertex side_data[4][6] = {
/* Top */
@@ -555,6 +516,19 @@ render_border_node (GskGLRenderer *self,
/* We sort them by color */
sort_border_sides (colors, indices);
/* Prepare outline */
outline = *rounded_outline;
graphene_matrix_transform_bounds (&builder->current_modelview,
&outline.bounds, &outline.bounds);
for (i = 0; i < 4; i ++)
{
outline.corner[i].width *= self->scale_factor;
outline.corner[i].height *= self->scale_factor;
}
ops_set_program (builder, &self->border_program);
ops_set_border (builder, widths, &outline);
for (i = 0; i < 4; i ++)
{
if (widths[indices[i]] > 0)
@@ -564,9 +538,6 @@ render_border_node (GskGLRenderer *self,
}
}
}
if (needs_clip)
ops_set_clip (builder, &prev_clip);
}
static inline void
@@ -1696,9 +1667,29 @@ static inline void
apply_border_op (const Program *program,
const RenderOp *op)
{
const GskRoundedRect *o = &op->border.outline;
float outline[4];
float widths[4];
float heights[4];
int i;
OP_PRINT (" -> Border (%f, %f, %f, %f)",
op->border.widths[0], op->border.widths[1], op->border.widths[2], op->border.widths[3]);
outline[0] = o->bounds.origin.x;
outline[1] = o->bounds.origin.y;
outline[2] = o->bounds.size.width;
outline[3] = o->bounds.size.height;
for (i = 0; i < 4; i ++)
{
widths[i] = o->corner[i].width;
heights[i] = o->corner[i].height;
}
glUniform4fv (program->border.widths_location, 1, op->border.widths);
glUniform4fv (program->border.outline_location, 1, outline);
glUniform4fv (program->border.corner_widths_location, 1, widths);
glUniform4fv (program->border.corner_heights_location, 1, heights);
}
static inline void
@@ -1889,6 +1880,9 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self,
/* border */
INIT_PROGRAM_UNIFORM_LOCATION (border, color);
INIT_PROGRAM_UNIFORM_LOCATION (border, widths);
INIT_PROGRAM_UNIFORM_LOCATION (border, outline);
INIT_PROGRAM_UNIFORM_LOCATION (border, corner_widths);
INIT_PROGRAM_UNIFORM_LOCATION (border, corner_heights);
/* cross fade */
INIT_PROGRAM_UNIFORM_LOCATION (cross_fade, progress);

View File

@@ -309,13 +309,18 @@ ops_set_color_matrix (RenderOpBuilder *builder,
}
void
ops_set_border (RenderOpBuilder *builder,
const float *widths)
ops_set_border (RenderOpBuilder *builder,
const float *widths,
const GskRoundedRect *outline)
{
RenderOp op;
/* TODO: Assert that current_program == border program? */
if (memcmp (&builder->program_state[builder->current_program->index].border.widths,
widths, sizeof (float) * 4) == 0)
widths, sizeof (float) * 4) == 0 &&
memcmp (&builder->program_state[builder->current_program->index].border.outline,
outline, sizeof (GskRoundedRect)) == 0)
return;
memcpy (&builder->program_state[builder->current_program->index].border.widths,
@@ -326,6 +331,7 @@ ops_set_border (RenderOpBuilder *builder,
op.border.widths[1] = widths[1];
op.border.widths[2] = widths[2];
op.border.widths[3] = widths[3];
op.border.outline = *outline;
g_array_append_val (builder->render_ops, op);
}

View File

@@ -106,6 +106,9 @@ typedef struct
struct {
int color_location;
int widths_location;
int outline_location;
int corner_widths_location;
int corner_heights_location;
} border;
struct {
int source2_location;
@@ -183,6 +186,7 @@ typedef struct
struct {
float widths[4];
float color[4];
GskRoundedRect outline;
} border;
struct {
float progress;
@@ -211,6 +215,7 @@ typedef struct
struct {
float widths[4];
float color[4];
GskRoundedRect outline;
} border;
};
} program_state[GL_N_PROGRAMS];
@@ -265,7 +270,8 @@ void ops_set_color_matrix (RenderOpBuilder *builder,
const graphene_vec4_t *offset);
void ops_set_border (RenderOpBuilder *builder,
const float *widths);
const float *widths,
const GskRoundedRect *outline);
void ops_set_border_color (RenderOpBuilder *builder,
const GdkRGBA *color);

View File

@@ -1,20 +1,21 @@
uniform vec4 u_color;// = vec4(1, 0, 1, 1);
uniform vec4 u_color;
uniform vec4 u_widths;
// For border we abuse, ehm, re-use, the global clip
// as rounded rect and shrink it by u_widths
uniform vec4 u_outline;
uniform vec4 u_corner_widths;
uniform vec4 u_corner_heights;
void main() {
vec4 bounds = u_clip;
vec4 f = gl_FragCoord;
f.x += u_viewport.x;
f.y = (u_viewport.y + u_viewport.w) - f.y;
vec4 bounds = u_outline;
bounds.z = bounds.x + bounds.z;
bounds.w = bounds.y + bounds.w;
RoundedRect routside = RoundedRect (bounds, u_clip_corner_widths, u_clip_corner_heights);
vec4 f = gl_FragCoord;
f.x += u_viewport.x;
f.y = (u_viewport.y + u_viewport.w) - f.y;
RoundedRect routside = RoundedRect (bounds, u_corner_widths, u_corner_heights);
RoundedRect rinside = rounded_rect_shrink (routside, u_widths);
float alpha = clamp (rounded_rect_coverage (routside, f.xy) -