gdkgl: Texture many quads at once for performance reasons

This isn't fully performant yet. To be fully performant, we'd need to
do everything in one giant buffer.
This commit is contained in:
Jasper St. Pierre 2014-11-22 09:47:35 -08:00
parent 7312c01f62
commit 37ad6e1147
3 changed files with 76 additions and 38 deletions

View File

@ -205,9 +205,10 @@ use_texture_rect_program (GdkGLContextPaintData *paint_data)
}
void
gdk_gl_texture_quad (GdkGLContext *paint_context,
guint texture_target,
GdkTexturedQuad *quad)
gdk_gl_texture_quads (GdkGLContext *paint_context,
guint texture_target,
int n_quads,
GdkTexturedQuad *quads)
{
GdkGLContextPaintData *paint_data = gdk_gl_context_get_paint_data (paint_context);
GdkGLContextProgram *program;
@ -215,18 +216,7 @@ gdk_gl_texture_quad (GdkGLContext *paint_context,
int window_scale = gdk_window_get_scale_factor (window);
float w = gdk_window_get_width (window) * window_scale;
float h = gdk_window_get_height (window) * window_scale;
float vertex_buffer_data[] = {
(quad->x2 * 2) / w - 1, (quad->y1 * 2) / h - 1,
(quad->x2 * 2) / w - 1, (quad->y2 * 2) / h - 1,
(quad->x1 * 2) / w - 1, (quad->y2 * 2) / h - 1,
(quad->x1 * 2) / w - 1, (quad->y1 * 2) / h - 1,
};
float uv_buffer_data[] = {
quad->u2, quad->v1,
quad->u2, quad->v2,
quad->u1, quad->v2,
quad->u1, quad->v1,
};
int i;
bind_vao (paint_data);
@ -247,14 +237,37 @@ gdk_gl_texture_quad (GdkGLContext *paint_context,
glUniform1i(program->map_location, 0); /* Use texture unit 0 */
glEnableVertexAttribArray (0);
glBindBuffer (GL_ARRAY_BUFFER, paint_data->tmp_vertex_buffer);
glBufferData (GL_ARRAY_BUFFER, sizeof(vertex_buffer_data), vertex_buffer_data, GL_STREAM_DRAW);
glVertexAttribPointer (program->position_location, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray (1);
glBindBuffer (GL_ARRAY_BUFFER, paint_data->tmp_vertex_buffer);
glVertexAttribPointer (program->position_location, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glBindBuffer (GL_ARRAY_BUFFER, paint_data->tmp_uv_buffer);
glBufferData (GL_ARRAY_BUFFER, sizeof(uv_buffer_data), uv_buffer_data, GL_STREAM_DRAW);
glVertexAttribPointer (program->uv_location, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glDrawArrays (GL_TRIANGLE_FAN, 0, 4);
for (i = 0; i < n_quads; i++)
{
GdkTexturedQuad *quad = &quads[i];
float vertex_buffer_data[] = {
(quad->x2 * 2) / w - 1, (quad->y1 * 2) / h - 1,
(quad->x2 * 2) / w - 1, (quad->y2 * 2) / h - 1,
(quad->x1 * 2) / w - 1, (quad->y2 * 2) / h - 1,
(quad->x1 * 2) / w - 1, (quad->y1 * 2) / h - 1,
};
float uv_buffer_data[] = {
quad->u2, quad->v1,
quad->u2, quad->v2,
quad->u1, quad->v2,
quad->u1, quad->v1,
};
glBindBuffer (GL_ARRAY_BUFFER, paint_data->tmp_vertex_buffer);
glBufferData (GL_ARRAY_BUFFER, sizeof(vertex_buffer_data), vertex_buffer_data, GL_STREAM_DRAW);
glBindBuffer (GL_ARRAY_BUFFER, paint_data->tmp_uv_buffer);
glBufferData (GL_ARRAY_BUFFER, sizeof(uv_buffer_data), uv_buffer_data, GL_STREAM_DRAW);
glDrawArrays (GL_TRIANGLE_FAN, 0, 4);
}
glDisableVertexAttribArray (0);
glDisableVertexAttribArray (1);
}
@ -460,7 +473,9 @@ gdk_cairo_draw_from_gl (cairo_t *cr,
int unscaled_window_height;
GLint texture_width;
GLint texture_height;
int i;
int i, n_rects;
GdkTexturedQuad *quads;
cairo_rectangle_int_t clip_rect;
/* Translate to impl coords */
cairo_region_translate (clip_region, dx, dy);
@ -506,9 +521,16 @@ gdk_cairo_draw_from_gl (cairo_t *cr,
#define FLIP_Y(_y) (unscaled_window_height - (_y))
for (i = 0; i < cairo_region_num_rectangles (clip_region); i++)
cairo_region_get_extents (clip_region, &clip_rect);
glScissor (clip_rect.x, FLIP_Y (clip_rect.y + clip_rect.height),
clip_rect.width, clip_rect.height);
n_rects = cairo_region_num_rectangles (clip_region);
quads = g_new (GdkTexturedQuad, n_rects);
for (i = 0; i < n_rects; i++)
{
cairo_rectangle_int_t clip_rect, dest;
cairo_rectangle_int_t dest;
cairo_region_get_rectangle (clip_region, i, &clip_rect);
@ -517,9 +539,6 @@ gdk_cairo_draw_from_gl (cairo_t *cr,
clip_rect.width *= window_scale;
clip_rect.height *= window_scale;
glScissor (clip_rect.x, FLIP_Y (clip_rect.y + clip_rect.height),
clip_rect.width, clip_rect.height);
dest.x = dx * window_scale;
dest.y = dy * window_scale;
dest.width = width * window_scale / buffer_scale;
@ -536,7 +555,7 @@ gdk_cairo_draw_from_gl (cairo_t *cr,
(clipped_src_x + dest.width) / (float)texture_width, clipped_src_y / (float)texture_height,
};
gdk_gl_texture_quad (paint_context, GL_TEXTURE_2D, &quad);
quads[i] = quad;
if (impl_window->current_paint.flushed_region)
{
@ -555,11 +574,13 @@ gdk_cairo_draw_from_gl (cairo_t *cr,
}
}
gdk_gl_texture_quads (paint_context, GL_TEXTURE_2D, n_rects, quads);
g_free (quads);
if (alpha_size != 0)
glDisable (GL_BLEND);
glDisable (GL_TEXTURE_2D);
glDisable (GL_SCISSOR_TEST);
#undef FLIP_Y
@ -636,6 +657,7 @@ gdk_gl_texture_from_surface (cairo_surface_t *surface,
float umax, vmax;
gboolean use_texture_rectangle;
guint target;
GdkTexturedQuad *quads;
paint_context = gdk_gl_context_get_current ();
if ((_gdk_gl_flags & GDK_GL_SOFTWARE_DRAW_SURFACE) == 0 &&
@ -673,6 +695,8 @@ gdk_gl_texture_from_surface (cairo_surface_t *surface,
glTexParameteri (target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
n_rects = cairo_region_num_rectangles (region);
quads = g_new (GdkTexturedQuad, n_rects);
for (i = 0; i < n_rects; i++)
{
cairo_region_get_rectangle (region, i, &rect);
@ -718,10 +742,13 @@ gdk_gl_texture_from_surface (cairo_surface_t *surface,
umax, vmax,
};
gdk_gl_texture_quad (paint_context, target, &quad);
quads[i] = quad;
}
}
gdk_gl_texture_quads (paint_context, target, n_rects, quads);
g_free (quads);
glDisable (GL_SCISSOR_TEST);
glDisable (target);
glDeleteTextures (1, &texture_id);

View File

@ -356,9 +356,10 @@ typedef struct {
float u1, v1, u2, v2;
} GdkTexturedQuad;
void gdk_gl_texture_quad (GdkGLContext *paint_context,
guint texture_target,
GdkTexturedQuad *quad);
void gdk_gl_texture_quads (GdkGLContext *paint_context,
guint texture_target,
int n_quads,
GdkTexturedQuad *quads);
void gdk_cairo_surface_mark_as_direct (cairo_surface_t *surface,
GdkWindow *window);

View File

@ -431,6 +431,7 @@ gdk_x11_gl_context_texture_from_surface (GdkGLContext *paint_context,
guint target;
double sx, sy;
float uscale, vscale;
GdkTexturedQuad *quads;
if (cairo_surface_get_type (surface) != CAIRO_SURFACE_TYPE_XLIB)
return FALSE;
@ -473,22 +474,25 @@ gdk_x11_gl_context_texture_from_surface (GdkGLContext *paint_context,
glEnable (GL_SCISSOR_TEST);
n_rects = cairo_region_num_rectangles (region);
quads = g_new (GdkTexturedQuad, n_rects);
#define FLIP_Y(_y) (window_height - (_y))
cairo_region_get_extents (region, &rect);
glScissor (rect.x * window_scale, FLIP_Y(rect.y) * window_scale,
(rect.x + rect.width) * window_scale, FLIP_Y (rect.y + rect.height) * window_scale);
for (i = 0; i < n_rects; i++)
{
int src_x, src_y, src_height, src_width;
cairo_region_get_rectangle (region, i, &rect);
glScissor (rect.x * window_scale, (window_height - rect.y - rect.height) * window_scale,
rect.width * window_scale, rect.height * window_scale);
src_x = rect.x * sx + device_x_offset;
src_y = rect.y * sy + device_y_offset;
src_width = rect.width * sx;
src_height = rect.height * sy;
#define FLIP_Y(_y) (window_height - (_y))
if (use_texture_rectangle)
{
uscale = 1.0;
@ -507,12 +511,18 @@ gdk_x11_gl_context_texture_from_surface (GdkGLContext *paint_context,
uscale * src_x, vscale * src_y,
uscale * (src_x + src_width), vscale * (src_y + src_height),
};
gdk_gl_texture_quad (paint_context, target, &quad);
quads[i] = quad;
}
}
#undef FLIP_Y
glDisable (GL_SCISSOR_TEST);
gdk_gl_texture_quads (paint_context, target, n_rects, quads);
g_free (quads);
glXReleaseTexImageEXT (glx_pixmap->display, glx_pixmap->drawable,
GLX_FRONT_LEFT_EXT);