Improves x11perf -aa10text performance by 1377.59% +/- 23.8198% (n=93) on Intel with GLES2.
Signed-off-by: Eric Anholt <e...@anholt.net> --- glamor/glamor.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++ glamor/glamor_priv.h | 11 +++++++++ glamor/glamor_utils.h | 4 +--- 3 files changed, 74 insertions(+), 3 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 935fb74..fbb1d85 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -274,6 +274,68 @@ glamor_set_debug_level(int *debug_level) int glamor_debug_level; +void +glamor_gldrawarrays_quads_using_indices(glamor_screen_private *glamor_priv, + unsigned count) +{ + unsigned i; + + /* For a single quad, don't bother with an index buffer. */ + if (count == 1) + goto fallback; + + if (glamor_priv->ib_size < count) { + /* Basic GLES2 doesn't have any way to map buffer objects for + * writing, but it's long past time for drivers to have + * MapBufferRange. + */ + if (!glamor_priv->has_map_buffer_range) + goto fallback; + + /* Lazy create the buffer name, and only bind it once since + * none of the glamor code binds it to anything else. + */ + if (!glamor_priv->ib) { + glGenBuffers(1, &glamor_priv->ib); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ib); + } + + /* For now, only support GL_UNSIGNED_SHORTs. */ + if (count > ((1 << 16) - 1) / 4) { + goto fallback; + } else { + uint16_t *data; + size_t size = count * 6 * sizeof(GLushort); + + glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, NULL, GL_STATIC_DRAW); + data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, + 0, size, + GL_MAP_WRITE_BIT | + GL_MAP_INVALIDATE_BUFFER_BIT); + for (i = 0; i < count; i++) { + data[i * 6 + 0] = i * 4 + 0; + data[i * 6 + 1] = i * 4 + 1; + data[i * 6 + 2] = i * 4 + 2; + data[i * 6 + 3] = i * 4 + 0; + data[i * 6 + 4] = i * 4 + 2; + data[i * 6 + 5] = i * 4 + 3; + } + glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); + + glamor_priv->ib_size = count; + glamor_priv->ib_type = GL_UNSIGNED_SHORT; + } + } + + glDrawElements(GL_TRIANGLES, count * 6, glamor_priv->ib_type, NULL); + return; + +fallback: + for (i = 0; i < count; i++) + glDrawArrays(GL_TRIANGLE_FAN, i * 4, 4); +} + + /** * Creates any pixmaps used internally by glamor, since those can't be * allocated at ScreenInit time. diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index c80df22..17f8253 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -261,6 +261,14 @@ typedef struct glamor_screen_private { */ char *vb; int vb_stride; + + /** Cached index buffer for translating GL_QUADS to triangles. */ + GLuint ib; + /** Index buffer type: GL_UNSIGNED_SHORT or GL_UNSIGNED_INT */ + GLenum ib_type; + /** Number of quads the index buffer has indices for. */ + unsigned ib_size; + Bool has_source_coords, has_mask_coords; int render_nr_quads; glamor_composite_shader composite_shader[SHADER_SOURCE_COUNT] @@ -643,6 +651,9 @@ glamor_pixmap_fbo *glamor_create_fbo_array(glamor_screen_private *glamor_priv, int flag, int block_w, int block_h, glamor_pixmap_private *); +void glamor_gldrawarrays_quads_using_indices(glamor_screen_private *glamor_priv, + unsigned count); + /* glamor_core.c */ void glamor_init_finish_access_shaders(ScreenPtr screen); diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index 0927ffb..73cda9c 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -1403,9 +1403,7 @@ glamor_glDrawArrays_GL_QUADS(glamor_screen_private *glamor_priv, unsigned count) if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { glDrawArrays(GL_QUADS, 0, count * 4); } else { - unsigned i; - for (i = 0; i < count; i++) - glDrawArrays(GL_TRIANGLE_FAN, i * 4, 4); + glamor_gldrawarrays_quads_using_indices(glamor_priv, count); } } -- 2.1.4 _______________________________________________ xorg-devel@lists.x.org: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel