diff options
author | Søren Sandmann Pedersen <ssp@redhat.com> | 2012-10-05 19:46:31 -0400 |
---|---|---|
committer | Søren Sandmann Pedersen <ssp@redhat.com> | 2012-10-05 19:46:31 -0400 |
commit | 0e0173d59087073a34feefc518447c68422c2ac6 (patch) | |
tree | 0adfeb030323f9ff2475eb315307d594838a8fac | |
parent | 644c2143eb023b6e26e22207a135621e969f27f0 (diff) |
asdfcommands
-rw-r--r-- | src/cairo-pixman-surface.c | 217 |
1 files changed, 216 insertions, 1 deletions
diff --git a/src/cairo-pixman-surface.c b/src/cairo-pixman-surface.c index 63148462..57d220da 100644 --- a/src/cairo-pixman-surface.c +++ b/src/cairo-pixman-surface.c @@ -342,6 +342,7 @@ cairo_pixman_surface_get_font_options (void *abstract_surface, typedef enum { + NOP, NEW_BLANK, NEW_BROKEN, NEW_WHITE, @@ -416,6 +417,9 @@ typedef union pixman_op_t op; int src; int mask; + + /* Generated by optimizer */ + pixman_region32_t * clip; } composite; } command_t; @@ -625,10 +629,203 @@ command_buffer_composite (command_buffer_t **buffer, command->composite.src = src; command->composite.mask = mask; command->composite.op = op; + + command->composite.clip = NULL; } static const pixman_color_t white = { 0xffff, 0xffff, 0xffff, 0xffff }; +static void +command_buffer_optimize (command_buffer_t *buffer) +{ + typedef struct + { + enum { + UNKNOWN, + BLANK, + REGION, + WHITE, + IMAGE, + TRAPS, + GLYPHS, + CLIPPED_MASK, + } type; + + int same_as; + + union + { + pixman_region32_t *region; + + struct + { + int mask; + pixman_region32_t *clip; + } clipped_mask; + } u; + + } image_info_t; + + image_info_t *info; + cairo_bool_t changed; + int i; + + if (!(info = calloc (sizeof (image_info_t), buffer->id))) + return; + + for (i = 0; i < buffer->id; ++i) + { + image_info_t *image = &(info[i]); + + image->type = UNKNOWN; + image->same_as = -1; + } + + for (i = 0; i < buffer->n_commands; ++i) + { + command_t *command = &(buffer->commands[i]); + + switch (command->type) + { + case NEW_BLANK: + info[command->new_blank.id].type = BLANK; + break; + + case NEW_WHITE: + info[command->new_white.id].type = WHITE; + break; + + case NEW_IMAGE: + info[command->new_image.id].type = IMAGE; + break; + + case NEW_REGION: + info[command->new_region.id].type = REGION; + + info[command->new_region.id].u.region = + command->new_region.region; + break; + + case NEW_TRAPS: + info[command->new_traps.id].type = TRAPS; + break; + + case NEW_GLYPHS: + info[command->new_glyphs.id].type = GLYPHS; + break; + + case NOP: + case NEW_BROKEN: + case COMPOSITE: + default: + break; + } + } + + do + { + changed = FALSE; + for (i = 0; i < buffer->n_commands; ++i) + { + command_t *command = &(buffer->commands[i]); + int src, mask, dest; + + switch (command->type) + { + case NOP: + break; + + case COMPOSITE: + src = command->composite.src; + mask = command->composite.mask; + dest = command->composite.dest; + + if (info[src].same_as != -1) + { + src = command->composite.src = info[src].same_as; + changed = TRUE; + } + if (info[mask].same_as != -1) + { + mask = command->composite.mask = info[mask].same_as; + changed = TRUE; + } + if (info[dest].same_as != -1) + { + dest = command->composite.dest = info[dest].same_as; + changed = TRUE; + } + if (command->composite.op == PIXMAN_OP_SRC) + { + if (info[src].type == REGION && + info[mask].type == WHITE && + info[dest].type == BLANK && + !command->composite.clip) + { + info[dest].same_as = src; + command->type = NOP; + + changed = TRUE; + } + else if (info[src].type == REGION && + info[dest].type == BLANK && + !command->composite.clip) + { + int j; + int white = -1; + + for (j = 0; j < i; ++j) + { + image_info_t *in = &(info[j]); + + if (in->type == WHITE) + { + white = j; + break; + } + } + + if (white != -1) + { + printf ("tick\n"); + command->composite.clip = info[src].u.region; + src = command->composite.src = white; + } + + changed = TRUE; + } + else if (info[src].type == WHITE && + info[dest].type == BLANK && + command->composite.clip) + { + info[dest].type = CLIPPED_MASK; + info[dest].u.clipped_mask.mask = mask; + info[dest].u.clipped_mask.clip = + command->composite.clip; + + changed = TRUE; + } + } + else if (command->composite.op == PIXMAN_OP_OVER || + command->composite.op == PIXMAN_OP_ADD) + { + if (info[mask].type == CLIPPED_MASK && + !command->composite.clip) + { + command->composite.mask = info[mask].u.clipped_mask.mask; + command->composite.clip = info[mask].u.clipped_mask.clip; + + changed = TRUE; + } + } + } + } + } while (changed); + +out: + free (info); +} + static cairo_int_status_t command_buffer_process (command_buffer_t *buffer, int width, int height) { @@ -642,6 +839,8 @@ command_buffer_process (command_buffer_t *buffer, int width, int height) if (buffer->oom) goto out; + command_buffer_optimize (buffer); + n_images = buffer->id; if (!(images = calloc (sizeof (pixman_image_t *), n_images))) goto out; @@ -657,6 +856,10 @@ command_buffer_process (command_buffer_t *buffer, int width, int height) switch (command->type) { + case NOP: + printf ("nop\n"); + break; + case NEW_BLANK: printf ("%d => blank\n", command->new_blank.id); @@ -752,13 +955,25 @@ command_buffer_process (command_buffer_t *buffer, int width, int height) break; case COMPOSITE: - printf ("composite %d (src: %d mask: %d dest: %d)\n", command->composite.op, command->composite.src, command->composite.mask, command->composite.dest); + printf ("composite %d (src: %d mask: %d dest: %d) clip: %d\n", command->composite.op, command->composite.src, command->composite.mask, command->composite.dest, command->composite.clip? pixman_region32_n_rects (command->composite.clip) : -1); + if (command->composite.clip) + { + pixman_image_set_clip_region32 ( + images[command->composite.dest], command->composite.clip); + } + pixman_image_composite32 ( command->composite.op, images[command->composite.src], images[command->composite.mask], images[command->composite.dest], 0, 0, 0, 0, 0, 0, width, height); + + if (command->composite.clip) + { + pixman_image_set_clip_region32 ( + images[command->composite.dest], NULL); + } break; } } |