mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-26 13:41:07 +00:00
gl renderer: Optimize text drawing
Text nodes will almost always end up using the exact same texture and the same program. So, in that case we can simply add vertex data for all the characters we need to draw and use just one draw call.
This commit is contained in:
parent
fa564e1f93
commit
832920c6ba
@ -328,6 +328,7 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self,
|
||||
goto out;
|
||||
}
|
||||
self->coloring_program.index = 3;
|
||||
self->coloring_program.name = "coloring";
|
||||
init_common_locations (self, builder, &self->coloring_program);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (coloring_program, color_location, "uColor");
|
||||
|
||||
@ -342,6 +343,7 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self,
|
||||
goto out;
|
||||
}
|
||||
self->color_matrix_program.index = 4;
|
||||
self->color_matrix_program.name = "color matrix";
|
||||
init_common_locations (self, builder, &self->color_matrix_program);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (color_matrix_program, color_matrix_location, "uColorMatrix");
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (color_matrix_program, color_offset_location, "uColorOffset");
|
||||
@ -357,6 +359,7 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self,
|
||||
goto out;
|
||||
}
|
||||
self->linear_gradient_program.index = 5;
|
||||
self->linear_gradient_program.name = "linear gradient";
|
||||
init_common_locations (self, builder, &self->linear_gradient_program);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (linear_gradient_program, color_stops_location, "uColorStops");
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (linear_gradient_program, color_offsets_location, "uColorOffsets");
|
||||
@ -858,6 +861,22 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
|
||||
int x = gsk_text_node_get_x (node);
|
||||
int y = gsk_text_node_get_y (node);
|
||||
|
||||
/* If the font has color glyphs, we don't need to recolor anything */
|
||||
if (has_color_glyphs)
|
||||
{
|
||||
ops_set_program (builder, &self->blit_program);
|
||||
}
|
||||
else
|
||||
{
|
||||
RenderOp op;
|
||||
|
||||
ops_set_program (builder, &self->coloring_program);
|
||||
|
||||
op.op = OP_CHANGE_COLOR;
|
||||
op.color = *gsk_text_node_peek_color (node);
|
||||
ops_add (builder, &op);
|
||||
}
|
||||
|
||||
/* We use one quad per character, unlike the other nodes which
|
||||
* use at most one quad altogether */
|
||||
for (i = 0; i < num_glyphs; i++)
|
||||
@ -888,22 +907,6 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
|
||||
cx = (double)(x_position + gi->geometry.x_offset) / PANGO_SCALE;
|
||||
cy = (double)(gi->geometry.y_offset) / PANGO_SCALE;
|
||||
|
||||
/* If the font has color glyphs, we don't need to recolor anything */
|
||||
if (has_color_glyphs)
|
||||
{
|
||||
ops_set_program (builder, &self->blit_program);
|
||||
}
|
||||
else
|
||||
{
|
||||
RenderOp op;
|
||||
|
||||
ops_set_program (builder, &self->coloring_program);
|
||||
|
||||
op.op = OP_CHANGE_COLOR;
|
||||
op.color = *gsk_text_node_peek_color (node);
|
||||
ops_add (builder, &op);
|
||||
}
|
||||
|
||||
ops_set_texture (builder, gsk_gl_glyph_cache_get_glyph_image (&self->glyph_cache,
|
||||
glyph)->texture_id);
|
||||
|
||||
@ -1156,8 +1159,9 @@ gsk_gl_renderer_render_ops (GskGLRenderer *self,
|
||||
break;
|
||||
|
||||
case OP_DRAW:
|
||||
OP_PRINT (" -> draw %ld and program %s\n", op->vao_offset, program->name);
|
||||
glDrawArrays (GL_TRIANGLES, op->vao_offset, GL_N_VERTICES);
|
||||
OP_PRINT (" -> draw %ld, size %ld and program %s\n",
|
||||
op->draw.vao_offset, op->draw.draw_size, program->name);
|
||||
glDrawArrays (GL_TRIANGLES, op->draw.vao_offset, op->draw.draw_size);//GL_N_VERTICES);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -223,17 +223,45 @@ void
|
||||
ops_draw (RenderOpBuilder *builder,
|
||||
const GskQuadVertex vertex_data[GL_N_VERTICES])
|
||||
{
|
||||
RenderOp op;
|
||||
gsize offset = builder->buffer_size / sizeof (GskQuadVertex);
|
||||
RenderOp *last_op;
|
||||
|
||||
op.op = OP_CHANGE_VAO;
|
||||
memcpy (&op.vertex_data, vertex_data, sizeof(GskQuadVertex) * GL_N_VERTICES);
|
||||
g_array_append_val (builder->render_ops, op);
|
||||
last_op = &g_array_index (builder->render_ops, RenderOp, builder->render_ops->len - 1);
|
||||
/* If the previous op was a DRAW as well, we didn't change anything between the two calls,
|
||||
* so these are just 2 subsequent draw calls. Same VAO, same program etc.
|
||||
* And the offsets into the vao are in order as well, so make it one draw call. */
|
||||
if (last_op->op == OP_DRAW)
|
||||
{
|
||||
/* We allow ourselves a little trick here. We still have to add a CHANGE_VAO op for
|
||||
* this draw call so we can add our vertex data there, but we want it to be placed before
|
||||
* the last draw call, so we reorder those. */
|
||||
RenderOp new_draw;
|
||||
new_draw.op = OP_DRAW;
|
||||
new_draw.draw.vao_offset = last_op->draw.vao_offset;
|
||||
new_draw.draw.draw_size = last_op->draw.draw_size + GL_N_VERTICES;
|
||||
|
||||
last_op->op = OP_CHANGE_VAO;
|
||||
memcpy (&last_op->vertex_data, vertex_data, sizeof(GskQuadVertex) * GL_N_VERTICES);
|
||||
|
||||
/* Now add the DRAW */
|
||||
g_array_append_val (builder->render_ops, new_draw);
|
||||
}
|
||||
else
|
||||
{
|
||||
RenderOp op;
|
||||
gsize offset = builder->buffer_size / sizeof (GskQuadVertex);
|
||||
|
||||
op.op = OP_CHANGE_VAO;
|
||||
memcpy (&op.vertex_data, vertex_data, sizeof(GskQuadVertex) * GL_N_VERTICES);
|
||||
g_array_append_val (builder->render_ops, op);
|
||||
|
||||
op.op = OP_DRAW;
|
||||
op.draw.vao_offset = offset;
|
||||
op.draw.draw_size = GL_N_VERTICES;
|
||||
g_array_append_val (builder->render_ops, op);
|
||||
}
|
||||
|
||||
/* We added new vertex data in both cases so increase the buffer size */
|
||||
builder->buffer_size += sizeof (GskQuadVertex) * GL_N_VERTICES;
|
||||
|
||||
op.op = OP_DRAW;
|
||||
op.vao_offset = offset;
|
||||
g_array_append_val (builder->render_ops, op);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -85,7 +85,6 @@ typedef struct
|
||||
int texture_id;
|
||||
int render_target_id;
|
||||
GdkRGBA color;
|
||||
gsize vao_offset;
|
||||
GskQuadVertex vertex_data[6];
|
||||
GskRoundedRect clip;
|
||||
graphene_rect_t viewport;
|
||||
@ -96,6 +95,10 @@ typedef struct
|
||||
graphene_point_t start_point;
|
||||
graphene_point_t end_point;
|
||||
} linear_gradient;
|
||||
struct {
|
||||
gsize vao_offset;
|
||||
gsize draw_size;
|
||||
} draw;
|
||||
};
|
||||
} RenderOp;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user