summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2009-09-03 17:47:34 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2009-09-03 20:12:41 +0100
commit769f4a4f47ab4636ec5cca3e92ce2c0ff19d2f75 (patch)
tree42fa5ac5323dee8df9aabf320daa0ec1a75c23d4
parent6ce200da9d01a85a1de576229e75732db65a8b70 (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.c43
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;
}