Render using wlr_scene

Apart from removing a lot of code, this commit also introduces (thanks
to wlr_scene) fine-grained damage tracking.

The lack of our own rendering code will only be an issue if the need for
custom effects (such as blur) arises; however, that's very unlikely and
it would probably require a lot of changes anyway.
This commit is contained in:
tiosgz 2022-05-08 08:25:15 +00:00
parent f144eb1438
commit 670b63b64a
6 changed files with 13 additions and 291 deletions

View file

@ -28,8 +28,6 @@ struct kiwmi_output {
struct wlr_box usable_area;
int damaged;
struct {
struct wl_signal destroy;
struct wl_signal resize;
@ -49,6 +47,4 @@ struct kiwmi_render_data {
void new_output_notify(struct wl_listener *listener, void *data);
void output_layout_change_notify(struct wl_listener *listener, void *data);
void output_damage(struct kiwmi_output *output);
#endif /* KIWMI_DESKTOP_OUTPUT_H */

View file

@ -61,7 +61,6 @@ kiwmi_layer_commit_notify(struct wl_listener *listener, void *UNUSED(data))
}
if (layer->layer_surface->current.committed != 0) {
output_damage(layer->output);
arrange_layers(output);
}
}
@ -75,7 +74,6 @@ kiwmi_layer_map_notify(struct wl_listener *listener, void *UNUSED(data))
wlr_scene_node_set_enabled(&layer->desktop_surface.popups_tree->node, true);
arrange_layers(layer->output);
output_damage(layer->output);
}
static void
@ -88,7 +86,6 @@ kiwmi_layer_unmap_notify(struct wl_listener *listener, void *UNUSED(data))
&layer->desktop_surface.popups_tree->node, false);
arrange_layers(layer->output);
output_damage(layer->output);
}
static void

View file

