Use the wlroots scene-graph API

References: https://github.com/swaywm/wlroots/pull/1966
This commit is contained in:
Simon Ser 2021-08-09 20:06:57 +02:00 committed by Jente Hidskes
parent 395189fb05
commit f544483340
11 changed files with 61 additions and 149 deletions

8
cage.c
View file

@ -28,6 +28,7 @@
#include <wlr/types/wlr_idle.h>
#include <wlr/types/wlr_idle_inhibit_v1.h>
#include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_scene.h>
#include <wlr/types/wlr_screencopy_v1.h>
#include <wlr/types/wlr_server_decoration.h>
#if CAGE_HAS_XWAYLAND
@ -342,6 +343,13 @@ main(int argc, char *argv[])
goto end;
}
server.scene = wlr_scene_create();
if (!server.scene) {
wlr_log(WLR_ERROR, "Unable to create scene");
ret = 1;
goto end;
}
compositor = wlr_compositor_create(server.wl_display, server.renderer);
if (!compositor) {
wlr_log(WLR_ERROR, "Unable to create the wlroots compositor");

View file

@ -26,6 +26,7 @@
#include <wlr/types/wlr_output.h>
#include <wlr/types/wlr_output_damage.h>
#include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_scene.h>
#include <wlr/types/wlr_surface.h>
#include <wlr/types/wlr_xdg_shell.h>
#include <wlr/util/log.h>
@ -105,63 +106,19 @@ output_surface_for_each_surface(struct cg_output *output, struct wlr_surface *su
wlr_surface_for_each_surface(surface, output_for_each_surface_iterator, &data);
}
static void
output_view_for_each_surface(struct cg_output *output, struct cg_view *view, cg_surface_iterator_func_t iterator,
void *user_data)
{
struct surface_iterator_data data = {
.user_iterator = iterator,
.user_data = user_data,
.output = output,
.ox = view->lx,
.oy = view->ly,
};
wlr_output_layout_output_coords(output->server->output_layout, output->wlr_output, &data.ox, &data.oy);
view_for_each_surface(view, output_for_each_surface_iterator, &data);
}
void
output_view_for_each_popup_surface(struct cg_output *output, struct cg_view *view, cg_surface_iterator_func_t iterator,
void *user_data)
{
struct surface_iterator_data data = {
.user_iterator = iterator,
.user_data = user_data,
.output = output,
.ox = view->lx,
.oy = view->ly,
};
wlr_output_layout_output_coords(output->server->output_layout, output->wlr_output, &data.ox, &data.oy);
view_for_each_popup_surface(view, output_for_each_surface_iterator, &data);
}
void
output_drag_icons_for_each_surface(struct cg_output *output, struct wl_list *drag_icons,
cg_surface_iterator_func_t iterator, void *user_data)
{
struct cg_drag_icon *drag_icon;
wl_list_for_each (drag_icon, drag_icons, link) {
if (drag_icon->wlr_drag_icon->mapped) {
double ox = drag_icon->lx;
double oy = drag_icon->ly;
wlr_output_layout_output_coords(output->server->output_layout, output->wlr_output, &ox, &oy);
output_surface_for_each_surface(output, drag_icon->wlr_drag_icon->surface, ox, oy, iterator,
user_data);
}
}
}
static void
output_for_each_surface(struct cg_output *output, cg_surface_iterator_func_t iterator, void *user_data)
{
struct cg_view *view;
wl_list_for_each_reverse (view, &output->server->views, link) {
output_view_for_each_surface(output, view, iterator, user_data);
}
struct surface_iterator_data data = {
.user_iterator = iterator,
.user_data = user_data,
.output = output,
.ox = 0,
.oy = 0,
};
wlr_output_layout_output_coords(output->server->output_layout, output->wlr_output, &data.ox, &data.oy);
output_drag_icons_for_each_surface(output, &output->server->seat->drag_icons, iterator, user_data);
wlr_scene_node_for_each_surface(&output->server->scene->node, output_for_each_surface_iterator, &data);
}
struct send_frame_done_data {
@ -182,7 +139,7 @@ send_frame_done(struct cg_output *output, struct send_frame_done_data *data)
}
static void
count_surface_iterator(struct cg_output *output, struct wlr_surface *surface, struct wlr_box *_box, void *data)
count_surface_iterator(struct wlr_surface *surface, int sx, int sy, void *data)
{
size_t *n = data;
(*n)++;
@ -207,7 +164,7 @@ scan_out_primary_view(struct cg_output *output)
}
size_t n_surfaces = 0;
output_view_for_each_surface(output, view, count_surface_iterator, &n_surfaces);
wlr_scene_node_for_each_surface(&view->scene_surface->node, count_surface_iterator, &n_surfaces);
if (n_surfaces > 1) {
return false;
}

View file

@ -28,10 +28,6 @@ typedef void (*cg_surface_iterator_func_t)(struct cg_output *output, struct wlr_
void handle_new_output(struct wl_listener *listener, void *data);
void output_surface_for_each_surface(struct cg_output *output, struct wlr_surface *surface, double ox, double oy,
cg_surface_iterator_func_t iterator, void *user_data);
void output_view_for_each_popup_surface(struct cg_output *output, struct cg_view *view,
cg_surface_iterator_func_t iterator, void *user_data);
void output_drag_icons_for_each_surface(struct cg_output *output, struct wl_list *drag_icons,
cg_surface_iterator_func_t iterator, void *user_data);
void output_damage_surface(struct cg_output *output, struct wlr_surface *surface, double lx, double ly, bool whole);
void output_set_window_title(struct cg_output *output, const char *title);

View file

@ -13,6 +13,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/util/box.h>
#include <wlr/util/log.h>
@ -46,84 +47,6 @@ struct render_data {
pixman_region32_t *damage;
};
static void
render_texture(struct wlr_output *wlr_output, pixman_region32_t *output_damage, struct wlr_texture *texture,
const struct wlr_box *box, const float matrix[static 9])
{
pixman_region32_t damage;
pixman_region32_init(&damage);
pixman_region32_union_rect(&damage, &damage, box->x, box->y, box->width, box->height);
pixman_region32_intersect(&damage, &damage, output_damage);
if (!pixman_region32_not_empty(&damage)) {
goto damage_finish;
}
int nrects;
pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects);
for (int i = 0; i < nrects; i++) {
scissor_output(wlr_output, &rects[i]);
wlr_render_texture_with_matrix(wlr_output->renderer, texture, matrix, 1.0f);
}
damage_finish:
pixman_region32_fini(&damage);
}
static void
render_surface_iterator(struct cg_output *output, struct wlr_surface *surface, struct wlr_box *box, void *user_data)
{
struct render_data *data = user_data;
struct wlr_output *wlr_output = output->wlr_output;
pixman_region32_t *output_damage = data->damage;
struct wlr_texture *texture = wlr_surface_get_texture(surface);
if (!texture) {
wlr_log(WLR_DEBUG, "Cannot obtain surface texture");
return;
}
scale_box(box, 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.0f, wlr_output->transform_matrix);
render_texture(wlr_output, output_damage, texture, box, matrix);
}
static void
render_drag_icons(struct cg_output *output, pixman_region32_t *damage, struct wl_list *drag_icons)
{
struct render_data data = {
.damage = damage,
};
output_drag_icons_for_each_surface(output, drag_icons, render_surface_iterator, &data);
}
/**
* Render all toplevels without descending into popups.
*/
static void
render_view_toplevels(struct cg_view *view, struct cg_output *output, pixman_region32_t *damage)
{
struct render_data data = {
.damage = damage,
};
double ox = view->lx;
double oy = view->ly;
wlr_output_layout_output_coords(output->server->output_layout, output->wlr_output, &ox, &oy);
output_surface_for_each_surface(output, view->wlr_surface, ox, oy, render_surface_iterator, &data);
}
static void
render_view_popups(struct cg_view *view, struct cg_output *output, pixman_region32_t *damage)
{
struct render_data data = {
.damage = damage,
};
output_view_for_each_popup_surface(output, view, render_surface_iterator, &data);
}
void
output_render(struct cg_output *output, pixman_region32_t *damage)
{
@ -151,18 +74,9 @@ output_render(struct cg_output *output, pixman_region32_t *damage)
wlr_renderer_clear(server->renderer, color);
}
// TODO: render only top view, possibly use focused view for this, see #35.
struct cg_view *view;
wl_list_for_each_reverse (view, &server->views, link) {
render_view_toplevels(view, output, damage);
}
struct cg_view *focused_view = seat_get_focus(server->seat);
if (focused_view) {
render_view_popups(focused_view, output, damage);
}
render_drag_icons(output, damage, &server->seat->drag_icons);
double lx = 0, ly = 0;
wlr_output_layout_output_coords(output->server->output_layout, output->wlr_output, &lx, &ly);
wlr_scene_render_output(server->scene, wlr_output, lx, ly, damage);
renderer_end:
/* Draw software cursor in case hardware cursors aren't

9
seat.c
View file

@ -18,6 +18,7 @@
#include <wlr/types/wlr_idle.h>
#include <wlr/types/wlr_keyboard_group.h>
#include <wlr/types/wlr_primary_selection.h>
#include <wlr/types/wlr_scene.h>
#include <wlr/types/wlr_seat.h>
#include <wlr/types/wlr_surface.h>
#include <wlr/types/wlr_touch.h>
@ -632,6 +633,8 @@ drag_icon_update_position(struct cg_drag_icon *drag_icon)
}
drag_icon_damage(drag_icon);
wlr_scene_node_set_position(&drag_icon->scene_surface->node, drag_icon->lx, drag_icon->ly);
}
static void
@ -642,6 +645,7 @@ handle_drag_icon_destroy(struct wl_listener *listener, void *data)
drag_icon_damage(drag_icon);
wl_list_remove(&drag_icon->link);
wl_list_remove(&drag_icon->destroy.link);
wlr_scene_node_destroy(&drag_icon->scene_surface->node);
free(drag_icon);
}
@ -684,6 +688,11 @@ handle_start_drag(struct wl_listener *listener, void *data)
}
drag_icon->seat = seat;
drag_icon->wlr_drag_icon = wlr_drag_icon;
drag_icon->scene_surface = wlr_scene_surface_create(&seat->server->scene->node, wlr_drag_icon->surface);
if (!drag_icon->scene_surface) {
free(drag_icon);
return;
}
drag_icon->destroy.notify = handle_drag_icon_destroy;
wl_signal_add(&wlr_drag_icon->events.destroy, &drag_icon->destroy);

1
seat.h
View file

@ -77,6 +77,7 @@ struct cg_drag_icon {
struct wl_list link; // seat::drag_icons
struct cg_seat *seat;
struct wlr_drag_icon *wlr_drag_icon;
struct wlr_scene_surface *scene_surface;
/* The drag icon has a position in layout coordinates. */
double lx, ly;

View file

@ -36,6 +36,7 @@ struct cg_server {
enum cg_multi_output_mode output_mode;
struct wlr_output_layout *output_layout;
struct wlr_scene *scene;
/* Includes disabled outputs; depending on the output_mode
* some outputs may be disabled. */
struct wl_list outputs; // cg_output::link

14
view.c
View file

@ -13,6 +13,7 @@
#include <string.h>
#include <wayland-server-core.h>
#include <wlr/types/wlr_output.h>
#include <wlr/types/wlr_scene.h>
#include <wlr/types/wlr_surface.h>
#include "output.h"
@ -173,6 +174,9 @@ view_maximize(struct cg_view *view, struct wlr_box *layout_box)
{
view->lx = layout_box->x;
view->ly = layout_box->y;
wlr_scene_node_set_position(&view->scene_surface->node, view->lx, view->ly);
view->impl->maximize(view, layout_box->width, layout_box->height);
}
@ -184,6 +188,8 @@ view_center(struct cg_view *view, struct wlr_box *layout_box)
view->lx = (layout_box->width - width) / 2;
view->ly = (layout_box->height - height) / 2;
wlr_scene_node_set_position(&view->scene_surface->node, view->lx, view->ly);
}
void
@ -225,6 +231,8 @@ view_unmap(struct cg_view *view)
child->destroy(child);
}
wlr_scene_node_destroy(&view->scene_surface->node);
view->wlr_surface = NULL;
}
@ -233,6 +241,12 @@ view_map(struct cg_view *view, struct wlr_surface *surface)
{
view->wlr_surface = surface;
view->scene_surface = wlr_scene_surface_create(&view->server->scene->node, surface);
if (!view->scene_surface) {
wl_resource_post_no_memory(surface->resource);
return;
}
struct wlr_subsurface *subsurface;
wl_list_for_each (subsurface, &view->wlr_surface->current.subsurfaces_below, current.link) {
subsurface_create(view, subsurface);

1
view.h
View file

@ -26,6 +26,7 @@ struct cg_view {
struct wl_list link; // server::views
struct wl_list children; // cg_view_child::link
struct wlr_surface *wlr_surface;
struct wlr_scene_surface *scene_surface;
/* The view has a position in layout coordinates. */
int lx, ly;

View file

@ -9,6 +9,7 @@
#include <stdbool.h>
#include <stdlib.h>
#include <wayland-server-core.h>
#include <wlr/types/wlr_scene.h>
#include <wlr/types/wlr_xdg_shell.h>
#include <wlr/util/log.h>
@ -60,6 +61,14 @@ static void
handle_xdg_popup_map(struct wl_listener *listener, void *data)
{
struct cg_xdg_popup *popup = wl_container_of(listener, popup, map);
struct wlr_scene_node *parent_node = &popup->view_child.view->scene_surface->node;
popup->scene_surface = wlr_scene_surface_create(parent_node, popup->view_child.wlr_surface);
if (!popup->scene_surface) {
return;
}
double sx, sy;
wlr_xdg_popup_get_position(popup->wlr_popup, &sx, &sy);
wlr_scene_node_set_position(&popup->scene_surface->node, sx, sy);
view_damage_whole(popup->view_child.view);
}
@ -67,6 +76,7 @@ static void
handle_xdg_popup_unmap(struct wl_listener *listener, void *data)
{
struct cg_xdg_popup *popup = wl_container_of(listener, popup, unmap);
wlr_scene_node_destroy(&popup->scene_surface->node);
view_damage_whole(popup->view_child.view);
}

View file

@ -22,6 +22,7 @@ struct cg_xdg_shell_view {
struct cg_xdg_popup {
struct cg_view_child view_child;
struct wlr_xdg_popup *wlr_popup;
struct wlr_scene_surface *scene_surface;
struct wl_listener destroy;
struct wl_listener map;