From 3c0d672ebd9e1776f106ca7d963654893585a5ca Mon Sep 17 00:00:00 2001 From: emersion Date: Thu, 21 Jun 2018 22:39:26 +0100 Subject: surface: make pending and current embedded structs --- rootston/cursor.c | 8 ++++---- rootston/desktop.c | 6 +++--- rootston/output.c | 30 +++++++++++++++--------------- rootston/wl_shell.c | 8 ++++---- rootston/xwayland.c | 8 ++++---- 5 files changed, 30 insertions(+), 30 deletions(-) (limited to 'rootston') diff --git a/rootston/cursor.c b/rootston/cursor.c index 1cf81704..904af67f 100644 --- a/rootston/cursor.c +++ b/rootston/cursor.c @@ -200,8 +200,8 @@ static void roots_cursor_update_position( case ROOTS_CURSOR_ROTATE: view = roots_seat_get_focus(seat); if (view != NULL) { - int ox = view->x + view->wlr_surface->current->width/2, - oy = view->y + view->wlr_surface->current->height/2; + int ox = view->x + view->wlr_surface->current.width/2, + oy = view->y + view->wlr_surface->current.height/2; int ux = cursor->offs_x - ox, uy = cursor->offs_y - oy; int vx = cursor->cursor->x - ox, @@ -239,12 +239,12 @@ static void roots_cursor_press_button(struct roots_cursor *cursor, break; case BTN_RIGHT: edges = 0; - if (sx < view->wlr_surface->current->width/2) { + if (sx < view->wlr_surface->current.width/2) { edges |= WLR_EDGE_LEFT; } else { edges |= WLR_EDGE_RIGHT; } - if (sy < view->wlr_surface->current->height/2) { + if (sy < view->wlr_surface->current.height/2) { edges |= WLR_EDGE_TOP; } else { edges |= WLR_EDGE_BOTTOM; diff --git a/rootston/desktop.c b/rootston/desktop.c index d670c33b..4b5a5c9a 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -69,8 +69,8 @@ enum roots_deco_part view_get_deco_part(struct roots_view *view, double sx, return ROOTS_DECO_PART_NONE; } - int sw = view->wlr_surface->current->width; - int sh = view->wlr_surface->current->height; + int sw = view->wlr_surface->current.width; + int sh = view->wlr_surface->current.height; int bw = view->border_width; int titlebar_h = view->titlebar_height; @@ -558,7 +558,7 @@ static bool view_at(struct roots_view *view, double lx, double ly, double view_sx = lx - view->x; double view_sy = ly - view->y; - struct wlr_surface_state *state = view->wlr_surface->current; + struct wlr_surface_state *state = &view->wlr_surface->current; struct wlr_box box = { .x = 0, .y = 0, .width = state->width, .height = state->height, diff --git a/rootston/output.c b/rootston/output.c index 8154816d..aecb0d76 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -44,8 +44,8 @@ struct layout_data { static void get_layout_position(struct layout_data *data, double *lx, double *ly, const struct wlr_surface *surface, int sx, int sy) { double _sx = sx, _sy = sy; - rotate_child_position(&_sx, &_sy, surface->current->width, - surface->current->height, data->width, data->height, data->rotation); + rotate_child_position(&_sx, &_sy, surface->current.width, + surface->current.height, data->width, data->height, data->rotation); *lx = data->x + _sx; *ly = data->y + _sy; } @@ -55,8 +55,8 @@ static void surface_for_each_surface(struct wlr_surface *surface, wlr_surface_iterator_func_t iterator, void *user_data) { layout_data->x = lx; layout_data->y = ly; - layout_data->width = surface->current->width; - layout_data->height = surface->current->height; + layout_data->width = surface->current.width; + layout_data->height = surface->current.height; layout_data->rotation = rotation; wlr_surface_for_each_surface(surface, iterator, user_data); @@ -67,8 +67,8 @@ static void view_for_each_surface(struct roots_view *view, void *user_data) { layout_data->x = view->x; layout_data->y = view->y; - layout_data->width = view->wlr_surface->current->width; - layout_data->height = view->wlr_surface->current->height; + layout_data->width = view->wlr_surface->current.width; + layout_data->height = view->wlr_surface->current.height; layout_data->rotation = view->rotation; switch (view->type) { @@ -149,13 +149,13 @@ static bool surface_intersect_output(struct wlr_surface *surface, if (box != NULL) { box->x = ox * wlr_output->scale; box->y = oy * wlr_output->scale; - box->width = surface->current->width * wlr_output->scale; - box->height = surface->current->height * wlr_output->scale; + box->width = surface->current.width * wlr_output->scale; + box->height = surface->current.height * wlr_output->scale; } struct wlr_box layout_box = { .x = lx, .y = ly, - .width = surface->current->width, .height = surface->current->height, + .width = surface->current.width, .height = surface->current.height, }; wlr_box_rotated_bounds(&layout_box, rotation, &layout_box); return wlr_output_layout_intersects(output_layout, wlr_output, &layout_box); @@ -223,7 +223,7 @@ static void render_surface(struct wlr_surface *surface, int sx, int sy, float matrix[9]; enum wl_output_transform transform = - wlr_output_transform_invert(surface->current->transform); + wlr_output_transform_invert(surface->current.transform); wlr_matrix_project_box(matrix, &box, transform, rotation, output->wlr_output->transform_matrix); @@ -247,8 +247,8 @@ static void get_decoration_box(struct roots_view *view, double sx = deco_box.x - view->x; double sy = deco_box.y - view->y; rotate_child_position(&sx, &sy, deco_box.width, deco_box.height, - view->wlr_surface->current->width, - view->wlr_surface->current->height, view->rotation); + view->wlr_surface->current.width, + view->wlr_surface->current.height, view->rotation); double x = sx + view->x; double y = sy + view->y; @@ -694,13 +694,13 @@ static void damage_from_surface(struct wlr_surface *surface, int sx, int sy, pixman_region32_t damage; pixman_region32_init(&damage); - pixman_region32_copy(&damage, &surface->current->surface_damage); + pixman_region32_copy(&damage, &surface->current.surface_damage); wlr_region_scale(&damage, &damage, wlr_output->scale); - if (ceil(wlr_output->scale) > surface->current->scale) { + if (ceil(wlr_output->scale) > surface->current.scale) { // When scaling up a surface, it'll become blurry so we need to // expand the damage region wlr_region_expand(&damage, &damage, - ceil(wlr_output->scale) - surface->current->scale); + ceil(wlr_output->scale) - surface->current.scale); } pixman_region32_translate(&damage, box.x, box.y); wlr_region_rotated_bounds(&damage, &damage, rotation, center_x, center_y); diff --git a/rootston/wl_shell.c b/rootston/wl_shell.c index d58f030a..02160773 100644 --- a/rootston/wl_shell.c +++ b/rootston/wl_shell.c @@ -158,8 +158,8 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) { view_apply_damage(view); - int width = wlr_surface->current->width; - int height = wlr_surface->current->height; + int width = wlr_surface->current.width; + int height = wlr_surface->current.height; view_update_size(view, width, height); double x = view->x; @@ -236,8 +236,8 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { return; } view->type = ROOTS_WL_SHELL_VIEW; - view->width = surface->surface->current->width; - view->height = surface->surface->current->height; + view->width = surface->surface->current.width; + view->height = surface->surface->current.height; view->wl_shell_surface = surface; view->roots_wl_shell_surface = roots_surface; diff --git a/rootston/xwayland.c b/rootston/xwayland.c index b7dbab54..d0b80821 100644 --- a/rootston/xwayland.c +++ b/rootston/xwayland.c @@ -206,8 +206,8 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) { view_apply_damage(view); - int width = wlr_surface->current->width; - int height = wlr_surface->current->height; + int width = wlr_surface->current.width; + int height = wlr_surface->current.height; view_update_size(view, width, height); double x = view->x; @@ -233,8 +233,8 @@ static void handle_map(struct wl_listener *listener, void *data) { view->x = surface->x; view->y = surface->y; - view->width = surface->surface->current->width; - view->height = surface->surface->current->height; + view->width = surface->surface->current.width; + view->height = surface->surface->current.height; roots_surface->surface_commit.notify = handle_surface_commit; wl_signal_add(&surface->surface->events.commit, -- cgit v1.2.3 From 233bfe2f4f7859fa293a33a5b4022eaae7eb6cb3 Mon Sep 17 00:00:00 2001 From: emersion Date: Mon, 25 Jun 2018 23:35:02 +0100 Subject: surface: do not monkey-patch state damage --- include/wlr/types/wlr_surface.h | 1 + rootston/output.c | 8 +- types/wlr_surface.c | 170 +++++++++++++++++++--------------------- 3 files changed, 89 insertions(+), 90 deletions(-) (limited to 'rootston') diff --git a/include/wlr/types/wlr_surface.h b/include/wlr/types/wlr_surface.h index ad1ee6f6..fdfc716d 100644 --- a/include/wlr/types/wlr_surface.h +++ b/include/wlr/types/wlr_surface.h @@ -33,6 +33,7 @@ struct wlr_surface_state { int width, height; // in surface-local coordinates int buffer_width, buffer_height; int sx, sy; // in surface-local coordinates + pixman_region32_t damage; // in buffer-local coordinates struct wl_listener buffer_destroy_listener; }; diff --git a/rootston/output.c b/rootston/output.c index aecb0d76..6abd60ae 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -146,6 +146,9 @@ static bool surface_intersect_output(struct wlr_surface *surface, double ox = lx, oy = ly; wlr_output_layout_output_coords(output_layout, wlr_output, &ox, &oy); + ox += surface->current.sx; + oy += surface->current.sy; + if (box != NULL) { box->x = ox * wlr_output->scale; box->y = oy * wlr_output->scale; @@ -694,8 +697,9 @@ static void damage_from_surface(struct wlr_surface *surface, int sx, int sy, pixman_region32_t damage; pixman_region32_init(&damage); - pixman_region32_copy(&damage, &surface->current.surface_damage); - wlr_region_scale(&damage, &damage, wlr_output->scale); + pixman_region32_copy(&damage, &surface->current.damage); + wlr_region_scale(&damage, &damage, + wlr_output->scale / (float)surface->current.scale); if (ceil(wlr_output->scale) > surface->current.scale) { // When scaling up a surface, it'll become blurry so we need to // expand the damage region diff --git a/types/wlr_surface.c b/types/wlr_surface.c index 964fe964..e6a67208 100644 --- a/types/wlr_surface.c +++ b/types/wlr_surface.c @@ -139,49 +139,49 @@ static void surface_set_input_region(struct wl_client *client, } } -static bool surface_update_size(struct wlr_surface *surface, - struct wlr_surface_state *state) { - if (!state->buffer) { - pixman_region32_union_rect(&state->surface_damage, - &state->surface_damage, 0, 0, state->width, state->height); - state->height = 0; - state->width = 0; - return true; - } - - int scale = state->scale; - enum wl_output_transform transform = state->transform; - - wlr_buffer_get_resource_size(state->buffer, surface->renderer, - &state->buffer_width, &state->buffer_height); +static void surface_state_update_size(struct wlr_surface_state *state) { + int width = state->buffer_width / state->scale; + int height = state->buffer_height / state->scale; - int width = state->buffer_width / scale; - int height = state->buffer_height / scale; - - if (transform == WL_OUTPUT_TRANSFORM_90 || - transform == WL_OUTPUT_TRANSFORM_270 || - transform == WL_OUTPUT_TRANSFORM_FLIPPED_90 || - transform == WL_OUTPUT_TRANSFORM_FLIPPED_270) { + if ((state->transform & WL_OUTPUT_TRANSFORM_90) != 0) { int tmp = width; width = height; height = tmp; } - bool update_damage = false; - if (width != state->width || height != state->height) { - // Damage the whole surface on resize - // This isn't in the spec, but Weston does it and QT expects it - pixman_region32_union_rect(&state->surface_damage, - &state->surface_damage, 0, 0, state->width, state->height); - pixman_region32_union_rect(&state->surface_damage, - &state->surface_damage, 0, 0, width, height); - update_damage = true; - } - state->width = width; state->height = height; +} + +static void surface_state_update_damage(struct wlr_surface_state *state, + struct wlr_surface_state *next) { + pixman_region32_clear(&state->damage); + + if (next->buffer_width != state->buffer_width || + next->buffer_height != state->buffer_height) { + // Damage the whole surface on resize + pixman_region32_union_rect(&state->damage, + &state->damage, state->sx * state->scale, state->sy * state->scale, + state->buffer_width, state->buffer_height); + pixman_region32_union_rect(&state->damage, + &state->damage, next->sx * next->scale, next->sy * next->scale, + next->buffer_width, next->buffer_height); + } else { + // Copy over surface damage + buffer damage + pixman_region32_union(&state->damage, &state->damage, + &next->buffer_damage); + + pixman_region32_t surface_damage; + pixman_region32_init(&surface_damage); + pixman_region32_copy(&surface_damage, &next->surface_damage); + wlr_region_transform(&surface_damage, &surface_damage, next->transform, + next->buffer_width, next->buffer_height); + wlr_region_scale(&surface_damage, &surface_damage, next->scale); + pixman_region32_union(&state->damage, &state->damage, &surface_damage); + pixman_region32_fini(&surface_damage); - return update_damage; + // TODO: handle sx, sy + } } /** @@ -189,16 +189,49 @@ static bool surface_update_size(struct wlr_surface *surface, */ static void surface_move_state(struct wlr_surface *surface, struct wlr_surface_state *next, struct wlr_surface_state *state) { - bool update_damage = false; - bool update_size = false; + // Commit next state + + if ((next->committed & WLR_SURFACE_STATE_BUFFER)) { + wlr_buffer_get_resource_size(next->buffer, surface->renderer, + &next->buffer_width, &next->buffer_height); + } + + surface_state_update_size(next); + + next->sx += next->dx; + next->sy += next->dy; + + pixman_region32_intersect_rect(&next->surface_damage, + &next->surface_damage, 0, 0, next->width, next->height); + + pixman_region32_intersect_rect(&next->buffer_damage, + &next->buffer_damage, 0, 0, next->buffer_width, + next->buffer_height); + + pixman_region32_intersect_rect(&next->opaque, &next->opaque, + 0, 0, next->width, next->height); + + pixman_region32_intersect_rect(&next->input, &next->input, + 0, 0, next->width, next->height); + + // Compute new state + + surface_state_update_damage(state, next); + + state->width = next->width; + state->height = next->height; + state->buffer_width = next->buffer_width; + state->buffer_height = next->buffer_height; + state->sx = next->sx; + state->sy = next->sy; + + // Move state from next one, clear next state if ((next->committed & WLR_SURFACE_STATE_SCALE)) { state->scale = next->scale; - update_size = true; } if ((next->committed & WLR_SURFACE_STATE_TRANSFORM)) { state->transform = next->transform; - update_size = true; } if ((next->committed & WLR_SURFACE_STATE_BUFFER)) { surface_state_set_buffer(state, next->buffer); @@ -206,64 +239,25 @@ static void surface_move_state(struct wlr_surface *surface, state->dx = next->dx; state->dy = next->dy; next->dx = next->dy = 0; - state->sx += state->dx; - state->sy += state->dy; - update_size = true; } else { state->dx = state->dy = 0; } - if (update_size) { - update_damage = surface_update_size(surface, state); - } if ((next->committed & WLR_SURFACE_STATE_SURFACE_DAMAGE)) { - pixman_region32_intersect_rect(&next->surface_damage, - &next->surface_damage, 0, 0, state->width, state->height); - pixman_region32_union(&state->surface_damage, &state->surface_damage, - &next->surface_damage); + pixman_region32_copy(&state->surface_damage, &next->surface_damage); pixman_region32_clear(&next->surface_damage); - update_damage = true; + } else { + pixman_region32_clear(&state->surface_damage); } if ((next->committed & WLR_SURFACE_STATE_BUFFER_DAMAGE)) { - pixman_region32_intersect_rect(&next->buffer_damage, - &next->buffer_damage, 0, 0, state->buffer_width, - state->buffer_height); - pixman_region32_union(&state->buffer_damage, &state->buffer_damage, - &next->buffer_damage); + pixman_region32_copy(&state->buffer_damage, &next->buffer_damage); pixman_region32_clear(&next->buffer_damage); - update_damage = true; - } - if (update_damage) { - pixman_region32_t buffer_damage, surface_damage; - pixman_region32_init(&buffer_damage); - pixman_region32_init(&surface_damage); - - // Surface to buffer damage - pixman_region32_copy(&buffer_damage, &state->surface_damage); - wlr_region_transform(&buffer_damage, &buffer_damage, - wlr_output_transform_invert(state->transform), - state->width, state->height); - wlr_region_scale(&buffer_damage, &buffer_damage, state->scale); - - // Buffer to surface damage - pixman_region32_copy(&surface_damage, &state->buffer_damage); - wlr_region_transform(&surface_damage, &surface_damage, state->transform, - state->buffer_width, state->buffer_height); - wlr_region_scale(&surface_damage, &surface_damage, 1.0f/state->scale); - - pixman_region32_union(&state->buffer_damage, &state->buffer_damage, - &buffer_damage); - pixman_region32_union(&state->surface_damage, &state->surface_damage, - &surface_damage); - - pixman_region32_fini(&buffer_damage); - pixman_region32_fini(&surface_damage); + } else { + pixman_region32_clear(&state->buffer_damage); } if ((next->committed & WLR_SURFACE_STATE_OPAQUE_REGION)) { - // TODO: process buffer - pixman_region32_clear(&next->opaque); + pixman_region32_copy(&state->opaque, &next->opaque); } if ((next->committed & WLR_SURFACE_STATE_INPUT_REGION)) { - // TODO: process buffer pixman_region32_copy(&state->input, &next->input); } if ((next->committed & WLR_SURFACE_STATE_FRAME_CALLBACK_LIST)) { @@ -307,7 +301,8 @@ static void surface_apply_damage(struct wlr_surface *surface) { if (surface->buffer != NULL && surface->buffer->released) { pixman_region32_t damage; pixman_region32_init(&damage); - pixman_region32_copy(&damage, &surface->current.buffer_damage); + pixman_region32_copy(&damage, &surface->current.damage); + // TODO: translate sx, sy pixman_region32_intersect_rect(&damage, &damage, 0, 0, surface->current.buffer_width, surface->current.buffer_height); @@ -361,9 +356,6 @@ static void surface_commit_pending(struct wlr_surface *surface) { } wlr_signal_emit_safe(&surface->events.commit, surface); - - pixman_region32_clear(&surface->current.surface_damage); - pixman_region32_clear(&surface->current.buffer_damage); } static bool subsurface_is_synchronized(struct wlr_subsurface *subsurface) { @@ -500,6 +492,7 @@ static void surface_state_init(struct wlr_surface_state *state) { pixman_region32_init(&state->opaque); pixman_region32_init_rect(&state->input, INT32_MIN, INT32_MIN, UINT32_MAX, UINT32_MAX); + pixman_region32_init(&state->damage); } static void surface_state_finish(struct wlr_surface_state *state) { @@ -514,6 +507,7 @@ static void surface_state_finish(struct wlr_surface_state *state) { pixman_region32_fini(&state->buffer_damage); pixman_region32_fini(&state->opaque); pixman_region32_fini(&state->input); + pixman_region32_fini(&state->damage); } static void subsurface_destroy(struct wlr_subsurface *subsurface) { -- cgit v1.2.3 From 78555abba3fdd272f50dcb8b8bf3b7811ddd9fc5 Mon Sep 17 00:00:00 2001 From: emersion Date: Thu, 28 Jun 2018 23:49:40 +0100 Subject: surface: move position and scale out of wlr_surface_state --- include/wlr/types/wlr_surface.h | 17 +++- rootston/output.c | 11 ++- types/wlr_output.c | 4 +- types/wlr_surface.c | 180 +++++++++++++++++++++------------------- 4 files changed, 121 insertions(+), 91 deletions(-) (limited to 'rootston') diff --git a/include/wlr/types/wlr_surface.h b/include/wlr/types/wlr_surface.h index fdfc716d..a587e7bc 100644 --- a/include/wlr/types/wlr_surface.h +++ b/include/wlr/types/wlr_surface.h @@ -32,8 +32,6 @@ struct wlr_surface_state { int width, height; // in surface-local coordinates int buffer_width, buffer_height; - int sx, sy; // in surface-local coordinates - pixman_region32_t damage; // in buffer-local coordinates struct wl_listener buffer_destroy_listener; }; @@ -48,6 +46,21 @@ struct wlr_surface { * or something went wrong with uploading the buffer. */ struct wlr_buffer *buffer; + /** + * The buffer position, in surface-local units. + */ + int sx, sy; + /** + * The last commit's buffer damage, in buffer-local coordinates. This + * contains both the damage accumulated by the client via + * `wlr_surface_state.surface_damage` and `wlr_surface_state.buffer_damage`. + * If the buffer has changed its size or moved, the whole buffer is + * damaged. + * + * This region needs to be scaled and transformed into output coordinates, + * just like the buffer's texture. + */ + pixman_region32_t buffer_damage; /** * `current` contains the current, committed surface state. `pending` * accumulates state changes from the client between commits and shouldn't diff --git a/rootston/output.c b/rootston/output.c index 6abd60ae..fd7df99c 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -146,8 +146,8 @@ static bool surface_intersect_output(struct wlr_surface *surface, double ox = lx, oy = ly; wlr_output_layout_output_coords(output_layout, wlr_output, &ox, &oy); - ox += surface->current.sx; - oy += surface->current.sy; + ox += surface->sx; + oy += surface->sy; if (box != NULL) { box->x = ox * wlr_output->scale; @@ -695,9 +695,14 @@ static void damage_from_surface(struct wlr_surface *surface, int sx, int sy, int center_x = box.x + box.width/2; int center_y = box.y + box.height/2; + enum wl_output_transform transform = + wlr_output_transform_invert(surface->current.transform); + pixman_region32_t damage; pixman_region32_init(&damage); - pixman_region32_copy(&damage, &surface->current.damage); + pixman_region32_copy(&damage, &surface->buffer_damage); + wlr_region_transform(&damage, &damage, transform, + surface->current.buffer_width, surface->current.buffer_height); wlr_region_scale(&damage, &damage, wlr_output->scale / (float)surface->current.scale); if (ceil(wlr_output->scale) > surface->current.scale) { diff --git a/types/wlr_output.c b/types/wlr_output.c index 9659eb85..831f1086 100644 --- a/types/wlr_output.c +++ b/types/wlr_output.c @@ -405,8 +405,8 @@ static void output_cursor_get_box(struct wlr_output_cursor *cursor, box->height = cursor->height; if (cursor->surface != NULL) { - box->x += cursor->surface->current.sx * cursor->output->scale; - box->y += cursor->surface->current.sy * cursor->output->scale; + box->x += cursor->surface->sx * cursor->output->scale; + box->y += cursor->surface->sy * cursor->output->scale; } } diff --git a/types/wlr_surface.c b/types/wlr_surface.c index e6a67208..7611d492 100644 --- a/types/wlr_surface.c +++ b/types/wlr_surface.c @@ -139,93 +139,83 @@ static void surface_set_input_region(struct wl_client *client, } } -static void surface_state_update_size(struct wlr_surface_state *state) { +static void surface_state_finalize(struct wlr_surface *surface, + struct wlr_surface_state *state) { + if ((state->committed & WLR_SURFACE_STATE_BUFFER)) { + wlr_buffer_get_resource_size(state->buffer, surface->renderer, + &state->buffer_width, &state->buffer_height); + } + int width = state->buffer_width / state->scale; int height = state->buffer_height / state->scale; - if ((state->transform & WL_OUTPUT_TRANSFORM_90) != 0) { int tmp = width; width = height; height = tmp; } - state->width = width; state->height = height; + + pixman_region32_intersect_rect(&state->surface_damage, + &state->surface_damage, 0, 0, state->width, state->height); + + pixman_region32_intersect_rect(&state->buffer_damage, + &state->buffer_damage, 0, 0, state->buffer_width, + state->buffer_height); + + pixman_region32_intersect_rect(&state->opaque, &state->opaque, + 0, 0, state->width, state->height); + + pixman_region32_intersect_rect(&state->input, &state->input, + 0, 0, state->width, state->height); } -static void surface_state_update_damage(struct wlr_surface_state *state, - struct wlr_surface_state *next) { - pixman_region32_clear(&state->damage); - - if (next->buffer_width != state->buffer_width || - next->buffer_height != state->buffer_height) { - // Damage the whole surface on resize - pixman_region32_union_rect(&state->damage, - &state->damage, state->sx * state->scale, state->sy * state->scale, - state->buffer_width, state->buffer_height); - pixman_region32_union_rect(&state->damage, - &state->damage, next->sx * next->scale, next->sy * next->scale, - next->buffer_width, next->buffer_height); +static void surface_update_damage(pixman_region32_t *buffer_damage, + struct wlr_surface_state *previous, struct wlr_surface_state *current) { + pixman_region32_clear(buffer_damage); + + if (current->buffer_width != previous->buffer_width || + current->buffer_height != previous->buffer_height || + current->dx != 0 || current->dy != 0) { + // Damage the whole surface on resize or move + int prev_x = -current->dx; + int prev_y = -current->dy; + if ((previous->transform & WL_OUTPUT_TRANSFORM_90) != 0) { + int tmp = prev_x; + prev_x = prev_y; + prev_y = tmp; + } + + pixman_region32_union_rect(buffer_damage, buffer_damage, + prev_x * previous->scale, prev_y * previous->scale, + previous->buffer_width, previous->buffer_height); + pixman_region32_union_rect(buffer_damage, buffer_damage, 0, 0, + current->buffer_width, current->buffer_height); } else { // Copy over surface damage + buffer damage - pixman_region32_union(&state->damage, &state->damage, - &next->buffer_damage); + pixman_region32_union(buffer_damage, buffer_damage, + ¤t->buffer_damage); pixman_region32_t surface_damage; pixman_region32_init(&surface_damage); - pixman_region32_copy(&surface_damage, &next->surface_damage); - wlr_region_transform(&surface_damage, &surface_damage, next->transform, - next->buffer_width, next->buffer_height); - wlr_region_scale(&surface_damage, &surface_damage, next->scale); - pixman_region32_union(&state->damage, &state->damage, &surface_damage); + pixman_region32_copy(&surface_damage, ¤t->surface_damage); + wlr_region_transform(&surface_damage, &surface_damage, + current->transform, current->buffer_width, current->buffer_height); + wlr_region_scale(&surface_damage, &surface_damage, current->scale); + pixman_region32_union(buffer_damage, buffer_damage, &surface_damage); pixman_region32_fini(&surface_damage); - - // TODO: handle sx, sy } } /** * Append pending state to current state and clear pending state. */ -static void surface_move_state(struct wlr_surface *surface, - struct wlr_surface_state *next, struct wlr_surface_state *state) { - // Commit next state - - if ((next->committed & WLR_SURFACE_STATE_BUFFER)) { - wlr_buffer_get_resource_size(next->buffer, surface->renderer, - &next->buffer_width, &next->buffer_height); - } - - surface_state_update_size(next); - - next->sx += next->dx; - next->sy += next->dy; - - pixman_region32_intersect_rect(&next->surface_damage, - &next->surface_damage, 0, 0, next->width, next->height); - - pixman_region32_intersect_rect(&next->buffer_damage, - &next->buffer_damage, 0, 0, next->buffer_width, - next->buffer_height); - - pixman_region32_intersect_rect(&next->opaque, &next->opaque, - 0, 0, next->width, next->height); - - pixman_region32_intersect_rect(&next->input, &next->input, - 0, 0, next->width, next->height); - - // Compute new state - - surface_state_update_damage(state, next); - +static void surface_state_move(struct wlr_surface_state *state, + struct wlr_surface_state *next) { state->width = next->width; state->height = next->height; state->buffer_width = next->buffer_width; state->buffer_height = next->buffer_height; - state->sx = next->sx; - state->sy = next->sy; - - // Move state from next one, clear next state if ((next->committed & WLR_SURFACE_STATE_SCALE)) { state->scale = next->scale; @@ -276,10 +266,9 @@ static void surface_damage_subsurfaces(struct wlr_subsurface *subsurface) { // seems to work ok. See the comment on weston_surface_damage for more info // about a better approach. struct wlr_surface *surface = subsurface->surface; - pixman_region32_union_rect(&surface->current.surface_damage, - &surface->current.surface_damage, - 0, 0, surface->current.width, - surface->current.height); + pixman_region32_union_rect(&surface->buffer_damage, + &surface->buffer_damage, 0, 0, + surface->current.buffer_width, surface->current.buffer_height); subsurface->reordered = false; @@ -301,8 +290,19 @@ static void surface_apply_damage(struct wlr_surface *surface) { if (surface->buffer != NULL && surface->buffer->released) { pixman_region32_t damage; pixman_region32_init(&damage); - pixman_region32_copy(&damage, &surface->current.damage); - // TODO: translate sx, sy + pixman_region32_copy(&damage, &surface->current.buffer_damage); + + pixman_region32_t surface_damage; + pixman_region32_init(&surface_damage); + pixman_region32_copy(&surface_damage, &surface->current.surface_damage); + wlr_region_transform(&surface_damage, &surface_damage, + surface->current.transform, + surface->current.buffer_width, surface->current.buffer_height); + wlr_region_scale(&surface_damage, &surface_damage, + surface->current.scale); + pixman_region32_union(&damage, &damage, &surface_damage); + pixman_region32_fini(&surface_damage); + pixman_region32_intersect_rect(&damage, &damage, 0, 0, surface->current.buffer_width, surface->current.buffer_height); @@ -332,7 +332,14 @@ static void surface_apply_damage(struct wlr_surface *surface) { static void surface_commit_pending(struct wlr_surface *surface) { bool invalid_buffer = surface->pending.committed & WLR_SURFACE_STATE_BUFFER; - surface_move_state(surface, &surface->pending, &surface->current); + surface_state_finalize(surface, &surface->pending); + + surface->sx += surface->pending.dx; + surface->sy += surface->pending.dy; + surface_update_damage(&surface->buffer_damage, + &surface->current, &surface->pending); + + surface_state_move(&surface->current, &surface->pending); if (invalid_buffer) { surface_apply_damage(surface); @@ -385,7 +392,7 @@ static void subsurface_parent_commit(struct wlr_subsurface *subsurface, struct wlr_surface *surface = subsurface->surface; if (synchronized || subsurface->synchronized) { if (subsurface->has_cache) { - surface_move_state(surface, &subsurface->cached, &surface->pending); + surface_state_move(&surface->pending, &subsurface->cached); surface_commit_pending(surface); subsurface->has_cache = false; subsurface->cached.committed = 0; @@ -402,11 +409,11 @@ static void subsurface_commit(struct wlr_subsurface *subsurface) { struct wlr_surface *surface = subsurface->surface; if (subsurface_is_synchronized(subsurface)) { - surface_move_state(surface, &surface->pending, &subsurface->cached); + surface_state_move(&subsurface->cached, &surface->pending); subsurface->has_cache = true; } else { if (subsurface->has_cache) { - surface_move_state(surface, &subsurface->cached, &surface->pending); + surface_state_move(&surface->pending, &subsurface->cached); surface_commit_pending(surface); subsurface->has_cache = false; } else { @@ -492,7 +499,6 @@ static void surface_state_init(struct wlr_surface_state *state) { pixman_region32_init(&state->opaque); pixman_region32_init_rect(&state->input, INT32_MIN, INT32_MIN, UINT32_MAX, UINT32_MAX); - pixman_region32_init(&state->damage); } static void surface_state_finish(struct wlr_surface_state *state) { @@ -507,7 +513,6 @@ static void surface_state_finish(struct wlr_surface_state *state) { pixman_region32_fini(&state->buffer_damage); pixman_region32_fini(&state->opaque); pixman_region32_fini(&state->input); - pixman_region32_fini(&state->damage); } static void subsurface_destroy(struct wlr_subsurface *subsurface) { @@ -543,6 +548,7 @@ static void surface_handle_resource_destroy(struct wl_resource *resource) { wl_list_remove(&surface->renderer_destroy.link); surface_state_finish(&surface->pending); surface_state_finish(&surface->current); + pixman_region32_fini(&surface->buffer_damage); wlr_buffer_unref(surface->buffer); free(surface); } @@ -586,6 +592,7 @@ struct wlr_surface *wlr_surface_create(struct wl_client *client, wl_signal_init(&surface->events.new_subsurface); wl_list_init(&surface->subsurfaces); wl_list_init(&surface->subsurface_pending_list); + pixman_region32_init(&surface->buffer_damage); wl_signal_add(&renderer->events.destroy, &surface->renderer_destroy); surface->renderer_destroy.notify = surface_handle_renderer_destroy; @@ -773,23 +780,28 @@ static void subsurface_role_committed(struct wlr_surface *surface, void *data) { if (subsurface->current.x != subsurface->pending.x || subsurface->current.y != subsurface->pending.y) { // Subsurface has moved - int dx = subsurface->pending.x - subsurface->current.x; - int dy = subsurface->pending.y - subsurface->current.y; + int dx = subsurface->current.x - subsurface->pending.x; + int dy = subsurface->current.y - subsurface->pending.y; subsurface->current.x = subsurface->pending.x; subsurface->current.y = subsurface->pending.y; + if ((surface->current.transform & WL_OUTPUT_TRANSFORM_90) != 0) { + int tmp = dx; + dx = dy; + dy = tmp; + } + // TODO: take the previous size - pixman_region32_union_rect( - &subsurface->surface->pending.surface_damage, - &subsurface->surface->pending.surface_damage, dx, dy, - subsurface->surface->current.width, - subsurface->surface->current.height); - pixman_region32_union_rect( - &subsurface->surface->pending.surface_damage, - &subsurface->surface->pending.surface_damage, 0, 0, - subsurface->surface->pending.width, - subsurface->surface->pending.height); + pixman_region32_union_rect(&surface->buffer_damage, + &surface->buffer_damage, + dx * surface->current.scale, dy * surface->current.scale, + surface->current.width, + surface->current.height); + pixman_region32_union_rect(&surface->buffer_damage, + &surface->buffer_damage, 0, 0, + surface->pending.width, + surface->pending.height); } } -- cgit v1.2.3