diff options
author | emersion <contact@emersion.fr> | 2018-01-26 22:11:09 +0100 |
---|---|---|
committer | emersion <contact@emersion.fr> | 2018-01-26 22:11:09 +0100 |
commit | ece2c1e4e200192bde19a2590b5a31f244e09524 (patch) | |
tree | d8b2bb12b076bf73b70c21b2283ded34fedaee86 /rootston | |
parent | a98ece68d32031dbd81b0064fad659515fc09f76 (diff) |
Damage tracking for transformed outputs
Diffstat (limited to 'rootston')
-rw-r--r-- | rootston/output.c | 79 |
1 files changed, 47 insertions, 32 deletions
diff --git a/rootston/output.c b/rootston/output.c index 5f08edf1..c6341b6a 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -170,6 +170,39 @@ static bool surface_intersect_output(struct wlr_surface *surface, return wlr_output_layout_intersects(output_layout, wlr_output, &layout_box); } +static void output_get_transformed_size(struct wlr_output *wlr_output, + int *width, int *height) { + if (wlr_output->transform % 2 == 0) { + *width = wlr_output->width; + *height = wlr_output->height; + } else { + *width = wlr_output->height; + *height = wlr_output->width; + } +} + +static void scissor_output(struct roots_output *output, pixman_box32_t *rect) { + struct wlr_output *wlr_output = output->wlr_output; + + struct wlr_box box = { + .x = rect->x1, + .y = rect->y1, + .width = rect->x2 - rect->x1, + .height = rect->y2 - rect->y1, + }; + + int ow, oh; + output_get_transformed_size(output->wlr_output, &ow, &oh); + + // Scissor is in renderer coordinates, ie. upside down + enum wl_output_transform transform = wlr_output_transform_compose( + wlr_output_transform_invert(wlr_output->transform), + WL_OUTPUT_TRANSFORM_FLIPPED_180); + wlr_box_transform(&box, transform, ow, oh, &box); + + wlr_renderer_scissor(output->desktop->server->renderer, &box); +} + static void render_surface(struct wlr_surface *surface, double lx, double ly, float rotation, void *_data) { struct render_data *data = _data; @@ -187,7 +220,6 @@ static void render_surface(struct wlr_surface *surface, double lx, double ly, return; } - // TODO: output transform support pixman_region32_t damage; pixman_region32_init(&damage); pixman_region32_union_rect(&damage, &damage, box.x, box.y, @@ -205,16 +237,9 @@ static void render_surface(struct wlr_surface *surface, double lx, double ly, &output->wlr_output->transform_matrix); int nrects; - pixman_box32_t *rects = - pixman_region32_rectangles(&damage, &nrects); + pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects); for (int i = 0; i < nrects; ++i) { - struct wlr_box scissor = { - .x = rects[i].x1, - .y = output->wlr_output->height - rects[i].y2, - .width = rects[i].x2 - rects[i].x1, - .height = rects[i].y2 - rects[i].y1, - }; - wlr_renderer_scissor(output->desktop->server->renderer, &scissor); + scissor_output(output, &rects[i]); wlr_render_with_matrix(output->desktop->server->renderer, surface->texture, &matrix); } @@ -258,7 +283,6 @@ static void render_decorations(struct roots_view *view, struct wlr_box box; get_decoration_box(view, output, &box); - // TODO: output transform support pixman_region32_t damage; pixman_region32_init(&damage); pixman_region32_union_rect(&damage, &damage, box.x, box.y, @@ -278,13 +302,7 @@ static void render_decorations(struct roots_view *view, pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects); for (int i = 0; i < nrects; ++i) { - struct wlr_box scissor = { - .x = rects[i].x1, - .y = output->wlr_output->height - rects[i].y2, - .width = rects[i].x2 - rects[i].x1, - .height = rects[i].y2 - rects[i].y1, - }; - wlr_renderer_scissor(output->desktop->server->renderer, &scissor); + scissor_output(output, &rects[i]); wlr_render_colored_quad(output->desktop->server->renderer, &color, &matrix); } @@ -359,13 +377,15 @@ static void render_output(struct roots_output *output) { int buffer_age = -1; wlr_output_make_current(wlr_output, &buffer_age); + int width, height; + output_get_transformed_size(output->wlr_output, &width, &height); + // Check if we can use damage tracking pixman_region32_t damage; pixman_region32_init(&damage); if (buffer_age <= 0 || buffer_age - 1 > ROOTS_OUTPUT_PREVIOUS_DAMAGE_LEN) { // Buffer new or too old, damage the whole output - pixman_region32_union_rect(&damage, &damage, 0, 0, - wlr_output->width, wlr_output->height); + pixman_region32_union_rect(&damage, &damage, 0, 0, width, height); } else { pixman_region32_copy(&damage, &output->damage); @@ -376,8 +396,7 @@ static void render_output(struct roots_output *output) { pixman_region32_union(&damage, &damage, &output->previous_damage[j]); } } - pixman_region32_intersect_rect(&damage, &damage, 0, 0, - wlr_output->width, wlr_output->height); + pixman_region32_intersect_rect(&damage, &damage, 0, 0, width, height); if (!pixman_region32_not_empty(&damage) && !wlr_output->needs_swap) { // Output doesn't need swap and isn't damaged, skip rendering completely @@ -401,13 +420,7 @@ static void render_output(struct roots_output *output) { int nrects; pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects); for (int i = 0; i < nrects; ++i) { - struct wlr_box scissor = { - .x = rects[i].x1, - .y = wlr_output->height - rects[i].y2, - .width = rects[i].x2 - rects[i].x1, - .height = rects[i].y2 - rects[i].y1, - }; - wlr_renderer_scissor(output->desktop->server->renderer, &scissor); + scissor_output(output, &rects[i]); wlr_renderer_clear(output->desktop->server->renderer, clear_color[0], clear_color[1], clear_color[2], 1); } @@ -491,8 +504,11 @@ static void schedule_render(struct roots_output *output) { } static void output_damage_whole(struct roots_output *output) { - pixman_region32_union_rect(&output->damage, &output->damage, - 0, 0, output->wlr_output->width, output->wlr_output->height); + int width, height; + output_get_transformed_size(output->wlr_output, &width, &height); + + pixman_region32_union_rect(&output->damage, &output->damage, 0, 0, + width, height); schedule_render(output); } @@ -584,7 +600,6 @@ static void damage_from_surface(struct wlr_surface *surface, return; } - // TODO: output transform support pixman_region32_t damage; pixman_region32_init(&damage); pixman_region32_copy(&damage, &surface->current->surface_damage); |