this is the START of something.. disabled at runtime for now - the

swapper infra is intended to have the ability to map pixels of
backbuffers right in for total zero-copy updates.



SVN revision: 79452
This commit is contained in:
Carsten Haitzler 2012-11-19 13:43:48 +00:00
parent 9aa23128b6
commit fac8ec4ca7
9 changed files with 1224 additions and 98 deletions

View File

@ -1007,6 +1007,7 @@ if BUILD_ENGINE_SOFTWARE_X11
dist_installed_evasmainheaders_DATA += modules/evas/engines/software_x11/Evas_Engine_Software_X11.h
SOFTWARE_X11_SOURCES = \
modules/evas/engines/software_x11/evas_engine.c \
modules/evas/engines/software_x11/evas_engine.h \
modules/evas/engines/software_x11/evas_x_egl.c \
modules/evas/engines/software_x11/evas_x_egl.h
SOFTWARE_X11_CPPFLAGS = \
@ -1025,10 +1026,17 @@ SOFTWARE_X11_CPPFLAGS = \
SOFTWARE_X11_LIBADD =
if BUILD_ENGINE_SOFTWARE_XLIB
SOFTWARE_X11_SOURCES += \
modules/evas/engines/software_x11/evas_xlib_swapbuf.c \
modules/evas/engines/software_x11/evas_xlib_outbuf.c \
modules/evas/engines/software_x11/evas_xlib_buffer.c \
modules/evas/engines/software_x11/evas_xlib_color.c \
modules/evas/engines/software_x11/evas_xlib_main.c
modules/evas/engines/software_x11/evas_xlib_main.c \
modules/evas/engines/software_x11/evas_xlib_swapper.c \
modules/evas/engines/software_x11/evas_xlib_outbuf.h \
modules/evas/engines/software_x11/evas_xlib_swapbuf.h \
modules/evas/engines/software_x11/evas_xlib_buffer.h \
modules/evas/engines/software_x11/evas_xlib_color.h \
modules/evas/engines/software_x11/evas_xlib_swapper.h
SOFTWARE_X11_CPPFLAGS += @evas_engine_software_xlib_cflags@
SOFTWARE_X11_LIBADD += @evas_engine_software_xlib_libs@
endif
@ -1039,10 +1047,6 @@ modules/evas/engines/software_x11/evas_xcb_outbuf.c \
modules/evas/engines/software_x11/evas_xcb_buffer.c \
modules/evas/engines/software_x11/evas_xcb_color.c \
modules/evas/engines/software_x11/evas_xcb_main.c \
modules/evas/engines/software_x11/evas_engine.h \
modules/evas/engines/software_x11/evas_xlib_outbuf.h \
modules/evas/engines/software_x11/evas_xlib_buffer.h \
modules/evas/engines/software_x11/evas_xlib_color.h \
modules/evas/engines/software_x11/evas_xcb_outbuf.h \
modules/evas/engines/software_x11/evas_xcb_buffer.h \
modules/evas/engines/software_x11/evas_xcb_color.h \

View File

