comp shape updates:

* move all shape rectangle stuff into e_container_shape

* use input rects for cutting comp shape when available

* set shape changed and render queue when container shape change callbacks are called

* create fewer comp wins (small memory improvement)
This commit is contained in:
Mike Blumenkrantz 2013-05-20 14:00:06 +01:00
parent 17f4e85042
commit c8d615f155
6 changed files with 133 additions and 131 deletions

View File

@ -4708,8 +4708,6 @@ _e_border_free(E_Border *bd)
bd->cur_mouse_action = NULL;
}
E_FREE(bd->shape_rects);
bd->shape_rects_num = 0;
/*
if (bd->dangling_ref_check)
{
@ -7679,6 +7677,8 @@ _e_border_eval0(E_Border *bd)
bd->client.border.changed = 1;
}
ecore_x_window_shape_rectangles_set(bd->win, rects, num);
bd->changes.shape_input = 0;
e_container_shape_input_rects_set(bd->shape, NULL, 0);
}
free(rects);
}
@ -7731,8 +7731,8 @@ _e_border_eval0(E_Border *bd)
bd->client.border.changed = 1;
}
ecore_x_window_shape_input_rectangles_set(bd->win, rects, num);
e_container_shape_input_rects_set(bd->shape, (Eina_Rectangle*)rects, num);
}
free(rects);
}
else
{
@ -8756,11 +8756,11 @@ _e_border_eval(E_Border *bd)
int changed;
changed = 1;
if ((num == bd->shape_rects_num) && (bd->shape_rects))
if ((num == bd->shape->shape_rects_num) && (bd->shape->shape_rects))
{
int i;
orects = bd->shape_rects;
orects = (Ecore_X_Rectangle*)bd->shape->shape_rects;
changed = 0;
for (i = 0; i < num; i++)
{
@ -8793,19 +8793,13 @@ _e_border_eval(E_Border *bd)
{
if (bd->client.shaped)
e_container_shape_solid_rect_set(bd->shape, 0, 0, 0, 0);
E_FREE(bd->shape_rects);
bd->shape_rects = rects;
bd->shape_rects_num = num;
e_container_shape_rects_set(bd->shape, rects, num);
e_container_shape_rects_set(bd->shape, (Eina_Rectangle*)rects, num);
}
else
free(rects);
}
else
{
E_FREE(bd->shape_rects);
bd->shape_rects = NULL;
bd->shape_rects_num = 0;
e_container_shape_rects_set(bd->shape, NULL, 0);
}
bd->need_shape_export = 0;

View File

@ -634,8 +634,6 @@ struct _E_Border
Ecore_Poller *ping_poller;
Ecore_Timer *kill_timer;
E_Border_Move_Intercept_Cb move_intercept_cb;
int shape_rects_num;
Ecore_X_Rectangle *shape_rects;
E_Remember *remember;
E_Border *modal;

View File

@ -224,24 +224,24 @@ _e_comp_fullscreen_check(E_Comp *c)
}
static inline Eina_Bool
_e_comp_shaped_check(int w, int h, const Ecore_X_Rectangle *rects, int num)
_e_comp_shaped_check(int w, int h, const Eina_Rectangle *rects, int num)
{
if ((!rects) || (num < 1)) return EINA_FALSE;
if (num > 1) return EINA_TRUE;
if ((rects[0].x == 0) && (rects[0].y == 0) &&
((int)rects[0].width == w) && ((int)rects[0].height == h))
((int)rects[0].w == w) && ((int)rects[0].h == h))
return EINA_FALSE;
return EINA_TRUE;
}
static inline Eina_Bool
_e_comp_win_shaped_check(const E_Comp_Win *cw, const Ecore_X_Rectangle *rects, int num)
_e_comp_win_shaped_check(const E_Comp_Win *cw, const Eina_Rectangle *rects, int num)
{
return _e_comp_shaped_check(cw->w, cw->h, rects, num);
}
static void
_e_comp_win_shape_rectangles_apply(E_Comp_Win *cw, const Ecore_X_Rectangle *rects, int num)
_e_comp_win_shape_rectangles_apply(E_Comp_Win *cw, const Eina_Rectangle *rects, int num)
{
Eina_List *l;
Evas_Object *o;
@ -286,7 +286,7 @@ _e_comp_win_shape_rectangles_apply(E_Comp_Win *cw, const Ecore_X_Rectangle *rect
int rx, ry, rw, rh;
rx = rects[i].x; ry = rects[i].y;
rw = rects[i].width; rh = rects[i].height;
rw = rects[i].w; rh = rects[i].h;
E_RECTS_CLIP_TO_RECT(rx, ry, rw, rh, 0, 0, w, h);
sp = spix + (w * ry) + rx;
for (py = 0; py < rh; py++)
@ -529,58 +529,48 @@ _e_comp_win_update(E_Comp_Win *cw)
Eina_List *l;
Evas_Object *o;
E_Comp_Render_Update_Rect *r;
int i;
int i, num;
int pw, ph;
int pshaped = cw->shaped;
Eina_Rectangle *rects;
DBG("UPDATE [0x%x] pm = %x", cw->win, cw->pixmap);
if (conf->grab) ecore_x_grab();
cw->update = 0;
pw = cw->pw, ph = cw->ph;
if (cw->argb)
if (cw->shape_changed)
{
if (cw->rects)
if (cw->free_shape)
{
free(cw->rects);
cw->rects = NULL;
cw->rects_num = 0;
}
}
else
{
if (cw->shape_changed)
{
if (cw->rects)
{
free(cw->rects);
cw->rects = NULL;
cw->rects_num = 0;
}
ecore_x_pixmap_geometry_get(cw->win, NULL, NULL, &(cw->w), &(cw->h));
cw->rects = ecore_x_window_shape_rectangles_get(cw->win, &(cw->rects_num));
if (cw->rects)
rects = (Eina_Rectangle*)ecore_x_window_shape_rectangles_get(cw->win, &num);
e_container_shape_rects_set(cw->shape, rects, num);
if (cw->shape->shape_rects)
e_container_shape_input_rects_set(cw->shape, NULL, 0);
else
{
for (i = 0; i < cw->rects_num; i++)
{
E_RECTS_CLIP_TO_RECT(cw->rects[i].x, cw->rects[i].y,
cw->rects[i].width, cw->rects[i].height, 0, 0, (int)cw->w, (int)cw->h);
}
}
if (!_e_comp_win_shaped_check(cw, cw->rects, cw->rects_num))
{
E_FREE(cw->rects);
cw->rects_num = 0;
}
if ((cw->rects) && (!cw->shaped))
{
cw->shaped = 1;
}
else if ((!cw->rects) && (cw->shaped))
{
cw->shaped = 0;
rects = (Eina_Rectangle*)ecore_x_window_shape_input_rectangles_get(cw->win, &num);
e_container_shape_input_rects_set(cw->shape, rects, num);
}
}
if (cw->shape->shape_rects)
{
for (i = 0; i < cw->shape->shape_rects_num; i++)
{
E_RECTS_CLIP_TO_RECT(cw->shape->shape_rects[i].x, cw->shape->shape_rects[i].y,
cw->shape->shape_rects[i].w, cw->shape->shape_rects[i].h, 0, 0, (int)cw->w, (int)cw->h);
}
}
if (cw->shape->shape_input_rects)
{
for (i = 0; i < cw->shape->shape_input_rects_num; i++)
{
E_RECTS_CLIP_TO_RECT(cw->shape->shape_input_rects[i].x, cw->shape->shape_input_rects[i].y,
cw->shape->shape_input_rects[i].w, cw->shape->shape_input_rects[i].h, 0, 0, (int)cw->w, (int)cw->h);
}
}
cw->shaped = _e_comp_win_shaped_check(cw, cw->shape->shape_rects, cw->shape->shape_rects_num);
}
if (((!cw->pixmap) || (cw->needpix)) &&
@ -671,7 +661,7 @@ _e_comp_win_update(E_Comp_Win *cw)
// was cw->w / cw->h
// evas_object_resize(cw->effect_obj, cw->pw, cw->ph);
if ((cw->c->gl) && (conf->texture_from_pixmap) &&
(!cw->shaped) && (!cw->rects) && (cw->pixmap))
(!cw->shaped) && (cw->pixmap))
{
/* #ifdef HAVE_WAYLAND_CLIENTS */
/* DBG("DEBUG - pm now %x", e_comp_wl_pixmap_get(cw->win)); */
@ -849,15 +839,8 @@ _e_comp_win_update(E_Comp_Win *cw)
}
}
free(r);
if (cw->shaped)
{
_e_comp_win_shape_rectangles_apply(cw, cw->rects, cw->rects_num);
}
else
{
if (cw->shape_changed)
_e_comp_win_shape_rectangles_apply(cw, cw->rects, cw->rects_num);
}
if (cw->shaped || cw->shape_changed)
_e_comp_win_shape_rectangles_apply(cw, cw->shape->shape_rects, cw->shape->shape_rects_num);
cw->shape_changed = 0;
}
else
@ -2124,6 +2107,19 @@ _e_comp_win_bd_setup(E_Comp_Win *cw, E_Border *bd)
cw->depth = cw->bd->client.initial_attributes.depth;
}
static void
_e_comp_win_shape_init(E_Comp_Win *cw, int w, int h)
{
int i;
for (i = 0; i < cw->shape->shape_rects_num; i++)
E_RECTS_CLIP_TO_RECT(cw->shape->shape_rects[i].x, cw->shape->shape_rects[i].y,
cw->shape->shape_rects[i].w, cw->shape->shape_rects[i].h, 0, 0, w, h);
if (_e_comp_shaped_check(w, h, cw->shape->shape_rects, cw->shape->shape_rects_num))
cw->shape_changed = 1;
}
static E_Comp_Win *
_e_comp_win_add(E_Comp *c, Ecore_X_Window win, E_Border *bd)
{
@ -2211,9 +2207,6 @@ _e_comp_win_add(E_Comp *c, Ecore_X_Window win, E_Border *bd)
cw->inhash = 1;
if ((!cw->input_only) && (!cw->invalid))
{
Ecore_X_Rectangle *rects;
int num;
cw->damage = ecore_x_damage_new
(cw->win, ECORE_X_DAMAGE_REPORT_DELTA_RECTANGLES);
eina_hash_add(damages, e_util_winid_str_get(cw->damage), cw);
@ -2239,23 +2232,10 @@ _e_comp_win_add(E_Comp *c, Ecore_X_Window win, E_Border *bd)
evas_object_show(cw->obj);
ecore_x_window_shape_events_select(cw->win, 1);
rects = ecore_x_window_shape_rectangles_get(cw->win, &num);
if (rects)
{
int i;
for (i = 0; i < num; i++)
E_RECTS_CLIP_TO_RECT(rects[i].x, rects[i].y,
rects[i].width, rects[i].height, 0, 0, w, h);
if (_e_comp_shaped_check(w, h, rects, num))
cw->shape_changed = 1;
free(rects);
}
if (cw->bd)
{
_e_comp_win_shape_init(cw, w, h);
evas_object_data_set(cw->shobj, "border", cw->bd);
evas_object_data_set(cw->effect_obj, "border", cw->bd);
#ifdef BORDER_ZOOMAPS
@ -2356,7 +2336,6 @@ _e_comp_win_del(E_Comp_Win *cw)
E_FREE_FUNC(cw->up, e_comp_render_update_free);
DBG(" [0x%x] del", cw->win);
E_FREE(cw->rects);
if (cw->update_timeout)
{
ecore_timer_del(cw->update_timeout);
@ -2935,11 +2914,12 @@ _e_comp_create(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
c = _e_comp_find(ev->parent);
if (!c) return ECORE_CALLBACK_PASS_ON;
if (_e_comp_win_find(ev->win)) return ECORE_CALLBACK_PASS_ON;
if (c->win == ev->win) return ECORE_CALLBACK_PASS_ON;
if (c->ee_win == ev->win) return ECORE_CALLBACK_PASS_ON;
if (c->man->root == ev->win) return ECORE_CALLBACK_PASS_ON;
if (_e_comp_ignore_find(ev->win)) return ECORE_CALLBACK_PASS_ON;
if (_e_comp_win_find(ev->win)) return ECORE_CALLBACK_PASS_ON;
if (!ev->override) return ECORE_CALLBACK_PASS_ON;
cw = _e_comp_win_add(c, ev->win, NULL);
if (!cw) return ECORE_CALLBACK_RENEW;
_e_comp_win_configure(cw, ev->x, ev->y, ev->w, ev->h, ev->border);
@ -2947,6 +2927,8 @@ _e_comp_create(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
{
Eina_List *l;
E_Container *con;
Eina_Rectangle *rects;
int num;
EINA_LIST_FOREACH(c->man->containers, l, con)
{
@ -2955,8 +2937,17 @@ _e_comp_create(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
break;
}
if (!cw->shape) cw->shape = e_container_shape_add(eina_list_data_get(c->man->containers));
e_container_shape_move(cw->shape, ev->x, ev->y);
e_container_shape_resize(cw->shape, ev->w, ev->h);
rects = (Eina_Rectangle*)ecore_x_window_shape_rectangles_get(cw->win, &num);
e_container_shape_rects_set(cw->shape, rects, num);
if (cw->shape->shape_rects)
e_container_shape_input_rects_set(cw->shape, NULL, 0);
else
{
rects = (Eina_Rectangle*)ecore_x_window_shape_input_rectangles_get(cw->win, &num);
e_container_shape_input_rects_set(cw->shape, rects, num);
}
_e_comp_win_shape_init(cw, ev->w, ev->h);
}
if (cw->shape) cw->shape->comp_win = cw;
return ECORE_CALLBACK_PASS_ON;
@ -3749,10 +3740,10 @@ _e_comp_shapes_update_comp_win_shape_comp_helper(E_Comp_Win *cw, Eina_Tiler *tb)
INF("COMP WIN: %u", cw->win);
#endif
if (cw->rects)
if (cw->shape->shape_input_rects || cw->shape->shape_rects)
{
int num;
Ecore_X_Rectangle *rect;
int num, tot;
Eina_Rectangle *rect, *rects;
/* add the frame */
if (cw->bd)
@ -3777,13 +3768,15 @@ _e_comp_shapes_update_comp_win_shape_comp_helper(E_Comp_Win *cw, Eina_Tiler *tb)
if (cw->bd->client_inset.b)
{
eina_tiler_rect_add(tb, &(Eina_Rectangle){cw->bd->x, cw->bd->y + cw->bd->client_inset.t + cw->bd->client.h, cw->bd->w, cw->bd->client_inset.b});
SHAPE_INF("ADD: %d,%d@%dx%d", cw->bd->x, cw->bd->y, cw->bd->w, cw->bd->h);
SHAPE_INF("ADD: %d,%d@%dx%d", cw->bd->x, cw->bd->y + cw->bd->client_inset.t + cw->bd->client.h, cw->bd->w, cw->bd->client_inset.b);
}
}
}
for (num = 0, rect = cw->rects; num < cw->rects_num; num++, rect++)
rects = cw->shape->shape_rects ?: cw->shape->shape_input_rects;
tot = cw->shape->shape_rects_num ?: cw->shape->shape_input_rects_num;
for (num = 0, rect = rects; num < tot; num++, rect++)
{
x = rect->x, y = rect->y, w = rect->width, h = rect->height;
x = rect->x, y = rect->y, w = rect->w, h = rect->h;
if (cw->bd)
{
x += cw->bd->x, y += cw->bd->y;
@ -3988,6 +3981,10 @@ _e_comp_shapes_update(void *data, E_Container_Shape *es, E_Container_Shape_Chang
case E_CONTAINER_SHAPE_HIDE:
case E_CONTAINER_SHAPE_DEL:
break;
case E_CONTAINER_SHAPE_RECTS:
case E_CONTAINER_SHAPE_INPUT_RECTS:
es->comp_win->shape_changed = 1;
_e_comp_win_render_queue(es->comp_win);
default:
/* any other changes only matter if the
* object is visible
@ -4105,6 +4102,17 @@ _e_comp_populate(E_Comp *c)
e_container_shape_move(cw->shape, x, y);
e_container_shape_resize(cw->shape, w, h);
}
if (cw->free_shape)
{
Eina_Rectangle *rects;
int rnum;
rects = (Eina_Rectangle*)ecore_x_window_shape_rectangles_get(cw->win, &rnum);
e_container_shape_rects_set(cw->shape, rects, rnum);
rects = (Eina_Rectangle*)ecore_x_window_shape_input_rectangles_get(cw->win, &rnum);
e_container_shape_input_rects_set(cw->shape, rects, rnum);
_e_comp_win_shape_init(cw, w, h);
}
if ((!cw->bd) && (ecore_x_window_visible_get(wins[i])))
_e_comp_win_show(cw);
}

View File

@ -139,8 +139,6 @@ struct _E_Comp_Win
Ecore_Timer *update_timeout; // max time between damage and "done" event
Ecore_Timer *ready_timeout; // max time on show (new window draw) to wait for window contents to be ready if sync protocol not handled. this is fallback.
int dmg_updates; // num of damage event updates since a redirect
Ecore_X_Rectangle *rects; // shape rects... if shaped :(
int rects_num; // num rects above
Ecore_X_Pixmap cache_pixmap; // the cached pixmap (1/nth the dimensions)
int cache_w, cache_h; // cached pixmap size

View File

@ -450,53 +450,52 @@ e_container_shape_change_callback_del(E_Container *con, E_Container_Shape_Cb fun
}
}
EAPI Eina_List *
e_container_shape_rects_get(E_Container_Shape *es)
{
E_OBJECT_CHECK_RETURN(es, NULL);
E_OBJECT_TYPE_CHECK_RETURN(es, E_CONTAINER_SHAPE_TYPE, NULL);
return es->shape;
}
EAPI void
e_container_shape_rects_set(E_Container_Shape *es, Ecore_X_Rectangle *rects, int num)
e_container_shape_rects_set(E_Container_Shape *es, Eina_Rectangle *rects, int num)
{
int i;
E_Rect *r;
E_OBJECT_CHECK(es);
E_OBJECT_TYPE_CHECK(es, E_CONTAINER_SHAPE_TYPE);
if (es->shape)
{
E_FREE_LIST(es->shape, free);
es->shape = NULL;
}
E_FREE(es->shape_rects);
es->shape_rects_num = 0;
if ((rects) && (num == 1) &&
(rects[0].x == 0) &&
(rects[0].y == 0) &&
((int)rects[0].width == es->w) &&
((int)rects[0].height == es->h))
((int)rects[0].w == es->w) &&
((int)rects[0].h == es->h))
{
/* do nothing */
}
else if (rects)
{
for (i = 0; i < num; i++)
{
r = malloc(sizeof(E_Rect));
if (r)
{
r->x = rects[i].x;
r->y = rects[i].y;
r->w = rects[i].width;
r->h = rects[i].height;
es->shape = eina_list_append(es->shape, r);
}
}
es->shape_rects = rects;
es->shape_rects_num = num;
}
_e_container_shape_change_call(es, E_CONTAINER_SHAPE_RECTS);
}
EAPI void
e_container_shape_input_rects_set(E_Container_Shape *es, Eina_Rectangle *rects, int num)
{
E_OBJECT_CHECK(es);
E_OBJECT_TYPE_CHECK(es, E_CONTAINER_SHAPE_TYPE);
E_FREE(es->shape_input_rects);
es->shape_input_rects_num = 0;
if ((rects) && (num == 1) &&
(rects[0].x == 0) &&
(rects[0].y == 0) &&
((int)rects[0].w == es->w) &&
((int)rects[0].h == es->h))
{
/* do nothing */
}
else if (rects)
{
es->shape_input_rects = rects;
es->shape_input_rects_num = num;
}
_e_container_shape_change_call(es, E_CONTAINER_SHAPE_INPUT_RECTS);
}
EAPI void
e_container_shape_solid_rect_set(E_Container_Shape *es, int x, int y, int w, int h)
{
@ -939,7 +938,8 @@ static void
_e_container_shape_free(E_Container_Shape *es)
{
es->con->shapes = eina_list_remove(es->con->shapes, es);
E_FREE_LIST(es->shape, free);
free(es->shape_rects);
free(es->shape_input_rects);
free(es);
}

View File

@ -8,7 +8,8 @@ typedef enum _E_Container_Shape_Change
E_CONTAINER_SHAPE_HIDE,
E_CONTAINER_SHAPE_MOVE,
E_CONTAINER_SHAPE_RESIZE,
E_CONTAINER_SHAPE_RECTS
E_CONTAINER_SHAPE_RECTS,
E_CONTAINER_SHAPE_INPUT_RECTS
} E_Container_Shape_Change;
typedef struct _E_Container E_Container;
@ -77,7 +78,10 @@ struct _E_Container_Shape
struct {
int x, y, w, h;
} solid_rect;
Eina_List *shape;
int shape_rects_num;
Eina_Rectangle *shape_rects;
int shape_input_rects_num;
Eina_Rectangle *shape_input_rects;
};
struct _E_Container_Shape_Callback
@ -127,8 +131,8 @@ EAPI void e_container_shape_geometry_get(E_Container_Shape *es, in
EAPI E_Container *e_container_shape_container_get(E_Container_Shape *es);
EAPI void e_container_shape_change_callback_add(E_Container *con, E_Container_Shape_Cb func, void *data);
EAPI void e_container_shape_change_callback_del(E_Container *con, E_Container_Shape_Cb func, void *data);
EAPI Eina_List *e_container_shape_rects_get(E_Container_Shape *es);
EAPI void e_container_shape_rects_set(E_Container_Shape *es, Ecore_X_Rectangle *rects, int num);
EAPI void e_container_shape_rects_set(E_Container_Shape *es, Eina_Rectangle *rects, int num);
EAPI void e_container_shape_input_rects_set(E_Container_Shape *es, Eina_Rectangle *rects, int num);
EAPI void e_container_shape_solid_rect_set(E_Container_Shape *es, int x, int y, int w, int h);
EAPI void e_container_shape_solid_rect_get(E_Container_Shape *es, int *x, int *y, int *w, int *h);