state->sx = 0;
state->sy = 0;
- pixman_region32_init(&state->damage);
+ pixman_region32_init(&state->damage_surface);
+ pixman_region32_init(&state->damage_buffer);
pixman_region32_init(&state->opaque);
region_init_infinite(&state->input);
pixman_region32_fini(&state->input);
pixman_region32_fini(&state->opaque);
- pixman_region32_fini(&state->damage);
+ pixman_region32_fini(&state->damage_surface);
+ pixman_region32_fini(&state->damage_buffer);
if (state->buffer)
wl_list_remove(&state->buffer_destroy_listener.link);
if (width <= 0 || height <= 0)
return;
- pixman_region32_union_rect(&surface->pending.damage,
- &surface->pending.damage,
+ pixman_region32_union_rect(&surface->pending.damage_surface,
+ &surface->pending.damage_surface,
+ x, y, width, height);
+}
+
+static void
+surface_damage_buffer(struct wl_client *client,
+ struct wl_resource *resource,
+ int32_t x, int32_t y, int32_t width, int32_t height)
+{
+ struct weston_surface *surface = wl_resource_get_user_data(resource);
+
+ if (width <= 0 || height <= 0)
+ return;
+
+ pixman_region32_union_rect(&surface->pending.damage_buffer,
+ &surface->pending.damage_buffer,
x, y, width, height);
}
weston_matrix_scale(matrix, vp->buffer.scale, vp->buffer.scale, 1);
}
+/* Translate pending damage in buffer co-ordinates to surface
+ * co-ordinates and union it with a pixman_region32_t.
+ * This should only be called after the buffer is attached.
+ */
+static void
+apply_damage_buffer(pixman_region32_t *dest,
+ struct weston_surface *surface,
+ struct weston_surface_state *state)
+{
+ struct weston_buffer *buffer = surface->buffer_ref.buffer;
+
+ /* wl_surface.damage_buffer needs to be clipped to the buffer,
+ * translated into surface co-ordinates and unioned with
+ * any other surface damage.
+ * None of this makes sense if there is no buffer though.
+ */
+ if (buffer && pixman_region32_not_empty(&state->damage_buffer)) {
+ pixman_region32_t buffer_damage;
+
+ pixman_region32_intersect_rect(&state->damage_buffer,
+ &state->damage_buffer,
+ 0, 0, buffer->width,
+ buffer->height);
+ pixman_region32_init(&buffer_damage);
+ weston_matrix_transform_region(&buffer_damage,
+ &surface->buffer_to_surface_matrix,
+ &state->damage_buffer);
+ pixman_region32_union(dest, dest, &buffer_damage);
+ pixman_region32_fini(&buffer_damage);
+ }
+ /* We should clear this on commit even if there was no buffer */
+ pixman_region32_clear(&state->damage_buffer);
+}
+
static void
weston_surface_commit_state(struct weston_surface *surface,
struct weston_surface_state *state)
state->newly_attached = 0;
state->buffer_viewport.changed = 0;
- /* wl_surface.damage */
+ /* wl_surface.damage and wl_surface.damage_buffer */
if (weston_timeline_enabled_ &&
- pixman_region32_not_empty(&state->damage))
+ (pixman_region32_not_empty(&state->damage_surface) ||
+ pixman_region32_not_empty(&state->damage_buffer)))
TL_POINT("core_commit_damage", TLP_SURFACE(surface), TLP_END);
+
pixman_region32_union(&surface->damage, &surface->damage,
- &state->damage);
+ &state->damage_surface);
+
+ apply_damage_buffer(&surface->damage, surface, state);
+
pixman_region32_intersect_rect(&surface->damage, &surface->damage,
0, 0, surface->width, surface->height);
- pixman_region32_clear(&state->damage);
+ pixman_region32_clear(&state->damage_surface);
/* wl_surface.set_opaque_region */
pixman_region32_init(&opaque);
surface_set_input_region,
surface_commit,
surface_set_buffer_transform,
- surface_set_buffer_scale
+ surface_set_buffer_scale,
+ surface_damage_buffer
};
static void
* translated to correspond to the new surface coordinate system
* origin.
*/
- pixman_region32_translate(&sub->cached.damage,
+ pixman_region32_translate(&sub->cached.damage_surface,
-surface->pending.sx, -surface->pending.sy);
- pixman_region32_union(&sub->cached.damage, &sub->cached.damage,
- &surface->pending.damage);
- pixman_region32_clear(&surface->pending.damage);
+ pixman_region32_union(&sub->cached.damage_surface,
+ &sub->cached.damage_surface,
+ &surface->pending.damage_surface);
+ pixman_region32_clear(&surface->pending.damage_surface);
if (surface->pending.newly_attached) {
sub->cached.newly_attached = 1;
sub->cached.sx += surface->pending.sx;
sub->cached.sy += surface->pending.sy;
+ apply_damage_buffer(&sub->cached.damage_surface, surface, &surface->pending);
+
sub->cached.buffer_viewport.changed |=
surface->pending.buffer_viewport.changed;
sub->cached.buffer_viewport.buffer =
ec->output_id_pool = 0;
ec->repaint_msec = DEFAULT_REPAINT_WINDOW;
- if (!wl_global_create(ec->wl_display, &wl_compositor_interface, 3,
+ if (!wl_global_create(ec->wl_display, &wl_compositor_interface, 4,
ec, compositor_bind))
goto fail;