@ -6,6 +6,7 @@
#ifdef BUILD_ENGINE_SOFTWARE_XLIB
# include "evas_xlib_outbuf.h"
# include "evas_xlib_swapbuf.h"
# include "evas_xlib_color.h"
#endif
@ -30,8 +31,11 @@ struct _Render_Engine
Tilebuf *tb;
Outbuf *ob;
Tilebuf_Rect *rects;
Tilebuf_Rect *rects_prev[3];
Eina_Inlist *cur_rect;
short mode;
unsigned char end : 1;
unsigned char lost_back : 1;
void (*outbuf_free)(Outbuf *ob);
void (*outbuf_reconfigure)(Outbuf *ob, int w, int h, int rot, Outbuf_Depth depth);
int (*outbuf_get_rot)(Outbuf *ob);
@ -40,6 +44,7 @@ struct _Render_Engine
void (*outbuf_free_region_for_update)(Outbuf *ob, RGBA_Image *update);
void (*outbuf_flush)(Outbuf *ob);
void (*outbuf_idle_flush)(Outbuf *ob);
int (*outbuf_swap_mode_get)(Outbuf *ob);
Eina_Bool (*outbuf_alpha_get)(Outbuf *ob);
struct {
@ -72,6 +77,7 @@ static void eng_output_idle_flush(void *data);
#ifdef BUILD_ENGINE_SOFTWARE_XLIB
/*
static void *
_output_egl_setup(int w, int h, int rot, Display *disp, Drawable draw,
Visual *vis, Colormap cmap, int depth, int debug,
@ -129,12 +135,12 @@ _output_egl_setup(int w, int h, int rot, Display *disp, Drawable draw,
return NULL;
}
/* in preliminary tests 16x16 gave highest framerates */
evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE);
return re;
debug = 0;
}
*/
static void
_output_egl_shutdown(Render_Engine *re)
@ -157,7 +163,7 @@ _output_xlib_setup(int w, int h, int rot, Display *disp, Drawable draw,
evas_software_xlib_x_init();
evas_software_xlib_x_color_init();
evas_software_xlib_outbuf_init();
re->ob =
evas_software_xlib_outbuf_setup_x(w, h, rot, OUTBUF_DEPTH_INHERIT, disp,
draw, vis, cmap, depth, grayscale,
@ -192,6 +198,44 @@ _output_xlib_setup(int w, int h, int rot, Display *disp, Drawable draw,
evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE);
return re;
}
static void *
_output_swapbuf_setup(int w, int h, int rot, Display *disp, Drawable draw,
Visual *vis, Colormap cmap, int depth,
int debug EINA_UNUSED,
int grayscale, int max_colors, Pixmap mask,
int shape_dither, int destination_alpha)
{
Render_Engine *re;
if (!(re = calloc(1, sizeof(Render_Engine)))) return NULL;
evas_software_xlib_x_init();
evas_software_xlib_x_color_init();
evas_software_xlib_swapbuf_init();
re->ob =
evas_software_xlib_swapbuf_setup_x(w, h, rot, OUTBUF_DEPTH_INHERIT, disp,
draw, vis, cmap, depth, grayscale,
max_colors, mask, shape_dither,
destination_alpha);
if (!re->ob)
{
free(re);
return NULL;
}
re->tb = evas_common_tilebuf_new(w, h);
if (!re->tb)
{
evas_software_xlib_swapbuf_free(re->ob);
free(re);
return NULL;
}
evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE);
return re;
}
#endif
#ifdef BUILD_ENGINE_SOFTWARE_XCB
@ -409,29 +453,34 @@ eng_setup(Evas *eo_e, void *in)
#ifdef BUILD_ENGINE_SOFTWARE_XLIB
if (info->info.backend == EVAS_ENGINE_INFO_SOFTWARE_X11_BACKEND_XLIB)
{
re = _output_egl_setup(e->output.w, e->output.h,
info->info.rotation, info->info.connection,
info->info.drawable, info->info.visual,
info->info.colormap,
info->info.depth, info->info.debug,
info->info.alloc_grayscale,
info->info.alloc_colors_max,
info->info.mask, info->info.shape_dither,
info->info.destination_alpha);
// this is disabled for now as we should only use/need the
// swapper infra *IF* we can get direct access to the "backbuffer"
// of a window in x11.
if (0)
re = _output_swapbuf_setup(e->output.w, e->output.h,
info->info.rotation, info->info.connection,
info->info.drawable, info->info.visual,
info->info.colormap,
info->info.depth, info->info.debug,
info->info.alloc_grayscale,
info->info.alloc_colors_max,
info->info.mask, info->info.shape_dither,
info->info.destination_alpha);
if (re)
{
// XXX these need to provide egl functions not xlib
re->outbuf_free = evas_software_xlib_outbuf_free;
re->outbuf_reconfigure = evas_software_xlib_outbuf_reconfigure;
re->outbuf_get_rot = evas_software_xlib_outbuf_get_rot;
re->outbuf_new_region_for_update = evas_software_xlib_outbuf_new_region_for_update;
re->outbuf_push_updated_region = evas_software_xlib_outbuf_push_updated_region;
re->outbuf_free_region_for_update = evas_software_xlib_outbuf_free_region_for_update;
re->outbuf_flush = evas_software_xlib_outbuf_flush;
re->outbuf_idle_flush = evas_software_xlib_outbuf_idle_flush;
re->outbuf_alpha_get = evas_software_xlib_outbuf_alpha_get;
re->outbuf_free = evas_software_xlib_swapbuf_free;
re->outbuf_reconfigure = evas_software_xlib_swapbuf_reconfigure;
re->outbuf_get_rot = evas_software_xlib_swapbuf_get_rot;
re->outbuf_new_region_for_update = evas_software_xlib_swapbuf_new_region_for_update;
re->outbuf_push_updated_region = evas_software_xlib_swapbuf_push_updated_region;
re->outbuf_free_region_for_update = evas_software_xlib_swapbuf_free_region_for_update;
re->outbuf_flush = evas_software_xlib_swapbuf_flush;
re->outbuf_idle_flush = evas_software_xlib_swapbuf_idle_flush;
re->outbuf_alpha_get = evas_software_xlib_swapbuf_alpha_get;
re->outbuf_swap_mode_get = evas_software_xlib_swapbuf_buffer_state_get;
}
else
if (!re)
{
re = _output_xlib_setup(e->output.w, e->output.h,
info->info.rotation, info->info.connection,
@ -443,15 +492,16 @@ eng_setup(Evas *eo_e, void *in)
info->info.mask, info->info.shape_dither,
info->info.destination_alpha);
re->outbuf_free = evas_software_xlib_outbuf_free;
re->outbuf_reconfigure = evas_software_xlib_outbuf_reconfigure;
re->outbuf_get_rot = evas_software_xlib_outbuf_get_rot;
re->outbuf_new_region_for_update = evas_software_xlib_outbuf_new_region_for_update;
re->outbuf_push_updated_region = evas_software_xlib_outbuf_push_updated_region;
re->outbuf_free = evas_software_xlib_outbuf_free;
re->outbuf_reconfigure = evas_software_xlib_outbuf_reconfigure;
re->outbuf_get_rot = evas_software_xlib_outbuf_get_rot;
re->outbuf_new_region_for_update = evas_software_xlib_outbuf_new_region_for_update;
re->outbuf_push_updated_region = evas_software_xlib_outbuf_push_updated_region;
re->outbuf_free_region_for_update = evas_software_xlib_outbuf_free_region_for_update;
re->outbuf_flush = evas_software_xlib_outbuf_flush;
re->outbuf_idle_flush = evas_software_xlib_outbuf_idle_flush;
re->outbuf_alpha_get = evas_software_xlib_outbuf_alpha_get;
re->outbuf_flush = evas_software_xlib_outbuf_flush;
re->outbuf_idle_flush = evas_software_xlib_outbuf_idle_flush;
re->outbuf_alpha_get = evas_software_xlib_outbuf_alpha_get;
re->outbuf_swap_mode_get = NULL;
}
}
#endif
@ -469,18 +519,16 @@ eng_setup(Evas *eo_e, void *in)
info->info.mask, info->info.shape_dither,
info->info.destination_alpha);
re->outbuf_free = evas_software_xcb_outbuf_free;
re->outbuf_reconfigure = evas_software_xcb_outbuf_reconfigure;
re->outbuf_get_rot = evas_software_xcb_outbuf_rotation_get;
re->outbuf_new_region_for_update =
evas_software_xcb_outbuf_new_region_for_update;
re->outbuf_push_updated_region =
evas_software_xcb_outbuf_push_updated_region;
re->outbuf_free_region_for_update =
evas_software_xcb_outbuf_free_region_for_update;
re->outbuf_flush = evas_software_xcb_outbuf_flush;
re->outbuf_idle_flush = evas_software_xcb_outbuf_idle_flush;
re->outbuf_alpha_get = evas_software_xcb_outbuf_alpha_get;
re->outbuf_free = evas_software_xcb_outbuf_free;
re->outbuf_reconfigure = evas_software_xcb_outbuf_reconfigure;
re->outbuf_get_rot = evas_software_xcb_outbuf_rotation_get;
re->outbuf_new_region_for_update = evas_software_xcb_outbuf_new_region_for_update;
re->outbuf_push_updated_region = evas_software_xcb_outbuf_push_updated_region;
re->outbuf_free_region_for_update = evas_software_xcb_outbuf_free_region_for_update;
re->outbuf_flush = evas_software_xcb_outbuf_flush;
re->outbuf_idle_flush = evas_software_xcb_outbuf_idle_flush;
re->outbuf_alpha_get = evas_software_xcb_outbuf_alpha_get;
re->outbuf_swap_mode_get = NULL;
}
#endif
@ -491,29 +539,49 @@ eng_setup(Evas *eo_e, void *in)
int ponebuf = 0;
re = e->engine.data.output;
ponebuf = re->ob->onebuf;
if ((re) && (re->ob)) ponebuf = re->ob->onebuf;
#ifdef BUILD_ENGINE_SOFTWARE_XLIB
if (info->info.backend == EVAS_ENGINE_INFO_SOFTWARE_X11_BACKEND_XLIB)
{
// XXXX do egl stuff as above
evas_software_xlib_outbuf_free(re->ob);
re->ob =
evas_software_xlib_outbuf_setup_x(e->output.w, e->output.h,
info->info.rotation,
OUTBUF_DEPTH_INHERIT,
info->info.connection,
info->info.drawable,
info->info.visual,
info->info.colormap,
info->info.depth,
info->info.alloc_grayscale,
info->info.alloc_colors_max,
info->info.mask,
info->info.shape_dither,
info->info.destination_alpha);
// XXX
re->outbuf_free(re->ob);
evas_software_xlib_outbuf_debug_set(re->ob, info->info.debug);
if (re->outbuf_free == evas_software_xlib_swapbuf_free)
{
re->ob =
evas_software_xlib_swapbuf_setup_x(e->output.w, e->output.h,
info->info.rotation,
OUTBUF_DEPTH_INHERIT,
info->info.connection,
info->info.drawable,
info->info.visual,
info->info.colormap,
info->info.depth,
info->info.alloc_grayscale,
info->info.alloc_colors_max,
info->info.mask,
info->info.shape_dither,
info->info.destination_alpha);
}
else
{
re->ob =
evas_software_xlib_outbuf_setup_x(e->output.w, e->output.h,
info->info.rotation,
OUTBUF_DEPTH_INHERIT,
info->info.connection,
info->info.drawable,
info->info.visual,
info->info.colormap,
info->info.depth,
info->info.alloc_grayscale,
info->info.alloc_colors_max,
info->info.mask,
info->info.shape_dither,
info->info.destination_alpha);
evas_software_xlib_outbuf_debug_set(re->ob, info->info.debug);
}
}
#endif
@ -536,11 +604,10 @@ eng_setup(Evas *eo_e, void *in)
info->info.mask,
info->info.shape_dither,
info->info.destination_alpha);
evas_software_xcb_outbuf_debug_set(re->ob, info->info.debug);
}
#endif
re->ob->onebuf = ponebuf;
if ((re) && (re->ob)) re->ob->onebuf = ponebuf;
}
if (!e->engine.data.output) return 0;
if (!e->engine.data.context)
@ -564,6 +631,9 @@ eng_output_free(void *data)
re->outbuf_free(re->ob);
evas_common_tilebuf_free(re->tb);
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]);
_output_egl_shutdown(re);
free(re);
}
@ -622,41 +692,189 @@ eng_output_redraws_clear(void *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 *r, *rects;
int x1, y1, x2, y2;
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 (r2)
{
EINA_INLIST_FOREACH(EINA_INLIST_GET(r3), 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)
{
x1 = rects->x; y1 = rects->y;
x2 = rects->x + rects->w; y2 = rects->y + rects->h;
EINA_INLIST_FOREACH(EINA_INLIST_GET(rects), r)
{
if (r->x < x1) x1 = r->x;
if (r->y < y1) y1 = r->y;
if ((r->x + r->w) > x2) x2 = r->x + r->w;
if ((r->y + r->h) > y2) y2 = r->y + r->h;
}
evas_common_tilebuf_free_render_rects(rects);
rects = calloc(1, sizeof(Tilebuf_Rect));
if (rects)
{
rects->x = x1;
rects->y = y1;
rects->w = x2 - x1;
rects->h = y2 - y1;
}
}
*/
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 *re;
RGBA_Image *surface;
Tilebuf_Rect *rect;
int ux, uy, uw, uh;
Eina_Bool first_rect = EINA_FALSE;
int i;
#define CLEAR_PREV_RECTS(x) \
do { \
if (re->rects_prev[i]) \
evas_common_tilebuf_free_render_rects(re->rects_prev[i]); \
re->rects_prev[i] = NULL; \
} while (0)
re = (Render_Engine *)data;
if (re->end)
{
re->end = 0;
return NULL;
}
if (!re->rects)
{
int mode = MODE_COPY;
if (re->outbuf_swap_mode_get) mode = re->outbuf_swap_mode_get(re->ob);
re->mode = mode;
re->rects = evas_common_tilebuf_get_render_rects(re->tb);
re->cur_rect = EINA_INLIST_GET(re->rects);
if (re->rects)
{
if (re->lost_back)
{
/* 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->ob->w, re->ob->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 */
switch (re->mode)
{
case MODE_FULL:
case MODE_COPY: // no prev rects needed
for (i = 0; i < 3; i++) CLEAR_PREV_RECTS(i);
break;
case MODE_DOUBLE: // double mode - only 1 level of prev rect
for (i = 1; i < 3; i++) CLEAR_PREV_RECTS(i);
re->rects_prev[1] = re->rects_prev[0];
re->rects_prev[0] = re->rects;
// merge prev[1] + prev[0] -> rects
re->rects = _merge_rects(re->tb, re->rects_prev[0], re->rects_prev[1], NULL);
break;
case MODE_TRIPLE: // keep all
for (i = 2; i < 3; i++) CLEAR_PREV_RECTS(i);
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;
// merge prev[2] + prev[1] + prev[0] -> rects
re->rects = _merge_rects(re->tb, re->rects_prev[0], re->rects_prev[1], re->rects_prev[2]);
break;
default:
break;
}
re->cur_rect = EINA_INLIST_GET(re->rects);
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;
ux = rect->x; uy = rect->y; uw = rect->w; uh = rect->h;
re->cur_rect = re->cur_rect->next;
if (!re->cur_rect)
if (re->rects)
{
evas_common_tilebuf_free_render_rects(re->rects);
re->rects = NULL;
re->end = 1;
switch (re->mode)
{
case MODE_COPY:
case MODE_DOUBLE:
case MODE_TRIPLE:
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->ob->w;
if (h) *h = re->ob->h;
if (cx) *cx = 0;
if (cy) *cy = 0;
if (cw) *cw = re->ob->w;
if (ch) *ch = re->ob->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;
}
surface =
re->outbuf_new_region_for_update(re->ob, ux, uy, uw, uh, cx, cy, cw, ch);
*x = ux; *y = uy; *w = uw; *h = uh;
return surface;
return NULL;
}
static void
@ -668,7 +886,6 @@ eng_output_redraws_next_update_push(void *data, void *surface, int x, int y, int
#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();
@ -681,6 +898,11 @@ eng_output_flush(void *data)
re = (Render_Engine *)data;
re->outbuf_flush(re->ob);
if (re->rects)
{
evas_common_tilebuf_free_render_rects(re->rects);
re->rects = NULL;
}
}
static void
@ -706,16 +928,6 @@ eng_canvas_alpha_get(void *data, void *context EINA_UNUSED)
static int
module_open(Evas_Module *em)
{
#ifdef BUILD_ENGINE_SOFTWARE_XLIB
static Eina_Bool xrm_inited = EINA_FALSE;
if (!xrm_inited)
{
xrm_inited = EINA_TRUE;
XrmInitialize();
}
#endif
if (!em) return 0;
/* get whatever engine module we inherit from */

View File

@ -60,6 +60,13 @@ enum _Outbuf_Depth
OUTBUF_DEPTH_LAST
};
enum {
MODE_FULL,
MODE_COPY,
MODE_DOUBLE,
MODE_TRIPLE
};
typedef struct _Outbuf Outbuf;
struct _Outbuf
@ -112,6 +119,8 @@ struct _Outbuf
/* 1 big buffer for updates - flush on idle_flush */
RGBA_Image *onebuf;
Eina_Array onebuf_regions;
void *swapper;
/* a list of pending regions to write to the target */
Eina_List *pending_writes;

View File

@ -93,6 +93,8 @@ evas_software_xcb_outbuf_setup(int w, int h, int rot, Outbuf_Depth depth, xcb_co
if (!(buf = calloc(1, sizeof(Outbuf))))
return NULL;
if (xdepth < 15) rot = 0;
setup = xcb_get_setup(conn);
buf->w = w;

View File

@ -14,7 +14,6 @@
#include "evas_xlib_buffer.h"
#include "evas_xlib_color.h"
typedef struct _Outbuf_Region Outbuf_Region;
struct _Outbuf_Region
@ -188,10 +187,10 @@ evas_software_xlib_outbuf_free(Outbuf *buf)
Outbuf *
evas_software_xlib_outbuf_setup_x(int w, int h, int rot, Outbuf_Depth depth,
Display *disp, Drawable draw, Visual *vis,
Colormap cmap, int x_depth,
int grayscale, int max_colors, Pixmap mask,
int shape_dither, int destination_alpha)
Display *disp, Drawable draw, Visual *vis,
Colormap cmap, int x_depth,
int grayscale, int max_colors, Pixmap mask,
int shape_dither, int destination_alpha)
{
Outbuf *buf;
@ -199,6 +198,8 @@ evas_software_xlib_outbuf_setup_x(int w, int h, int rot, Outbuf_Depth depth,
if (!buf)
return NULL;
if (x_depth < 15) rot = 0;
buf->w = w;
buf->h = h;
buf->depth = depth;
@ -214,7 +215,7 @@ evas_software_xlib_outbuf_setup_x(int w, int h, int rot, Outbuf_Depth depth,
eina_array_step_set(&buf->priv.onebuf_regions, sizeof (Eina_Array), 8);
{
{
Gfx_Func_Convert conv_func;
X_Output_Buffer *xob;

View File

@ -0,0 +1,549 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <sys/time.h>
#include <sys/utsname.h>
#ifdef EVAS_CSERVE2
#include "evas_cs2_private.h"
#endif
#include "evas_common.h"
#include "evas_macros.h"
#include "evas_xlib_swapbuf.h"
#include "evas_xlib_color.h"
#include "evas_xlib_swapper.h"
typedef struct _Outbuf_Region Outbuf_Region;
struct _Outbuf_Region
{
RGBA_Image *im;
int x;
int y;
int w;
int h;
};
void
evas_software_xlib_swapbuf_init(void)
{
}
void
evas_software_xlib_swapbuf_free(Outbuf *buf)
{
evas_software_xlib_swapbuf_flush(buf);
evas_software_xlib_swapbuf_idle_flush(buf);
if (buf->priv.pal)
evas_software_xlib_x_color_deallocate
(buf->priv.x11.xlib.disp, buf->priv.x11.xlib.cmap,
buf->priv.x11.xlib.vis, buf->priv.pal);
eina_array_flush(&buf->priv.onebuf_regions);
free(buf);
}
Outbuf *
evas_software_xlib_swapbuf_setup_x(int w, int h, int rot, Outbuf_Depth depth,
Display *disp, Drawable draw, Visual *vis,
Colormap cmap, int x_depth,
int grayscale, int max_colors, Pixmap mask,
int shape_dither, int destination_alpha)
{
Outbuf *buf;
Gfx_Func_Convert conv_func = NULL;
int d;
buf = calloc(1, sizeof(Outbuf));
if (!buf) return NULL;
if (x_depth < 15) rot = 0;
buf->onebuf = 1;
buf->w = w;
buf->h = h;
buf->depth = depth;
buf->rot = rot;
buf->priv.x11.xlib.disp = disp;
buf->priv.x11.xlib.win = draw;
buf->priv.x11.xlib.vis = vis;
buf->priv.x11.xlib.cmap = cmap;
buf->priv.x11.xlib.depth = x_depth;
buf->priv.mask_dither = shape_dither;
buf->priv.destination_alpha = destination_alpha;
if ((buf->rot == 0) || (buf->rot == 180))
buf->priv.swapper = evas_xlib_swapper_new(buf->priv.x11.xlib.disp,
buf->priv.x11.xlib.win,
buf->priv.x11.xlib.vis,
buf->priv.x11.xlib.depth,
buf->w, buf->h);
else if ((buf->rot == 90) || (buf->rot == 270))
buf->priv.swapper = evas_xlib_swapper_new(buf->priv.x11.xlib.disp,
buf->priv.x11.xlib.win,
buf->priv.x11.xlib.vis,
buf->priv.x11.xlib.depth,
buf->h, buf->w);
if (!buf->priv.swapper)
{
free(buf);
return NULL;
}
eina_array_step_set(&buf->priv.onebuf_regions, sizeof (Eina_Array), 8);
#ifdef WORDS_BIGENDIAN
if (evas_xlib_swapper_byte_order_get(buf->priv.swapper) == LSBFirst)
buf->priv.x11.xlib.swap = 1;
if (evas_xlib_swapper_bit_order_get(buf->priv.swapper) == MSBFirst)
buf->priv.x11.xlib.bit_swap = 1;
#else
if (evas_xlib_swapper_byte_order_get(buf->priv.swapper) == MSBFirst)
buf->priv.x11.xlib.swap = 1;
if (evas_xlib_swapper_bit_order_get(buf->priv.swapper) == MSBFirst)
buf->priv.x11.xlib.bit_swap = 1;
#endif
if (((vis->class == TrueColor) || (vis->class == DirectColor)) &&
(x_depth > 8))
{
buf->priv.mask.r = (DATA32) vis->red_mask;
buf->priv.mask.g = (DATA32) vis->green_mask;
buf->priv.mask.b = (DATA32) vis->blue_mask;
if (buf->priv.x11.xlib.swap)
{
SWAP32(buf->priv.mask.r);
SWAP32(buf->priv.mask.g);
SWAP32(buf->priv.mask.b);
}
}
else if ((vis->class == PseudoColor) || (vis->class == StaticColor) ||
(vis->class == GrayScale) || (vis->class == StaticGray) ||
(x_depth <= 8))
{
Convert_Pal_Mode pm = PAL_MODE_RGB332;
if ((vis->class == GrayScale) || (vis->class == StaticGray))
grayscale = 1;
if (grayscale)
{
if (max_colors >= 256) pm = PAL_MODE_GRAY256;
else if (max_colors >= 64) pm = PAL_MODE_GRAY64;
else if (max_colors >= 16) pm = PAL_MODE_GRAY16;
else if (max_colors >= 4) pm = PAL_MODE_GRAY4;
else pm = PAL_MODE_MONO;
}
else
{
if (max_colors >= 256) pm = PAL_MODE_RGB332;
else if (max_colors >= 216) pm = PAL_MODE_RGB666;
else if (max_colors >= 128) pm = PAL_MODE_RGB232;
else if (max_colors >= 64) pm = PAL_MODE_RGB222;
else if (max_colors >= 32) pm = PAL_MODE_RGB221;
else if (max_colors >= 16) pm = PAL_MODE_RGB121;
else if (max_colors >= 8) pm = PAL_MODE_RGB111;
else if (max_colors >= 4) pm = PAL_MODE_GRAY4;
else pm = PAL_MODE_MONO;
}
/* FIXME: only alloc once per display+cmap */
buf->priv.pal = evas_software_xlib_x_color_allocate
(disp, cmap, vis, pm);
if (!buf->priv.pal)
{
evas_xlib_swapper_free(buf->priv.swapper);
free(buf);
return NULL;
}
}
d = evas_xlib_swapper_depth_get(buf->priv.swapper);
if (buf->priv.pal)
{
if (buf->rot == 0 || buf->rot == 180)
conv_func = evas_common_convert_func_get(0, buf->w, buf->h, d,
buf->priv.mask.r,
buf->priv.mask.g,
buf->priv.mask.b,
buf->priv.pal->colors,
buf->rot);
else if (buf->rot == 90 || buf->rot == 270)
conv_func = evas_common_convert_func_get(0, buf->h, buf->w, d,
buf->priv.mask.r,
buf->priv.mask.g,
buf->priv.mask.b,
buf->priv.pal->colors,
buf->rot);
}
else
{
if (buf->rot == 0 || buf->rot == 180)
conv_func = evas_common_convert_func_get(0, buf->w, buf->h, d,
buf->priv.mask.r,
buf->priv.mask.g,
buf->priv.mask.b,
PAL_MODE_NONE,
buf->rot);
else if (buf->rot == 90 || buf->rot == 270)
conv_func = evas_common_convert_func_get(0, buf->h, buf->w, d,
buf->priv.mask.r,
buf->priv.mask.g,
buf->priv.mask.b,
PAL_MODE_NONE,
buf->rot);
}
if (!conv_func)
{
ERR("At depth: %i, RGB format mask: %08x %08x %08x, "
"Palette mode: %i. "
"Not supported by compiled in converters!",
buf->priv.x11.xlib.depth,
buf->priv.mask.r,
buf->priv.mask.g,
buf->priv.mask.b,
buf->priv.pal ? (int)buf->priv.pal->colors : -1);
}
return buf;
}
RGBA_Image *
evas_software_xlib_swapbuf_new_region_for_update(Outbuf *buf, int x, int y, int w, int h, int *cx, int *cy, int *cw, int *ch)
{
RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, buf->w, buf->h);
if ((w <= 0) || (h <= 0)) return NULL;
// if rotation is 0, and 32bit argb, we can use the buffer directly
if ((buf->rot == 0) &&
(buf->priv.mask.r == 0xff0000) &&
(buf->priv.mask.g == 0x00ff00) &&
(buf->priv.mask.b == 0x0000ff))
{
RGBA_Image *im;
void *data;
int bpl = 0;
Eina_Rectangle *rect;
im = buf->priv.onebuf;
if (!im)
{
data = evas_xlib_swapper_buffer_map(buf->priv.swapper, &bpl);
#ifdef EVAS_CSERVE2
if (evas_cserve2_use_get())
im = (RGBA_Image *)evas_cache2_image_data(evas_common_image_cache2_get(),
buf->w, buf->h, data,
buf->priv.destination_alpha,
EVAS_COLORSPACE_ARGB8888);
else
#endif
im = (RGBA_Image *)evas_cache_image_data(evas_common_image_cache_get(),
buf->w, buf->h, data,
buf->priv.destination_alpha,
EVAS_COLORSPACE_ARGB8888);
buf->priv.onebuf = im;
if (!im) return NULL;
}
rect = eina_rectangle_new(x, y, w, h);
if (!eina_array_push(&buf->priv.onebuf_regions, rect))
{
#ifdef EVAS_CSERVE2
if (evas_cserve2_use_get())
evas_cache2_image_close(&im->cache_entry);
else
#endif
evas_cache_image_drop(&im->cache_entry);
return NULL;
}
// the clip region of the onebuf to render
*cx = x;
*cy = y;
*cw = w;
*ch = h;
return im;
}
else
{
RGBA_Image *im;
Eina_Rectangle *rect;
rect = eina_rectangle_new(x, y, w, h);
if (!rect) return NULL;
#ifdef EVAS_CSERVE2
if (evas_cserve2_use_get())
im = (RGBA_Image *)evas_cache2_image_empty(evas_common_image_cache2_get());
else
#endif
im = (RGBA_Image *)evas_cache_image_empty(evas_common_image_cache_get());
if (!im)
{
free(rect);
return NULL;
}
im->cache_entry.flags.alpha |= buf->priv.destination_alpha ? 1 : 0;
#ifdef EVAS_CSERVE2
if (evas_cserve2_use_get())
evas_cache2_image_surface_alloc(&im->cache_entry, w, h);
else
#endif
evas_cache_image_surface_alloc(&im->cache_entry, w, h);
im->extended_info = rect;
buf->priv.pending_writes = eina_list_append(buf->priv.pending_writes, im);
// the region is the update image
*cx = 0;
*cy = 0;
*cw = w;
*ch = h;
return im;
}
return NULL;
}
void
evas_software_xlib_swapbuf_free_region_for_update(Outbuf *buf EINA_UNUSED, RGBA_Image *update EINA_UNUSED)
{
/* no need to do anything - they are cleaned up on flush */
}
void
evas_software_xlib_swapbuf_flush(Outbuf *buf)
{
if (!buf->priv.pending_writes)
{
Eina_Rectangle *rects, *rect;
Eina_Array_Iterator it;
unsigned int n, i;
RGBA_Image *im;
n = eina_array_count_get(&buf->priv.onebuf_regions);
if (n == 0) return;
rects = alloca(n * sizeof(Eina_Rectangle));
EINA_ARRAY_ITER_NEXT(&buf->priv.onebuf_regions, i, rect, it)
{
rects[i] = *rect;
}
evas_xlib_swapper_buffer_unmap(buf->priv.swapper);
evas_xlib_swapper_swap(buf->priv.swapper, rects, n);
eina_array_clean(&buf->priv.onebuf_regions);
im = buf->priv.onebuf;
buf->priv.onebuf = NULL;
if (im)
{
#ifdef EVAS_CSERVE2
if (evas_cserve2_use_get())
evas_cache2_image_close(&im->cache_entry);
else
#endif
evas_cache_image_drop(&im->cache_entry);
}
}
else
{
RGBA_Image *im;
Eina_Rectangle *rects;
unsigned int n, i = 0;
n = eina_list_count(buf->priv.pending_writes);
if (n == 0) return;
rects = alloca(n * sizeof(Eina_Rectangle));
EINA_LIST_FREE(buf->priv.pending_writes, im)
{
Eina_Rectangle *rect = im->extended_info;
int x, y, w, h;
x = rect->x; y = rect->y; w = rect->w; h = rect->h;
rects[i] = *rect;
if (buf->rot == 0)
{
rects[i].x = x;
rects[i].y = y;
}
else if (buf->rot == 90)
{
rects[i].x = y;
rects[i].y = buf->w - x - w;
}
else if (buf->rot == 180)
{
rects[i].x = buf->w - x - w;
rects[i].y = buf->h - y - h;
}
else if (buf->rot == 270)
{
rects[i].x = buf->h - y - h;
rects[i].y = x;
}
if ((buf->rot == 0) || (buf->rot == 180))
{
rects[i].w = w;
rects[i].h = h;
}
else if ((buf->rot == 90) || (buf->rot == 270))
{
rects[i].w = h;
rects[i].h = w;
}
free(rect);
#ifdef EVAS_CSERVE2
if (evas_cserve2_use_get())
evas_cache2_image_close(&im->cache_entry);
else
#endif
evas_cache_image_drop(&im->cache_entry);
}
evas_xlib_swapper_buffer_unmap(buf->priv.swapper);
evas_xlib_swapper_swap(buf->priv.swapper, rects, n);
// evas_xlib_swapper_swap(buf->priv.swapper, NULL, 0);
}
}
void
evas_software_xlib_swapbuf_idle_flush(Outbuf *buf)
{
return;
buf = NULL;
}
void
evas_software_xlib_swapbuf_push_updated_region(Outbuf *buf, RGBA_Image *update, int x, int y, int w, int h)
{
Gfx_Func_Convert conv_func = NULL;
Eina_Rectangle r = { 0, 0, 0, 0 };
int d, bpl = 0, wid, bpp;
DATA32 *src_data;
DATA8 *dst_data;
if (!buf->priv.pending_writes) return;
d = evas_xlib_swapper_depth_get(buf->priv.swapper);
if (buf->priv.pal)
{
if ((buf->rot == 0) || (buf->rot == 180))
conv_func = evas_common_convert_func_get(0, w, h, d,
buf->priv.mask.r,
buf->priv.mask.g,
buf->priv.mask.b,
buf->priv.pal->colors,
buf->rot);
else if ((buf->rot == 90) || (buf->rot == 270))
conv_func = evas_common_convert_func_get(0, h, w, d,
buf->priv.mask.r,
buf->priv.mask.g,
buf->priv.mask.b,
buf->priv.pal->colors,
buf->rot);
}
else
{
if ((buf->rot == 0) || (buf->rot == 180))
conv_func = evas_common_convert_func_get(0, w, h, d,
buf->priv.mask.r,
buf->priv.mask.g,
buf->priv.mask.b,
PAL_MODE_NONE,
buf->rot);
else if ((buf->rot == 90) || (buf->rot == 270))
conv_func = evas_common_convert_func_get(0, h, w, d,
buf->priv.mask.r,
buf->priv.mask.g,
buf->priv.mask.b,
PAL_MODE_NONE,
buf->rot);
}
if (!conv_func) return;
if (buf->rot == 0)
{
r.x = x;
r.y = y;
}
else if (buf->rot == 90)
{
r.x = y;
r.y = buf->w - x - w;
}
else if (buf->rot == 180)
{
r.x = buf->w - x - w;
r.y = buf->h - y - h;
}
else if (buf->rot == 270)
{
r.x = buf->h - y - h;
r.y = x;
}
if ((buf->rot == 0) || (buf->rot == 180))
{
r.w = w;
r.h = h;
}
else if ((buf->rot == 90) || (buf->rot == 270))
{
r.w = h;
r.h = w;
}
src_data = update->image.data;
if (!src_data) return;
dst_data = evas_xlib_swapper_buffer_map(buf->priv.swapper, &bpl);
if (!dst_data) return;
bpp = d / 8;
if (bpp <= 0) return;
wid = bpl / bpp;
dst_data += (bpl * r.y) + (r.x * bpp);
if (buf->priv.pal)
conv_func(src_data, dst_data,
update->cache_entry.w - w,
wid - r.w,
r.w, r.h,
x, y,
buf->priv.pal->lookup);
else
conv_func(src_data, dst_data,
update->cache_entry.w - w,
wid - r.w,
r.w, r.h,
x, y,
NULL);
}
void
evas_software_xlib_swapbuf_reconfigure(Outbuf *buf, int w, int h, int rot,
Outbuf_Depth depth)
{
if ((w == buf->w) && (h == buf->h) && (rot == buf->rot) &&
(depth == buf->depth))
return;
buf->w = w;
buf->h = h;
buf->rot = rot;
evas_xlib_swapper_free(buf->priv.swapper);
if ((buf->rot == 0) || (buf->rot == 180))
buf->priv.swapper = evas_xlib_swapper_new(buf->priv.x11.xlib.disp,
buf->priv.x11.xlib.win,
buf->priv.x11.xlib.vis,
buf->priv.x11.xlib.depth,
buf->w, buf->h);
else if ((buf->rot == 90) || (buf->rot == 270))
buf->priv.swapper = evas_xlib_swapper_new(buf->priv.x11.xlib.disp,
buf->priv.x11.xlib.win,
buf->priv.x11.xlib.vis,
buf->priv.x11.xlib.depth,
buf->h, buf->w);
}
int
evas_software_xlib_swapbuf_get_rot(Outbuf * buf)
{
return buf->rot;
}
Eina_Bool
evas_software_xlib_swapbuf_alpha_get(Outbuf *buf)
{
return buf->priv.destination_alpha;
}
int
evas_software_xlib_swapbuf_buffer_state_get(Outbuf *buf)
{
int mode;
if (!buf->priv.swapper) return MODE_FULL;
mode = evas_xlib_swapper_buffer_state_get(buf->priv.swapper);
return mode;
}

View File

@ -0,0 +1,53 @@
#ifndef EVAS_XLIB_SWAPBUF_H
#define EVAS_XLIB_SWAPBUF_H
#include "evas_engine.h"
void evas_software_xlib_swapbuf_init(void);
void evas_software_xlib_swapbuf_free(Outbuf *buf);
Outbuf *evas_software_xlib_swapbuf_setup_x(int w,
int h,
int rot,
Outbuf_Depth depth,
Display *disp,
Drawable draw,
Visual *vis,
Colormap cmap,
int x_depth,
int grayscale,
int max_colors,
Pixmap mask,
int shape_dither,
int destination_alpha);
RGBA_Image *evas_software_xlib_swapbuf_new_region_for_update(Outbuf *buf,
int x,
int y,
int w,
int h,
int *cx,
int *cy,
int *cw,
int *ch);
void evas_software_xlib_swapbuf_free_region_for_update(Outbuf *buf,
RGBA_Image *update);
void evas_software_xlib_swapbuf_flush(Outbuf *buf);
void evas_software_xlib_swapbuf_idle_flush(Outbuf *buf);
void evas_software_xlib_swapbuf_push_updated_region(Outbuf *buf,
RGBA_Image *update,
int x,
int y,
int w,
int h);
void evas_software_xlib_swapbuf_reconfigure(Outbuf *buf,
int w,
int h,
int rot,
Outbuf_Depth depth);
int evas_software_xlib_swapbuf_get_rot(Outbuf *buf);
void evas_software_xlib_swapbuf_rotation_set(Outbuf *buf,
int rot);
Eina_Bool evas_software_xlib_swapbuf_alpha_get(Outbuf *buf);
int evas_software_xlib_swapbuf_buffer_state_get(Outbuf *buf);
#endif

View File

@ -0,0 +1,281 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "evas_common.h"
#include "evas_macros.h"
#include "evas_xlib_swapper.h"
typedef struct
{
XImage *xim;
XShmSegmentInfo shm_info;
void *data;
int w, h, bpl;
Eina_Bool shm : 1;
Eina_Bool valid : 1;
} Buffer;
struct _X_Swapper
{
Display *disp;
Drawable draw;
Visual *vis;
GC gc;
Buffer buf[3];
int w, h, depth;
int buf_cur, buf_num;
Eina_Bool mapped: 1;
};
static Eina_Bool _x_err = EINA_FALSE;
static void
_x_err_hand(Display *d EINA_UNUSED, XErrorEvent *ev EINA_UNUSED)
{
_x_err = 1;
return;
}
static Eina_Bool
_buf_new(X_Swapper *swp, Buffer *buf)
{
buf->w = swp->w;
buf->h = swp->h;
// try shm first
buf->xim = XShmCreateImage(swp->disp, swp->vis, swp->depth, ZPixmap,
NULL, &(buf->shm_info), buf->w, buf->h);
if (buf->xim)
{
buf->bpl = buf->xim->bytes_per_line;
buf->shm_info.shmid = shmget(IPC_PRIVATE, buf->bpl * buf->h,
IPC_CREAT | 0777);
if (buf->shm_info.shmid >= 0)
{
buf->shm_info.readOnly = False;
buf->shm_info.shmaddr = buf->data = buf->xim->data =
shmat(buf->shm_info.shmid, 0, 0);
if (buf->shm_info.shmaddr != ((void *)-1))
{
XErrorHandler ph;
XSync(swp->disp, False);
_x_err = EINA_FALSE;
ph = XSetErrorHandler((XErrorHandler)_x_err_hand);
XShmAttach(swp->disp, &(buf->shm_info));
XSync(swp->disp, False);
XSetErrorHandler((XErrorHandler)ph);
if (!_x_err)
{
buf->shm = EINA_TRUE;
}
else
{
shmdt(buf->shm_info.shmaddr);
shmctl(buf->shm_info.shmid, IPC_RMID, 0);
XDestroyImage(buf->xim);
buf->xim = NULL;
}
}
else
{
shmdt(buf->shm_info.shmaddr);
shmctl(buf->shm_info.shmid, IPC_RMID, 0);
XDestroyImage(buf->xim);
buf->xim = NULL;
}
}
else
{
XDestroyImage(buf->xim);
buf->xim = NULL;
}
}
if (!buf->xim) // shm failed - try normal ximage
{
buf->xim = XCreateImage(swp->disp, swp->vis, swp->depth, ZPixmap,
0, NULL, buf->w, buf->h, 32, 0);
if (!buf->xim) return EINA_FALSE;
buf->bpl = buf->xim->bytes_per_line;
buf->data = buf->xim->data = malloc(buf->bpl * buf->h);
if (!buf->data)
{
XDestroyImage(buf->xim);
buf->xim = NULL;
return EINA_FALSE;
}
}
return EINA_TRUE;
}
static void
_buf_free(X_Swapper *swp, Buffer *buf)
{
if (!buf->xim) return;
if (buf->shm)
{
XShmDetach(swp->disp, &(buf->shm