Add hacky lazy damage tracking implementation

This commit is contained in:
buffet 2021-08-14 19:44:20 +00:00
parent c94804588e
commit cd5ce00f74
10 changed files with 108 additions and 17 deletions

View file

@ -30,6 +30,7 @@ The dependencies required are:
- [wlroots](https://github.com/swaywm/wlroots)
- lua or luajit
- pixman
- meson (build)
- ninja (build)
- git (build, optional)

View file

@ -25,6 +25,8 @@ struct kiwmi_layer {
struct wl_listener destroy;
struct wl_listener commit;
struct wl_listener map;
struct wl_listener unmap;
struct wlr_box geom;
};

View file

@ -23,6 +23,8 @@ struct kiwmi_output {
struct wl_list layers[4]; // struct kiwmi_layer_surface::link
struct wlr_box usable_area;
bool damaged;
struct {
struct wl_signal destroy;
struct wl_signal resize;

View file

@ -24,6 +24,8 @@ kiwmi_layer_destroy_notify(struct wl_listener *listener, void *UNUSED(data))
wl_list_remove(&layer->link);
wl_list_remove(&layer->destroy.link);
wl_list_remove(&layer->map.link);
wl_list_remove(&layer->unmap.link);
wlr_layer_surface_v1_close(layer->layer_surface);
@ -38,7 +40,12 @@ kiwmi_layer_commit_notify(struct wl_listener *listener, void *UNUSED(data))
struct kiwmi_layer *layer = wl_container_of(listener, layer, commit);
struct kiwmi_output *output = layer->output;
struct wlr_box old_geom = layer->geom;
arrange_layers(output);
bool layer_changed = layer->layer != layer->layer_surface->current.layer;
bool geom_changed = memcmp(&old_geom, &layer->geom, sizeof(old_geom)) != 0;
if (layer_changed) {
wl_list_remove(&layer->link);
@ -46,7 +53,25 @@ kiwmi_layer_commit_notify(struct wl_listener *listener, void *UNUSED(data))
wl_list_insert(&output->layers[layer->layer], &layer->link);
}
arrange_layers(output);
if (layer_changed || geom_changed) {
output->damaged = true;
}
}
static void
kiwmi_layer_map_notify(struct wl_listener *listener, void *UNUSED(data))
{
struct kiwmi_layer *layer = wl_container_of(listener, layer, map);
layer->output->damaged = true;
}
static void
kiwmi_layer_unmap_notify(struct wl_listener *listener, void *UNUSED(data))
{
struct kiwmi_layer *layer = wl_container_of(listener, layer, unmap);
layer->output->damaged = true;
}
static void
@ -390,6 +415,12 @@ layer_shell_new_surface_notify(struct wl_listener *listener, void *data)
layer->commit.notify = kiwmi_layer_commit_notify;
wl_signal_add(&layer_surface->surface->events.commit, &layer->commit);
layer->map.notify = kiwmi_layer_map_notify;
wl_signal_add(&layer_surface->events.map, &layer->map);
layer->unmap.notify = kiwmi_layer_unmap_notify;
wl_signal_add(&layer_surface->events.unmap, &layer->unmap);
wl_list_insert(&output->layers[layer->layer], &layer->link);
// Temporarily set the layer's current state to client_pending

View file

@ -31,29 +31,35 @@ static void
render_layer_surface(struct wlr_surface *surface, int x, int y, void *data)
{
struct kiwmi_render_data *rdata = data;
struct wlr_output *output = rdata->output;
struct wlr_output *wlr_output = rdata->output;
struct wlr_box *geom = rdata->data;
struct kiwmi_output *output = wlr_output->data;
struct wlr_texture *texture = wlr_surface_get_texture(surface);
if (!texture) {
return;
}
if (!output->damaged) {
wlr_surface_send_frame_done(surface, rdata->when);
return;
}
int ox = x + geom->x;
int oy = y + geom->y;
struct wlr_box box = {
.x = ox * output->scale,
.y = oy * output->scale,
.width = surface->current.width * output->scale,
.height = surface->current.height * output->scale,
.x = ox * wlr_output->scale,
.y = oy * wlr_output->scale,
.width = surface->current.width * wlr_output->scale,
.height = surface->current.height * wlr_output->scale,
};
float matrix[9];
enum wl_output_transform transform =
wlr_output_transform_invert(surface->current.transform);
wlr_matrix_project_box(
matrix, &box, transform, 0, output->transform_matrix);
matrix, &box, transform, 0, wlr_output->transform_matrix);
wlr_render_texture_with_matrix(rdata->renderer, texture, matrix, 1);
@ -77,28 +83,34 @@ render_surface(struct wlr_surface *surface, int sx, int sy, void *data)
{
struct kiwmi_render_data *rdata = data;
struct kiwmi_view *view = rdata->data;
struct wlr_output *output = rdata->output;
struct wlr_output *wlr_output = rdata->output;
struct kiwmi_output *output = wlr_output->data;
struct wlr_texture *texture = wlr_surface_get_texture(surface);
if (!texture) {
return;
}
if (!output->damaged) {
wlr_surface_send_frame_done(surface, rdata->when);
return;
}
int ox = rdata->output_lx + sx + view->x - view->geom.x;
int oy = rdata->output_ly + sy + view->y - view->geom.y;
struct wlr_box box = {
.x = ox * output->scale,
.y = oy * output->scale,
.width = surface->current.width * output->scale,
.height = surface->current.height * output->scale,
.x = ox * wlr_output->scale,
.y = oy * wlr_output->scale,
.width = surface->current.width * wlr_output->scale,
.height = surface->current.height * wlr_output->scale,
};
float matrix[9];
enum wl_output_transform transform =
wlr_output_transform_invert(surface->current.transform);
wlr_matrix_project_box(
matrix, &box, transform, 0, output->transform_matrix);
matrix, &box, transform, 0, wlr_output->transform_matrix);
wlr_render_texture_with_matrix(rdata->renderer, texture, matrix, 1);
@ -128,7 +140,9 @@ output_frame_notify(struct wl_listener *listener, void *data)
wlr_output_effective_resolution(wlr_output, &width, &height);
wlr_renderer_begin(renderer, width, height);
wlr_renderer_clear(renderer, desktop->bg_color);
if (output->damaged) {
wlr_renderer_clear(renderer, desktop->bg_color);
}
double output_lx = 0;
double output_ly = 0;
@ -154,9 +168,13 @@ output_frame_notify(struct wl_listener *listener, void *data)
rdata.data = view;
wl_signal_emit(&view->events.pre_render, &rdata);
view_for_each_surface(view, render_surface, &rdata);
wl_signal_emit(&view->events.post_render, &rdata);
if (output->damaged) {
wl_signal_emit(&view->events.pre_render, &rdata);
view_for_each_surface(view, render_surface, &rdata);
wl_signal_emit(&view->events.post_render, &rdata);
} else {
view_for_each_surface(view, render_surface, &rdata);
}
}
render_layer(&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &rdata);
@ -165,6 +183,8 @@ output_frame_notify(struct wl_listener *listener, void *data)
wlr_output_render_software_cursors(wlr_output, NULL);
wlr_renderer_end(renderer);
output->damaged = false;
wlr_output_commit(wlr_output);
}
@ -176,6 +196,7 @@ output_commit_notify(struct wl_listener *listener, void *data)
if (event->committed & WLR_OUTPUT_STATE_TRANSFORM) {
arrange_layers(output);
output->damaged = true;
wl_signal_emit(&output->events.resize, output);
}
@ -204,6 +225,7 @@ output_mode_notify(struct wl_listener *listener, void *UNUSED(data))
struct kiwmi_output *output = wl_container_of(listener, output, mode);
arrange_layers(output);
output->damaged = true;
wl_signal_emit(&output->events.resize, output);
}
@ -222,6 +244,8 @@ output_create(struct wlr_output *wlr_output, struct kiwmi_desktop *desktop)
output->usable_area.width = wlr_output->width;
output->usable_area.height = wlr_output->height;
output->damaged = true;
output->frame.notify = output_frame_notify;
wl_signal_add(&wlr_output->events.frame, &output->frame);

