gl renderer: Moar state tracking

Track what we really need to send for inset shadows, which are used
as a border replacement in many cases.

Fishbowl says I can draw around 200-300 more switches per frame like
this too.
This commit is contained in:
Timm Bäder 2020-07-24 08:49:24 +02:00
parent f4d9e4032f
commit 72d4a83af8
7 changed files with 227 additions and 60 deletions

View File

@ -742,15 +742,9 @@ render_border_node (GskGLRenderer *self,
gdk_rgba_equal (&colors[0], &colors[2]) &&
gdk_rgba_equal (&colors[0], &colors[3]))
{
OpShadow *op;
ops_set_program (builder, &self->programs->inset_shadow_program);
op = ops_begin (builder, OP_CHANGE_INSET_SHADOW);
op->color = &colors[0];
op->outline = transform_rect (self, builder, rounded_outline);
op->spread = widths[0];
op->offset[0] = 0;
op->offset[1] = 0;
ops_set_inset_shadow (builder, transform_rect (self, builder, rounded_outline),
widths[0], &colors[0], 0, 0);
load_vertex_data (ops_draw (builder, NULL), node, builder);
return;
@ -1607,17 +1601,14 @@ render_unblurred_inset_shadow_node (GskGLRenderer *self,
const float dx = gsk_inset_shadow_node_get_dx (node);
const float dy = gsk_inset_shadow_node_get_dy (node);
const float spread = gsk_inset_shadow_node_get_spread (node);
OpShadow *op;
g_assert (blur_radius == 0);
ops_set_program (builder, &self->programs->inset_shadow_program);
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;
op->offset[0] = dx;
op->offset[1] = dy;
ops_set_inset_shadow (builder, transform_rect (self, builder, gsk_inset_shadow_node_peek_outline (node)),
spread,
gsk_inset_shadow_node_peek_color (node),
dx, dy);
load_vertex_data (ops_draw (builder, NULL), node, builder);
}
@ -1635,7 +1626,6 @@ render_inset_shadow_node (GskGLRenderer *self,
const GskRoundedRect *node_outline = gsk_inset_shadow_node_peek_outline (node);
float texture_width;
float texture_height;
OpShadow *op;
int blurred_texture_id;
g_assert (blur_radius > 0);
@ -1699,12 +1689,10 @@ render_inset_shadow_node (GskGLRenderer *self,
/* Actual inset shadow outline drawing */
ops_set_program (builder, &self->programs->inset_shadow_program);
op = ops_begin (builder, OP_CHANGE_INSET_SHADOW);
op->color = gsk_inset_shadow_node_peek_color (node);
op->outline = transform_rect (self, builder, &outline_to_blur);
op->spread = spread * scale;
op->offset[0] = dx * scale;
op->offset[1] = dy * scale;
ops_set_inset_shadow (builder, transform_rect (self, builder, &outline_to_blur),
spread * scale,
gsk_inset_shadow_node_peek_color (node),
dx * scale, dy * scale);
ops_draw (builder, (GskQuadVertex[GL_N_VERTICES]) {
{ { 0, 0 }, { 0, 1 }, },
@ -1772,15 +1760,12 @@ render_unblurred_outset_shadow_node (GskGLRenderer *self,
const float spread = gsk_outset_shadow_node_get_spread (node);
const float dx = gsk_outset_shadow_node_get_dx (node);
const float dy = gsk_outset_shadow_node_get_dy (node);
OpShadow *op;
ops_set_program (builder, &self->programs->unblurred_outset_shadow_program);
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;
op->offset[0] = dx;
op->offset[1] = dy;
ops_set_unblurred_outset_shadow (builder, transform_rect (self, builder, outline),
spread,
gsk_outset_shadow_node_peek_color (node),
dx, dy);
load_vertex_data (ops_draw (builder, NULL), node, builder);
}
@ -1803,7 +1788,7 @@ render_outset_shadow_node (GskGLRenderer *self,
const float dy = gsk_outset_shadow_node_get_dy (node);
GskRoundedRect scaled_outline;
int texture_width, texture_height;
OpShadow *shadow;
OpOutsetShadow *shadow;
int blurred_texture_id;
int cached_tid;
bool do_slicing;
@ -1928,7 +1913,8 @@ render_outset_shadow_node (GskGLRenderer *self,
ops_set_texture (builder, blurred_texture_id);
shadow = ops_begin (builder, OP_CHANGE_OUTSET_SHADOW);
shadow->outline = transform_rect (self, builder, outline);
shadow->outline.value = transform_rect (self, builder, outline);
shadow->outline.send = TRUE;
tx1 = 0; tx2 = 1;
ty1 = 0; ty2 = 1;
@ -1956,7 +1942,8 @@ render_outset_shadow_node (GskGLRenderer *self,
ops_set_texture (builder, blurred_texture_id);
shadow = ops_begin (builder, OP_CHANGE_OUTSET_SHADOW);
shadow->outline = transform_rect (self, builder, outline);
shadow->outline.value = transform_rect (self, builder, outline);
shadow->outline.send = TRUE;
{
const float min_x = floorf (builder->dx + outline->bounds.origin.x - spread - (blur_extra / 2.0) + dx);
@ -2610,15 +2597,27 @@ apply_inset_shadow_op (const Program *program,
const OpShadow *op)
{
OP_PRINT (" -> inset shadow. Color: %s, Offset: (%f, %f), Spread: %f, Outline: %s",
gdk_rgba_to_string (op->color),
op->offset[0],
op->offset[1],
op->spread,
gsk_rounded_rect_to_string (&op->outline));
glUniform4fv (program->inset_shadow.color_location, 1, (float *)op->color);
glUniform2fv (program->inset_shadow.offset_location, 1, op->offset);
glUniform1f (program->inset_shadow.spread_location, op->spread);
glUniform4fv (program->inset_shadow.outline_rect_location, 3, (float *)&op->outline.bounds);
op->color.send ? gdk_rgba_to_string (op->color.value) : "don't send",
op->offset.send ? op->offset.value[0] : -1337.0,
op->offset.send ? op->offset.value[1] : -1337.0,
op->spread.send ? op->spread.value : -1337.0,
op->outline.send ? gsk_rounded_rect_to_string (&op->outline.value) : "don't send");
if (op->outline.send)
{
if (op->outline.send_corners)
glUniform4fv (program->inset_shadow.outline_rect_location, 3, (float *)&op->outline.value);
else
glUniform4fv (program->inset_shadow.outline_rect_location, 1, (float *)&op->outline.value);
}
if (op->color.send)
glUniform4fv (program->inset_shadow.color_location, 1, (float *)op->color.value);
if (op->spread.send)
glUniform1f (program->inset_shadow.spread_location, op->spread.value);
if (op->offset.send)
glUniform2fv (program->inset_shadow.offset_location, 1, op->offset.value);
}
static inline void
@ -2626,18 +2625,31 @@ apply_unblurred_outset_shadow_op (const Program *program,
const OpShadow *op)
{
OP_PRINT (" -> unblurred outset shadow");
glUniform4fv (program->unblurred_outset_shadow.color_location, 1, (float *)op->color);
glUniform2fv (program->unblurred_outset_shadow.offset_location, 1, op->offset);
glUniform1f (program->unblurred_outset_shadow.spread_location, op->spread);
glUniform4fv (program->unblurred_outset_shadow.outline_rect_location, 3, (float *)&op->outline.bounds);
if (op->outline.send)
{
if (op->outline.send_corners)
glUniform4fv (program->unblurred_outset_shadow.outline_rect_location, 3, (float *)&op->outline.value);
else
glUniform4fv (program->unblurred_outset_shadow.outline_rect_location, 1, (float *)&op->outline.value);
}
if (op->color.send)
glUniform4fv (program->unblurred_outset_shadow.color_location, 1, (float *)op->color.value);
if (op->spread.send)
glUniform1f (program->unblurred_outset_shadow.spread_location, op->spread.value);
if (op->offset.send)
glUniform2fv (program->unblurred_outset_shadow.offset_location, 1, op->offset.value);
}
static inline void
apply_outset_shadow_op (const Program *program,
const OpShadow *op)
apply_outset_shadow_op (const Program *program,
const OpOutsetShadow *op)
{
OP_PRINT (" -> outset shadow");
glUniform4fv (program->outset_shadow.outline_rect_location, 3, (float *)&op->outline.bounds);
glUniform4fv (program->outset_shadow.outline_rect_location, 3, (float *)&op->outline.value.bounds);
}
static inline void
@ -2694,6 +2706,7 @@ static inline void
apply_cross_fade_op (const Program *program,
const OpCrossFade *op)
{
OP_PRINT (" -> Cross fade");
/* End texture id */
glUniform1i (program->cross_fade.source2_location, 1);
glActiveTexture (GL_TEXTURE0 + 1);
@ -3505,6 +3518,7 @@ gsk_gl_renderer_render_ops (GskGLRenderer *self)
break;
case OP_CLEAR:
OP_PRINT ("-> CLEAR");
glClearColor (0, 0, 0, 0);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
break;

View File

@ -747,3 +747,118 @@ ops_get_buffer (RenderOpBuilder *builder)
{
return &builder->render_ops;
}
void
ops_set_inset_shadow (RenderOpBuilder *self,
const GskRoundedRect outline,
float spread,
const GdkRGBA *color,
float dx,
float dy)
{
ProgramState *current_program_state = get_current_program_state (self);
OpShadow *op;
op = ops_begin (self, OP_CHANGE_INSET_SHADOW);
if (!rounded_rect_equal (&outline, &current_program_state->inset_shadow.outline))
{
op->outline.value = outline;
op->outline.send = TRUE;
op->outline.send_corners = !rounded_rect_corners_equal (&current_program_state->inset_shadow.outline,
&outline);
current_program_state->inset_shadow.outline = outline;
}
else
op->outline.send = FALSE;
if (spread != current_program_state->inset_shadow.spread)
{
op->spread.value = spread;
op->spread.send = TRUE;
current_program_state->inset_shadow.spread = spread;
}
else
op->spread.send = FALSE;
if (!gdk_rgba_equal (color, &current_program_state->inset_shadow.color))
{
op->color.value = color;
op->color.send = TRUE;
current_program_state->inset_shadow.color = *color;
}
else
op->color.send = FALSE;
if (dx != current_program_state->inset_shadow.dx ||
dy != current_program_state->inset_shadow.dy)
{
op->offset.value[0] = dx;
op->offset.value[1] = dy;
op->offset.send = TRUE;
current_program_state->inset_shadow.dx = dx;
current_program_state->inset_shadow.dy = dy;
}
else
op->offset.send = FALSE;
}
void
ops_set_unblurred_outset_shadow (RenderOpBuilder *self,
const GskRoundedRect outline,
float spread,
const GdkRGBA *color,
float dx,
float dy)
{
ProgramState *current_program_state = get_current_program_state (self);
OpShadow *op;
op = ops_begin (self, OP_CHANGE_UNBLURRED_OUTSET_SHADOW);
if (!rounded_rect_equal (&outline, &current_program_state->unblurred_outset_shadow.outline))
{
op->outline.value = outline;
op->outline.send = TRUE;
op->outline.send_corners = !rounded_rect_corners_equal (&current_program_state->unblurred_outset_shadow.outline,
&outline);
current_program_state->unblurred_outset_shadow.outline = outline;
}
else
op->outline.send = FALSE;
if (spread != current_program_state->unblurred_outset_shadow.spread)
{
op->spread.value = spread;
op->spread.send = TRUE;
current_program_state->unblurred_outset_shadow.spread = spread;
}
else
op->spread.send = FALSE;
if (!gdk_rgba_equal (color, &current_program_state->unblurred_outset_shadow.color))
{
op->color.value = color;
op->color.send = TRUE;
current_program_state->unblurred_outset_shadow.color = *color;
}
else
op->color.send = FALSE;
if (dx != current_program_state->unblurred_outset_shadow.dx ||
dy != current_program_state->unblurred_outset_shadow.dy)
{
op->offset.value[0] = dx;
op->offset.value[1] = dy;
op->offset.send = TRUE;
current_program_state->unblurred_outset_shadow.dx = dx;
current_program_state->unblurred_outset_shadow.dy = dy;
}
else
op->offset.send = FALSE;
}

View File

@ -122,6 +122,20 @@ typedef struct
GdkRGBA color;
GskRoundedRect outline;
} border;
struct {
GskRoundedRect outline;
float dx;
float dy;
float spread;
GdkRGBA color;
} inset_shadow;
struct {
GskRoundedRect outline;
float dx;
float dy;
float spread;
GdkRGBA color;
} unblurred_outset_shadow;
};
} ProgramState;
@ -237,6 +251,18 @@ void ops_set_border_width (RenderOpBuilder *builder,
void ops_set_border_color (RenderOpBuilder *builder,
const GdkRGBA *color);
void ops_set_inset_shadow (RenderOpBuilder *self,
const GskRoundedRect outline,
float spread,
const GdkRGBA *color,
float dx,
float dy);
void ops_set_unblurred_outset_shadow (RenderOpBuilder *self,
const GskRoundedRect outline,
float spread,
const GdkRGBA *color,
float dx,
float dy);
GskQuadVertex * ops_draw (RenderOpBuilder *builder,
const GskQuadVertex vertex_data[GL_N_VERTICES]);

View File

@ -18,7 +18,7 @@ static guint op_sizes[OP_LAST] = {
sizeof (OpColorMatrix),
sizeof (OpBlur),
sizeof (OpShadow),
sizeof (OpShadow),
sizeof (OpOutsetShadow),
sizeof (OpBorder),
sizeof (OpBorder),
sizeof (OpBorder),

View File

@ -41,11 +41,30 @@ typedef enum
OP_LAST
} OpKind;
typedef struct { float value; guint send: 1; } FloatUniformValue;
typedef struct { float value[2]; guint send: 1; } Float2UniformValue;
typedef struct { GskRoundedRect value; guint send: 1; guint send_corners: 1; } RRUniformValue;
typedef struct { const GdkRGBA *value; guint send: 1; } RGBAUniformValue;
/* OpNode are allocated within OpBuffer.pos, but we keep
* a secondary index into the locations of that buffer
* from OpBuffer.index. This allows peeking at the kind
* and quickly replacing existing entries when necessary.
*/
typedef struct
{
RRUniformValue outline;
FloatUniformValue spread;
Float2UniformValue offset;
RGBAUniformValue color;
} OpShadow;
typedef struct
{
RRUniformValue outline;
} OpOutsetShadow;
typedef struct
{
guint pos;
@ -128,14 +147,6 @@ typedef struct
float dir[2];
} OpBlur;
typedef struct
{
GskRoundedRect outline;
float spread;
float offset[2];
const GdkRGBA *color;
} OpShadow;
typedef struct
{
float widths[4];

View File

@ -35,9 +35,9 @@ _IN_ _ROUNDED_RECT_UNIFORM_ transformed_inside_outline;
void main() {
vec2 frag = get_frag_coord();
float alpha = clamp (rounded_rect_coverage(decode_rect(transformed_outside_outline), frag) -
rounded_rect_coverage(decode_rect(transformed_inside_outline), frag),
0.0, 1.0);
float alpha = clamp(rounded_rect_coverage(decode_rect(transformed_outside_outline), frag) -
rounded_rect_coverage(decode_rect(transformed_inside_outline), frag),
0.0, 1.0);
setOutputColor(final_color * alpha);
}

View File

@ -41,3 +41,4 @@ void main() {
setOutputColor(final_color * alpha);
}