Add hacky lazy damage tracking implementation
This commit is contained in:
parent
c94804588e
commit
cd5ce00f74
10 changed files with 108 additions and 17 deletions
|
@ -30,6 +30,7 @@ The dependencies required are:
|
||||||
|
|
||||||
- [wlroots](https://github.com/swaywm/wlroots)
|
- [wlroots](https://github.com/swaywm/wlroots)
|
||||||
- lua or luajit
|
- lua or luajit
|
||||||
|
- pixman
|
||||||
- meson (build)
|
- meson (build)
|
||||||
- ninja (build)
|
- ninja (build)
|
||||||
- git (build, optional)
|
- git (build, optional)
|
||||||
|
|
|
@ -25,6 +25,8 @@ struct kiwmi_layer {
|
||||||
|
|
||||||
struct wl_listener destroy;
|
struct wl_listener destroy;
|
||||||
struct wl_listener commit;
|
struct wl_listener commit;
|
||||||
|
struct wl_listener map;
|
||||||
|
struct wl_listener unmap;
|
||||||
|
|
||||||
struct wlr_box geom;
|
struct wlr_box geom;
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,6 +23,8 @@ struct kiwmi_output {
|
||||||
struct wl_list layers[4]; // struct kiwmi_layer_surface::link
|
struct wl_list layers[4]; // struct kiwmi_layer_surface::link
|
||||||
struct wlr_box usable_area;
|
struct wlr_box usable_area;
|
||||||
|
|
||||||
|
bool damaged;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct wl_signal destroy;
|
struct wl_signal destroy;
|
||||||
struct wl_signal resize;
|
struct wl_signal resize;
|
||||||
|
|
|
@ -24,6 +24,8 @@ kiwmi_layer_destroy_notify(struct wl_listener *listener, void *UNUSED(data))
|
||||||
|
|
||||||
wl_list_remove(&layer->link);
|
wl_list_remove(&layer->link);
|
||||||
wl_list_remove(&layer->destroy.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);
|
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_layer *layer = wl_container_of(listener, layer, commit);
|
||||||
struct kiwmi_output *output = layer->output;
|
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 layer_changed = layer->layer != layer->layer_surface->current.layer;
|
||||||
|
bool geom_changed = memcmp(&old_geom, &layer->geom, sizeof(old_geom)) != 0;
|
||||||
|
|
||||||
if (layer_changed) {
|
if (layer_changed) {
|
||||||
wl_list_remove(&layer->link);
|
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);
|
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
|
static void
|
||||||
|
@ -390,6 +415,12 @@ layer_shell_new_surface_notify(struct wl_listener *listener, void *data)
|
||||||
layer->commit.notify = kiwmi_layer_commit_notify;
|
layer->commit.notify = kiwmi_layer_commit_notify;
|
||||||
wl_signal_add(&layer_surface->surface->events.commit, &layer->commit);
|
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);
|
wl_list_insert(&output->layers[layer->layer], &layer->link);
|
||||||
|
|
||||||
// Temporarily set the layer's current state to client_pending
|
// Temporarily set the layer's current state to client_pending
|
||||||
|
|
|
@ -31,29 +31,35 @@ static void
|
||||||
render_layer_surface(struct wlr_surface *surface, int x, int y, void *data)
|
render_layer_surface(struct wlr_surface *surface, int x, int y, void *data)
|
||||||
{
|
{
|
||||||
struct kiwmi_render_data *rdata = 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 wlr_box *geom = rdata->data;
|
||||||
|
struct kiwmi_output *output = wlr_output->data;
|
||||||
|
|
||||||
struct wlr_texture *texture = wlr_surface_get_texture(surface);
|
struct wlr_texture *texture = wlr_surface_get_texture(surface);
|
||||||
if (!texture) {
|
if (!texture) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!output->damaged) {
|
||||||
|
wlr_surface_send_frame_done(surface, rdata->when);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int ox = x + geom->x;
|
int ox = x + geom->x;
|
||||||
int oy = y + geom->y;
|
int oy = y + geom->y;
|
||||||
|
|
||||||
struct wlr_box box = {
|
struct wlr_box box = {
|
||||||
.x = ox * output->scale,
|
.x = ox * wlr_output->scale,
|
||||||
.y = oy * output->scale,
|
.y = oy * wlr_output->scale,
|
||||||
.width = surface->current.width * output->scale,
|
.width = surface->current.width * wlr_output->scale,
|
||||||
.height = surface->current.height * output->scale,
|
.height = surface->current.height * wlr_output->scale,
|
||||||
};
|
};
|
||||||
|
|
||||||
float matrix[9];
|
float matrix[9];
|
||||||
enum wl_output_transform transform =
|
enum wl_output_transform transform =
|
||||||
wlr_output_transform_invert(surface->current.transform);
|
wlr_output_transform_invert(surface->current.transform);
|
||||||
wlr_matrix_project_box(
|
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);
|
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_render_data *rdata = data;
|
||||||
struct kiwmi_view *view = 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);
|
struct wlr_texture *texture = wlr_surface_get_texture(surface);
|
||||||
if (!texture) {
|
if (!texture) {
|
||||||
return;
|
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 ox = rdata->output_lx + sx + view->x - view->geom.x;
|
||||||
int oy = rdata->output_ly + sy + view->y - view->geom.y;
|
int oy = rdata->output_ly + sy + view->y - view->geom.y;
|
||||||
|
|
||||||
struct wlr_box box = {
|
struct wlr_box box = {
|
||||||
.x = ox * output->scale,
|
.x = ox * wlr_output->scale,
|
||||||
.y = oy * output->scale,
|
.y = oy * wlr_output->scale,
|
||||||
.width = surface->current.width * output->scale,
|
.width = surface->current.width * wlr_output->scale,
|
||||||
.height = surface->current.height * output->scale,
|
.height = surface->current.height * wlr_output->scale,
|
||||||
};
|
};
|
||||||
|
|
||||||
float matrix[9];
|
float matrix[9];
|
||||||
enum wl_output_transform transform =
|
enum wl_output_transform transform =
|
||||||
wlr_output_transform_invert(surface->current.transform);
|
wlr_output_transform_invert(surface->current.transform);
|
||||||
wlr_matrix_project_box(
|
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);
|
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_output_effective_resolution(wlr_output, &width, &height);
|
||||||
|
|
||||||
wlr_renderer_begin(renderer, 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_lx = 0;
|
||||||
double output_ly = 0;
|
double output_ly = 0;
|
||||||
|
@ -154,9 +168,13 @@ output_frame_notify(struct wl_listener *listener, void *data)
|
||||||
|
|
||||||
rdata.data = view;
|
rdata.data = view;
|
||||||
|
|
||||||
wl_signal_emit(&view->events.pre_render, &rdata);
|
if (output->damaged) {
|
||||||
view_for_each_surface(view, render_surface, &rdata);
|
wl_signal_emit(&view->events.pre_render, &rdata);
|
||||||
wl_signal_emit(&view->events.post_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);
|
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_output_render_software_cursors(wlr_output, NULL);
|
||||||
wlr_renderer_end(renderer);
|
wlr_renderer_end(renderer);
|
||||||
|
|
||||||
|
output->damaged = false;
|
||||||
|
|
||||||
wlr_output_commit(wlr_output);
|
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) {
|
if (event->committed & WLR_OUTPUT_STATE_TRANSFORM) {
|
||||||
arrange_layers(output);
|
arrange_layers(output);
|
||||||
|
output->damaged = true;
|
||||||
|
|
||||||
wl_signal_emit(&output->events.resize, output);
|
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);
|
struct kiwmi_output *output = wl_container_of(listener, output, mode);
|
||||||
|
|
||||||
arrange_layers(output);
|
arrange_layers(output);
|
||||||
|
output->damaged = true;
|
||||||
|
|
||||||
wl_signal_emit(&output->events.resize, output);
|
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.width = wlr_output->width;
|
||||||
output->usable_area.height = wlr_output->height;
|
output->usable_area.height = wlr_output->height;
|
||||||
|
|
||||||
|
output->damaged = true;
|
||||||
|
|
||||||
output->frame.notify = output_frame_notify;
|
output->frame.notify = output_frame_notify;
|
||||||
wl_signal_add(&wlr_output->events.frame, &output->frame);
|
wl_signal_add(&wlr_output->events.frame, &output->frame);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
struct kiwmi_view *view = wl_container_of(listener, view, map);
|
||||||
view->mapped = true;
|
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);
|
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) {
|
if (view->mapped) {
|
||||||
view->mapped = false;
|
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);
|
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);
|
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);
|
wlr_xdg_surface_get_geometry(view->xdg_surface, &view->geom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -126,6 +126,10 @@ process_cursor_motion(struct kiwmi_server *server, uint32_t time)
|
||||||
} else {
|
} else {
|
||||||
wlr_seat_pointer_clear_focus(seat);
|
wlr_seat_pointer_clear_focus(seat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wl_list_for_each (output, &server->desktop.outputs, link) {
|
||||||
|
output->damaged = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -111,6 +111,14 @@ request_set_cursor_notify(struct wl_listener *listener, void *data)
|
||||||
return;
|
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(
|
wlr_cursor_set_surface(
|
||||||
cursor->cursor, event->surface, event->hotspot_x, event->hotspot_y);
|
cursor->cursor, event->surface, event->hotspot_x, event->hotspot_y);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ kiwmi_sources = files(
|
||||||
|
|
||||||
kiwmi_deps = [
|
kiwmi_deps = [
|
||||||
lua,
|
lua,
|
||||||
|
pixman,
|
||||||
protocols_server,
|
protocols_server,
|
||||||
wayland_server,
|
wayland_server,
|
||||||
wlroots,
|
wlroots,
|
||||||
|
|
|
@ -18,6 +18,7 @@ add_project_arguments(
|
||||||
|
|
||||||
git = find_program('git', required: false)
|
git = find_program('git', required: false)
|
||||||
lua = dependency(get_option('lua-pkg'))
|
lua = dependency(get_option('lua-pkg'))
|
||||||
|
pixman = dependency('pixman-1')
|
||||||
wayland_client = dependency('wayland-client')
|
wayland_client = dependency('wayland-client')
|
||||||
wayland_protocols = dependency('wayland-protocols')
|
wayland_protocols = dependency('wayland-protocols')
|
||||||
wayland_scanner = dependency('wayland-scanner')
|
wayland_scanner = dependency('wayland-scanner')
|
||||||
|
|
Loading…
Reference in a new issue