From b6d7c3ed8ec6ae29af5d585db5417394ff49f3c7 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 23 Sep 2017 00:29:53 -0400 Subject: [PATCH] Initialize display, backend; add frame handling --- backend/wayland/backend.c | 42 +++++++-------- backend/wayland/output.c | 2 +- include/backend/wayland.h | 2 + include/rootston/desktop.h | 27 ++++++++-- include/rootston/server.h | 9 ++-- rootston/desktop.c | 59 ++++++++++++++++++++++ rootston/main.c | 41 +++++++++++++-- rootston/meson.build | 6 ++- rootston/output.c | 101 +++++++++++++++++++++++++++++++++++++ 9 files changed, 253 insertions(+), 36 deletions(-) create mode 100644 rootston/desktop.c create mode 100644 rootston/output.c diff --git a/backend/wayland/backend.c b/backend/wayland/backend.c index d917c7e9..3ac2ea7d 100644 --- a/backend/wayland/backend.c +++ b/backend/wayland/backend.c @@ -35,26 +35,7 @@ static bool wlr_wl_backend_start(struct wlr_backend *_backend) { struct wlr_wl_backend *backend = (struct wlr_wl_backend *)_backend; wlr_log(L_INFO, "Initializating wayland backend"); - backend->remote_display = wl_display_connect(NULL); - if (!backend->remote_display) { - wlr_log_errno(L_ERROR, "Could not connect to remote display"); - return false; - } - - if (!(backend->registry = wl_display_get_registry(backend->remote_display))) { - wlr_log_errno(L_ERROR, "Could not obtain reference to remote registry"); - return false; - } - - wlr_wl_registry_poll(backend); - if (!(backend->compositor) || (!(backend->shell))) { - wlr_log_errno(L_ERROR, "Could not obtain retrieve required globals"); - return false; - } - - wlr_egl_init(&backend->egl, EGL_PLATFORM_WAYLAND_EXT, backend->remote_display); - wlr_egl_bind_display(&backend->egl, backend->local_display); - + backend->started = true; for (size_t i = 0; i < backend->requested_outputs; ++i) { wlr_wl_output_create(&backend->backend); } @@ -146,6 +127,27 @@ struct wlr_backend *wlr_wl_backend_create(struct wl_display *display) { } backend->local_display = display; + + backend->remote_display = wl_display_connect(NULL); + if (!backend->remote_display) { + wlr_log_errno(L_ERROR, "Could not connect to remote display"); + return false; + } + + if (!(backend->registry = wl_display_get_registry(backend->remote_display))) { + wlr_log_errno(L_ERROR, "Could not obtain reference to remote registry"); + return false; + } + + wlr_wl_registry_poll(backend); + if (!(backend->compositor) || (!(backend->shell))) { + wlr_log_errno(L_ERROR, "Could not obtain retrieve required globals"); + return false; + } + + wlr_egl_init(&backend->egl, EGL_PLATFORM_WAYLAND_EXT, backend->remote_display); + wlr_egl_bind_display(&backend->egl, backend->local_display); + return &backend->backend; error: diff --git a/backend/wayland/output.c b/backend/wayland/output.c index 3e673bcc..ba04aede 100644 --- a/backend/wayland/output.c +++ b/backend/wayland/output.c @@ -209,7 +209,7 @@ static struct zxdg_toplevel_v6_listener xdg_toplevel_listener = { struct wlr_output *wlr_wl_output_create(struct wlr_backend *_backend) { assert(wlr_backend_is_wl(_backend)); struct wlr_wl_backend *backend = (struct wlr_wl_backend *)_backend; - if (!backend->remote_display) { + if (!backend->started) { ++backend->requested_outputs; return NULL; } diff --git a/include/backend/wayland.h b/include/backend/wayland.h index 5e278dc9..42739c18 100644 --- a/include/backend/wayland.h +++ b/include/backend/wayland.h @@ -1,6 +1,7 @@ #ifndef _WLR_INTERNAL_BACKEND_WAYLAND_H #define _WLR_INTERNAL_BACKEND_WAYLAND_H +#include #include #include #include @@ -14,6 +15,7 @@ struct wlr_wl_backend { struct wlr_backend backend; /* local state */ + bool started; struct wl_display *local_display; list_t *devices; list_t *outputs; diff --git a/include/rootston/desktop.h b/include/rootston/desktop.h index 7881e599..3d31059c 100644 --- a/include/rootston/desktop.h +++ b/include/rootston/desktop.h @@ -7,13 +7,13 @@ #include #include #include -#include #include #include "rootston/view.h" +#include "rootston/config.h" struct roots_output { struct roots_desktop *desktop; - struct wlr_output *output; + struct wlr_output *wlr_output; struct wl_listener frame; struct wl_listener resolution; struct timespec last_frame; @@ -22,12 +22,29 @@ struct roots_output { struct roots_desktop { struct wl_list outputs; + struct timespec last_frame; + struct roots_server *server; + struct roots_config *config; + struct wlr_output_layout *layout; - struct wlr_compositor *wlr_compositor; + + struct wlr_compositor *compositor; struct wlr_wl_shell *wl_shell; - struct wlr_xdg_shell_v6 *xdg_shell; - struct wlr_data_device_manager *data_device_manager; + struct wlr_xdg_shell_v6 *xdg_shell_v6; struct wlr_gamma_control_manager *gamma_control_manager; + + struct wl_listener output_add; + struct wl_listener output_remove; + struct wl_listener xdg_shell_v6_surface; }; +struct roots_server; + +struct roots_desktop *desktop_create(struct roots_server *server, + struct roots_config *config); +void desktop_destroy(struct roots_desktop *desktop); + +void output_add_notify(struct wl_listener *listener, void *data); +void output_remove_notify(struct wl_listener *listener, void *data); + #endif diff --git a/include/rootston/server.h b/include/rootston/server.h index f4d1de95..d9fa8f9e 100644 --- a/include/rootston/server.h +++ b/include/rootston/server.h @@ -3,13 +3,14 @@ #include #include #include +#include #include #include #include "rootston/config.h" #include "rootston/desktop.h" #include "rootston/input.h" -struct rootston { +struct roots_server { /* Rootston resources */ struct roots_config *config; struct roots_desktop *desktop; @@ -21,11 +22,13 @@ struct rootston { /* WLR tools */ struct wlr_backend *backend; - struct wlr_session *session; struct wlr_renderer *renderer; struct wlr_xwayland *xwayland; + + /* Global resources */ + struct wlr_data_device_manager *data_device_manager; }; -extern struct rootston root; +extern struct roots_server server; #endif diff --git a/rootston/desktop.c b/rootston/desktop.c new file mode 100644 index 00000000..551d289a --- /dev/null +++ b/rootston/desktop.c @@ -0,0 +1,59 @@ +#define _POSIX_C_SOURCE 199309L +#include +#include +#include +#include +#include +#include +#include +#include +#include "rootston/desktop.h" +#include "rootston/server.h" + +static void handle_xdg_shell_v6_surface(struct wl_listener *listener, + void *data) { + struct roots_desktop *desktop = + wl_container_of(listener, desktop, xdg_shell_v6_surface); + struct wlr_xdg_surface_v6 *surface = data; + wlr_log(L_DEBUG, "new xdg surface: title=%s, app_id=%s", + surface->title, surface->app_id); + wlr_xdg_surface_v6_ping(surface); +} + +struct roots_desktop *desktop_create(struct roots_server *server, + struct roots_config *config) { + struct roots_desktop *desktop = calloc(1, sizeof(struct roots_desktop)); + wlr_log(L_DEBUG, "Initializing roots desktop"); + + wl_list_init(&desktop->outputs); + wl_list_init(&desktop->output_add.link); + desktop->output_add.notify = output_add_notify; + wl_list_init(&desktop->output_remove.link); + desktop->output_remove.notify = output_remove_notify; + + wl_signal_add(&server->backend->events.output_add, + &desktop->output_add); + wl_signal_add(&server->backend->events.output_remove, + &desktop->output_remove); + + desktop->server = server; + desktop->config = config; + desktop->layout = wlr_output_layout_create(); + desktop->compositor = wlr_compositor_create( + server->wl_display, server->renderer); + desktop->wl_shell = wlr_wl_shell_create(server->wl_display); + + desktop->xdg_shell_v6 = wlr_xdg_shell_v6_create(server->wl_display); + wl_signal_add(&desktop->xdg_shell_v6->events.new_surface, + &desktop->xdg_shell_v6_surface); + desktop->xdg_shell_v6_surface.notify = handle_xdg_shell_v6_surface; + + desktop->gamma_control_manager = wlr_gamma_control_manager_create( + server->wl_display); + + return desktop; +} + +void desktop_destroy(struct roots_desktop *desktop) { + // TODO +} diff --git a/rootston/main.c b/rootston/main.c index 9be2ff41..b95840a9 100644 --- a/rootston/main.c +++ b/rootston/main.c @@ -1,14 +1,45 @@ +#define _POSIX_C_SOURCE 200112L +#include +#include #include +#include +#include +#include #include #include "rootston/config.h" #include "rootston/server.h" -struct rootston root = { 0 }; +struct roots_server server = { 0 }; int main(int argc, char **argv) { - root.config = parse_args(argc, argv); - root.wl_display = wl_display_create(); - root.wl_event_loop = wl_display_get_event_loop(root.wl_display); - wl_display_init_shm(root.wl_display); + assert(server.config = parse_args(argc, argv)); + assert(server.wl_display = wl_display_create()); + assert(server.wl_event_loop = wl_display_get_event_loop(server.wl_display)); + + assert(server.backend = wlr_backend_autocreate(server.wl_display)); + + assert(server.renderer = wlr_gles2_renderer_create(server.backend)); + wl_display_init_shm(server.wl_display); + server.desktop = desktop_create(&server, server.config); + server.data_device_manager = wlr_data_device_manager_create( + server.wl_display); + + const char *socket = wl_display_add_socket_auto(server.wl_display); + if (!socket) { + wlr_log_errno(L_ERROR, "Unable to open wayland socket"); + wlr_backend_destroy(server.backend); + return 1; + } + + wlr_log(L_INFO, "Running compositor on wayland display '%s'", socket); + setenv("_WAYLAND_DISPLAY", socket, true); + + if (!wlr_backend_start(server.backend)) { + wlr_log(L_ERROR, "Failed to start backend"); + wlr_backend_destroy(server.backend); + return 1; + } + + wl_display_run(server.wl_display); return 0; } diff --git a/rootston/meson.build b/rootston/meson.build index 501fe17e..9342d19c 100644 --- a/rootston/meson.build +++ b/rootston/meson.build @@ -1,7 +1,9 @@ executable( - 'rooston', [ - 'main.c', + 'rootson', [ 'config.c', + 'desktop.c', 'ini.c', + 'main.c', + 'output.c', ], dependencies: wlroots ) diff --git a/rootston/output.c b/rootston/output.c new file mode 100644 index 00000000..39586e0e --- /dev/null +++ b/rootston/output.c @@ -0,0 +1,101 @@ +#define _POSIX_C_SOURCE 199309L +#include +#include +#include +#include +#include +#include +#include +#include "rootston/server.h" +#include "rootston/desktop.h" +#include "rootston/config.h" + +static void output_frame_notify(struct wl_listener *listener, void *data) { + struct wlr_output *wlr_output = data; + struct roots_output *output = wl_container_of(listener, output, frame); + struct roots_desktop *desktop = output->desktop; + struct roots_server *server = desktop->server; + + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + + wlr_output_make_current(wlr_output); + wlr_renderer_begin(server->renderer, wlr_output); + + // TODO: render views + + wlr_renderer_end(server->renderer); + wlr_output_swap_buffers(wlr_output); + + output->last_frame = desktop->last_frame = now; +} + +void output_add_notify(struct wl_listener *listener, void *data) { + struct wlr_output *wlr_output = data; + struct roots_desktop *desktop = wl_container_of(listener, desktop, output_add); + struct roots_config *config = desktop->config; + + wlr_log(L_DEBUG, "Output '%s' added", wlr_output->name); + wlr_log(L_DEBUG, "%s %s %"PRId32"mm x %"PRId32"mm", + wlr_output->make, wlr_output->model, + wlr_output->phys_width, wlr_output->phys_height); + if (wlr_output->modes->length > 0) { + wlr_output_set_mode(wlr_output, wlr_output->modes->items[0]); + } + + struct roots_output *output = calloc(1, sizeof(struct roots_output)); + clock_gettime(CLOCK_MONOTONIC, &output->last_frame); + output->desktop = desktop; + output->wlr_output = wlr_output; + output->frame.notify = output_frame_notify; + wl_list_init(&output->frame.link); + wl_signal_add(&wlr_output->events.frame, &output->frame); + wl_list_insert(&desktop->outputs, &output->link); + + struct output_config *output_config = config_get_output(config, wlr_output); + if (output_config) { + wlr_output_transform(wlr_output, output_config->transform); + wlr_output_layout_add(desktop->layout, + wlr_output, output_config->x, output_config->y); + } else { + wlr_output_layout_add_auto(desktop->layout, wlr_output); + } + + /* TODO: cursor + example_config_configure_cursor(sample->config, sample->cursor, + sample->compositor); + + // TODO the cursor must be set depending on which surface it is displayed + // over which should happen in the compositor. + if (!wlr_output_set_cursor(wlr_output, image->buffer, + image->width, image->width, image->height)) { + wlr_log(L_DEBUG, "Failed to set hardware cursor"); + return; + } + + wlr_cursor_warp(sample->cursor, NULL, sample->cursor->x, sample->cursor->y); + */ +} + +void output_remove_notify(struct wl_listener *listener, void *data) { + struct wlr_output *wlr_output = data; + struct roots_desktop *desktop = wl_container_of(listener, desktop, output_remove); + struct roots_output *output = NULL, *_output; + wl_list_for_each(_output, &desktop->outputs, link) { + if (_output->wlr_output == wlr_output) { + output = _output; + break; + } + } + if (!output) { + return; // We are unfamiliar with this output + } + wlr_output_layout_remove(desktop->layout, output->wlr_output); + // TODO: cursor + //example_config_configure_cursor(sample->config, sample->cursor, + // sample->compositor); + wl_list_remove(&output->link); + wl_list_remove(&output->frame.link); + wl_list_remove(&output->resolution.link); + free(output); +}