wlr_surface: add wlr_surface_get_effective_damage
This calculates and returns the effective damage of the surface in surface coordinates, including the client damage (in buffer coordinates), and damage induced by resize or move events.
This commit is contained in:
parent
84ecfb546b
commit
3e0a0f3c3a
|
@ -229,4 +229,12 @@ struct wlr_surface *wlr_surface_from_resource(struct wl_resource *resource);
|
||||||
void wlr_surface_for_each_surface(struct wlr_surface *surface,
|
void wlr_surface_for_each_surface(struct wlr_surface *surface,
|
||||||
wlr_surface_iterator_func_t iterator, void *user_data);
|
wlr_surface_iterator_func_t iterator, void *user_data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the effective damage to the surface in terms of surface local
|
||||||
|
* coordinates. This includes damage induced by resizing and moving the
|
||||||
|
* surface. The damage is not expected to be bounded by the surface itself.
|
||||||
|
*/
|
||||||
|
void wlr_surface_get_effective_damage(struct wlr_surface *surface,
|
||||||
|
pixman_region32_t *damage);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -696,13 +696,10 @@ static void damage_from_surface(struct wlr_surface *surface, int sx, int sy,
|
||||||
int center_x = box.x + box.width/2;
|
int center_x = box.x + box.width/2;
|
||||||
int center_y = box.y + box.height/2;
|
int center_y = box.y + box.height/2;
|
||||||
|
|
||||||
enum wl_output_transform transform = surface->current.transform;
|
|
||||||
|
|
||||||
pixman_region32_t damage;
|
pixman_region32_t damage;
|
||||||
pixman_region32_init(&damage);
|
pixman_region32_init(&damage);
|
||||||
pixman_region32_copy(&damage, &surface->buffer_damage);
|
wlr_surface_get_effective_damage(surface, &damage);
|
||||||
wlr_region_transform(&damage, &damage, transform,
|
|
||||||
surface->current.buffer_width, surface->current.buffer_height);
|
|
||||||
wlr_region_scale(&damage, &damage,
|
wlr_region_scale(&damage, &damage,
|
||||||
wlr_output->scale / (float)surface->current.scale);
|
wlr_output->scale / (float)surface->current.scale);
|
||||||
if (ceil(wlr_output->scale) > surface->current.scale) {
|
if (ceil(wlr_output->scale) > surface->current.scale) {
|
||||||
|
|
|
@ -173,39 +173,29 @@ static void surface_update_damage(pixman_region32_t *buffer_damage,
|
||||||
struct wlr_surface_state *current, struct wlr_surface_state *pending) {
|
struct wlr_surface_state *current, struct wlr_surface_state *pending) {
|
||||||
pixman_region32_clear(buffer_damage);
|
pixman_region32_clear(buffer_damage);
|
||||||
|
|
||||||
|
if (pending->width != current->width ||
|
||||||
|
pending->height != current->height) {
|
||||||
|
// Damage the whole buffer on resize
|
||||||
|
pixman_region32_union_rect(buffer_damage, buffer_damage, 0, 0,
|
||||||
|
pending->buffer_width, pending->buffer_height);
|
||||||
|
} else {
|
||||||
|
// Copy over surface damage + buffer damage
|
||||||
pixman_region32_t surface_damage;
|
pixman_region32_t surface_damage;
|
||||||
pixman_region32_init(&surface_damage);
|
pixman_region32_init(&surface_damage);
|
||||||
|
|
||||||
if (pending->width != current->width ||
|
|
||||||
pending->height != current->height ||
|
|
||||||
pending->dx != 0 || pending->dy != 0) {
|
|
||||||
// Damage the whole surface on resize or move
|
|
||||||
int prev_x = -pending->dx;
|
|
||||||
int prev_y = -pending->dy;
|
|
||||||
if ((current->transform & WL_OUTPUT_TRANSFORM_90) != 0) {
|
|
||||||
int tmp = prev_x;
|
|
||||||
prev_x = prev_y;
|
|
||||||
prev_y = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
pixman_region32_union_rect(&surface_damage, &surface_damage, prev_x,
|
|
||||||
prev_y, current->width, current->height);
|
|
||||||
pixman_region32_union_rect(&surface_damage, &surface_damage, 0, 0,
|
|
||||||
pending->width, pending->height);
|
|
||||||
} else {
|
|
||||||
// Copy over surface damage + buffer damage
|
|
||||||
pixman_region32_union(buffer_damage, buffer_damage,
|
pixman_region32_union(buffer_damage, buffer_damage,
|
||||||
&pending->buffer_damage);
|
&pending->buffer_damage);
|
||||||
pixman_region32_copy(&surface_damage, &pending->surface_damage);
|
pixman_region32_copy(&surface_damage, &pending->surface_damage);
|
||||||
}
|
|
||||||
|
|
||||||
wlr_region_transform(&surface_damage, &surface_damage,
|
wlr_region_transform(&surface_damage, &surface_damage,
|
||||||
wlr_output_transform_invert(pending->transform),
|
wlr_output_transform_invert(pending->transform),
|
||||||
pending->width, pending->height);
|
pending->width, pending->height);
|
||||||
wlr_region_scale(&surface_damage, &surface_damage, pending->scale);
|
wlr_region_scale(&surface_damage, &surface_damage, pending->scale);
|
||||||
|
|
||||||
pixman_region32_union(buffer_damage, buffer_damage, &surface_damage);
|
pixman_region32_union(buffer_damage, buffer_damage, &surface_damage);
|
||||||
pixman_region32_fini(&surface_damage);
|
pixman_region32_fini(&surface_damage);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void surface_state_copy(struct wlr_surface_state *state,
|
static void surface_state_copy(struct wlr_surface_state *state,
|
||||||
struct wlr_surface_state *next) {
|
struct wlr_surface_state *next) {
|
||||||
|
@ -1030,3 +1020,34 @@ void wlr_surface_get_extends(struct wlr_surface *surface, struct wlr_box *box) {
|
||||||
box->width = acc.max_x - acc.min_x;
|
box->width = acc.max_x - acc.min_x;
|
||||||
box->height = acc.max_y - acc.min_y;
|
box->height = acc.max_y - acc.min_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wlr_surface_get_effective_damage(struct wlr_surface *surface,
|
||||||
|
pixman_region32_t *damage) {
|
||||||
|
pixman_region32_clear(damage);
|
||||||
|
|
||||||
|
// Transform and copy the buffer damage in terms of surface coordinates.
|
||||||
|
wlr_region_transform(damage, &surface->buffer_damage,
|
||||||
|
surface->current.transform, surface->current.buffer_width,
|
||||||
|
surface->current.buffer_height);
|
||||||
|
|
||||||
|
// On resize, damage the previous bounds of the surface. The current bounds
|
||||||
|
// have already been damaged in surface_update_damage.
|
||||||
|
if (surface->previous.width > surface->current.width ||
|
||||||
|
surface->previous.height > surface->current.height) {
|
||||||
|
pixman_region32_union_rect(damage, damage, 0, 0,
|
||||||
|
surface->previous.width, surface->previous.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
// On move, damage where the surface was with its old dimensions.
|
||||||
|
if (surface->current.dx != 0 || surface->current.dy != 0) {
|
||||||
|
int prev_x = -surface->current.dx;
|
||||||
|
int prev_y = -surface->current.dy;
|
||||||
|
if ((surface->previous.transform & WL_OUTPUT_TRANSFORM_90) != 0) {
|
||||||
|
int temp = prev_x;
|
||||||
|
prev_x = prev_y;
|
||||||
|
prev_y = temp;
|
||||||
|
}
|
||||||
|
pixman_region32_union_rect(damage, damage, prev_x, prev_y,
|
||||||
|
surface->previous.width, surface->previous.height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue