forked from enlightenment/efl
Use a single XShmImage and XShmPutImage with clip region.
By using a single XShmImage we avoid round trips to X and avoid having kernel to allocate (and zero) memory on every redraw. This also enable us to issue a single XShmPutImage() with the whole XShmImage just by using X Region and setting it as clip on Graphics Context (GC). On Nokia N800, expedite gains is about 10fps, while my other test with fewer objects (and thus drawing areas) I could go from 50fps to 160fps. Drawback is that we hold XShmImage until evas is resized or destroyed, we need a new API to flush engine memory so when it is idle for time we flush this memory, but it is kept alive during animations. SVN revision: 30390
This commit is contained in:
parent
f2b945b53d
commit
638a790c63
|
@ -20,6 +20,7 @@ struct _Render_Engine
|
||||||
Tilebuf_Rect *rects;
|
Tilebuf_Rect *rects;
|
||||||
Tilebuf_Rect *cur_rect;
|
Tilebuf_Rect *cur_rect;
|
||||||
X_Output_Buffer *shbuf;
|
X_Output_Buffer *shbuf;
|
||||||
|
Region clip_rects;
|
||||||
unsigned char end : 1;
|
unsigned char end : 1;
|
||||||
unsigned char shm : 1;
|
unsigned char shm : 1;
|
||||||
};
|
};
|
||||||
|
@ -143,6 +144,8 @@ eng_output_free(void *data)
|
||||||
Render_Engine *re;
|
Render_Engine *re;
|
||||||
|
|
||||||
re = (Render_Engine *)data;
|
re = (Render_Engine *)data;
|
||||||
|
if (re->shbuf) evas_software_x11_x_output_buffer_free(re->shbuf, 0);
|
||||||
|
if (re->clip_rects) XDestroyRegion(re->clip_rects);
|
||||||
if (re->gc) XFreeGC(re->disp, re->gc);
|
if (re->gc) XFreeGC(re->disp, re->gc);
|
||||||
if (re->tb) evas_common_tilebuf_free(re->tb);
|
if (re->tb) evas_common_tilebuf_free(re->tb);
|
||||||
if (re->rects) evas_common_tilebuf_free_render_rects(re->rects);
|
if (re->rects) evas_common_tilebuf_free_render_rects(re->rects);
|
||||||
|
@ -158,12 +161,25 @@ eng_output_resize(void *data, int w, int h)
|
||||||
Render_Engine *re;
|
Render_Engine *re;
|
||||||
|
|
||||||
re = (Render_Engine *)data;
|
re = (Render_Engine *)data;
|
||||||
|
|
||||||
|
if ((re->w == w) && (re->h == h)) return;
|
||||||
|
|
||||||
evas_common_tilebuf_free(re->tb);
|
evas_common_tilebuf_free(re->tb);
|
||||||
re->w = w;
|
re->w = w;
|
||||||
re->h = h;
|
re->h = h;
|
||||||
re->tb = evas_common_tilebuf_new(w, h);
|
re->tb = evas_common_tilebuf_new(w, h);
|
||||||
if (re->tb)
|
if (re->tb)
|
||||||
evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE);
|
evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE);
|
||||||
|
if (re->shbuf)
|
||||||
|
{
|
||||||
|
evas_software_x11_x_output_buffer_free(re->shbuf, 0);
|
||||||
|
re->shbuf = NULL;
|
||||||
|
}
|
||||||
|
if (re->clip_rects)
|
||||||
|
{
|
||||||
|
XDestroyRegion(re->clip_rects);
|
||||||
|
re->clip_rects = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -206,48 +222,31 @@ 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)
|
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;
|
Render_Engine *re;
|
||||||
Soft16_Image *surface = NULL;
|
|
||||||
Tilebuf_Rect *rect;
|
Tilebuf_Rect *rect;
|
||||||
int ux, uy, uw, uh;
|
int ux, uy, uw, uh;
|
||||||
|
|
||||||
re = (Render_Engine *)data;
|
re = (Render_Engine *)data;
|
||||||
if (re->end)
|
if (re->end)
|
||||||
{
|
{
|
||||||
if (re->shbuf)
|
|
||||||
{
|
|
||||||
evas_software_x11_x_output_buffer_free(re->shbuf, 0);
|
|
||||||
re->shbuf = NULL;
|
|
||||||
}
|
|
||||||
re->end = 0;
|
re->end = 0;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (!re->rects)
|
if (!re->rects)
|
||||||
{
|
{
|
||||||
int mw, mh;
|
|
||||||
|
|
||||||
mw = 0;
|
|
||||||
mh = 0;
|
|
||||||
re->rects = evas_common_tilebuf_get_render_rects(re->tb);
|
re->rects = evas_common_tilebuf_get_render_rects(re->tb);
|
||||||
|
if (!re->rects) return NULL;
|
||||||
|
|
||||||
re->cur_rect = re->rects;
|
re->cur_rect = re->rects;
|
||||||
for (rect = re->cur_rect; rect; rect = (Tilebuf_Rect *)(rect->_list_data.next))
|
if (!re->shbuf)
|
||||||
{
|
|
||||||
if (rect->w > mw) mw = rect->w;
|
|
||||||
if (rect->h > mh) mh = rect->h;
|
|
||||||
}
|
|
||||||
if (re->rects)
|
|
||||||
re->shbuf = evas_software_x11_x_output_buffer_new
|
re->shbuf = evas_software_x11_x_output_buffer_new
|
||||||
(re->disp, DefaultVisual(re->disp, DefaultScreen(re->disp)),
|
(re->disp, DefaultVisual(re->disp, DefaultScreen(re->disp)),
|
||||||
DefaultDepth(re->disp, DefaultScreen(re->disp)), mw, mh, 1, NULL);
|
DefaultDepth(re->disp, DefaultScreen(re->disp)),
|
||||||
|
re->w, re->h, 1, NULL);
|
||||||
}
|
}
|
||||||
if ((!re->cur_rect) || (!re->shbuf))
|
if (!re->cur_rect)
|
||||||
{
|
{
|
||||||
if (re->rects) evas_common_tilebuf_free_render_rects(re->rects);
|
if (re->rects) evas_common_tilebuf_free_render_rects(re->rects);
|
||||||
re->rects = NULL;
|
re->rects = NULL;
|
||||||
if (re->shbuf)
|
|
||||||
{
|
|
||||||
evas_software_x11_x_output_buffer_free(re->shbuf, 0);
|
|
||||||
re->shbuf = NULL;
|
|
||||||
}
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
rect = re->cur_rect;
|
rect = re->cur_rect;
|
||||||
|
@ -259,26 +258,28 @@ eng_output_redraws_next_update_get(void *data, int *x, int *y, int *w, int *h, i
|
||||||
re->rects = NULL;
|
re->rects = NULL;
|
||||||
re->end = 1;
|
re->end = 1;
|
||||||
}
|
}
|
||||||
surface = re->shbuf;
|
|
||||||
surface->w = uw;
|
|
||||||
surface->h = uh;
|
|
||||||
|
|
||||||
*cx = 0; *cy = 0; *cw = uw; *ch = uh;
|
*cx = ux; *cy = uy; *cw = uw; *ch = uh;
|
||||||
*x = ux; *y = uy; *w = uw; *h = uh;
|
*x = ux; *y = uy; *w = uw; *h = uh;
|
||||||
return surface;
|
return &re->shbuf->im;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
eng_output_redraws_next_update_push(void *data, void *surface, int x, int y, int w, int h)
|
eng_output_redraws_next_update_push(void *data, void *surface, int x, int y, int w, int h)
|
||||||
{
|
{
|
||||||
Render_Engine *re;
|
Render_Engine *re;
|
||||||
|
XRectangle r;
|
||||||
|
|
||||||
re = (Render_Engine *)data;
|
re = (Render_Engine *)data;
|
||||||
evas_software_x11_x_output_buffer_paste(surface, re->draw, re->gc,
|
|
||||||
x, y, w, h, 1);
|
if (!re->clip_rects)
|
||||||
// evas_software_x11_outbuf_push_updated_region(re->ob, surface, x, y, w, h);
|
re->clip_rects = XCreateRegion();
|
||||||
// evas_software_x11_outbuf_free_region_for_update(re->ob, surface);
|
|
||||||
// evas_common_cpu_end_opt();
|
r.x = x;
|
||||||
|
r.y = y;
|
||||||
|
r.width = w;
|
||||||
|
r.height = h;
|
||||||
|
XUnionRectWithRegion(&r, re->clip_rects, re->clip_rects);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -287,9 +288,17 @@ eng_output_flush(void *data)
|
||||||
Render_Engine *re;
|
Render_Engine *re;
|
||||||
|
|
||||||
re = (Render_Engine *)data;
|
re = (Render_Engine *)data;
|
||||||
/* FIXME: later on defer the eng_output_redraws_next_update_push() until
|
if (re->clip_rects)
|
||||||
* flush and keep a list */
|
{
|
||||||
// evas_software_x11_outbuf_flush(re->ob);
|
XSetRegion(re->disp, re->gc, re->clip_rects);
|
||||||
|
XDestroyRegion(re->clip_rects);
|
||||||
|
re->clip_rects = NULL;
|
||||||
|
}
|
||||||
|
else return;
|
||||||
|
|
||||||
|
evas_software_x11_x_output_buffer_paste(re->shbuf, re->draw, re->gc,
|
||||||
|
0, 0, re->w, re->h, 0);
|
||||||
|
XSetClipMask(re->disp, re->gc, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
Loading…
Reference in New Issue