From 4cd07871a417b15b0382c07fecec497e93697a5d Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sun, 8 Jan 2012 08:45:08 +0800 Subject: [PATCH] glamor-composite: Use glDrawElements to reduce the count of vertices. To split a rectangle (0,1,2,3) to two separated triangles need to feed 6 vertices, (0,1,2) and (0,2,3). use glDrawElements can reuse the shared vertices. Signed-off-by: Zhigang Gong --- glamor/glamor_gl_dispatch.c | 2 ++ glamor/glamor_gl_dispatch.h | 6 +++- glamor/glamor_priv.h | 2 +- glamor/glamor_render.c | 59 ++++++++++++++++++++++++++----------- 4 files changed, 49 insertions(+), 20 deletions(-) diff --git a/glamor/glamor_gl_dispatch.c b/glamor/glamor_gl_dispatch.c index 788562c5e..5a47b4576 100644 --- a/glamor/glamor_gl_dispatch.c +++ b/glamor/glamor_gl_dispatch.c @@ -16,6 +16,7 @@ glamor_gl_dispatch_init_impl(struct glamor_gl_dispatch *dispatch, INIT_FUNC(dispatch, glViewport, get_proc_address); INIT_FUNC(dispatch, glRasterPos2i, get_proc_address); INIT_FUNC(dispatch, glDrawArrays, get_proc_address); + INIT_FUNC(dispatch, glDrawElements, get_proc_address); INIT_FUNC(dispatch, glReadPixels, get_proc_address); INIT_FUNC(dispatch, glDrawPixels, get_proc_address); INIT_FUNC(dispatch, glPixelStorei, get_proc_address); @@ -37,6 +38,7 @@ glamor_gl_dispatch_init_impl(struct glamor_gl_dispatch *dispatch, INIT_FUNC(dispatch, glGenBuffers, get_proc_address); INIT_FUNC(dispatch, glBufferData, get_proc_address); INIT_FUNC(dispatch, glMapBuffer, get_proc_address); + INIT_FUNC(dispatch, glMapBufferRange, get_proc_address); INIT_FUNC(dispatch, glUnmapBuffer, get_proc_address); INIT_FUNC(dispatch, glBindBuffer, get_proc_address); INIT_FUNC(dispatch, glDeleteBuffers, get_proc_address); diff --git a/glamor/glamor_gl_dispatch.h b/glamor/glamor_gl_dispatch.h index 5f1831a7e..8fcb3dc96 100644 --- a/glamor/glamor_gl_dispatch.h +++ b/glamor/glamor_gl_dispatch.h @@ -10,6 +10,9 @@ typedef struct glamor_gl_dispatch { /* Vertex Array */ void (*glDrawArrays) (GLenum mode, GLint first, GLsizei count); + /* Elements Array*/ + void (*glDrawElements) (GLenum mode, GLsizei count, GLenum type, const GLvoid * indices); + /* Raster functions */ void (*glReadPixels) (GLint x, GLint y, GLsizei width, GLsizei height, @@ -55,7 +58,8 @@ typedef struct glamor_gl_dispatch { void (*glBufferData) (GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage); GLvoid *(*glMapBuffer) (GLenum target, GLenum access); - GLboolean(*glUnmapBuffer) (GLenum target); + GLvoid *(*glMapBufferRange) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); + GLboolean(*glUnmapBuffer) (GLenum target); void (*glBindBuffer) (GLenum target, GLuint buffer); void (*glDeleteBuffers) (GLsizei n, const GLuint * buffers); diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 08db6316f..f3b0996bf 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -158,7 +158,7 @@ typedef struct glamor_screen_private { int yInverted; int screen_fbo; - GLuint vbo; + GLuint vbo, ebo; int vbo_offset; int vbo_size; char *vb; diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 4f09bbf19..29c33b08f 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -288,7 +288,7 @@ glamor_lookup_composite_shader(ScreenPtr screen, struct return shader; } -#define GLAMOR_COMPOSITE_VBO_SIZE 8192 +#define GLAMOR_COMPOSITE_VBO_VERT_CNT 1024 static void glamor_reset_composite_vbo(ScreenPtr screen) @@ -296,18 +296,44 @@ glamor_reset_composite_vbo(ScreenPtr screen) glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); glamor_priv->vbo_offset = 0; - glamor_priv->vbo_size = GLAMOR_COMPOSITE_VBO_SIZE; + glamor_priv->vbo_size = GLAMOR_COMPOSITE_VBO_VERT_CNT * sizeof(float) * 2; glamor_priv->render_nr_verts = 0; } +static void +glamor_init_eb(unsigned short *eb, int vert_cnt) +{ + int i, j; + for(i = 0, j = 0; j < vert_cnt; i += 6, j += 4) + { + eb[i] = j; + eb[i + 1] = j + 1; + eb[i + 2] = j + 2; + eb[i + 3] = j; + eb[i + 4] = j + 2; + eb[i + 5] = j + 3; + } +} + void glamor_init_composite_shaders(ScreenPtr screen) { glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - glamor_priv->vb = malloc(GLAMOR_COMPOSITE_VBO_SIZE); - assert(glamor_priv->vb != NULL); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + unsigned short *eb; + + dispatch->glGenBuffers(1, &glamor_priv->vbo); + dispatch->glGenBuffers(1, &glamor_priv->ebo); + dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo); + dispatch->glBufferData(GL_ELEMENT_ARRAY_BUFFER, + GLAMOR_COMPOSITE_VBO_VERT_CNT * sizeof(short) * 2, + NULL, GL_DYNAMIC_DRAW); + eb = dispatch->glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY); + glamor_init_eb(eb, GLAMOR_COMPOSITE_VBO_VERT_CNT); + dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + dispatch->glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); glamor_reset_composite_vbo(screen); } @@ -542,6 +568,12 @@ glamor_setup_composite_vbo(ScreenPtr screen) glamor_priv->vb_stride += 2 * sizeof(float); dispatch->glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo); + dispatch->glBufferData(GL_ARRAY_BUFFER, + GLAMOR_COMPOSITE_VBO_VERT_CNT * sizeof(float) * 2, + NULL, GL_DYNAMIC_DRAW); + + glamor_priv->vb = dispatch->glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); + dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo); dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, glamor_priv->vb_stride, @@ -609,11 +641,9 @@ glamor_flush_composite_rects(ScreenPtr screen) glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; if (!glamor_priv->render_nr_verts) return; - dispatch->glBufferData(GL_ARRAY_BUFFER, glamor_priv->vbo_offset, - glamor_priv->vb, GL_STREAM_DRAW); - - dispatch->glDrawArrays(GL_TRIANGLES, 0, - glamor_priv->render_nr_verts); + dispatch->glUnmapBuffer(GL_ARRAY_BUFFER); + dispatch->glDrawElements(GL_TRIANGLES, (glamor_priv->render_nr_verts * 3) / 2, + GL_UNSIGNED_SHORT, NULL); glamor_reset_composite_vbo(screen); } @@ -627,15 +657,12 @@ glamor_emit_composite_rect(ScreenPtr screen, glamor_get_screen_private(screen); glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; - if (glamor_priv->vbo_offset + 6 * glamor_priv->vb_stride > + if (glamor_priv->vbo_offset + 4 * glamor_priv->vb_stride > glamor_priv->vbo_size) { glamor_flush_composite_rects(screen); } if (glamor_priv->vbo_offset == 0) { - if (glamor_priv->vbo == 0) - dispatch->glGenBuffers(1, &glamor_priv->vbo); - glamor_setup_composite_vbo(screen); } @@ -645,10 +672,6 @@ glamor_emit_composite_rect(ScreenPtr screen, dst_coords, 1); glamor_emit_composite_vert(screen, src_coords, mask_coords, dst_coords, 2); - glamor_emit_composite_vert(screen, src_coords, mask_coords, - dst_coords, 0); - glamor_emit_composite_vert(screen, src_coords, mask_coords, - dst_coords, 2); glamor_emit_composite_vert(screen, src_coords, mask_coords, dst_coords, 3); } @@ -969,7 +992,6 @@ glamor_composite_with_shader(CARD8 op, dispatch->glUseProgram(shader->prog); - if (key.source == SHADER_SOURCE_SOLID) { glamor_set_composite_solid(dispatch, source_solid_color, shader->source_uniform_location); @@ -1079,6 +1101,7 @@ glamor_composite_with_shader(CARD8 op, glamor_flush_composite_rects(screen); dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0); + dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_MASK);