aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoremersion <contact@emersion.fr>2018-01-19 11:20:27 +0100
committeremersion <contact@emersion.fr>2018-01-19 11:20:27 +0100
commit443bd4cd898b86cf1056416f58e30cb451d1fcd4 (patch)
tree81dc07f933698eab584102a5c234e5574c05209b
parent977a401fa112ad198d7920e5aa1b0e94eb6f05b2 (diff)
output: fullscreen surface damage tracking
-rw-r--r--include/wlr/types/wlr_output.h2
-rw-r--r--types/wlr_output.c40
2 files changed, 34 insertions, 8 deletions
diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h
index f6a5ac84..bc05dfbf 100644
--- a/include/wlr/types/wlr_output.h
+++ b/include/wlr/types/wlr_output.h
@@ -53,7 +53,7 @@ struct wlr_output {
enum wl_output_subpixel subpixel;
enum wl_output_transform transform;
- pixman_region32_t damage;
+ pixman_region32_t damage, previous_damage;
float transform_matrix[16];
// Note: some backends may have zero modes
diff --git a/types/wlr_output.c b/types/wlr_output.c
index af35f2b5..dfcba906 100644
--- a/types/wlr_output.c
+++ b/types/wlr_output.c
@@ -280,6 +280,7 @@ void wlr_output_init(struct wlr_output *output, struct wlr_backend *backend,
wl_signal_init(&output->events.transform);
wl_signal_init(&output->events.destroy);
pixman_region32_init(&output->damage);
+ pixman_region32_init(&output->previous_damage);
output->display_destroy.notify = handle_display_destroy;
wl_display_add_destroy_listener(display, &output->display_destroy);
@@ -293,7 +294,6 @@ void wlr_output_destroy(struct wlr_output *output) {
wl_list_remove(&output->display_destroy.link);
wlr_output_destroy_global(output);
wlr_output_set_fullscreen_surface(output, NULL);
- pixman_region32_fini(&output->damage);
wl_signal_emit(&output->events.destroy, output);
@@ -308,6 +308,9 @@ void wlr_output_destroy(struct wlr_output *output) {
wlr_output_cursor_destroy(cursor);
}
+ pixman_region32_fini(&output->damage);
+ pixman_region32_fini(&output->previous_damage);
+
if (output->impl && output->impl->destroy) {
output->impl->destroy(output);
} else {
@@ -347,12 +350,15 @@ static void output_fullscreen_surface_get_box(struct wlr_output *output,
}
static void output_fullscreen_surface_render(struct wlr_output *output,
- struct wlr_surface *surface, const struct timespec *when) {
+ struct wlr_surface *surface, const struct timespec *when,
+ pixman_region32_t *damage) {
glViewport(0, 0, output->width, output->height);
- glClearColor(0, 0, 0, 0);
- glClear(GL_COLOR_BUFFER_BIT);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
if (!wlr_surface_has_buffer(surface)) {
+ glClearColor(0, 0, 0, 0);
+ glClear(GL_COLOR_BUFFER_BIT);
return;
}
@@ -369,7 +375,17 @@ static void output_fullscreen_surface_render(struct wlr_output *output,
wlr_matrix_mul(&translate, &scale, &matrix);
wlr_matrix_mul(&output->transform_matrix, &matrix, &matrix);
- wlr_render_with_matrix(surface->renderer, surface->texture, &matrix);
+ int nrects;
+ pixman_box32_t *rects = pixman_region32_rectangles(damage, &nrects);
+ glEnable(GL_SCISSOR_TEST);
+ for (int i = 0; i < nrects; ++i) {
+ glScissor(rects[i].x1, output->height - rects[i].y2,
+ rects[i].x2 - rects[i].x1, rects[i].y2 - rects[i].y1);
+ glClearColor(0, 0, 0, 0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ wlr_render_with_matrix(surface->renderer, surface->texture, &matrix);
+ }
+ glDisable(GL_SCISSOR_TEST);
wlr_surface_send_frame_done(surface, when);
}
@@ -434,8 +450,17 @@ void wlr_output_swap_buffers(struct wlr_output *output) {
clock_gettime(CLOCK_MONOTONIC, &now);
if (output->fullscreen_surface != NULL) {
- output_fullscreen_surface_render(output, output->fullscreen_surface,
- &now);
+ pixman_region32_t damage;
+ pixman_region32_init(&damage);
+ pixman_region32_copy(&damage, &output->damage);
+ pixman_region32_union(&damage, &damage, &output->previous_damage);
+
+ if (pixman_region32_not_empty(&damage)) {
+ output_fullscreen_surface_render(output, output->fullscreen_surface,
+ &now, &damage);
+ }
+
+ pixman_region32_fini(&damage);
}
struct wlr_output_cursor *cursor;
@@ -448,6 +473,7 @@ void wlr_output_swap_buffers(struct wlr_output *output) {
}
output->impl->swap_buffers(output);
+ pixman_region32_copy(&output->previous_damage, &output->damage);
pixman_region32_clear(&output->damage);
}