From 30da8a2ac209a03cb969a20192e39320b7b4c0dc Mon Sep 17 00:00:00 2001 From: Stuart Dilts Date: Wed, 25 Oct 2023 19:45:35 -0600 Subject: [PATCH] hrt: Add initial surface rendering Render surfaces as they are recieved as a proof of concept. --- heart/include/hrt/hrt_server.h | 2 ++ heart/include/hrt/hrt_view.h | 1 + heart/src/output.c | 28 +++++++++------------- heart/src/xdg_shell.c | 41 ++++++++++++++++++++++++++------- lisp/bindings/hrt-bindings.lisp | 10 ++++++++ lisp/bindings/hrt-bindings.yml | 2 +- 6 files changed, 58 insertions(+), 26 deletions(-) diff --git a/heart/include/hrt/hrt_server.h b/heart/include/hrt/hrt_server.h index 58d4746..31dc61a 100644 --- a/heart/include/hrt/hrt_server.h +++ b/heart/include/hrt/hrt_server.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -20,6 +21,7 @@ struct hrt_server { struct wlr_compositor *compositor; struct wlr_allocator *allocator; + struct wlr_scene *scene; struct wl_list outputs; struct wl_listener new_output; struct wlr_output_manager_v1 *output_manager; diff --git a/heart/include/hrt/hrt_view.h b/heart/include/hrt/hrt_view.h index b19d24c..c4aafe6 100644 --- a/heart/include/hrt/hrt_view.h +++ b/heart/include/hrt/hrt_view.h @@ -3,6 +3,7 @@ struct hrt_view { struct wlr_xdg_toplevel *xdg_toplevel; + struct wlr_scene_tree *scene_tree; struct wl_listener map; struct wl_listener unmap; struct wl_listener destroy; diff --git a/heart/src/output.c b/heart/src/output.c index 64621f3..2f3bfcd 100644 --- a/heart/src/output.c +++ b/heart/src/output.c @@ -8,27 +8,19 @@ static void handle_frame_notify(struct wl_listener *listener, void *data) { struct hrt_output *output = wl_container_of(listener, output, frame); - struct hrt_server *server = output->server; - struct wlr_renderer *renderer = server->renderer; + struct wlr_scene *scene = output->server->scene; + /* struct wlr_renderer *renderer = server->renderer; */ - //TODO: damage tracking - if (!wlr_output_attach_render(output->wlr_output, NULL)) { - return; - } + /* //TODO: damage tracking */ + /* if (!wlr_output_attach_render(output->wlr_output, NULL)) { */ + /* return; */ + /* } */ + struct wlr_scene_output *scene_output = wlr_scene_get_scene_output(scene, output->wlr_output); + wlr_scene_output_commit(scene_output); struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); - - int width, height; - wlr_output_effective_resolution(output->wlr_output, &width, &height); - wlr_renderer_begin(renderer, width, height); - - wlr_renderer_clear(renderer, output->color); - - wlr_output_render_software_cursors(output->wlr_output, NULL); - - wlr_renderer_end(renderer); - wlr_output_commit(output->wlr_output); + wlr_scene_output_send_frame_done(scene_output, &now); } static void handle_output_destroy(struct wl_listener *listener, void *data) { @@ -111,6 +103,8 @@ bool hrt_output_init(struct hrt_server *server, const struct hrt_output_callback wl_signal_add(&server->backend->events.new_output, &server->new_output); server->output_layout = wlr_output_layout_create(); + server->scene = wlr_scene_create(); + wlr_scene_attach_output_layout(server->scene, server->output_layout); server->output_manager = wlr_output_manager_v1_create(server->wl_display); diff --git a/heart/src/xdg_shell.c b/heart/src/xdg_shell.c index eb8ebe7..d9bbf97 100644 --- a/heart/src/xdg_shell.c +++ b/heart/src/xdg_shell.c @@ -1,3 +1,4 @@ +#include #include #include @@ -31,21 +32,45 @@ static void handle_xdg_toplevel_destroy(struct wl_listener *listener, free(view); } +struct hrt_view *initialize_view(struct wlr_xdg_surface *xdg_surface, struct wlr_scene_tree *tree) { + // This method can only deal with toplevel xdg_surfaces: + assert(xdg_surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL); + struct hrt_view *view = calloc(1, sizeof(struct hrt_view)); + view->xdg_toplevel = xdg_surface->toplevel; + + // Add the view to the scene tree (we should probab + view->scene_tree = wlr_scene_xdg_surface_create(tree, view->xdg_toplevel->base); + view->scene_tree->node.data = view; + xdg_surface->data = view->scene_tree; + + // Listen to events: + view->map.notify = handle_xdg_toplevel_map; + wl_signal_add(&xdg_surface->events.map, &view->map); + view->unmap.notify = handle_xdg_toplevel_unmap; + wl_signal_add(&xdg_surface->events.unmap, &view->unmap); + view->destroy.notify = handle_xdg_toplevel_destroy; + wl_signal_add(&xdg_surface->events.destroy, &view->destroy); + + return view; +} + + void handle_new_xdg_surface(struct wl_listener *listener, void *data) { wlr_log(WLR_DEBUG, "New XDG Surface recieved"); struct hrt_server *server = wl_container_of(listener, server, new_xdg_surface); struct wlr_xdg_surface *xdg_surface = data; if(xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) { + // We the front end doesn't need to know about popups; wlroots handles it for us. + // we do need to set some internal data so that they can be rendered though. + struct wlr_xdg_surface *parent = wlr_xdg_surface_from_wlr_surface(xdg_surface->popup->parent); + struct wlr_scene_tree *parent_tree = parent->data; + xdg_surface->data = wlr_scene_xdg_surface_create( + parent_tree, xdg_surface); return; } - struct hrt_view *view = calloc(1, sizeof(struct hrt_view)); - - view->map.notify = handle_xdg_toplevel_map; - wl_signal_add(&xdg_surface->events.map, &view->map); - view->unmap.notify = handle_xdg_toplevel_unmap; - wl_signal_add(&xdg_surface->events.unmap, &view->unmap); - view->destroy.notify = handle_xdg_toplevel_destroy; - wl_signal_add(&xdg_surface->events.destroy, &view->destroy); + // At some point, we will want the front end to call this, as it should decide what node + // of the scene graph the view gets added to: + initialize_view(xdg_surface, &server->scene->tree); } diff --git a/lisp/bindings/hrt-bindings.lisp b/lisp/bindings/hrt-bindings.lisp index baa884d..58fce85 100644 --- a/lisp/bindings/hrt-bindings.lisp +++ b/lisp/bindings/hrt-bindings.lisp @@ -90,6 +90,7 @@ See themes section of man xcursor(3) to find where to find valid cursor names." (renderer :pointer #| (:struct wlr-renderer) |# ) (compositor :pointer #| (:struct wlr-compositor) |# ) (allocator :pointer #| (:struct wlr-allocator) |# ) + (scene :pointer #| (:struct wlr-scene) |# ) (outputs (:struct wl-list)) (new-output (:struct wl-listener)) (output-manager :pointer #| (:struct wlr-output-manager-v1) |# ) @@ -115,3 +116,12 @@ See themes section of man xcursor(3) to find where to find valid cursor names." (cffi:defcfun ("hrt_server_finish" hrt-server-finish) :void (server (:pointer (:struct hrt-server)))) + +;; next section imported from file build/include/hrt/hrt_view.h + +(cffi:defcstruct hrt-view + (xdg-toplevel :pointer #| (:struct wlr-xdg-toplevel) |# ) + (scene-tree :pointer #| (:struct wlr-scene-tree) |# ) + (map (:struct wl-listener)) + (unmap (:struct wl-listener)) + (destroy (:struct wl-listener))) diff --git a/lisp/bindings/hrt-bindings.yml b/lisp/bindings/hrt-bindings.yml index a9695dc..39c47e4 100644 --- a/lisp/bindings/hrt-bindings.yml +++ b/lisp/bindings/hrt-bindings.yml @@ -9,7 +9,7 @@ files: - build/include/hrt/hrt_input.h - build/include/hrt/hrt_output.h - build/include/hrt/hrt_server.h - + - build/include/hrt/hrt_view.h pointer-expansion: include: match: "hrt.*"