From 54fdc48d6a69bcf4f56ce8490669d666e73ad3cc Mon Sep 17 00:00:00 2001 From: Cedric BAIL Date: Thu, 19 Jan 2012 15:17:24 +0000 Subject: [PATCH] evas: add double buffer support to buffer engine. NOTE: This patch is a first step to replace and remove Evas SDL Software backend. SVN revision: 67347 --- legacy/evas/ChangeLog | 3 + legacy/evas/NEWS | 1 + .../engines/buffer/Evas_Engine_Buffer.h | 3 + .../src/modules/engines/buffer/evas_engine.c | 60 ++++++++++++++++--- .../src/modules/engines/buffer/evas_engine.h | 8 ++- .../src/modules/engines/buffer/evas_outbuf.c | 25 +++++++- 6 files changed, 91 insertions(+), 9 deletions(-) diff --git a/legacy/evas/ChangeLog b/legacy/evas/ChangeLog index fa77400a76..efae30869b 100644 --- a/legacy/evas/ChangeLog +++ b/legacy/evas/ChangeLog @@ -644,3 +644,6 @@ * Add EVAS_OBJECT_POINTER_MODE_NOGRAB_NO_REPEAT_UPDOWN pointer mode for some very specific behavior needed for accessibility. +2012-01-19 Cedric Bail + + * Add double buffer support to buffer engine. diff --git a/legacy/evas/NEWS b/legacy/evas/NEWS index 945fd96cff..68df381eae 100644 --- a/legacy/evas/NEWS +++ b/legacy/evas/NEWS @@ -8,6 +8,7 @@ Additions: * Textblock now supports self-closing tags, i.e
. Those should be used instead of the old
way. * Shm engine for drawing in Wayland. * evas_object_smart_callback_del_full API. + * Add double buffer support to the buffer engine. Improvements: diff --git a/legacy/evas/src/modules/engines/buffer/Evas_Engine_Buffer.h b/legacy/evas/src/modules/engines/buffer/Evas_Engine_Buffer.h index e6d11d145a..a9cbbfbf45 100644 --- a/legacy/evas/src/modules/engines/buffer/Evas_Engine_Buffer.h +++ b/legacy/evas/src/modules/engines/buffer/Evas_Engine_Buffer.h @@ -29,7 +29,10 @@ struct _Evas_Engine_Info_Buffer struct { void * (*new_update_region) (int x, int y, int w, int h, int *row_bytes); void (*free_update_region) (int x, int y, int w, int h, void *data); + void * (*switch_buffer) (void *data, void *dest_buffer); } func; + + void *switch_data; } info; /* non-blocking or blocking mode */ diff --git a/legacy/evas/src/modules/engines/buffer/evas_engine.c b/legacy/evas/src/modules/engines/buffer/evas_engine.c index e8dff7aa33..355ef7e894 100644 --- a/legacy/evas/src/modules/engines/buffer/evas_engine.c +++ b/legacy/evas/src/modules/engines/buffer/evas_engine.c @@ -25,11 +25,12 @@ struct _Render_Engine Outbuf *ob; Tilebuf_Rect *rects; Eina_Inlist *cur_rect; + Eina_Inarray previous_rects; int end : 1; }; /* prototypes we will use here */ -static void *_output_setup(int w, int h, void *dest_buffer, int dest_buffer_row_bytes, int depth_type, int use_color_key, int alpha_threshold, int color_key_r, int color_key_g, int color_key_b, void *(*new_update_region) (int x, int y, int w, int h, int *row_bytes), void (*free_update_region) (int x, int y, int w, int h, void *data)); +static void *_output_setup(int w, int h, void *dest_buffer, int dest_buffer_row_bytes, int depth_type, int use_color_key, int alpha_threshold, int color_key_r, int color_key_g, int color_key_b, void *(*new_update_region) (int x, int y, int w, int h, int *row_bytes), void (*free_update_region) (int x, int y, int w, int h, void *data), void *(*switch_buffer) (void *data, void *dest_buffer), void *switch_data); static void *eng_info(Evas *e __UNUSED__); static void eng_info_free(Evas *e __UNUSED__, void *info); @@ -58,7 +59,9 @@ _output_setup(int w, int color_key_g, int color_key_b, void *(*new_update_region) (int x, int y, int w, int h, int *row_bytes), - void (*free_update_region) (int x, int y, int w, int h, void *data) + void (*free_update_region) (int x, int y, int w, int h, void *data), + void *(*switch_buffer) (void *data, void *dest_buffer), + void *switch_data ) { Render_Engine *re; @@ -81,7 +84,7 @@ _output_setup(int w, evas_common_tilebuf_init(); evas_buffer_outbuf_buf_init(); - + { Outbuf_Depth dep; DATA32 color_key = 0; @@ -110,10 +113,13 @@ _output_setup(int w, color_key, alpha_threshold, new_update_region, - free_update_region); + free_update_region, + switch_buffer, + switch_data); } re->tb = evas_common_tilebuf_new(w, h); evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE); + eina_inarray_setup(&re->previous_rects, sizeof (Eina_Rectangle), 8); return re; } @@ -155,7 +161,9 @@ eng_setup(Evas *e, void *in) info->info.color_key_g, info->info.color_key_b, info->info.func.new_update_region, - info->info.func.free_update_region); + info->info.func.free_update_region, + info->info.func.switch_buffer, + info->info.switch_data); if (e->engine.data.output) eng_output_free(e->engine.data.output); e->engine.data.output = re; @@ -195,6 +203,8 @@ eng_output_resize(void *data, int w, int h) char use_color_key; void * (*new_update_region) (int x, int y, int w, int h, int *row_bytes); void (*free_update_region) (int x, int y, int w, int h, void *data); + void * (*switch_buffer) (void *switch_data, void *dest); + void *switch_data; depth = re->ob->depth; dest = re->ob->dest; @@ -204,6 +214,8 @@ eng_output_resize(void *data, int w, int h) use_color_key = re->ob->use_color_key; new_update_region = re->ob->func.new_update_region; free_update_region = re->ob->func.free_update_region; + switch_buffer = re->ob->func.switch_buffer; + switch_data = re->ob->switch_data; evas_buffer_outbuf_buf_free(re->ob); re->ob = evas_buffer_outbuf_buf_setup_fb(w, h, @@ -214,7 +226,9 @@ eng_output_resize(void *data, int w, int h) color_key, alpha_level, new_update_region, - free_update_region); + free_update_region, + switch_buffer, + switch_data); } evas_common_tilebuf_free(re->tb); re->tb = evas_common_tilebuf_new(w, h); @@ -275,6 +289,37 @@ eng_output_redraws_next_update_get(void *data, int *x, int *y, int *w, int *h, i if (!re->rects) { re->rects = evas_common_tilebuf_get_render_rects(re->tb); + + /* handle double buffering */ + if (re->ob->func.switch_buffer) + { + Eina_Rectangle *pushing; + + if (re->ob->first_frame && !re->previous_rects.len) + { + evas_common_tilebuf_add_redraw(re->tb, 0, 0, re->ob->w, re->ob->h); + re->ob->first_frame = 0; + } + + /* push previous frame */ + EINA_INARRAY_FOREACH(&re->previous_rects, pushing) + evas_common_tilebuf_add_redraw(re->tb, pushing->x, pushing->y, pushing->w, pushing->h); + eina_inarray_flush(&re->previous_rects); + + /* save current list of damage */ + EINA_INLIST_FOREACH(re->rects, rect) + { + Eina_Rectangle local; + + EINA_RECTANGLE_SET(&local, rect->x, rect->y, rect->w, rect->h); + eina_inarray_append(&re->previous_rects, &local); + } + + /* and regenerate the damage list by tacking into account the damage over two frames */ + evas_common_tilebuf_free_render_rects(re->rects); + re->rects = evas_common_tilebuf_get_render_rects(re->tb); + } + re->cur_rect = EINA_INLIST_GET(re->rects); } if (!re->cur_rect) return NULL; @@ -306,7 +351,7 @@ eng_output_redraws_next_update_push(void *data, void *surface, int x, int y, int re = (Render_Engine *)data; #ifdef BUILD_PIPE_RENDER evas_common_pipe_map_begin(surface); -#endif +#endif evas_buffer_outbuf_buf_push_updated_region(re->ob, surface, x, y, w, h); evas_buffer_outbuf_buf_free_region_for_update(re->ob, surface); evas_common_cpu_end_opt(); @@ -318,6 +363,7 @@ eng_output_flush(void *data) Render_Engine *re; re = (Render_Engine *)data; + evas_buffer_outbuf_buf_switch_buffer(re->ob); } static void diff --git a/legacy/evas/src/modules/engines/buffer/evas_engine.h b/legacy/evas/src/modules/engines/buffer/evas_engine.h index 21c988c545..af824776ab 100644 --- a/legacy/evas/src/modules/engines/buffer/evas_engine.h +++ b/legacy/evas/src/modules/engines/buffer/evas_engine.h @@ -52,14 +52,17 @@ struct _Outbuf void *dest; unsigned int dest_row_bytes; + void *switch_data; int alpha_level; DATA32 color_key; char use_color_key : 1; + char first_frame : 1; struct { void * (*new_update_region) (int x, int y, int w, int h, int *row_bytes); void (*free_update_region) (int x, int y, int w, int h, void *data); + void * (*switch_buffer) (void *data, void *dest_buffer); } func; struct { @@ -74,12 +77,15 @@ void evas_buffer_outbuf_buf_free (Outbuf *buf); Outbuf *evas_buffer_outbuf_buf_setup_fb (int w, int h, Outbuf_Depth depth, void *dest, int dest_row_bytes, int use_color_key, DATA32 color_key, int alpha_level, void * (*new_update_region) (int x, int y, int w, int h, int *row_bytes), - void (*free_update_region) (int x, int y, int w, int h, void *data)); + void (*free_update_region) (int x, int y, int w, int h, void *data), + void * (*switch_buffer)(void *switch_data, void *dest), + void *switch_data); RGBA_Image *evas_buffer_outbuf_buf_new_region_for_update (Outbuf *buf, int x, int y, int w, int h, int *cx, int *cy, int *cw, int *ch); void evas_buffer_outbuf_buf_free_region_for_update (Outbuf *buf, RGBA_Image *update); void evas_buffer_outbuf_buf_push_updated_region (Outbuf *buf, RGBA_Image *update, int x, int y, int w, int h); +void evas_buffer_outbuf_buf_switch_buffer (Outbuf *buf); #endif diff --git a/legacy/evas/src/modules/engines/buffer/evas_outbuf.c b/legacy/evas/src/modules/engines/buffer/evas_outbuf.c index 27f7a2c6a5..db42f23481 100644 --- a/legacy/evas/src/modules/engines/buffer/evas_outbuf.c +++ b/legacy/evas/src/modules/engines/buffer/evas_outbuf.c @@ -19,7 +19,9 @@ evas_buffer_outbuf_buf_free(Outbuf *buf) Outbuf * evas_buffer_outbuf_buf_setup_fb(int w, int h, Outbuf_Depth depth, void *dest, int dest_row_bytes, int use_color_key, DATA32 color_key, int alpha_level, void * (*new_update_region) (int x, int y, int w, int h, int *row_bytes), - void (*free_update_region) (int x, int y, int w, int h, void *data) + void (*free_update_region) (int x, int y, int w, int h, void *data), + void * (*switch_buffer) (void *data, void *dest_buffer), + void *switch_data ) { Outbuf *buf; @@ -38,9 +40,12 @@ evas_buffer_outbuf_buf_setup_fb(int w, int h, Outbuf_Depth depth, void *dest, in buf->alpha_level = alpha_level; buf->color_key = color_key; buf->use_color_key = use_color_key; + buf->first_frame = 1; buf->func.new_update_region = new_update_region; buf->func.free_update_region = free_update_region; + buf->func.switch_buffer = switch_buffer; + buf->switch_data = switch_data; bpp = sizeof(DATA32); if ((buf->depth == OUTBUF_DEPTH_RGB_24BPP_888_888) || @@ -101,6 +106,24 @@ evas_buffer_outbuf_buf_free_region_for_update(Outbuf *buf, RGBA_Image *update) if (update != buf->priv.back_buf) evas_cache_image_drop(&update->cache_entry); } +void +evas_buffer_outbuf_buf_switch_buffer(Outbuf *buf) +{ + if (buf->func.switch_buffer) + { + buf->dest = buf->func.switch_buffer(buf->switch_data, buf->dest); + if (buf->priv.back_buf) + { + evas_cache_image_drop(&buf->priv.back_buf->cache_entry); + buf->priv.back_buf = (RGBA_Image *) evas_cache_image_data(evas_common_image_cache_get(), + buf->w, buf->h, + buf->dest, + buf->depth == OUTBUF_DEPTH_ARGB_32BPP_8888_8888 ? 1 : 0, + EVAS_COLORSPACE_ARGB8888); + } + } +} + void evas_buffer_outbuf_buf_push_updated_region(Outbuf *buf, RGBA_Image *update, int x, int y, int w, int h) {