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:
parent
ca45867506
commit
d5940c396c
6 changed files with 13 additions and 291 deletions
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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,18 +407,12 @@ 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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue