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
parent 1a3ab3eb3a
commit 60a7106343
12 changed files with 60 additions and 152 deletions

8
cage.c
View file

@ -27,6 +27,7 @@
#include <wlr/types/wlr_idle.h> #include <wlr/types/wlr_idle.h>
#include <wlr/types/wlr_idle_inhibit_v1.h> #include <wlr/types/wlr_idle_inhibit_v1.h>
#include <wlr/types/wlr_output_layout.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_screencopy_v1.h>
#include <wlr/types/wlr_server_decoration.h> #include <wlr/types/wlr_server_decoration.h>
#if CAGE_HAS_XWAYLAND #if CAGE_HAS_XWAYLAND
@ -329,6 +330,13 @@ main(int argc, char *argv[])
goto end; 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, renderer); compositor = wlr_compositor_create(server.wl_display, renderer);
if (!compositor) { if (!compositor) {
wlr_log(WLR_ERROR, "Unable to create the wlroots compositor"); wlr_log(WLR_ERROR, "Unable to create the wlroots compositor");

View file

@ -34,7 +34,7 @@ if is_freebsd
) )
endif endif
wlroots = dependency('wlroots', version: '>= 0.14.0', fallback: ['wlroots', 'wlroots']) wlroots = dependency('wlroots', version: '>= 0.15.0', fallback: ['wlroots', 'wlroots'])
wayland_protos = dependency('wayland-protocols', version: '>=1.14') wayland_protos = dependency('wayland-protocols', version: '>=1.14')
wayland_server = dependency('wayland-server') wayland_server = dependency('wayland-server')
pixman = dependency('pixman-1') pixman = dependency('pixman-1')

View file

