cedric pushed a commit to branch master. http://git.enlightenment.org/core/efl.git/commit/?id=3e3fde5db9d05cab5be10a9ef40e5c1416ef6cc1
commit 3e3fde5db9d05cab5be10a9ef40e5c1416ef6cc1 Author: Cedric BAIL <[email protected]> Date: Tue Jun 17 22:08:51 2014 +0200 evas: add possibility for engine to also inherit part of the Render_Engine from software generic. --- src/Makefile_Evas.am | 4 +- .../Evas_Engine_Software_Generic.h | 145 ++++++++++ .../evas/engines/software_generic/evas_engine.c | 314 ++++++++++++++++++++- 3 files changed, 452 insertions(+), 11 deletions(-) diff --git a/src/Makefile_Evas.am b/src/Makefile_Evas.am index c98f80c..9acfad1 100644 --- a/src/Makefile_Evas.am +++ b/src/Makefile_Evas.am @@ -588,12 +588,12 @@ lib/evas/filters/blur/blur_box_rgba_neon.c ### Engines if EVAS_STATIC_BUILD_SOFTWARE_GENERIC -lib_evas_libevas_la_SOURCES += modules/evas/engines/software_generic/evas_engine.c +lib_evas_libevas_la_SOURCES += modules/evas/engines/software_generic/evas_engine.c modules/evas/engines/software_generic/Evas_Engine_Software_Generic.h lib_evas_libevas_la_LIBADD += else enginesoftwaregenericpkgdir = $(libdir)/evas/modules/engines/software_generic/$(MODULE_ARCH) enginesoftwaregenericpkg_LTLIBRARIES = modules/evas/engines/software_generic/module.la -modules_evas_engines_software_generic_module_la_SOURCES = modules/evas/engines/software_generic/evas_engine.c +modules_evas_engines_software_generic_module_la_SOURCES = modules/evas/engines/software_generic/evas_engine.c modules/evas/engines/software_generic/Evas_Engine_Software_Generic.h modules_evas_engines_software_generic_module_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl \ -I$(top_srcdir)/src/lib/evas/include \ -I$(top_srcdir)/src/lib/evas/cserve2 \ diff --git a/src/modules/evas/engines/software_generic/Evas_Engine_Software_Generic.h b/src/modules/evas/engines/software_generic/Evas_Engine_Software_Generic.h new file mode 100644 index 0000000..483cb46 --- /dev/null +++ b/src/modules/evas/engines/software_generic/Evas_Engine_Software_Generic.h @@ -0,0 +1,145 @@ +#ifndef EVAS_ENGINE_SOFTWARE_GENERIC_H_ +# define EVAS_ENGINE_SOFTWARE_GENERIC_H_ + +#include "evas_private.h" + +typedef enum _Outbuf_Depth +{ + OUTBUF_DEPTH_NONE, + OUTBUF_DEPTH_INHERIT, + + /* From X11 */ + OUTBUF_DEPTH_RGB_16BPP_565_565_DITHERED, + OUTBUF_DEPTH_RGB_16BPP_555_555_DITHERED, + OUTBUF_DEPTH_RGB_16BPP_444_444_DITHERED, + OUTBUF_DEPTH_RGB_16BPP_565_444_DITHERED, + OUTBUF_DEPTH_RGB_32BPP_888_8888, + + /* From buffer */ + OUTBUF_DEPTH_ARGB_32BPP_8888_8888, + OUTBUF_DEPTH_BGRA_32BPP_8888_8888, + OUTBUF_DEPTH_BGR_32BPP_888_8888, + OUTBUF_DEPTH_RGB_24BPP_888_888, + OUTBUF_DEPTH_BGR_24BPP_888_888, + + OUTBUF_DEPTH_LAST +} Outbuf_Depth; + +typedef enum { + MODE_FULL, + MODE_COPY, + MODE_DOUBLE, + MODE_TRIPLE, + MODE_QUADRUPLE +} Render_Engine_Swap_Mode; + +typedef struct _Render_Engine_Software_Generic Render_Engine_Software_Generic; +typedef struct _Outbuf Outbuf; + +typedef Render_Engine_Swap_Mode (*Outbuf_Swap_Mode_Get)(Outbuf *ob); +typedef void (*Outbuf_Reconfigure)(Outbuf *ob, int w, int h, int rot, Outbuf_Depth depth); +typedef RGBA_Image *(*Outbuf_New_Region_For_Update)(Outbuf *ob, int x, int y, int w, int h, int *cx, int *cy, int *cw, int *ch); +typedef void (*Outbuf_Push_Updated_Region)(Outbuf *ob, RGBA_Image *update, int x, int y, int w, int h); +typedef void (*Outbuf_Idle_Flush)(Outbuf *ob); +typedef void (*Outbuf_Free_Region_For_Update)(Outbuf *ob, RGBA_Image *update); +typedef void (*Outbuf_Free)(Outbuf *ob); +typedef int (*Outbuf_Get_Rot)(Outbuf *ob); +typedef void (*Outbuf_Flush)(Outbuf *ob); + +struct _Render_Engine_Software_Generic +{ + Outbuf *ob; + Tilebuf *tb; + Tilebuf_Rect *rects; + Tilebuf_Rect *rects_prev[4]; + Eina_Inlist *cur_rect; + + Outbuf_Swap_Mode_Get outbuf_swap_mode_get; + Outbuf_Get_Rot outbuf_get_rot; + Outbuf_Reconfigure outbuf_reconfigure; + Outbuf_New_Region_For_Update outbuf_new_region_for_update; + Outbuf_Push_Updated_Region outbuf_push_updated_region; + Outbuf_Idle_Flush outbuf_idle_flush; + Outbuf_Free_Region_For_Update outbuf_free_region_for_update; + Outbuf_Free outbuf_free; + Outbuf_Flush outbuf_flush; + + unsigned int w, h; + + Render_Engine_Swap_Mode mode; + + unsigned char end : 1; + unsigned char lost_back : 1; +}; + +static inline Eina_Bool +evas_render_engine_software_generic_init(Render_Engine_Software_Generic *re, + Outbuf *ob, + Outbuf_Swap_Mode_Get outbuf_swap_mode_get, + Outbuf_Get_Rot outbuf_get_rot, + Outbuf_Reconfigure outbuf_reconfigure, + Outbuf_New_Region_For_Update outbuf_new_region_for_update, + Outbuf_Push_Updated_Region outbuf_push_updated_region, + Outbuf_Free_Region_For_Update outbuf_free_region_for_update, + Outbuf_Idle_Flush outbuf_idle_flush, + Outbuf_Flush outbuf_flush, + Outbuf_Free outbuf_free, + int w, int h) +{ + unsigned int i; + + re->ob = ob; + re->outbuf_swap_mode_get = outbuf_swap_mode_get; + re->outbuf_get_rot = outbuf_get_rot; + re->outbuf_reconfigure = outbuf_reconfigure; + re->outbuf_new_region_for_update = outbuf_new_region_for_update; + re->outbuf_push_updated_region = outbuf_push_updated_region; + re->outbuf_idle_flush = outbuf_idle_flush; + re->outbuf_free_region_for_update = outbuf_free_region_for_update; + re->outbuf_free = outbuf_free; + re->outbuf_flush = outbuf_flush; + + re->rects = NULL; + for (i = 0; i < 4; i++) + re->rects_prev[i] = NULL; + re->cur_rect = NULL; + + re->w = w; + re->h = h; + re->mode = MODE_FULL; + re->end = 0; + re->lost_back = 0; + + re->tb = evas_common_tilebuf_new(w, h); + if (!re->tb) return EINA_FALSE; + + /* in preliminary tests 16x16 gave highest framerates */ + evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE); + + return EINA_TRUE; +} + +static inline void +evas_render_engine_software_generic_clean(Render_Engine_Software_Generic *re) +{ + if (re->tb) evas_common_tilebuf_free(re->tb); + if (re->ob) re->outbuf_free(re->ob); + + if (re->rects) evas_common_tilebuf_free_render_rects(re->rects); + if (re->rects_prev[0]) evas_common_tilebuf_free_render_rects(re->rects_prev[0]); + if (re->rects_prev[1]) evas_common_tilebuf_free_render_rects(re->rects_prev[1]); + if (re->rects_prev[2]) evas_common_tilebuf_free_render_rects(re->rects_prev[2]); + if (re->rects_prev[3]) evas_common_tilebuf_free_render_rects(re->rects_prev[3]); + + memset(re, 0, sizeof (Render_Engine_Software_Generic)); +} + +static inline void +evas_render_engine_software_generic_update(Render_Engine_Software_Generic *re, + Outbuf *ob) +{ + if (re->ob) re->outbuf_free(re->ob); + re->ob = ob; +} + +#endif diff --git a/src/modules/evas/engines/software_generic/evas_engine.c b/src/modules/evas/engines/software_generic/evas_engine.c index 70a625d..6342e20 100644 --- a/src/modules/evas/engines/software_generic/evas_engine.c +++ b/src/modules/evas/engines/software_generic/evas_engine.c @@ -16,6 +16,8 @@ # warning software_generic will not be able to have Evas_GL API. #endif +#include "Evas_Engine_Software_Generic.h" + #ifdef EVAS_GL //----------------------------------// // OSMesa... @@ -2565,6 +2567,300 @@ eng_gl_api_get(void *data EINA_UNUSED) //------------------------------------------------// +/* The following function require that any engine + inheriting from software generic to have at the + top of their render engine structure a + Render_Engine_Software_Generic structure that is + initialized by evas_render_engine_software_generic_init(). + */ + +static void +eng_output_resize(void *data, int w, int h) +{ + Render_Engine_Software_Generic *re; + + re = (Render_Engine_Software_Generic *)data; + re->outbuf_reconfigure(re->ob, w, h, re->outbuf_get_rot(re->ob), + OUTBUF_DEPTH_INHERIT); + evas_common_tilebuf_free(re->tb); + re->tb = evas_common_tilebuf_new(w, h); + if (re->tb) + evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE); + re->w = w; + re->h = h; +} + +static void +eng_output_tile_size_set(void *data, int w, int h) +{ + Render_Engine_Software_Generic *re; + + re = (Render_Engine_Software_Generic *)data; + evas_common_tilebuf_set_tile_size(re->tb, w, h); +} + +static void +eng_output_redraws_rect_add(void *data, int x, int y, int w, int h) +{ + Render_Engine_Software_Generic *re; + + re = (Render_Engine_Software_Generic *)data; + evas_common_tilebuf_add_redraw(re->tb, x, y, w, h); +} + +static void +eng_output_redraws_rect_del(void *data, int x, int y, int w, int h) +{ + Render_Engine_Software_Generic *re; + + re = (Render_Engine_Software_Generic *)data; + evas_common_tilebuf_del_redraw(re->tb, x, y, w, h); +} + +static void +eng_output_redraws_clear(void *data) +{ + Render_Engine_Software_Generic *re; + + re = (Render_Engine_Software_Generic *)data; + evas_common_tilebuf_clear(re->tb); +} + +static Tilebuf_Rect * +_merge_rects(Tilebuf *tb, Tilebuf_Rect *r1, Tilebuf_Rect *r2, Tilebuf_Rect *r3, Tilebuf_Rect *r4) +{ + Tilebuf_Rect *r, *rects; + + if (r1) + { + EINA_INLIST_FOREACH(EINA_INLIST_GET(r1), r) + { + evas_common_tilebuf_add_redraw(tb, r->x, r->y, r->w, r->h); + } + } + if (r2) + { + EINA_INLIST_FOREACH(EINA_INLIST_GET(r2), r) + { + evas_common_tilebuf_add_redraw(tb, r->x, r->y, r->w, r->h); + } + } + if (r3) + { + EINA_INLIST_FOREACH(EINA_INLIST_GET(r3), r) + { + evas_common_tilebuf_add_redraw(tb, r->x, r->y, r->w, r->h); + } + } + + if (r4) + { + EINA_INLIST_FOREACH(EINA_INLIST_GET(r4), r) + { + evas_common_tilebuf_add_redraw(tb, r->x, r->y, r->w, r->h); + } + } + + rects = evas_common_tilebuf_get_render_rects(tb); + /* + // bounding box -> make a bounding box single region update of all regions. + // yes we could try and be smart and figure out size of regions, how far + // apart etc. etc. to try and figure out an optimal "set". this is a tradeoff + // between multiple update regions to render and total pixels to render. + if (rects) + { + int px1, py1, px2, py2; + + px1 = rects->x; py1 = rects->y; + px2 = rects->x + rects->w; py2 = rects->y + rects->h; + EINA_INLIST_FOREACH(EINA_INLIST_GET(rects), r) + { + if (r->x < px1) px1 = r->x; + if (r->y < py1) py1 = r->y; + if ((r->x + r->w) > px2) px2 = r->x + r->w; + if ((r->y + r->h) > py2) py2 = r->y + r->h; + } + evas_common_tilebuf_free_render_rects(rects); + rects = calloc(1, sizeof(Tilebuf_Rect)); + if (rects) + { + rects->x = px1; + rects->y = py1; + rects->w = px2 - px1; + rects->h = py2 - py1; + } + } + */ + evas_common_tilebuf_clear(tb); + return rects; +} + + +static void * +eng_output_redraws_next_update_get(void *data, int *x, int *y, int *w, int *h, int *cx, int *cy, int *cw, int *ch) +{ + Render_Engine_Software_Generic *re; + RGBA_Image *surface; + Tilebuf_Rect *rect; + Eina_Bool first_rect = EINA_FALSE; + +#define CLEAR_PREV_RECTS(x) \ + do { \ + if (re->rects_prev[x]) \ + evas_common_tilebuf_free_render_rects(re->rects_prev[x]); \ + re->rects_prev[x] = NULL; \ + } while (0) + + re = (Render_Engine_Software_Generic *)data; + if (re->end) + { + re->end = 0; + return NULL; + } + + if (!re->rects) + { + int mode = MODE_COPY; + + re->rects = evas_common_tilebuf_get_render_rects(re->tb); + if (re->rects) + { + if (re->outbuf_swap_mode_get) mode = re->outbuf_swap_mode_get(re->ob); + re->mode = mode; + if ((re->lost_back) || (re->mode == MODE_FULL)) + { + /* if we lost our backbuffer since the last frame redraw all */ + re->lost_back = 0; + evas_common_tilebuf_add_redraw(re->tb, 0, 0, re->w, re->h); + evas_common_tilebuf_free_render_rects(re->rects); + re->rects = evas_common_tilebuf_get_render_rects(re->tb); + } + /* ensure we get rid of previous rect lists we dont need if mode + * changed/is appropriate */ + evas_common_tilebuf_clear(re->tb); + CLEAR_PREV_RECTS(3); + re->rects_prev[3] = re->rects_prev[2]; + re->rects_prev[2] = re->rects_prev[1]; + re->rects_prev[1] = re->rects_prev[0]; + re->rects_prev[0] = re->rects; + re->rects = NULL; + switch (re->mode) + { + case MODE_FULL: + case MODE_COPY: // no prev rects needed + re->rects = _merge_rects(re->tb, re->rects_prev[0], NULL, NULL, NULL); + break; + case MODE_DOUBLE: // double mode - only 1 level of prev rect + re->rects = _merge_rects(re->tb, re->rects_prev[0], re->rects_prev[1], NULL, NULL); + break; + case MODE_TRIPLE: // triple mode - 2 levels of prev rect + re->rects = _merge_rects(re->tb, re->rects_prev[0], re->rects_prev[1], re->rects_prev[2], NULL); + break; + case MODE_QUADRUPLE: // keep all + re->rects = _merge_rects(re->tb, re->rects_prev[0], re->rects_prev[1], re->rects_prev[2], re->rects_prev[3]); + break; + default: + break; + } + first_rect = EINA_TRUE; + } + evas_common_tilebuf_clear(re->tb); + re->cur_rect = EINA_INLIST_GET(re->rects); + } + if (!re->cur_rect) return NULL; + rect = (Tilebuf_Rect *)re->cur_rect; + if (re->rects) + { + switch (re->mode) + { + case MODE_COPY: + case MODE_DOUBLE: + case MODE_TRIPLE: + case MODE_QUADRUPLE: + rect = (Tilebuf_Rect *)re->cur_rect; + *x = rect->x; + *y = rect->y; + *w = rect->w; + *h = rect->h; + *cx = rect->x; + *cy = rect->y; + *cw = rect->w; + *ch = rect->h; + re->cur_rect = re->cur_rect->next; + break; + case MODE_FULL: + re->cur_rect = NULL; + if (x) *x = 0; + if (y) *y = 0; + if (w) *w = re->w; + if (h) *h = re->h; + if (cx) *cx = 0; + if (cy) *cy = 0; + if (cw) *cw = re->w; + if (ch) *ch = re->h; + break; + default: + break; + } + if (first_rect) + { + // do anything needed fir the first frame + } + surface = re->outbuf_new_region_for_update(re->ob, + *x, *y, *w, *h, + cx, cy, cw, ch); + if (!re->cur_rect) + { + re->end = 1; + } + return surface; + } + return NULL; +} + +static void +eng_output_redraws_next_update_push(void *data, void *surface, int x, int y, int w, int h, Evas_Render_Mode render_mode) +{ + Render_Engine_Software_Generic *re; + + if (render_mode == EVAS_RENDER_MODE_ASYNC_INIT) return; + + re = (Render_Engine_Software_Generic *)data; +#if defined(BUILD_PIPE_RENDER) + evas_common_pipe_map_begin(surface); +#endif /* BUILD_PIPE_RENDER */ + re->outbuf_push_updated_region(re->ob, surface, x, y, w, h); + re->outbuf_free_region_for_update(re->ob, surface); + evas_common_cpu_end_opt(); +} + +static void +eng_output_flush(void *data, Evas_Render_Mode render_mode) +{ + Render_Engine_Software_Generic *re; + + if (render_mode == EVAS_RENDER_MODE_ASYNC_INIT) return; + + re = (Render_Engine_Software_Generic *)data; + if (re->outbuf_flush) re->outbuf_flush(re->ob); + if (re->rects) + { + evas_common_tilebuf_free_render_rects(re->rects); + re->rects = NULL; + } +} + +static void +eng_output_idle_flush(void *data) +{ + Render_Engine_Software_Generic *re; + + re = (Render_Engine_Software_Generic *)data; + if (re->outbuf_idle_flush) re->outbuf_idle_flush(re->ob); +} + + +//------------------------------------------------// /* ***** @@ -2580,15 +2876,15 @@ static Evas_Func func = NULL, NULL, NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, + eng_output_resize, + eng_output_tile_size_set, + eng_output_redraws_rect_add, + eng_output_redraws_rect_del, + eng_output_redraws_clear, + eng_output_redraws_next_update_get, + eng_output_redraws_next_update_push, + eng_output_flush, + eng_output_idle_flush, eng_output_dump, /* draw context virtual methods */ eng_context_new, --
