diff --git a/src/modules/comp/e_mod_comp.c b/src/modules/comp/e_mod_comp.c index 85f5289b0..dddd7844d 100644 --- a/src/modules/comp/e_mod_comp.c +++ b/src/modules/comp/e_mod_comp.c @@ -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; }