@ -26,6 +26,7 @@
#include <wlr/types/wlr_output.h> #include <wlr/types/wlr_output.h>
#include <wlr/types/wlr_output_damage.h> #include <wlr/types/wlr_output_damage.h>
#include <wlr/types/wlr_output_layout.h> #include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_scene.h>
#include <wlr/types/wlr_surface.h> #include <wlr/types/wlr_surface.h>
#include <wlr/types/wlr_xdg_shell.h> #include <wlr/types/wlr_xdg_shell.h>
#include <wlr/util/log.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); 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 static void
output_for_each_surface(struct cg_output *output, cg_surface_iterator_func_t iterator, void *user_data) output_for_each_surface(struct cg_output *output, cg_surface_iterator_func_t iterator, void *user_data)
{ {
struct cg_view *view; struct surface_iterator_data data = {
wl_list_for_each_reverse (view, &output->server->views, link) { .user_iterator = iterator,
output_view_for_each_surface(output, view, iterator, user_data); .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 { struct send_frame_done_data {
@ -182,7 +139,7 @@ send_frame_done(struct cg_output *output, struct send_frame_done_data *data)
} }
static void 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; size_t *n = data;
n++; n++;
@ -207,7 +164,7 @@ scan_out_primary_view(struct cg_output *output)
} }
size_t n_surfaces = 0; 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) { if (n_surfaces > 1) {
return false; 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 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, 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); 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_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); void output_set_window_title(struct cg_output *output, const char *title);

View file

@ -14,6 +14,7 @@
#include <wlr/types/wlr_matrix.h> #include <wlr/types/wlr_matrix.h>
#include <wlr/types/wlr_output.h> #include <wlr/types/wlr_output.h>
#include <wlr/types/wlr_output_layout.h> #include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_scene.h>
#include <wlr/types/wlr_surface.h> #include <wlr/types/wlr_surface.h>
#include <wlr/util/log.h> #include <wlr/util/log.h>
#include <wlr/util/region.h> #include <wlr/util/region.h>
@ -48,86 +49,6 @@ struct render_data {
pixman_region32_t *damage; 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])
{
struct wlr_renderer *renderer = wlr_backend_get_renderer(wlr_output->backend);
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(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 void
output_render(struct cg_output *output, pixman_region32_t *damage) output_render(struct cg_output *output, pixman_region32_t *damage)
{ {
@ -161,18 +82,9 @@ output_render(struct cg_output *output, pixman_region32_t *damage)
wlr_renderer_clear(renderer, color); wlr_renderer_clear(renderer, color);
} }
// TODO: render only top view, possibly use focused view for this, see #35. double lx = 0, ly = 0;
struct cg_view *view; wlr_output_layout_output_coords(output->server->output_layout, output->wlr_output, &lx, &ly);
wl_list_for_each_reverse (view, &server->views, link) { wlr_scene_render_output(server->scene, wlr_output, lx, ly, damage);
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);
renderer_end: renderer_end:
/* Draw software cursor in case hardware cursors aren't /* Draw software cursor in case hardware cursors aren't

8
seat.c
View file

@ -18,6 +18,7 @@
#include <wlr/types/wlr_idle.h> #include <wlr/types/wlr_idle.h>
#include <wlr/types/wlr_keyboard_group.h> #include <wlr/types/wlr_keyboard_group.h>
#include <wlr/types/wlr_primary_selection.h> #include <wlr/types/wlr_primary_selection.h>
#include <wlr/types/wlr_scene.h>
#include <wlr/types/wlr_seat.h> #include <wlr/types/wlr_seat.h>
#include <wlr/types/wlr_surface.h> #include <wlr/types/wlr_surface.h>
#include <wlr/types/wlr_touch.h> #include <wlr/types/wlr_touch.h>
@ -635,6 +636,8 @@ drag_icon_update_position(struct cg_drag_icon *drag_icon)
} }
drag_icon_damage(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 static void
@ -645,6 +648,7 @@ handle_drag_icon_destroy(struct wl_listener *listener, void *data)
drag_icon_damage(drag_icon); drag_icon_damage(drag_icon);
wl_list_remove(&drag_icon->link); wl_list_remove(&drag_icon->link);
wl_list_remove(&drag_icon->destroy.link); wl_list_remove(&drag_icon->destroy.link);
wlr_scene_node_destroy(&drag_icon->scene_surface->node);
free(drag_icon); free(drag_icon);
} }
@ -687,6 +691,10 @@ handle_start_drag(struct wl_listener *listener, void *data)
} }
drag_icon->seat = seat; drag_icon->seat = seat;
drag_icon->wlr_drag_icon = wlr_drag_icon; 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) {
return;
}
drag_icon->destroy.notify = handle_drag_icon_destroy; drag_icon->destroy.notify = handle_drag_icon_destroy;
wl_signal_add(&wlr_drag_icon->events.destroy, &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 wl_list link; // seat::drag_icons
struct cg_seat *seat; struct cg_seat *seat;
struct wlr_drag_icon *wlr_drag_icon; struct wlr_drag_icon *wlr_drag_icon;
struct wlr_scene_surface *scene_surface;
/* The drag icon has a position in layout coordinates. */ /* The drag icon has a position in layout coordinates. */
double lx, ly; double lx, ly;

View file

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

13
view.c
View file

@ -15,6 +15,7 @@
#include <wlr/types/wlr_box.h> #include <wlr/types/wlr_box.h>
#include <wlr/types/wlr_output.h> #include <wlr/types/wlr_output.h>
#include <wlr/types/wlr_surface.h> #include <wlr/types/wlr_surface.h>
#include <wlr/types/wlr_scene.h>
#include "output.h" #include "output.h"
#include "seat.h" #include "seat.h"
@ -174,6 +175,9 @@ view_maximize(struct cg_view *view, struct wlr_box *layout_box)
{ {
view->lx = layout_box->x; view->lx = layout_box->x;
view->ly = layout_box->y; 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); view->impl->maximize(view, layout_box->width, layout_box->height);
} }
@ -185,6 +189,8 @@ view_center(struct cg_view *view, struct wlr_box *layout_box)
view->lx = (layout_box->width - width) / 2; view->lx = (layout_box->width - width) / 2;
view->ly = (layout_box->height - height) / 2; view->ly = (layout_box->height - height) / 2;
wlr_scene_node_set_position(&view->scene_surface->node, view->lx, view->ly);
} }
void void
@ -226,6 +232,8 @@ view_unmap(struct cg_view *view)
child->destroy(child); child->destroy(child);
} }
wlr_scene_node_destroy(&view->scene_surface->node);
view->wlr_surface = NULL; view->wlr_surface = NULL;
} }
@ -234,6 +242,11 @@ view_map(struct cg_view *view, struct wlr_surface *surface)
{ {
view->wlr_surface = surface; view->wlr_surface = surface;
view->scene_surface = wlr_scene_surface_create(&view->server->scene->node, surface);
if (!view->scene_surface) {
return;
}
struct wlr_subsurface *subsurface; struct wlr_subsurface *subsurface;
wl_list_for_each (subsurface, &view->wlr_surface->subsurfaces_below, parent_link) { wl_list_for_each (subsurface, &view->wlr_surface->subsurfaces_below, parent_link) {
subsurface_create(view, subsurface); 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 link; // server::views
struct wl_list children; // cg_view_child::link struct wl_list children; // cg_view_child::link
struct wlr_surface *wlr_surface; struct wlr_surface *wlr_surface;
struct wlr_scene_surface *scene_surface;
/* The view has a position in layout coordinates. */ /* The view has a position in layout coordinates. */
int lx, ly; int lx, ly;

View file

@ -10,6 +10,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <wayland-server-core.h> #include <wayland-server-core.h>
#include <wlr/types/wlr_box.h> #include <wlr/types/wlr_box.h>
#include <wlr/types/wlr_scene.h>
#include <wlr/types/wlr_xdg_shell.h> #include <wlr/types/wlr_xdg_shell.h>
#include <wlr/util/log.h> #include <wlr/util/log.h>
@ -61,6 +62,14 @@ static void
handle_xdg_popup_map(struct wl_listener *listener, void *data) handle_xdg_popup_map(struct wl_listener *listener, void *data)
{ {
struct cg_xdg_popup *popup = wl_container_of(listener, popup, map); 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); view_damage_whole(popup->view_child.view);
} }
@ -68,6 +77,7 @@ static void
handle_xdg_popup_unmap(struct wl_listener *listener, void *data) handle_xdg_popup_unmap(struct wl_listener *listener, void *data)
{ {
struct cg_xdg_popup *popup = wl_container_of(listener, popup, unmap); 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_damage_whole(popup->view_child.view);
} }

View file

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