output: add output_init() and refactor

This commit is contained in:
Johan Malm 2020-09-29 19:53:46 +01:00
parent 53b360dd11
commit 763f5c3455
3 changed files with 69 additions and 79 deletions

View file

@ -45,6 +45,7 @@ enum cursor_mode {
struct server {
struct wl_display *wl_display;
struct wlr_renderer *renderer;
struct wlr_backend *backend;
struct wlr_xdg_shell *xdg_shell;
struct wl_listener new_xdg_surface;
@ -88,6 +89,7 @@ struct output {
struct server *server;
struct wlr_output *wlr_output;
struct wl_listener frame;
struct wl_listener destroy;
};
enum view_type { LAB_XDG_SHELL_VIEW, LAB_XWAYLAND_VIEW };
@ -232,8 +234,7 @@ void cursor_new(struct server *server, struct wlr_input_device *device);
void keyboard_new(struct server *server, struct wlr_input_device *device);
void output_frame(struct wl_listener *listener, void *data);
void output_new(struct wl_listener *listener, void *data);
void output_init(struct server *server);
struct border deco_thickness(struct view *view);
struct wlr_box deco_max_extents(struct view *view);

View file

@ -1,3 +1,4 @@
#include <wlr/types/wlr_xdg_output_v1.h>
#include "labwc.h"
#include "theme/theme.h"
@ -231,11 +232,13 @@ render_surface(struct wlr_surface *surface, int sx, int sy, void *data)
wlr_surface_send_frame_done(surface, rdata->when);
}
void
output_frame(struct wl_listener *listener, void *data)
static void
output_frame_notify(struct wl_listener *listener, void *data)
{
/* This function is called every time an output is ready to display a
* frame, generally at the output's refresh rate (e.g. 60Hz). */
/*
* This function is called every time an output is ready to display a
* frame, generally at the output's refresh rate (e.g. 60Hz).
*/
struct output *output = wl_container_of(listener, output, frame);
struct wlr_renderer *renderer = output->server->renderer;
@ -246,19 +249,17 @@ output_frame(struct wl_listener *listener, void *data)
if (!wlr_output_attach_render(output->wlr_output, NULL)) {
return;
}
/* The "effective" resolution can change if you rotate your outputs. */
int width, height;
wlr_output_effective_resolution(output->wlr_output, &width, &height);
/* Begin the renderer (calls glViewport and some other GL sanity checks)
*/
/* Calls glViewport and some other GL sanity checks */
wlr_renderer_begin(renderer, width, height);
float color[4] = { 0.3, 0.3, 0.3, 1.0 };
wlr_renderer_clear(renderer, color);
/* Each subsequent window we render is rendered on top of the last.
* Because our view list is ordered front-to-back, we iterate over it
* backwards. */
struct view *view;
wl_list_for_each_reverse (view, &output->server->views, link) {
if (!view->mapped)
@ -305,23 +306,23 @@ output_frame(struct wl_listener *listener, void *data)
render_surface(s, 0, 0, &rdata);
}
/* Hardware cursors are rendered by the GPU on a separate plane, and can
* be moved around without re-rendering what's beneath them - which is
* more efficient. However, not all hardware supports hardware cursors.
* For this reason, wlroots provides a software fallback, which we ask
* it to render here. wlr_cursor handles configuring hardware vs
* software cursors for you,
* and this function is a no-op when hardware cursors are in use. */
/* Just in case hardware cursors not supported by GPU */
wlr_output_render_software_cursors(output->wlr_output, NULL);
/* Conclude rendering and swap the buffers, showing the final frame
* on-screen. */
wlr_renderer_end(renderer);
wlr_output_commit(output->wlr_output);
}
void
output_new(struct wl_listener *listener, void *data)
static void
output_destroy_notify(struct wl_listener *listener, void *data)
{
struct output *output = wl_container_of(listener, output, destroy);
wl_list_remove(&output->link);
}
static void
new_output_notify(struct wl_listener *listener, void *data)
{
/* This event is rasied by the backend when a new output (aka a display
* or monitor) becomes available. */
@ -329,39 +330,51 @@ output_new(struct wl_listener *listener, void *data)
struct wlr_output *wlr_output = data;
/*
* Some backends don't have modes. DRM+KMS does, and we need to set a
* mode before we can use the output. The mode is a tuple of (width,
* height, refresh rate), and each monitor supports only a specific set
* of modes. We just pick the monitor's preferred mode.
* The mode is a tuple of (width, height, refresh rate).
* TODO: support user configuration
*/
if (!wl_list_empty(&wlr_output->modes)) {
struct wlr_output_mode *mode =
wlr_output_preferred_mode(wlr_output);
struct wlr_output_mode *mode = wlr_output_preferred_mode(wlr_output);
if (mode) {
wlr_output_set_mode(wlr_output, mode);
wlr_output_enable(wlr_output, true);
if (!wlr_output_commit(wlr_output)) {
return;
}
wlr_output_commit(wlr_output);
}
/* Allocates and configures our state for this output */
struct output *output = calloc(1, sizeof(struct output));
output->wlr_output = wlr_output;
output->server = server;
/* Sets up a listener for the frame notify event. */
output->frame.notify = output_frame;
output->frame.notify = output_frame_notify;
wl_signal_add(&wlr_output->events.frame, &output->frame);
wl_list_insert(&server->outputs, &output->link);
output->destroy.notify = output_destroy_notify;
wl_signal_add(&wlr_output->events.destroy, &output->destroy);
/* Adds this to the output layout. The add_auto function arranges
* outputs from left-to-right in the order they appear. A more
* sophisticated compositor would let the user configure the arrangement
* of outputs in the layout.
*
* The output layout utility automatically adds a wl_output global to
* the display, which Wayland clients can see to find out information
* about the output (such as DPI, scale factor, manufacturer, etc).
/*
* Arrange outputs from left-to-right in the order they appear.
* TODO: support configuration in run-time
*/
wlr_output_layout_add_auto(server->output_layout, wlr_output);
wlr_output_schedule_frame(wlr_output);
}
void
output_init(struct server *server)
{
server->new_output.notify = new_output_notify;
wl_signal_add(&server->backend->events.new_output, &server->new_output);
/*
* Create an output layout, which is a wlroots utility for working with
* an arrangement of screens in a physical layout.
*/
server->output_layout = wlr_output_layout_create();
if (!server->output_layout) {
wlr_log(WLR_ERROR, "unable to create output layout");
exit(EXIT_FAILURE);
}
/* Enable screen recording with wf-recorder */
wlr_xdg_output_manager_v1_create(server->wl_display,
server->output_layout);
wl_list_init(&server->outputs);
}

View file

@ -9,9 +9,7 @@
#include <wlr/types/wlr_gamma_control_v1.h>
#include <wlr/types/wlr_primary_selection_v1.h>
#include <wlr/types/wlr_screencopy_v1.h>
#include <wlr/types/wlr_xdg_output_v1.h>
static struct wlr_backend *backend;
static struct wlr_compositor *compositor;
static struct wl_event_source *sighup_source;
@ -117,18 +115,14 @@ server_init(struct server *server)
event_loop, SIGHUP, handle_signal, &server->wl_display);
/*
* The backend is a wlroots feature which abstracts the underlying
* input and output hardware. the autocreate option will choose the
* most suitable backend based on the current environment, such as
* opening an x11 window if an x11 server is running. the null
* argument here optionally allows you to pass in a custom renderer if
* wlr_renderer doesn't meet your needs. the backend uses the
* renderer, for example, to fall back to software cursors if the
* backend does not support hardware cursors (some older gpus don't).
* The backend is a feature which abstracts the underlying input and
* output hardware. The autocreate option will choose the most suitable
* backend based on the current environment, such as opening an x11
* window if an x11 server is running.
*/
backend = wlr_backend_autocreate(server->wl_display, NULL);
if (!backend) {
wlr_log(WLR_ERROR, "unable to create the wlroots backend");
server->backend = wlr_backend_autocreate(server->wl_display, NULL);
if (!server->backend) {
wlr_log(WLR_ERROR, "unable to create backend");
exit(EXIT_FAILURE);
}
@ -138,22 +132,11 @@ server_init(struct server *server)
* formats it supports for shared memory, this configures that for
* clients.
*/
server->renderer = wlr_backend_get_renderer(backend);
server->renderer = wlr_backend_get_renderer(server->backend);
wlr_renderer_init_wl_display(server->renderer, server->wl_display);
wl_list_init(&server->views);
wl_list_init(&server->unmanaged_surfaces);
wl_list_init(&server->outputs);
/*
* Create an output layout, which a wlroots utility for working with
* an arrangement of screens in a physical layout.
*/
server->output_layout = wlr_output_layout_create();
if (!server->output_layout) {
wlr_log(WLR_ERROR, "unable to create output layout");
exit(EXIT_FAILURE);
}
/*
* Create some hands-off wlroots interfaces. The compositor is
@ -176,12 +159,7 @@ server_init(struct server *server)
exit(EXIT_FAILURE);
}
/*
* Configure a listener to be notified when new outputs are available
* on the backend.
*/
server->new_output.notify = output_new;
wl_signal_add(&backend->events.new_output, &server->new_output);
output_init(server);
/*
* Configures a seat, which is a single "seat" at which a user sits
@ -218,7 +196,7 @@ server_init(struct server *server)
wl_list_init(&server->keyboards);
server->new_input.notify = server_new_input;
wl_signal_add(&backend->events.new_input, &server->new_input);
wl_signal_add(&server->backend->events.new_input, &server->new_input);
server->request_cursor.notify = seat_request_cursor;
wl_signal_add(&server->seat->events.request_set_cursor,
&server->request_cursor);
@ -263,8 +241,6 @@ server_init(struct server *server)
wlr_data_control_manager_v1_create(server->wl_display);
wlr_gamma_control_manager_v1_create(server->wl_display);
wlr_primary_selection_v1_device_manager_create(server->wl_display);
wlr_xdg_output_manager_v1_create(server->wl_display,
server->output_layout);
/* Init xwayland */
server->xwayland =
@ -320,7 +296,7 @@ server_start(struct server *server)
* Start the backend. This will enumerate outputs and inputs, become
* the DRM master, etc
*/
if (!wlr_backend_start(backend)) {
if (!wlr_backend_start(server->backend)) {
wlr_log(WLR_ERROR, "unable to start the wlroots backend");
exit(EXIT_FAILURE);
}