libweston: Track damage on paint nodes instead of planes
Remove plane->damage and instead accumulate damage on paint nodes. This is a step towards allowing multiple overlapping outputs. Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
This commit is contained in:
parent
fe2b5db01e
commit
820346a372
@ -1267,7 +1267,6 @@ struct weston_layer {
|
|||||||
|
|
||||||
struct weston_plane {
|
struct weston_plane {
|
||||||
struct weston_compositor *compositor;
|
struct weston_compositor *compositor;
|
||||||
pixman_region32_t damage; /**< in global coords */
|
|
||||||
pixman_region32_t clip;
|
pixman_region32_t clip;
|
||||||
int32_t x, y;
|
int32_t x, y;
|
||||||
struct wl_list link;
|
struct wl_list link;
|
||||||
|
@ -708,8 +708,6 @@ drm_output_set_cursor(struct drm_output_state *output_state)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (!state->fb) {
|
if (!state->fb) {
|
||||||
pixman_region32_fini(&plane->base.damage);
|
|
||||||
pixman_region32_init(&plane->base.damage);
|
|
||||||
drmModeSetCursor(device->drm.fd, crtc->crtc_id, 0, 0, 0);
|
drmModeSetCursor(device->drm.fd, crtc->crtc_id, 0, 0, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -727,9 +725,6 @@ drm_output_set_cursor(struct drm_output_state *output_state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pixman_region32_fini(&plane->base.damage);
|
|
||||||
pixman_region32_init(&plane->base.damage);
|
|
||||||
|
|
||||||
if (drmModeMoveCursor(device->drm.fd, crtc->crtc_id,
|
if (drmModeMoveCursor(device->drm.fd, crtc->crtc_id,
|
||||||
state->dest_x, state->dest_y)) {
|
state->dest_x, state->dest_y)) {
|
||||||
weston_log("failed to move cursor: %s\n", strerror(errno));
|
weston_log("failed to move cursor: %s\n", strerror(errno));
|
||||||
|
@ -149,6 +149,25 @@ weston_output_dirty_paint_nodes(struct weston_output *output)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
paint_node_damage_below(struct weston_paint_node *pnode)
|
||||||
|
{
|
||||||
|
struct weston_paint_node *lower_node;
|
||||||
|
|
||||||
|
if (!pnode->plane)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wl_list_for_each(lower_node, &pnode->z_order_link,
|
||||||
|
z_order_link) {
|
||||||
|
|
||||||
|
if (lower_node->plane != pnode->plane)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
pixman_region32_union(&lower_node->damage, &lower_node->damage,
|
||||||
|
&pnode->visible);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Paint nodes contain filter and transform information that needs to be
|
/* Paint nodes contain filter and transform information that needs to be
|
||||||
* up to date before assign_planes() is called. But there are also
|
* up to date before assign_planes() is called. But there are also
|
||||||
* damage related bits that must be updated after assign_planes()
|
* damage related bits that must be updated after assign_planes()
|
||||||
@ -181,8 +200,20 @@ paint_node_update_early(struct weston_paint_node *pnode)
|
|||||||
static void
|
static void
|
||||||
paint_node_update_late(struct weston_paint_node *pnode)
|
paint_node_update_late(struct weston_paint_node *pnode)
|
||||||
{
|
{
|
||||||
|
bool vis_dirty = pnode->status & PAINT_NODE_VISIBILITY_DIRTY;
|
||||||
bool plane_dirty = pnode->status & PAINT_NODE_PLANE_DIRTY;
|
bool plane_dirty = pnode->status & PAINT_NODE_PLANE_DIRTY;
|
||||||
|
|
||||||
|
/* The geoemtry may be shrinking, so we shouldn't just
|
||||||
|
* add the old visible region to our damage region, because
|
||||||
|
* our damage region shouldn't contain anything outside of
|
||||||
|
* our geometry.
|
||||||
|
*
|
||||||
|
* On a plane change, we need to damage below now before
|
||||||
|
* we update visibility.
|
||||||
|
*/
|
||||||
|
if (vis_dirty || plane_dirty)
|
||||||
|
paint_node_damage_below(pnode);
|
||||||
|
|
||||||
/* Even if our geometry didn't change, our visible region may
|
/* Even if our geometry didn't change, our visible region may
|
||||||
* have been updated by some other node changing. Keep the
|
* have been updated by some other node changing. Keep the
|
||||||
* visible region up to date.
|
* visible region up to date.
|
||||||
@ -191,6 +222,15 @@ paint_node_update_late(struct weston_paint_node *pnode)
|
|||||||
&pnode->view->visible,
|
&pnode->view->visible,
|
||||||
&pnode->output->region);
|
&pnode->output->region);
|
||||||
|
|
||||||
|
/* If our visible region was dirty, we should damage the entire
|
||||||
|
* new visible region to ensure a redraw of our content.
|
||||||
|
*
|
||||||
|
* If we chanaged planes, we need full visible region damage
|
||||||
|
* on the new plane now that visibility is updated.
|
||||||
|
*/
|
||||||
|
if (pnode->plane && (vis_dirty || plane_dirty))
|
||||||
|
pixman_region32_copy(&pnode->damage, &pnode->visible);
|
||||||
|
|
||||||
if (plane_dirty) {
|
if (plane_dirty) {
|
||||||
assert(pnode->plane_next);
|
assert(pnode->plane_next);
|
||||||
|
|
||||||
@ -247,6 +287,7 @@ weston_paint_node_create(struct weston_surface *surface,
|
|||||||
|
|
||||||
wl_list_init(&pnode->z_order_link);
|
wl_list_init(&pnode->z_order_link);
|
||||||
|
|
||||||
|
pixman_region32_init(&pnode->damage);
|
||||||
pixman_region32_init(&pnode->visible);
|
pixman_region32_init(&pnode->visible);
|
||||||
pixman_region32_copy(&pnode->visible, &view->visible);
|
pixman_region32_copy(&pnode->visible, &view->visible);
|
||||||
|
|
||||||
@ -262,12 +303,16 @@ static void
|
|||||||
weston_paint_node_destroy(struct weston_paint_node *pnode)
|
weston_paint_node_destroy(struct weston_paint_node *pnode)
|
||||||
{
|
{
|
||||||
assert(pnode->view->surface == pnode->surface);
|
assert(pnode->view->surface == pnode->surface);
|
||||||
|
|
||||||
|
paint_node_damage_below(pnode);
|
||||||
|
|
||||||
wl_list_remove(&pnode->surface_link);
|
wl_list_remove(&pnode->surface_link);
|
||||||
wl_list_remove(&pnode->view_link);
|
wl_list_remove(&pnode->view_link);
|
||||||
wl_list_remove(&pnode->output_link);
|
wl_list_remove(&pnode->output_link);
|
||||||
wl_list_remove(&pnode->z_order_link);
|
wl_list_remove(&pnode->z_order_link);
|
||||||
assert(pnode->surf_xform_valid || !pnode->surf_xform.transform);
|
assert(pnode->surf_xform_valid || !pnode->surf_xform.transform);
|
||||||
weston_surface_color_transform_fini(&pnode->surf_xform);
|
weston_surface_color_transform_fini(&pnode->surf_xform);
|
||||||
|
pixman_region32_fini(&pnode->damage);
|
||||||
pixman_region32_fini(&pnode->visible);
|
pixman_region32_fini(&pnode->visible);
|
||||||
free(pnode);
|
free(pnode);
|
||||||
}
|
}
|
||||||
@ -1004,46 +1049,15 @@ weston_paint_node_move_to_plane(struct weston_paint_node *pnode,
|
|||||||
if (pnode->plane == plane)
|
if (pnode->plane == plane)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
weston_view_damage_below(pnode->view);
|
|
||||||
pnode->plane_next = plane;
|
pnode->plane_next = plane;
|
||||||
weston_surface_damage(pnode->view->surface);
|
|
||||||
|
|
||||||
pnode->status |= PAINT_NODE_PLANE_DIRTY |
|
pnode->status |= PAINT_NODE_PLANE_DIRTY |
|
||||||
PAINT_NODE_VISIBILITY_DIRTY;
|
PAINT_NODE_VISIBILITY_DIRTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Inflict damage on the plane where the view is visible.
|
|
||||||
*
|
|
||||||
* \param view The view that causes the damage.
|
|
||||||
*
|
|
||||||
* If the view is currently on a plane (including the primary plane),
|
|
||||||
* take the view's boundingbox, subtract all the opaque views that cover it,
|
|
||||||
* and add the remaining region as damage to the plane. This corresponds
|
|
||||||
* to the damage inflicted to the plane if this view disappeared.
|
|
||||||
*
|
|
||||||
* A repaint is scheduled for this view.
|
|
||||||
*
|
|
||||||
* The region of all opaque views covering this view is stored in
|
|
||||||
* weston_view::clip and updated by output_update_visibility() during
|
|
||||||
* weston_output_repaint(). Specifically, that region matches the
|
|
||||||
* scenegraph as it was last painted.
|
|
||||||
*/
|
|
||||||
WL_EXPORT void
|
WL_EXPORT void
|
||||||
weston_view_damage_below(struct weston_view *view)
|
weston_view_damage_below(struct weston_view *view)
|
||||||
{
|
{
|
||||||
struct weston_paint_node *pnode;
|
|
||||||
pixman_region32_t damage;
|
|
||||||
|
|
||||||
pixman_region32_init(&damage);
|
|
||||||
pixman_region32_subtract(&damage, &view->transform.boundingbox,
|
|
||||||
&view->clip);
|
|
||||||
wl_list_for_each(pnode, &view->paint_node_list, view_link) {
|
|
||||||
assert(pnode->plane);
|
|
||||||
|
|
||||||
pixman_region32_union(&pnode->plane->damage,
|
|
||||||
&pnode->plane->damage, &damage);
|
|
||||||
}
|
|
||||||
pixman_region32_fini(&damage);
|
|
||||||
weston_view_schedule_repaint(view);
|
weston_view_schedule_repaint(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2930,39 +2944,10 @@ weston_output_damage(struct weston_output *output)
|
|||||||
weston_output_schedule_repaint(output);
|
weston_output_schedule_repaint(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: note that we don't flush any damage when the core wants us to
|
|
||||||
* do so as it will sometimes ask for a flush not necessarily at the
|
|
||||||
* right time.
|
|
||||||
*
|
|
||||||
* A (more) proper way is to handle correctly damage whenever there's
|
|
||||||
* compositor side damage. See the comment for weston_surface_damage().
|
|
||||||
*/
|
|
||||||
static bool
|
|
||||||
buffer_can_be_accessed_BANDAID_XXX(struct weston_buffer_reference buffer_ref)
|
|
||||||
{
|
|
||||||
return buffer_ref.type == BUFFER_MAY_BE_ACCESSED;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
surface_flush_damage(struct weston_surface *surface, struct weston_output *output)
|
paint_node_add_damage(struct weston_paint_node *node)
|
||||||
{
|
{
|
||||||
struct weston_buffer *buffer = surface->buffer_ref.buffer;
|
struct weston_view *view = node->view;
|
||||||
|
|
||||||
if (buffer->type == WESTON_BUFFER_SHM &&
|
|
||||||
buffer_can_be_accessed_BANDAID_XXX(surface->buffer_ref))
|
|
||||||
surface->compositor->renderer->flush_damage(surface, buffer);
|
|
||||||
|
|
||||||
if (pixman_region32_not_empty(&surface->damage))
|
|
||||||
TL_POINT(surface->compositor, "core_flush_damage",
|
|
||||||
TLP_SURFACE(surface), TLP_OUTPUT(output), TLP_END);
|
|
||||||
|
|
||||||
pixman_region32_clear(&surface->damage);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
view_accumulate_damage(struct weston_view *view)
|
|
||||||
{
|
|
||||||
struct weston_paint_node *pnode;
|
|
||||||
pixman_region32_t damage;
|
pixman_region32_t damage;
|
||||||
|
|
||||||
assert(!view->transform.dirty);
|
assert(!view->transform.dirty);
|
||||||
@ -2980,15 +2965,48 @@ view_accumulate_damage(struct weston_view *view)
|
|||||||
view->geometry.pos_offset.y);
|
view->geometry.pos_offset.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
pixman_region32_intersect(&damage, &damage, &view->visible);
|
pixman_region32_intersect(&damage, &damage, &node->visible);
|
||||||
|
pixman_region32_union(&node->damage, &node->damage, &damage);
|
||||||
wl_list_for_each(pnode, &view->paint_node_list, view_link) {
|
|
||||||
pixman_region32_union(&pnode->plane->damage,
|
|
||||||
&pnode->plane->damage, &damage);
|
|
||||||
}
|
|
||||||
pixman_region32_fini(&damage);
|
pixman_region32_fini(&damage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FIXME: note that we don't flush any damage when the core wants us to
|
||||||
|
* do so as it will sometimes ask for a flush not necessarily at the
|
||||||
|
* right time.
|
||||||
|
*
|
||||||
|
* A (more) proper way is to handle correctly damage whenever there's
|
||||||
|
* compositor side damage. See the comment for weston_surface_damage().
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
buffer_can_be_accessed_BANDAID_XXX(struct weston_buffer_reference buffer_ref)
|
||||||
|
{
|
||||||
|
return buffer_ref.type == BUFFER_MAY_BE_ACCESSED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
surface_flush_damage(struct weston_surface *surface, struct weston_output *output)
|
||||||
|
{
|
||||||
|
struct weston_buffer *buffer = surface->buffer_ref.buffer;
|
||||||
|
struct weston_paint_node *node;
|
||||||
|
|
||||||
|
if (buffer->type == WESTON_BUFFER_SHM &&
|
||||||
|
buffer_can_be_accessed_BANDAID_XXX(surface->buffer_ref))
|
||||||
|
surface->compositor->renderer->flush_damage(surface, buffer);
|
||||||
|
|
||||||
|
if (!pixman_region32_not_empty(&surface->damage))
|
||||||
|
return;
|
||||||
|
|
||||||
|
TL_POINT(surface->compositor, "core_flush_damage",
|
||||||
|
TLP_SURFACE(surface), TLP_OUTPUT(output), TLP_END);
|
||||||
|
|
||||||
|
wl_list_for_each(node, &surface->paint_node_list, surface_link) {
|
||||||
|
assert(node->surface == surface);
|
||||||
|
|
||||||
|
paint_node_add_damage(node);
|
||||||
|
}
|
||||||
|
pixman_region32_clear(&surface->damage);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
view_update_clip_and_visible(struct weston_view *view,
|
view_update_clip_and_visible(struct weston_view *view,
|
||||||
pixman_region32_t *opaque)
|
pixman_region32_t *opaque)
|
||||||
@ -3035,20 +3053,8 @@ output_update_visibility(struct weston_output *output)
|
|||||||
static void
|
static void
|
||||||
output_accumulate_damage(struct weston_output *output)
|
output_accumulate_damage(struct weston_output *output)
|
||||||
{
|
{
|
||||||
struct weston_compositor *ec = output->compositor;
|
|
||||||
struct weston_plane *plane;
|
|
||||||
struct weston_paint_node *pnode;
|
struct weston_paint_node *pnode;
|
||||||
|
|
||||||
wl_list_for_each(plane, &ec->plane_list, link) {
|
|
||||||
wl_list_for_each(pnode, &output->paint_node_z_order_list,
|
|
||||||
z_order_link) {
|
|
||||||
if (pnode->plane != plane)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
view_accumulate_damage(pnode->view);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
wl_list_for_each(pnode, &output->paint_node_z_order_list,
|
wl_list_for_each(pnode, &output->paint_node_z_order_list,
|
||||||
z_order_link) {
|
z_order_link) {
|
||||||
pnode->surface->touched = false;
|
pnode->surface->touched = false;
|
||||||
@ -3133,15 +3139,6 @@ view_list_add_subsurface_view(struct weston_compositor *compositor,
|
|||||||
|
|
||||||
assert(view);
|
assert(view);
|
||||||
|
|
||||||
/* We used to mysteriously depend on the view->plane transition
|
|
||||||
* from NULL to primary to generate damage when a view that was
|
|
||||||
* unmapped became remapped. Forcing damage here is a little
|
|
||||||
* more obvious.
|
|
||||||
*
|
|
||||||
* We can't use weston_view_damage_below() because the clip region
|
|
||||||
* isn't correct until after we render, and by then it's too late.
|
|
||||||
*/
|
|
||||||
weston_surface_damage(view->surface);
|
|
||||||
weston_view_update_transform(view);
|
weston_view_update_transform(view);
|
||||||
view->is_mapped = true;
|
view->is_mapped = true;
|
||||||
|
|
||||||
@ -3272,6 +3269,28 @@ weston_output_take_feedback_list(struct weston_output *output,
|
|||||||
wl_list_init(&surface->feedback_list);
|
wl_list_init(&surface->feedback_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
weston_output_flush_damage_for_plane(struct weston_output *output,
|
||||||
|
struct weston_plane *plane,
|
||||||
|
pixman_region32_t *damage)
|
||||||
|
{
|
||||||
|
struct weston_paint_node *pnode;
|
||||||
|
bool changed = false;
|
||||||
|
|
||||||
|
wl_list_for_each(pnode, &output->paint_node_z_order_list,
|
||||||
|
z_order_link) {
|
||||||
|
if (pnode->plane != plane)
|
||||||
|
continue;
|
||||||
|
changed = true;
|
||||||
|
|
||||||
|
pixman_region32_union(damage, damage, &pnode->damage);
|
||||||
|
pixman_region32_clear(&pnode->damage);
|
||||||
|
}
|
||||||
|
pixman_region32_intersect(damage, damage, &output->region);
|
||||||
|
pixman_region32_subtract(damage, damage, &plane->clip);
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
weston_output_repaint(struct weston_output *output)
|
weston_output_repaint(struct weston_output *output)
|
||||||
{
|
{
|
||||||
@ -3353,10 +3372,9 @@ weston_output_repaint(struct weston_output *output)
|
|||||||
output_accumulate_damage(output);
|
output_accumulate_damage(output);
|
||||||
|
|
||||||
pixman_region32_init(&output_damage);
|
pixman_region32_init(&output_damage);
|
||||||
pixman_region32_intersect(&output_damage,
|
|
||||||
&ec->primary_plane.damage, &output->region);
|
weston_output_flush_damage_for_plane(output, &ec->primary_plane,
|
||||||
pixman_region32_subtract(&output_damage,
|
&output_damage);
|
||||||
&output_damage, &ec->primary_plane.clip);
|
|
||||||
|
|
||||||
if (output->full_repaint_needed) {
|
if (output->full_repaint_needed) {
|
||||||
pixman_region32_copy(&output_damage, &output->region);
|
pixman_region32_copy(&output_damage, &output->region);
|
||||||
@ -3365,9 +3383,6 @@ weston_output_repaint(struct weston_output *output)
|
|||||||
|
|
||||||
r = output->repaint(output, &output_damage);
|
r = output->repaint(output, &output_damage);
|
||||||
|
|
||||||
pixman_region32_subtract(&ec->primary_plane.damage,
|
|
||||||
&ec->primary_plane.damage, &output_damage);
|
|
||||||
|
|
||||||
pixman_region32_fini(&output_damage);
|
pixman_region32_fini(&output_damage);
|
||||||
|
|
||||||
output->repaint_needed = false;
|
output->repaint_needed = false;
|
||||||
@ -5668,7 +5683,6 @@ idle_handler(void *data)
|
|||||||
WL_EXPORT void
|
WL_EXPORT void
|
||||||
weston_plane_init(struct weston_plane *plane, struct weston_compositor *ec)
|
weston_plane_init(struct weston_plane *plane, struct weston_compositor *ec)
|
||||||
{
|
{
|
||||||
pixman_region32_init(&plane->damage);
|
|
||||||
pixman_region32_init(&plane->clip);
|
pixman_region32_init(&plane->clip);
|
||||||
plane->x = 0;
|
plane->x = 0;
|
||||||
plane->y = 0;
|
plane->y = 0;
|
||||||
@ -5684,7 +5698,6 @@ weston_plane_release(struct weston_plane *plane)
|
|||||||
{
|
{
|
||||||
struct weston_output *output;
|
struct weston_output *output;
|
||||||
|
|
||||||
pixman_region32_fini(&plane->damage);
|
|
||||||
pixman_region32_fini(&plane->clip);
|
pixman_region32_fini(&plane->clip);
|
||||||
|
|
||||||
wl_list_for_each(output, &plane->compositor->output_list, link) {
|
wl_list_for_each(output, &plane->compositor->output_list, link) {
|
||||||
|
@ -547,6 +547,7 @@ struct weston_paint_node {
|
|||||||
struct wl_list z_order_link;
|
struct wl_list z_order_link;
|
||||||
|
|
||||||
pixman_region32_t visible;
|
pixman_region32_t visible;
|
||||||
|
pixman_region32_t damage; /* In global coordinates */
|
||||||
struct weston_plane *plane;
|
struct weston_plane *plane;
|
||||||
struct weston_plane *plane_next;
|
struct weston_plane *plane_next;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user