#include <string.h>
static void
-view_mark_plane_entries_damaged(pepper_view_t *view)
-{
- int i;
-
- for (i = 0; i < PEPPER_MAX_OUTPUT_COUNT; i++)
- view->plane_entries[i].need_damage = PEPPER_TRUE;
-}
-
-static void
-view_handle_surface_destroy(struct wl_listener *listener, void *data)
-{
- pepper_view_t *view = pepper_container_of(listener, pepper_view_t, surface_destroy_listener);
- PEPPER_ASSERT(view->surface != NULL);
- pepper_view_destroy(view);
-}
-
-static void
-view_geometry_dirty(pepper_view_t *view)
+view_mark_dirty(pepper_view_t *view, uint32_t flag)
{
pepper_list_t *l;
- if (view->geometry_dirty)
+ if (view->dirty & flag)
return;
- view->geometry_dirty = PEPPER_TRUE;
- pepper_view_damage_below(view);
-
- PEPPER_LIST_FOR_EACH(&view->children_list, l)
- view_geometry_dirty((pepper_view_t *)l->item);
-}
-
-static void
-view_update_visibility(pepper_view_t *view)
-{
- pepper_bool_t visibility;
+ view->dirty |= flag;
- if (view->parent)
- visibility = view->parent->visibility && view->mapped;
- else
- visibility = view->mapped;
-
- if (visibility != view->visibility)
+ if ((flag & PEPPER_VIEW_VISIBILITY_DIRTY) ||
+ (flag & PEPPER_VIEW_GEOMETRY_DIRTY))
{
- pepper_list_t *l;
-
- view->visibility = visibility;
-
- /* We simply treat a visibility change as a geometry change. */
- view_geometry_dirty(view);
-
PEPPER_LIST_FOR_EACH(&view->children_list, l)
- view_update_visibility((pepper_view_t *)l->item);
+ view_mark_dirty((pepper_view_t *)l->item, flag);
}
-}
-static void
-view_map(pepper_view_t *view)
-{
- if (view->mapped)
- return;
-
- view->mapped = PEPPER_TRUE;
- view_update_visibility(view);
+ pepper_compositor_schedule_repaint(view->compositor);
}
static void
-view_unmap(pepper_view_t *view)
-{
- if (!view->mapped)
- return;
-
- view->mapped = PEPPER_FALSE;
- view_update_visibility(view);
-}
-
-static inline void
-add_bbox_point(double *box, int x, int y, const pepper_mat4_t *matrix)
+view_mark_damaged(pepper_view_t *view)
{
- pepper_vec2_t v = { x, y };
-
- pepper_mat4_transform_vec2(matrix, &v);
+ int i;
- box[0] = PEPPER_MIN(box[0], v.x);
- box[1] = PEPPER_MIN(box[1], v.y);
- box[2] = PEPPER_MAX(box[2], v.x);
- box[3] = PEPPER_MAX(box[3], v.y);
+ for (i = 0; i < PEPPER_MAX_OUTPUT_COUNT; i++)
+ view->plane_entries[i].need_damage = PEPPER_TRUE;
}
-static inline void
-transform_bounding_box(pixman_box32_t *box, const pepper_mat4_t *matrix)
+static void
+view_damage_below(pepper_view_t *view)
{
- double b[4] = { HUGE_VAL, HUGE_VAL, -HUGE_VAL, -HUGE_VAL };
+ int i;
- add_bbox_point(b, box->x1, box->y1, matrix);
- add_bbox_point(b, box->x2, box->y1, matrix);
- add_bbox_point(b, box->x2, box->y2, matrix);
- add_bbox_point(b, box->x1, box->y2, matrix);
+ for (i = 0; i < PEPPER_MAX_OUTPUT_COUNT; i++)
+ {
+ pepper_plane_entry_t *entry = &view->plane_entries[i];
- box->x1 = floor(b[0]);
- box->y1 = floor(b[1]);
- box->x2 = ceil(b[2]);
- box->y2 = ceil(b[3]);
+ if (entry->plane)
+ pepper_plane_add_damage_region(entry->plane, &entry->base.visible_region);
+ }
}
-static inline void
-transform_region_bounding(pixman_region32_t *region, const pepper_mat4_t *matrix)
+void
+pepper_view_surface_damage(pepper_view_t *view)
{
- pixman_region32_t result;
- pixman_box32_t *rects;
- int i, num_rects;
-
- pixman_region32_init(&result);
- rects = pixman_region32_rectangles(region, &num_rects);
+ int i;
- for (i = 0; i < num_rects; i++)
+ for (i = 0; i < PEPPER_MAX_OUTPUT_COUNT; i++)
{
- pixman_box32_t box = rects[i];
+ pepper_plane_entry_t *entry = &view->plane_entries[i];
- transform_bounding_box(&box, matrix);
- pixman_region32_union_rect(&result, &result,
- box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ if (entry->plane)
+ {
+ pixman_region32_t damage;
+
+ pixman_region32_init(&damage);
+ pixman_region32_copy(&damage, &view->surface->damage_region);
+ pepper_transform_pixman_region(&damage, &view->global_transform);
+ pixman_region32_translate(&damage,
+ -entry->plane->output->geometry.x,
+ -entry->plane->output->geometry.y);
+ pixman_region32_intersect(&damage, &damage, &entry->base.visible_region);
+ pepper_plane_add_damage_region(entry->plane, &damage);
+ }
}
-
- pixman_region32_copy(region, &result);
- pixman_region32_fini(&result);
}
static void
-view_update_output_overlap(pepper_view_t *view)
+view_handle_surface_destroy(struct wl_listener *listener, void *data)
{
- pepper_list_t *l;
-
- view->output_overlap = 0;
-
- PEPPER_LIST_FOR_EACH(&view->compositor->output_list, l)
- {
- pepper_output_t *output = l->item;
- pixman_box32_t box =
- {
- output->geometry.x,
- output->geometry.y,
- output->geometry.x + output->geometry.w,
- output->geometry.y + output->geometry.h
- };
-
- if (pixman_region32_contains_rectangle(&view->bounding_region, &box) != PIXMAN_REGION_OUT)
- view->output_overlap |= (1 << output->id);
- }
+ pepper_view_t *view = pepper_container_of(listener, pepper_view_t, surface_destroy_listener);
+ PEPPER_ASSERT(view->surface != NULL);
+ pepper_view_destroy(view);
}
static pepper_list_t *
{
pepper_list_remove(&view->compositor_link, NULL);
pepper_list_insert(pos, &view->compositor_link);
-
- if (view->visibility)
- {
- pepper_view_damage_below(view);
- view_mark_plane_entries_damaged(view);
- }
+ view_mark_dirty(view, PEPPER_VIEW_Z_ORDER_DIRTY);
}
pos = &view->compositor_link;
return pos;
}
+
static void
view_handle_plane_destroy(struct wl_listener *listener, void *data);
if (entry->plane)
{
- pepper_view_damage_below((pepper_view_t *)entry->base.view);
+ view_damage_below((pepper_view_t *)entry->base.view);
entry->plane = NULL;
wl_list_remove(&entry->plane_destroy_listener.link);
pixman_region32_fini(&entry->base.visible_region);
}
void
-pepper_view_damage_below(pepper_view_t *view)
+view_update_geometry(pepper_view_t *view)
{
- int i;
+ pepper_list_t *l;
- for (i = 0; i < PEPPER_MAX_OUTPUT_COUNT; i++)
+ if (view->surface)
{
- pepper_plane_entry_t *entry = &view->plane_entries[i];
-
- if (entry->plane)
- pepper_plane_add_damage_region(entry->plane, &entry->base.visible_region);
+ view->w = view->surface->w;
+ view->h = view->surface->h;
}
-}
-
-void
-pepper_view_update_geometry(pepper_view_t *view)
-{
- if (!view->geometry_dirty)
- return;
pepper_mat4_init_translate(&view->global_transform, view->x, view->y, 0.0);
pepper_mat4_multiply(&view->global_transform, &view->transform, &view->global_transform);
if (view->parent)
{
- pepper_view_update_geometry(view->parent);
pepper_mat4_multiply(&view->global_transform,
&view->parent->global_transform, &view->global_transform);
}
- if (view->surface)
- {
- view->w = view->surface->w;
- view->h = view->surface->h;
- }
-
/* Bounding region. */
pixman_region32_init_rect(&view->bounding_region, 0, 0, view->w, view->h);
- transform_region_bounding(&view->bounding_region, &view->global_transform);
+ pepper_transform_pixman_region(&view->bounding_region, &view->global_transform);
/* Opaque region. */
pixman_region32_init(&view->opaque_region);
view->global_transform.m[3], view->global_transform.m[7]);
}
- view->geometry_dirty = PEPPER_FALSE;
- view_update_output_overlap(view);
- view_mark_plane_entries_damaged(view);
+ view->output_overlap = 0;
+
+ PEPPER_LIST_FOR_EACH(&view->compositor->output_list, l)
+ {
+ pepper_output_t *output = l->item;
+ pixman_box32_t box =
+ {
+ output->geometry.x,
+ output->geometry.y,
+ output->geometry.x + output->geometry.w,
+ output->geometry.y + output->geometry.h
+ };
+
+ if (pixman_region32_contains_rectangle(&view->bounding_region, &box) != PIXMAN_REGION_OUT)
+ view->output_overlap |= (1 << output->id);
+ }
+
+}
+
+static void
+view_update_visibility(pepper_view_t *view)
+{
+ pepper_bool_t visible;
+
+ if (!(view->dirty & PEPPER_VIEW_VISIBILITY_DIRTY))
+ return;
+
+ if (view->parent)
+ view_update_visibility(view->parent);
+
+ view->visible = view->parent->visible && view->mapped;
+ view->dirty &= ~PEPPER_VIEW_VISIBILITY_DIRTY;
+}
+
+void
+pepper_view_update(pepper_view_t *view)
+{
+ if (!view->dirty)
+ return;
+
+ if (view->parent)
+ {
+ pepper_view_update(view->parent);
+ view->visible = view->parent->visible && view->mapped;
+ }
+ else
+ {
+ view->visible = view->mapped;
+ }
+
+ if (view->visible == view->prev_visible)
+ view->dirty &= ~PEPPER_VIEW_VISIBILITY_DIRTY;
+
+ if (!view->dirty)
+ return;
+
+ if (view->prev_visible)
+ view_damage_below(view);
+
+ if ((view->dirty & PEPPER_VIEW_GEOMETRY_DIRTY) || (!view->prev_visible && view->visible))
+ view_update_geometry(view);
+
+ if (view->visible)
+ view_mark_damaged(view);
+
+ view->dirty = 0;
+ view->prev_visible = view->visible;
}
static void
view->w = surface->w;
view->h = surface->h;
- view->geometry_dirty = PEPPER_TRUE;
-
view->surface = surface;
view->surface_link.item = view;
pepper_list_insert(&surface->view_list, &view->surface_link);
* destruction can detach from their parent.
*/
pepper_object_fini(&view->base);
- view_unmap(view);
for (i = 0; i < PEPPER_MAX_OUTPUT_COUNT; i++)
plane_entry_set_plane(&view->plane_entries[i], NULL);
if (view->parent == parent)
return;
+ if (view->parent)
+ pepper_list_remove(&view->parent_link, NULL);
+
view->parent = parent;
- pepper_list_remove(&view->parent_link, NULL);
if (view->parent)
pepper_list_insert(view->parent->children_list.prev, &view->parent_link);
- view_geometry_dirty(view);
+ view_mark_dirty(view, PEPPER_VIEW_VISIBILITY_DIRTY | PEPPER_VIEW_GEOMETRY_DIRTY);
}
PEPPER_API pepper_view_t *
view->w = w;
view->h = h;
- view_geometry_dirty(view);
+ view_mark_dirty(view, PEPPER_VIEW_GEOMETRY_DIRTY);
}
PEPPER_API void
view->x = x;
view->y = y;
- view_geometry_dirty(view);
+ view_mark_dirty(view, PEPPER_VIEW_GEOMETRY_DIRTY);
}
PEPPER_API void
pepper_view_set_transform(pepper_view_t *view, const pepper_mat4_t *matrix)
{
pepper_mat4_copy(&view->transform, matrix);
- view_geometry_dirty(view);
+ view_mark_dirty(view, PEPPER_VIEW_GEOMETRY_DIRTY);
}
PEPPER_API const pepper_mat4_t *
PEPPER_API void
pepper_view_map(pepper_view_t *view)
{
- view_map(view);
+ if (view->mapped)
+ return;
+
+ view->mapped = PEPPER_TRUE;
+ view_mark_dirty(view, PEPPER_VIEW_VISIBILITY_DIRTY);
}
PEPPER_API void
pepper_view_unmap(pepper_view_t *view)
{
- view_unmap(view);
+ if (!view->mapped)
+ return;
+
+ view->mapped = PEPPER_FALSE;
+ view_mark_dirty(view, PEPPER_VIEW_VISIBILITY_DIRTY);
}
PEPPER_API pepper_bool_t
PEPPER_API pepper_bool_t
pepper_view_is_visible(pepper_view_t *view)
{
- return view->visibility;
+ return view->visible;
}