@ -18,6 +18,7 @@
#include <wlr/types/wlr_matrix.h>
#include <wlr/types/wlr_output.h>
#include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_scene.h>
#include <wlr/types/wlr_surface.h>
#include <wlr/types/wlr_xcursor_manager.h>
#include <wlr/util/log.h>
@ -30,216 +31,24 @@
#include "input/pointer.h"
#include "server.h"
static void
render_layer_surface(struct wlr_surface *surface, int x, int y, void *data)
{
struct kiwmi_render_data *rdata = data;
struct wlr_output *wlr_output = rdata->output;
struct wlr_box *geom = rdata->data;
struct wlr_texture *texture = wlr_surface_get_texture(surface);
if (!texture) {
return;
}
int ox = x + geom->x;
int oy = y + geom->y;
struct wlr_box box = {
.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, wlr_output->transform_matrix);
wlr_render_texture_with_matrix(rdata->renderer, texture, matrix, 1);
wlr_surface_send_frame_done(surface, rdata->when);
}
static void
render_layer(struct wl_list *layer, struct kiwmi_render_data *rdata)
{
struct kiwmi_layer *surface;
wl_list_for_each (surface, layer, link) {
rdata->data = &surface->geom;
wlr_layer_surface_v1_for_each_surface(
surface->layer_surface, render_layer_surface, rdata);
}
}
static void
send_frame_done_to_layer_surface(
struct wlr_surface *surface,
int UNUSED(x),
int UNUSED(y),
void *data)
{
struct timespec *now = data;
wlr_surface_send_frame_done(surface, now);
}
static void
send_frame_done_to_layer(struct wl_list *layer, struct timespec *now)
{
struct kiwmi_layer *surface;
wl_list_for_each (surface, layer, link) {
wlr_layer_surface_v1_for_each_surface(
surface->layer_surface, send_frame_done_to_layer_surface, now);
}
}
static void
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 *wlr_output = rdata->output;
struct wlr_texture *texture = wlr_surface_get_texture(surface);
if (!texture) {
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 * 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, wlr_output->transform_matrix);
wlr_render_texture_with_matrix(rdata->renderer, texture, matrix, 1);
wlr_surface_send_frame_done(surface, rdata->when);
}
static void
send_frame_done_to_surface(
struct wlr_surface *surface,
int UNUSED(sx),
int UNUSED(sy),
void *data)
{
struct timespec *now = data;
wlr_surface_send_frame_done(surface, now);
}
static bool
render_cursors(struct wlr_output *wlr_output)
{
pixman_region32_t damage;
pixman_region32_init(&damage);
wlr_output_render_software_cursors(wlr_output, &damage);
bool damaged = pixman_region32_not_empty(&damage);
pixman_region32_fini(&damage);
return damaged;
}
static void
output_frame_notify(struct wl_listener *listener, void *data)
{
struct kiwmi_output *output = wl_container_of(listener, output, frame);
struct wlr_output *wlr_output = data;
struct kiwmi_desktop *desktop = output->desktop;
struct wlr_scene_output *scene_output =
wlr_scene_get_scene_output(output->desktop->scene, wlr_output);
if (!scene_output) {
return;
}
wlr_scene_output_commit(scene_output);
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
int buffer_age;
if (!wlr_output_attach_render(wlr_output, &buffer_age)) {
wlr_log(WLR_ERROR, "Failed to attach renderer to output");
return;
}
if (output->damaged == 0 && buffer_age > 0) {
send_frame_done_to_layer(
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &now);
send_frame_done_to_layer(
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], &now);
send_frame_done_to_layer(
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &now);
send_frame_done_to_layer(
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &now);
struct kiwmi_view *view;
wl_list_for_each (view, &desktop->views, link) {
view_for_each_surface(view, send_frame_done_to_surface, &now);
}
if (render_cursors(wlr_output)) {
output_damage(output);
}
wlr_output_commit(wlr_output);
return;
}
struct wlr_output_layout *output_layout = desktop->output_layout;
struct kiwmi_server *server = wl_container_of(desktop, server, desktop);
struct wlr_renderer *renderer = server->renderer;
wlr_renderer_begin(renderer, wlr_output->width, wlr_output->height);
wlr_renderer_clear(renderer, desktop->bg_color);
double output_lx = 0;
double output_ly = 0;
wlr_output_layout_output_coords(
output_layout, wlr_output, &output_lx, &output_ly);
struct kiwmi_render_data rdata = {
.output = output->wlr_output,
.output_lx = output_lx,
.output_ly = output_ly,
.renderer = renderer,
.when = &now,
};
render_layer(&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &rdata);
render_layer(&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], &rdata);
struct kiwmi_view *view;
wl_list_for_each_reverse (view, &desktop->views, link) {
if (view->hidden || !view->mapped) {
continue;
}
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);
}
render_layer(&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &rdata);
render_layer(&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &rdata);
bool damaged = render_cursors(wlr_output);
wlr_renderer_end(renderer);
if (damaged) {
output_damage(output);
} else {
--output->damaged;
}
wlr_output_commit(wlr_output);
wlr_scene_output_send_frame_done(scene_output, &now);
}
static void
@ -250,7 +59,6 @@ output_commit_notify(struct wl_listener *listener, void *data)
if (event->committed & WLR_OUTPUT_STATE_TRANSFORM) {
arrange_layers(output);
output_damage(output);
wl_signal_emit(&output->events.resize, output);
}
@ -304,7 +112,6 @@ output_mode_notify(struct wl_listener *listener, void *UNUSED(data))
struct kiwmi_output *output = wl_container_of(listener, output, mode);
arrange_layers(output);
output_damage(output);
wl_signal_emit(&output->events.resize, output);
}
@ -335,8 +142,6 @@ output_create(struct wlr_output *wlr_output, struct kiwmi_desktop *desktop)
output->mode.notify = output_mode_notify;
wl_signal_add(&wlr_output->events.mode, &output->mode);
output_damage(output);
return output;
}
@ -408,14 +213,6 @@ new_output_notify(struct wl_listener *listener, void *data)
wl_signal_emit(&desktop->events.new_output, output);
}
void
output_damage(struct kiwmi_output *output)
{
if (output != NULL) {
output->damaged = 2;
}
}
void
output_layout_change_notify(struct wl_listener *listener, void *UNUSED(data))
{

View file

@ -92,11 +92,6 @@ view_set_size(struct kiwmi_view *view, uint32_t width, uint32_t height)
child->impl->reconfigure(child);
}
}
struct kiwmi_output *output;
wl_list_for_each (output, &view->desktop->outputs, link) {
output_damage(output);
}
}
}
@ -120,11 +115,6 @@ view_set_pos(struct kiwmi_view *view, uint32_t x, uint32_t y)
struct kiwmi_server *server = wl_container_of(desktop, server, desktop);
struct kiwmi_cursor *cursor = server->input.cursor;
cursor_refresh_focus(cursor, NULL, NULL, NULL);
struct kiwmi_output *output;
wl_list_for_each (output, &desktop->outputs, link) {
output_damage(output);
}
}
void
@ -355,24 +345,9 @@ view_child_is_mapped(struct kiwmi_view_child *child)
return child->view->mapped;
}
void
view_child_damage(struct kiwmi_view_child *child)
{
// Note for later: this is supposed to damage the child and all subchildren
struct kiwmi_output *output;
wl_list_for_each (output, &child->view->desktop->outputs, link) {
output_damage(output);
}
}
void
view_child_destroy(struct kiwmi_view_child *child)
{
bool visible = view_child_is_mapped(child) && !child->view->hidden;
if (visible) {
view_child_damage(child);
}
wl_list_remove(&child->link);
child->parent = NULL;
@ -414,12 +389,8 @@ view_child_surface_destroy_notify(
}
static void
view_child_commit_notify(struct wl_listener *listener, void *UNUSED(data))
view_child_commit_notify()
{
struct kiwmi_view_child *child = wl_container_of(listener, child, commit);
if (view_child_is_mapped(child)) {
view_child_damage(child);
}
}
static void
@ -436,19 +407,13 @@ view_child_map_notify(struct wl_listener *listener, void *UNUSED(data))
{
struct kiwmi_view_child *child = wl_container_of(listener, child, map);
child->mapped = true;
if (view_child_is_mapped(child)) {
view_child_damage(child);
}
}
static void
view_child_unmap_notify(struct wl_listener *listener, void *UNUSED(data))
{
struct kiwmi_view_child *child = wl_container_of(listener, child, unmap);
if (view_child_is_mapped(child)) {
view_child_damage(child);
}
child->mapped = false;
child->mapped = false;
}
struct kiwmi_view_child *
@ -520,10 +485,6 @@ view_child_subsurface_create(
child->wlr_subsurface = subsurface;
child->mapped = subsurface->mapped;
if (view_child_is_mapped(child)) {
view_child_damage(child);
}
wl_signal_add(&subsurface->events.map, &child->map);
wl_signal_add(&subsurface->events.unmap, &child->unmap);

View file

@ -137,10 +137,6 @@ view_child_popup_create(
child->wlr_xdg_popup = wlr_popup;
child->mapped = wlr_popup->base->mapped;
if (view_child_is_mapped(child)) {
view_child_damage(child);
}
wl_signal_add(&wlr_popup->base->events.map, &child->map);
wl_signal_add(&wlr_popup->base->events.unmap, &child->unmap);
@ -177,11 +173,6 @@ 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_damage(output);
}
wl_signal_emit(&view->desktop->events.view_map, view);
}
@ -201,11 +192,6 @@ xdg_surface_unmap_notify(struct wl_listener *listener, void *UNUSED(data))
struct kiwmi_server *server = wl_container_of(desktop, server, desktop);
cursor_refresh_focus(server->input.cursor, NULL, NULL, NULL);
struct kiwmi_output *output;
wl_list_for_each (output, &view->desktop->outputs, link) {
output_damage(output);
}
wl_signal_emit(&view->events.unmap, view);
}
}
@ -220,13 +206,6 @@ xdg_surface_commit_notify(struct wl_listener *listener, void *UNUSED(data))
struct kiwmi_cursor *cursor = server->input.cursor;
cursor_refresh_focus(cursor, NULL, NULL, NULL);
if (pixman_region32_not_empty(&view->wlr_surface->buffer_damage)) {
struct kiwmi_output *output;
wl_list_for_each (output, &desktop->outputs, link) {
output_damage(output);
}
}
wlr_xdg_surface_get_geometry(view->xdg_surface, &view->geom);
}

View file

@ -116,14 +116,6 @@ 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_damage(output);
}
wlr_cursor_set_surface(
cursor->cursor, event->surface, event->hotspot_x, event->hotspot_y);
}