output: fullscreen surface damage tracking

This commit is contained in:
emersion 2018-01-19 11:20:27 +01:00
parent 977a401fa1
commit 443bd4cd89
No known key found for this signature in database
GPG key ID: 0FDE7BE0E88F5E48
2 changed files with 34 additions and 8 deletions

View file

@ -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

View file

@ -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);
}