View file

@ -26,6 +26,11 @@ xdg_surface_map_notify(struct wl_listener *listener, void *UNUSED(data))
struct kiwmi_view *view = wl_container_of(listener, view, map);
view->mapped = true;
struct kiwmi_output *output;
wl_list_for_each (output, &view->desktop->outputs, link) {
output->damaged = true;
}
wl_signal_emit(&view->desktop->events.view_map, view);
}
@ -37,6 +42,11 @@ xdg_surface_unmap_notify(struct wl_listener *listener, void *UNUSED(data))
if (view->mapped) {
view->mapped = false;
struct kiwmi_output *output;
wl_list_for_each (output, &view->desktop->outputs, link) {
output->damaged = true;
}
wl_signal_emit(&view->events.unmap, view);
}
}
@ -46,6 +56,13 @@ xdg_surface_commit_notify(struct wl_listener *listener, void *UNUSED(data))
{
struct kiwmi_view *view = wl_container_of(listener, view, commit);
if (pixman_region32_not_empty(&view->wlr_surface->buffer_damage)) {
struct kiwmi_output *output;
wl_list_for_each (output, &view->desktop->outputs, link) {
output->damaged = true;
}
}
wlr_xdg_surface_get_geometry(view->xdg_surface, &view->geom);
}

View file

@ -126,6 +126,10 @@ process_cursor_motion(struct kiwmi_server *server, uint32_t time)
} else {
wlr_seat_pointer_clear_focus(seat);
}
wl_list_for_each (output, &server->desktop.outputs, link) {
output->damaged = true;
}
}
static void

View file

@ -111,6 +111,14 @@ request_set_cursor_notify(struct wl_listener *listener, void *data)
return;
}
struct kiwmi_input *input = seat->input;
struct kiwmi_server *server = wl_container_of(input, server, input);
struct kiwmi_output *output;
wl_list_for_each (output, &server->desktop.outputs, link) {
output->damaged = true;
}
wlr_cursor_set_surface(
cursor->cursor, event->surface, event->hotspot_x, event->hotspot_y);
}

View file

@ -25,6 +25,7 @@ kiwmi_sources = files(
kiwmi_deps = [
lua,
pixman,
protocols_server,
wayland_server,
wlroots,

View file

@ -18,6 +18,7 @@ add_project_arguments(
git = find_program('git', required: false)
lua = dependency(get_option('lua-pkg'))
pixman = dependency('pixman-1')
wayland_client = dependency('wayland-client')
wayland_protocols = dependency('wayland-protocols')
wayland_scanner = dependency('wayland-scanner')