lots of fixes. looking solid now. bugs gone. argb windows handled. proper

update queue with tile updates etc.



SVN revision: 44946
This commit is contained in:
Carsten Haitzler 2010-01-07 13:45:51 +00:00
parent 7f91199f2a
commit 5e891880f1
1 changed files with 238 additions and 23 deletions

View File

@ -3,6 +3,24 @@
#include "e_mod_comp.h"
#include "config.h"
typedef struct _Update Update;
typedef struct _Update_Rect Update_Rect;
struct _Update
{
int w, h;
int tw, th;
int tsw, tsh;
unsigned char *tiles;
};
struct _Update_Rect
{
EINA_INLIST;
int x, y, w, h;
};
typedef struct _Comp Comp;
typedef struct _Comp_Win Comp_Win;
@ -34,11 +52,13 @@ struct _Comp_Win
int depth;
Evas_Object *obj; // shadow object
Ecore_X_Image *xim; // x image - software fallback
// fixme: evas object its mapped to
Update *up; // update handler
// fixme: shape rects
// fixme: argb windows
// ...
Eina_Bool visible : 1; // is visible
Eina_Bool input_only : 1; // is input_only
Eina_Bool argb : 1; // is argb
Eina_Bool update : 1; // has updates to fetch
};
@ -47,6 +67,174 @@ static Eina_List *compositors = NULL;
static Eina_Hash *windows = NULL;
static Eina_Hash *damages = NULL;
//////////////////////////////////////////////////////////////////////////
static Update *
_e_mod_comp_update_new(void)
{
Update *up;
up = calloc(1, sizeof(Update));
up->tsw = 32;
up->tsh = 32;
return up;
}
static void
_e_mod_comp_update_free(Update *up)
{
if (up->tiles) free(up->tiles);
free(up);
}
static void
_e_mod_comp_update_resize(Update *up, int w, int h)
{
if ((up->w == w) && (up->h == h)) return;
up->w = w;
up->h = h;
up->tw = (up->w + up->tsw - 1) / up->tsw;
up->th = (up->h + up->tsh - 1) / up->tsh;
if (up->tiles)
{
free(up->tiles);
up->tiles = NULL;
}
}
static void
_e_mod_comp_tiles_alloc(Update *up)
{
if (up->tiles) return;
up->tiles = calloc(up->tw * up->th, sizeof(unsigned char));
}
static void
_e_mod_comp_update_add(Update *up, int x, int y, int w, int h)
{
int tx, ty, txx, tyy, xx, yy;
unsigned char *t, *t2;
_e_mod_comp_tiles_alloc(up);
// fixme: adjust to allow for optimizations in grabbing of ximages
if (1)
{
if (w > (up->w / 2))
{
x = 0;
w = up->w;
}
}
tx = x / up->tsw;
ty = y / up->tsh;
txx = (x + w - 1) / up->tsw;
tyy = (y + h - 1) / up->tsh;
t = up->tiles + (ty * up->tw) + tx;
for (yy = ty; yy <= tyy; yy++)
{
t2 = t;
for (xx = tx; xx <= txx; xx++)
{
*t2 = 1;
t2++;
}
t += up->tw;
}
}
static Update_Rect *
_e_mod_comp_update_rects_get(Update *up)
{
Update_Rect *r;
int ri = 0;
int x, y;
unsigned char *t, *t2, *t3;
r = calloc((up->tw * up->th) + 1, sizeof(Update_Rect));
if (!r) return NULL;
t = up->tiles;
for (y = 0; y < up->th; y++)
{
for (x = 0; x < up->tw; x++)
{
if (*t)
{
int can_expand_x = 1, can_expand_y = 1;
int xx = 0, yy = 0;
t2 = t + 1;
while (can_expand_x)
{
xx++;
if ((x + xx) >= up->tw) can_expand_x = 0;
else if (!*t2) can_expand_x = 0;
if (can_expand_x) *t2 = 0;
t2++;
}
t3 = t;
while (can_expand_y)
{
int i;
yy++;
t3 += up->tw;
if ((y + yy) >= up->th) can_expand_y = 0;
if (can_expand_y)
{
t2 = t3;
for (i = 0; i < xx; i++)
{
if (!*t2)
{
can_expand_y = 0;
break;
}
t2++;
}
}
if (can_expand_y)
{
t2 = t3;
for (i = 0; i < xx; i++)
{
*t2 = 0;
t2++;
}
}
}
*t = 0;
r[ri].x = x * up->tsw;
r[ri].y = y * up->tsh;
r[ri].w = xx * up->tsw;
r[ri].h = yy * up->tsh;
if ((r[ri].x + r[ri].w) > up->w) r[ri].w = up->w - r[ri].x;
if ((r[ri].y + r[ri].h) > up->h) r[ri].h = up->h - r[ri].y;
if ((r[ri].w <= 0) || (r[ri].h <= 0)) r[ri].w = 0;
else ri++;
x += xx - 1;
t += xx - 1;
}
t++;
}
}
return r;
}
static void
_e_mod_comp_update_clear(Update *up)
{
if (up->tiles)
{
free(up->tiles);
up->tiles = NULL;
}
}
//////////////////////////////////////////////////////////////////////////
static void _e_mod_comp_win_damage(Comp_Win *cw, int x, int y, int w, int h);
static int
@ -58,8 +246,31 @@ _e_mod_comp_cb_animator(void *data)
c->render_animator = NULL;
EINA_LIST_FREE(c->updates, cw)
{
Update_Rect *r;
int i;
cw->update = 0;
// FIXME: accumulate updates and fetch them all here
r = _e_mod_comp_update_rects_get(cw->up);
_e_mod_comp_update_clear(cw->up);
if (cw->xim)
{
for (i = 0; r[i].w > 0; i++)
{
unsigned int *pix;
int x, y, w, h;
x = r[i].x;
y = r[i].y;
w = r[i].w;
h = r[i].h;
ecore_x_image_get(cw->xim, cw->pixmap, x, y, x, y, w, h);
pix = ecore_x_image_data_get(cw->xim, NULL, NULL, NULL);
evas_object_image_size_set(cw->obj, cw->w, cw->h);
evas_object_image_data_set(cw->obj, pix);
evas_object_image_data_update_add(cw->obj, x, y, w, h);
}
}
free(r);
}
ecore_evas_manual_render(c->ee);
return 0;
@ -128,6 +339,7 @@ _e_mod_comp_win_add(Comp *c, Ecore_X_Window win)
cw->input_only = att.input_only;
cw->vis = att.visual;
cw->depth = att.depth;
cw->argb = ecore_x_window_argb_get(cw->win);
eina_hash_add(windows, e_util_winid_str_get(cw->win), cw);
if (!cw->input_only)
{
@ -135,21 +347,26 @@ _e_mod_comp_win_add(Comp *c, Ecore_X_Window win)
eina_hash_add(damages, e_util_winid_str_get(cw->damage), cw);
cw->obj = evas_object_image_filled_add(c->evas);
evas_object_image_colorspace_set(cw->obj, EVAS_COLORSPACE_ARGB8888);
evas_object_image_alpha_set(cw->obj, 0);
if (cw->argb)
evas_object_image_alpha_set(cw->obj, 1);
else
evas_object_image_alpha_set(cw->obj, 0);
}
else
{
cw->obj = evas_object_rectangle_add(c->evas);
evas_object_color_set(cw->obj, 0, 0, 0, 64);
}
printf(" [0x%x] add\n", cw->win);
cw->up = _e_mod_comp_update_new();
// printf(" [0x%x] add\n", cw->win);
return cw;
}
static void
_e_mod_comp_win_del(Comp_Win *cw)
{
printf(" [0x%x] del\n", cw->win);
_e_mod_comp_update_free(cw->up);
// printf(" [0x%x] del\n", cw->win);
if (cw->update)
{
cw->update = 0;
@ -181,7 +398,7 @@ _e_mod_comp_win_show(Comp_Win *cw)
if (cw->visible) return;
cw->visible = 1;
if (cw->input_only) return;
printf(" [0x%x] sho\n", cw->win);
// printf(" [0x%x] sho\n", cw->win);
if (!cw->pixmap)
{
ecore_x_composite_redirect_window(cw->win, ECORE_X_COMPOSITE_UPDATE_MANUAL);
@ -197,7 +414,7 @@ _e_mod_comp_win_hide(Comp_Win *cw)
if (!cw->visible) return;
cw->visible = 0;
if (cw->input_only) return;
printf(" [0x%x] hid\n", cw->win);
// printf(" [0x%x] hid\n", cw->win);
if (cw->pixmap)
{
ecore_x_pixmap_free(cw->pixmap);
@ -211,7 +428,7 @@ _e_mod_comp_win_hide(Comp_Win *cw)
static void
_e_mod_comp_win_raise_above(Comp_Win *cw, Comp_Win *cw2)
{
printf(" [0x%x] abv [0x%x]\n", cw->win, cw2->win);
// printf(" [0x%x] abv [0x%x]\n", cw->win, cw2->win);
cw->c->wins = eina_inlist_remove(cw->c->wins, EINA_INLIST_GET(cw));
cw->c->wins = eina_inlist_append_relative(cw->c->wins,
EINA_INLIST_GET(cw),
@ -224,7 +441,7 @@ _e_mod_comp_win_raise_above(Comp_Win *cw, Comp_Win *cw2)
static void
_e_mod_comp_win_raise(Comp_Win *cw)
{
printf(" [0x%x] rai\n", cw->win);
// printf(" [0x%x] rai\n", cw->win);
cw->c->wins = eina_inlist_remove(cw->c->wins, EINA_INLIST_GET(cw));
cw->c->wins = eina_inlist_append(cw->c->wins, EINA_INLIST_GET(cw));
evas_object_raise(cw->obj);
@ -235,7 +452,7 @@ _e_mod_comp_win_raise(Comp_Win *cw)
static void
_e_mod_comp_win_lower(Comp_Win *cw)
{
printf(" [0x%x] low\n", cw->win);
// printf(" [0x%x] low\n", cw->win);
cw->c->wins = eina_inlist_remove(cw->c->wins, EINA_INLIST_GET(cw));
cw->c->wins = eina_inlist_prepend(cw->c->wins, EINA_INLIST_GET(cw));
evas_object_lower(cw->obj);
@ -248,14 +465,14 @@ _e_mod_comp_win_configure(Comp_Win *cw, int x, int y, int w, int h, int border)
{
if (!((x == cw->x) && (y == cw->y)))
{
printf(" [0x%x] mov %4i %4i\n", cw->win, x, y);
// printf(" [0x%x] mov %4i %4i\n", cw->win, x, y);
cw->x = x;
cw->y = y;
evas_object_move(cw->obj, cw->x, cw->y);
}
if (!((w == cw->w) && (h == cw->h)))
{
printf(" [0x%x] rsz %4ix%4i\n", cw->win, w, h);
// printf(" [0x%x] rsz %4ix%4i\n", cw->win, w, h);
// ecore_x_composite_unredirect_window(cw->win, ECORE_X_COMPOSITE_UPDATE_MANUAL);
// ecore_x_composite_redirect_window(cw->win, ECORE_X_COMPOSITE_UPDATE_MANUAL);
if (cw->pixmap)
@ -272,6 +489,7 @@ _e_mod_comp_win_configure(Comp_Win *cw, int x, int y, int w, int h, int border)
ecore_x_image_free(cw->xim);
cw->xim = NULL;
}
_e_mod_comp_update_resize(cw->up, cw->w, cw->h);
}
cw->border = border;
if (cw->input_only) return;
@ -284,11 +502,10 @@ _e_mod_comp_win_damage(Comp_Win *cw, int x, int y, int w, int h)
Ecore_X_Region parts;
if (cw->input_only) return;
printf(" [0x%x] dmg %4i %4i %4ix%4i\n", cw->win, x, y, w, h);
// printf(" [0x%x] dmg %4i %4i %4ix%4i\n", cw->win, x, y, w, h);
parts = ecore_x_region_new(NULL, 0);
ecore_x_damage_subtract(cw->damage, 0, parts);
ecore_x_region_free(parts);
// FIXME: add rect to queue for this compwin
if (!cw->pixmap)
cw->pixmap = ecore_x_composite_name_window_pixmap_get(cw->win);
@ -302,6 +519,7 @@ _e_mod_comp_win_damage(Comp_Win *cw, int x, int y, int w, int h)
h = cw->h;
}
}
/*
if (cw->xim)
{
unsigned int *pix;
@ -312,12 +530,14 @@ _e_mod_comp_win_damage(Comp_Win *cw, int x, int y, int w, int h)
evas_object_image_size_set(cw->obj, cw->w, cw->h);
evas_object_image_data_update_add(cw->obj, x, y, w, h);
}
*/
_e_mod_comp_win_render_queue(cw);
if (!cw->update)
{
cw->update = 1;
cw->c->updates = eina_list_append(cw->c->updates, cw);
}
_e_mod_comp_update_add(cw->up, x, y, w, h);
}
//////////////////////////////////////////////////////////////////////////
@ -404,14 +624,7 @@ _e_mod_comp_configure(void *data, int type, void *event)
Comp_Win *cw3 = (Comp_Win *)(EINA_INLIST_GET(cw)->prev);
if (cw3 != cw2)
{
if (cw3)
printf("... currently above [0x%x]\n", cw3->win);
else
printf("... currently at bottom\n");
printf("... ... move above [0x%x]\n", cw2->win);
_e_mod_comp_win_raise_above(cw, cw2);
}
_e_mod_comp_win_raise_above(cw, cw2);
}
}
@ -465,7 +678,9 @@ _e_mod_comp_damage(void *data, int type, void *event)
Ecore_X_Event_Damage *ev = event;
Comp_Win *cw = _e_mod_comp_win_damage_find(ev->damage);
if (!cw) return 1;
_e_mod_comp_win_damage(cw, ev->area.x, ev->area.y, ev->area.width, ev->area.height);
_e_mod_comp_win_damage(cw,
ev->area.x, ev->area.y,
ev->area.width, ev->area.height);
return 1;
}