forked from enlightenment/efl
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:
parent
9aa23128b6
commit
fac8ec4ca7
|
@ -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 \
|
||||
|
|
|
@ -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)
|
||||
|
@ -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,13 +692,82 @@ 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)
|
||||
|
@ -636,27 +775,106 @@ eng_output_redraws_next_update_get(void *data, int *x, int *y, int *w, int *h, i
|
|||
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 */
|
||||
|
|
|
@ -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
|
||||
|
@ -113,6 +120,8 @@ struct _Outbuf
|
|||
RGBA_Image *onebuf;
|
||||
Eina_Array onebuf_regions;
|
||||
|
||||
void *swapper;
|
||||
|
||||
/* a list of pending regions to write to the target */
|
||||
Eina_List *pending_writes;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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_info));
|
||||
XDestroyImage(buf->xim);
|
||||
shmdt(buf->shm_info.shmaddr);
|
||||
shmctl(buf->shm_info.shmid, IPC_RMID, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
XDestroyImage(buf->xim);
|
||||
}
|
||||
buf->xim = NULL;
|
||||
buf->shm = EINA_FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
_buf_put(X_Swapper *swp, Buffer *buf, Eina_Rectangle *rects, int nrects)
|
||||
{
|
||||
Region tmpr;
|
||||
int i;
|
||||
|
||||
if (!buf->xim) return;
|
||||
tmpr = XCreateRegion();
|
||||
if (rects)
|
||||
{
|
||||
for (i = 0; i < nrects; i++)
|
||||
{
|
||||
XRectangle xr;
|
||||
|
||||
xr.x = rects[i].x; xr.y = rects[i].y;
|
||||
xr.width = rects[i].w; xr.height = rects[i].h;
|
||||
XUnionRectWithRegion(&xr, tmpr, tmpr);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
XRectangle xr;
|
||||
|
||||
xr.x = 0; xr.y = 0;
|
||||
xr.width = buf->w; xr.height = buf->h;
|
||||
XUnionRectWithRegion(&xr, tmpr, tmpr);
|
||||
}
|
||||
XSetRegion(swp->disp, swp->gc, tmpr);
|
||||
XDestroyRegion(tmpr);
|
||||
if (buf->shm)
|
||||
{
|
||||
XShmPutImage(swp->disp, swp->draw, swp->gc, buf->xim, 0, 0, 0, 0,
|
||||
buf->w, buf->h, False);
|
||||
}
|
||||
else
|
||||
{
|
||||
XPutImage(swp->disp, swp->draw, swp->gc, buf->xim, 0, 0, 0, 0,
|
||||
buf->w, buf->h);
|
||||
}
|
||||
XSync(swp->disp, False);
|
||||
}
|
||||
|
||||
////////////////////////////////////
|
||||
|
||||
X_Swapper *
|
||||
evas_xlib_swapper_new(Display *disp, Drawable draw, Visual *vis,
|
||||
int depth, int w, int h)
|
||||
{
|
||||
X_Swapper *swp;
|
||||
XGCValues gcv;
|
||||
int i;
|
||||
|
||||
int nbuf = 3; // pretend we are triple buffered
|
||||
|
||||
swp = calloc(1, sizeof(X_Swapper));
|
||||
if (!swp) return NULL;
|
||||
swp->disp = disp;
|
||||
swp->draw = draw;
|
||||
swp->vis = vis;
|
||||
swp->depth = depth;
|
||||
swp->w = w;
|
||||
swp->h = h;
|
||||
swp->buf_num = nbuf;
|
||||
swp->gc = XCreateGC(swp->disp, swp->draw, 0, &gcv);
|
||||
for (i = 0; i < swp->buf_num; i++)
|
||||
{
|
||||
if (!_buf_new(swp, &(swp->buf[i])))
|
||||
{
|
||||
evas_xlib_swapper_free(swp);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return swp;
|
||||
}
|
||||
|
||||
void
|
||||
evas_xlib_swapper_free(X_Swapper *swp)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < swp->buf_num; i++)
|
||||
{
|
||||
_buf_free(swp, &(swp->buf[i]));
|
||||
}
|
||||
free(swp);
|
||||
}
|
||||
|
||||
void *
|
||||
evas_xlib_swapper_buffer_map(X_Swapper *swp, int *bpl)
|
||||
{
|
||||
swp->mapped = EINA_TRUE;
|
||||
if (bpl) *bpl = swp->buf[swp->buf_cur].bpl;
|
||||
return swp->buf[swp->buf_cur].data;
|
||||
}
|
||||
|
||||
void
|
||||
evas_xlib_swapper_buffer_unmap(X_Swapper *swp)
|
||||
{
|
||||
swp->mapped = EINA_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
evas_xlib_swapper_swap(X_Swapper *swp, Eina_Rectangle *rects, int nrects)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = swp->buf_cur;
|
||||
_buf_put(swp, &(swp->buf[n]), rects, nrects);
|
||||
swp->buf[n].valid = 1;
|
||||
swp->buf_cur = (swp->buf_cur + 1) % swp->buf_num;
|
||||
}
|
||||
|
||||
int
|
||||
evas_xlib_swapper_buffer_state_get(X_Swapper *swp)
|
||||
{
|
||||
int i, n, count = 0;
|
||||
|
||||
for (i = 0; i < swp->buf_num; i++)
|
||||
{
|
||||
n = (swp->buf_num + swp->buf_cur - (i)) % swp->buf_num;
|
||||
if (swp->buf[n].valid) count++;
|
||||
else break;
|
||||
}
|
||||
if (count == swp->buf_num)
|
||||
{
|
||||
if (count == 1) return MODE_COPY;
|
||||
else if (count == 2) return MODE_DOUBLE;
|
||||
else if (count == 3) return MODE_TRIPLE;
|
||||
}
|
||||
return MODE_FULL;
|
||||
}
|
||||
|
||||
int
|
||||
evas_xlib_swapper_depth_get(X_Swapper *swp)
|
||||
{
|
||||
return swp->buf[0].xim->bits_per_pixel;
|
||||
}
|
||||
|
||||
int
|
||||
evas_xlib_swapper_byte_order_get(X_Swapper *swp)
|
||||
{
|
||||
return swp->buf[0].xim->byte_order;
|
||||
}
|
||||
|
||||
int
|
||||
evas_xlib_swapper_bit_order_get(X_Swapper *swp)
|
||||
{
|
||||
return swp->buf[0].xim->bitmap_bit_order;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
#include "evas_engine.h"
|
||||
|
||||
typedef struct _X_Swapper X_Swapper;
|
||||
|
||||
X_Swapper *evas_xlib_swapper_new(Display *disp, Drawable draw, Visual *vis,
|
||||
int depth, int w, int h);
|
||||
void evas_xlib_swapper_free(X_Swapper *swp);
|
||||
void *evas_xlib_swapper_buffer_map(X_Swapper *swp, int *bpl);
|
||||
void evas_xlib_swapper_buffer_unmap(X_Swapper *swp);
|
||||
void evas_xlib_swapper_swap(X_Swapper *swp, Eina_Rectangle *rects, int nrects);
|
||||
int evas_xlib_swapper_buffer_state_get(X_Swapper *swp);
|
||||
int evas_xlib_swapper_depth_get(X_Swapper *swp);
|
||||
int evas_xlib_swapper_byte_order_get(X_Swapper *swp);
|
||||
int evas_xlib_swapper_bit_order_get(X_Swapper *swp);
|
||||
|
Loading…
Reference in New Issue