diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2009-09-03 17:47:34 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2009-09-03 20:12:41 +0100 |
commit | 769f4a4f47ab4636ec5cca3e92ce2c0ff19d2f75 (patch) | |
tree | 42fa5ac5323dee8df9aabf320daa0ec1a75c23d4 | |
parent | 6ce200da9d01a85a1de576229e75732db65a8b70 (diff) |
[gl] Allocate small number of rectangles on the stack
FillRectangle is most frequently used to fill an entire imagee with the
background colour, i.e. with just a single, or few, rectangle. Avoid
heap allocation for this common case by allocating enough space for 4
rectangles (vertices+colors) on the stack.
-rw-r--r-- | src/cairo-gl-surface.c | 43 |
1 files changed, 29 insertions, 14 deletions
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c index 22efbd4e..a2c5b971 100644 --- a/src/cairo-gl-surface.c +++ b/src/cairo-gl-surface.c @@ -1522,7 +1522,10 @@ _cairo_gl_surface_fill_rectangles (void *abstract_surface, cairo_rectangle_int_t *rects, int num_rects) { +#define N_STACK_RECTS 4 cairo_gl_surface_t *surface = abstract_surface; + GLfloat vertices_stack[N_STACK_RECTS*4*2]; + GLfloat colors_stack[N_STACK_RECTS*4*4] cairo_gl_context_t *ctx; int i; GLfloat *vertices; @@ -1536,23 +1539,32 @@ _cairo_gl_surface_fill_rectangles (void *abstract_surface, _cairo_gl_set_destination (surface); _cairo_gl_set_operator (surface, op); - vertices = _cairo_malloc_ab (num_rects, sizeof (GLfloat) * 4 * 2); - colors = _cairo_malloc_ab (num_rects, sizeof (GLfloat) * 4 * 4); - if (!vertices || !colors) { - _cairo_gl_context_release (ctx); - free (vertices); - free (colors); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); + if (num_rects > N_STACK_RECTS) { + vertices = _cairo_malloc_ab (num_rects, sizeof (GLfloat) * 4 * 2); + colors = _cairo_malloc_ab (num_rects, sizeof (GLfloat) * 4 * 4); + if (!vertices || !colors) { + _cairo_gl_context_release (ctx); + free (vertices); + free (colors); + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + } + } else { + vertices = vertices_stack; + colors = colors_stack; } /* This should be loaded in as either a blend constant and an operator * setup specific to this, or better, a fragment shader constant. */ - for (i = 0; i < num_rects * 4; i++) { - colors[i * 4 + 0] = color->red * color->alpha; - colors[i * 4 + 1] = color->green * color->alpha; - colors[i * 4 + 2] = color->blue * color->alpha; - colors[i * 4 + 3] = color->alpha; + colors[0] = color->red * color->alpha; + colors[1] = color->green * color->alpha; + colors[2] = color->blue * color->alpha; + colors[3] = color->alpha; + for (i = 1; i < num_rects * 4; i++) { + colors[i*4 + 0] = colors[0]; + colors[i*4 + 1] = colors[1]; + colors[i*4 + 2] = colors[2]; + colors[i*4 + 3] = colors[3]; } for (i = 0; i < num_rects; i++) { @@ -1570,6 +1582,7 @@ _cairo_gl_surface_fill_rectangles (void *abstract_surface, glEnableClientState (GL_VERTEX_ARRAY); glColorPointer (4, GL_FLOAT, sizeof (GLfloat)*4, colors); glEnableClientState (GL_COLOR_ARRAY); + glDrawArrays (GL_QUADS, 0, 4 * num_rects); glDisableClientState (GL_COLOR_ARRAY); @@ -1577,8 +1590,10 @@ _cairo_gl_surface_fill_rectangles (void *abstract_surface, glDisable (GL_BLEND); _cairo_gl_context_release (ctx); - free (vertices); - free (colors); + if (vertices != vertices_stack) + free (vertices); + if (colors != colors_stack) + free (colors); return CAIRO_STATUS_SUCCESS; } |