432 lines
11 KiB
C
432 lines
11 KiB
C
#include "evas_common.h"
|
|
#include "evas_private.h"
|
|
|
|
/**
|
|
* To be documented.
|
|
*
|
|
* FIXME: To be fixed.
|
|
*
|
|
*/
|
|
void
|
|
evas_damage_rectangle_add(Evas *e, int x, int y, int w, int h)
|
|
{
|
|
Evas_Rectangle *r;
|
|
|
|
MAGIC_CHECK(e, Evas, MAGIC_EVAS);
|
|
return;
|
|
MAGIC_CHECK_END();
|
|
r = malloc(sizeof(Evas_Rectangle));
|
|
if (!r) return;
|
|
r->x = x; r->y = y; r->w = w; r->h = h;
|
|
e->damages = evas_list_append(e->damages, r);
|
|
e->changed = 1;
|
|
}
|
|
|
|
/**
|
|
* To be documented.
|
|
*
|
|
* FIXME: To be fixed.
|
|
*
|
|
*/
|
|
void
|
|
evas_obscured_rectangle_add(Evas *e, int x, int y, int w, int h)
|
|
{
|
|
Evas_Rectangle *r;
|
|
|
|
MAGIC_CHECK(e, Evas, MAGIC_EVAS);
|
|
return;
|
|
MAGIC_CHECK_END();
|
|
r = malloc(sizeof(Evas_Rectangle));
|
|
if (!r) return;
|
|
r->x = x; r->y = y; r->w = w; r->h = h;
|
|
e->obscures = evas_list_append(e->obscures, r);
|
|
}
|
|
|
|
/**
|
|
* To be documented.
|
|
*
|
|
* FIXME: To be fixed.
|
|
*
|
|
*/
|
|
void
|
|
evas_obscured_clear(Evas *e)
|
|
{
|
|
MAGIC_CHECK(e, Evas, MAGIC_EVAS);
|
|
return;
|
|
MAGIC_CHECK_END();
|
|
while (e->obscures)
|
|
{
|
|
Evas_Rectangle *r;
|
|
|
|
r = (Evas_Rectangle *)e->obscures->data;
|
|
e->obscures = evas_list_remove(e->obscures, r);
|
|
free(r);
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
_evas_render_phase1_object_process(Evas *e, Evas_Object *obj, Evas_List **active_objects, Evas_List **restack_objects, int restack)
|
|
{
|
|
int is_active;
|
|
|
|
/* if (obj->cur.cache.clip.dirty) */
|
|
evas_object_clip_recalc(obj);
|
|
/* build active object list */
|
|
is_active = evas_object_is_active(obj);
|
|
if ((is_active) || (obj->delete_me != 0))
|
|
*active_objects = evas_list_append(*active_objects, obj);
|
|
if (restack)
|
|
{
|
|
obj->restack = 1;
|
|
obj->changed = 1;
|
|
}
|
|
if (obj->changed)
|
|
{
|
|
if (obj->smart.smart)
|
|
{
|
|
Evas_Object_List *l;
|
|
|
|
obj->func->render_pre(obj);
|
|
for (l = obj->smart.contained; l; l = l->next)
|
|
{
|
|
Evas_Object *obj2;
|
|
|
|
obj2 = (Evas_Object *)l;
|
|
_evas_render_phase1_object_process(e, obj2,
|
|
active_objects,
|
|
restack_objects,
|
|
obj->restack);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((is_active) && (obj->restack) && (!obj->clip.clipees) &&
|
|
((evas_object_is_visible(obj) && (!obj->cur.have_clipees)) ||
|
|
(evas_object_was_visible(obj) && (!obj->prev.have_clipees))))
|
|
*restack_objects = evas_list_append(*restack_objects, obj);
|
|
else if ((is_active) && (!obj->clip.clipees))
|
|
obj->func->render_pre(obj);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((!obj->clip.clipees) && (obj->delete_me == 0))
|
|
{
|
|
if (obj->smart.smart)
|
|
{
|
|
Evas_Object_List *l;
|
|
|
|
obj->func->render_pre(obj);
|
|
for (l = obj->smart.contained; l; l = l->next)
|
|
{
|
|
Evas_Object *obj2;
|
|
|
|
obj2 = (Evas_Object *)l;
|
|
_evas_render_phase1_object_process(e, obj2,
|
|
active_objects,
|
|
restack_objects,
|
|
restack);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (evas_object_is_opaque(obj) &&
|
|
evas_object_is_visible(obj))
|
|
e->engine.func->output_redraws_rect_del(e->engine.data.output,
|
|
obj->cur.cache.clip.x,
|
|
obj->cur.cache.clip.y,
|
|
obj->cur.cache.clip.w,
|
|
obj->cur.cache.clip.h);
|
|
}
|
|
}
|
|
}
|
|
if (!is_active) obj->restack = 0;
|
|
}
|
|
|
|
static void
|
|
_evas_render_phase1_process(Evas *e, Evas_List **active_objects, Evas_List **restack_objects)
|
|
{
|
|
Evas_Object_List *l;
|
|
|
|
for (l = (Evas_Object_List *)e->layers; l; l = l->next)
|
|
{
|
|
Evas_Object_List *l2;
|
|
Evas_Layer *lay;
|
|
|
|
lay = (Evas_Layer *)l;
|
|
for (l2 = (Evas_Object_List *)lay->objects; l2; l2 = l2->next)
|
|
{
|
|
Evas_Object *obj;
|
|
|
|
obj = (Evas_Object *)l2;
|
|
_evas_render_phase1_object_process(e, obj, active_objects, restack_objects, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* To be documented.
|
|
*
|
|
* FIXME: To be fixed.
|
|
*
|
|
*/
|
|
Evas_List *
|
|
evas_render_updates(Evas *e)
|
|
{
|
|
Evas_List *updates = NULL;
|
|
Evas_List *obscuring_objects = NULL;
|
|
Evas_List *obscuring_objects_orig = NULL;
|
|
Evas_List *active_objects = NULL;
|
|
Evas_List *delete_objects = NULL;
|
|
Evas_List *restack_objects = NULL;
|
|
Evas_List *ll;
|
|
Evas_Object_List *l;
|
|
void *surface;
|
|
int ux, uy, uw, uh;
|
|
int cx, cy, cw, ch;
|
|
|
|
MAGIC_CHECK(e, Evas, MAGIC_EVAS);
|
|
return NULL;
|
|
MAGIC_CHECK_END();
|
|
if (!e->changed) return NULL;
|
|
|
|
/* phase 1. add extra updates for changed objects */
|
|
_evas_render_phase1_process(e, &active_objects, &restack_objects);
|
|
/* phase 2. force updates for restacks */
|
|
while (restack_objects)
|
|
{
|
|
Evas_Object *obj;
|
|
|
|
obj = restack_objects->data;
|
|
restack_objects = evas_list_remove(restack_objects, obj);
|
|
obj->func->render_pre(obj);
|
|
e->engine.func->output_redraws_rect_add(e->engine.data.output,
|
|
obj->prev.cache.clip.x,
|
|
obj->prev.cache.clip.y,
|
|
obj->prev.cache.clip.w,
|
|
obj->prev.cache.clip.h);
|
|
e->engine.func->output_redraws_rect_add(e->engine.data.output,
|
|
obj->cur.cache.clip.x,
|
|
obj->cur.cache.clip.y,
|
|
obj->cur.cache.clip.w,
|
|
obj->cur.cache.clip.h);
|
|
}
|
|
/* phase 3. add exposes */
|
|
while (e->damages)
|
|
{
|
|
Evas_Rectangle *r;
|
|
|
|
r = e->damages->data;
|
|
e->damages = evas_list_remove(e->damages, r);
|
|
e->engine.func->output_redraws_rect_add(e->engine.data.output,
|
|
r->x, r->y, r->w, r->h);
|
|
free(r);
|
|
}
|
|
/* phase 4. output & viewport changes */
|
|
if (e->viewport.changed)
|
|
{
|
|
e->engine.func->output_redraws_rect_add(e->engine.data.output,
|
|
0, 0,
|
|
e->output.w, e->output.h);
|
|
}
|
|
if (e->output.changed)
|
|
{
|
|
e->engine.func->output_resize(e->engine.data.output,
|
|
e->output.w, e->output.h);
|
|
e->engine.func->output_redraws_rect_add(e->engine.data.output,
|
|
0, 0,
|
|
e->output.w, e->output.h);
|
|
}
|
|
/* phase 5. add obscures */
|
|
for (ll = e->obscures; ll; ll = ll->next)
|
|
{
|
|
Evas_Rectangle *r;
|
|
|
|
r = ll->data;
|
|
e->engine.func->output_redraws_rect_del(e->engine.data.output,
|
|
r->x, r->y, r->w, r->h);
|
|
}
|
|
/* build obscure objects list of active objects that obscure */
|
|
for (ll = active_objects; ll; ll = ll->next)
|
|
{
|
|
Evas_Object *obj;
|
|
|
|
obj = (Evas_Object *)(ll->data);
|
|
if (evas_object_is_opaque(obj) &&
|
|
evas_object_is_visible(obj) &&
|
|
(!obj->clip.clipees) &&
|
|
(obj->cur.visible) &&
|
|
(!obj->delete_me) &&
|
|
(obj->cur.cache.clip.visible) &&
|
|
(!obj->smart.smart))
|
|
obscuring_objects = evas_list_append(obscuring_objects, obj);
|
|
}
|
|
/* save this list */
|
|
obscuring_objects_orig = obscuring_objects;
|
|
obscuring_objects = NULL;
|
|
/* phase 6. go thru each update rect and render objects in it*/
|
|
while ((surface =
|
|
e->engine.func->output_redraws_next_update_get(e->engine.data.output,
|
|
&ux, &uy, &uw, &uh,
|
|
&cx, &cy, &cw, &ch)))
|
|
{
|
|
Evas_Rectangle *rect;
|
|
int off_x, off_y;
|
|
|
|
rect = malloc(sizeof(Evas_Rectangle));
|
|
if (rect)
|
|
{
|
|
rect->x = ux; rect->y = uy; rect->w = uw; rect->h = uh;
|
|
updates = evas_list_append(updates, rect);
|
|
}
|
|
off_x = cx - ux;
|
|
off_y = cy - uy;
|
|
/* build obscuring objects list (in order from bottom to top) */
|
|
for (ll = obscuring_objects_orig; ll; ll = ll->next)
|
|
{
|
|
Evas_Object *obj;
|
|
|
|
obj = (Evas_Object *)(ll->data);
|
|
if (evas_object_is_in_output_rect(obj, ux, uy, uw, uh))
|
|
obscuring_objects = evas_list_append(obscuring_objects, obj);
|
|
}
|
|
/* render all object that intersect with rect */
|
|
for (ll = active_objects; ll; ll = ll->next)
|
|
{
|
|
Evas_Object *obj;
|
|
Evas_List *l3;
|
|
obj = (Evas_Object *)(ll->data);
|
|
|
|
/* if it's in our outpout rect and it doesn't clip anything */
|
|
if (evas_object_is_in_output_rect(obj, ux, uy, uw, uh) &&
|
|
(!obj->clip.clipees) &&
|
|
(obj->cur.visible) &&
|
|
(!obj->delete_me) &&
|
|
(obj->cur.cache.clip.visible) &&
|
|
(!obj->smart.smart) &&
|
|
(obj->cur.color.a > 0))
|
|
{
|
|
int x, y, w, h;
|
|
|
|
if ((obscuring_objects) && (obscuring_objects->data == obj))
|
|
obscuring_objects = evas_list_remove(obscuring_objects, obj);
|
|
x = cx; y = cy; w = cw; h = ch;
|
|
RECTS_CLIP_TO_RECT(x, y, w, h,
|
|
obj->cur.cache.clip.x + off_x,
|
|
obj->cur.cache.clip.y + off_y,
|
|
obj->cur.cache.clip.w,
|
|
obj->cur.cache.clip.h);
|
|
if ((w > 0) && (h > 0))
|
|
{
|
|
e->engine.func->context_clip_set(e->engine.data.output,
|
|
e->engine.data.context,
|
|
x, y, w, h);
|
|
#if 1 /* FIXME: this can slow things down... figure out optimum... coverage */
|
|
for (l3 = obscuring_objects; l3; l3 = l3->next)
|
|
{
|
|
Evas_Object *obj2;
|
|
|
|
obj2 = (Evas_Object *)l3->data;
|
|
e->engine.func->context_cutout_add(e->engine.data.output,
|
|
e->engine.data.context,
|
|
obj2->cur.cache.clip.x + off_x,
|
|
obj2->cur.cache.clip.y + off_y,
|
|
obj2->cur.cache.clip.w,
|
|
obj2->cur.cache.clip.h);
|
|
}
|
|
#endif
|
|
obj->func->render(obj,
|
|
e->engine.data.output,
|
|
e->engine.data.context,
|
|
surface,
|
|
off_x, off_y);
|
|
e->engine.func->context_cutout_clear(e->engine.data.output,
|
|
e->engine.data.context);
|
|
}
|
|
}
|
|
}
|
|
/* punch rect out */
|
|
e->engine.func->output_redraws_next_update_push(e->engine.data.output,
|
|
surface,
|
|
ux, uy, uw, uh);
|
|
/* free obscuring objects list */
|
|
obscuring_objects = evas_list_free(obscuring_objects);
|
|
}
|
|
/* flush redraws */
|
|
e->engine.func->output_flush(e->engine.data.output);
|
|
/* clear redraws */
|
|
e->engine.func->output_redraws_clear(e->engine.data.output);
|
|
/* and do a post render pass */
|
|
for (ll = active_objects; ll; ll = ll->next)
|
|
{
|
|
Evas_Object *obj;
|
|
|
|
obj = (Evas_Object *)(ll->data);
|
|
obj->pre_render_done = 0;
|
|
if (obj->changed)
|
|
{
|
|
obj->func->render_post(obj);
|
|
obj->restack = 0;
|
|
obj->changed = 0;
|
|
}
|
|
if (obj->delete_me == 2)
|
|
{
|
|
delete_objects = evas_list_append(delete_objects, obj);
|
|
}
|
|
else if (obj->delete_me != 0) obj->delete_me++;
|
|
}
|
|
/* free our obscuring object list */
|
|
evas_list_free(obscuring_objects_orig);
|
|
/* free our active object list */
|
|
evas_list_free(active_objects);
|
|
/* delete all objects flagged for deletion now */
|
|
while (delete_objects)
|
|
{
|
|
Evas_Object *obj;
|
|
|
|
obj = (Evas_Object *)(delete_objects->data);
|
|
delete_objects = evas_list_remove_list(delete_objects, delete_objects);
|
|
evas_object_free(obj, 1);
|
|
}
|
|
e->changed = 0;
|
|
e->viewport.changed = 0;
|
|
e->output.changed = 0;
|
|
return updates;
|
|
}
|
|
|
|
/**
|
|
* To be documented.
|
|
*
|
|
* FIXME: To be fixed.
|
|
*
|
|
*/
|
|
void
|
|
evas_render_updates_free(Evas_List *updates)
|
|
{
|
|
while (updates)
|
|
{
|
|
free(updates->data);
|
|
updates = evas_list_remove(updates, updates->data);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* To be documented.
|
|
*
|
|
* FIXME: To be fixed.
|
|
*
|
|
*/
|
|
void
|
|
evas_render(Evas *e)
|
|
{
|
|
Evas_List *updates;
|
|
|
|
MAGIC_CHECK(e, Evas, MAGIC_EVAS);
|
|
return;
|
|
MAGIC_CHECK_END();
|
|
|
|
updates = evas_render_updates(e);
|
|
if (updates) evas_render_updates_free(updates);
|
|
}
|