Commit ea2825ea authored by Dorota Czaplejewicz's avatar Dorota Czaplejewicz
Browse files

Merge branch 'sway/master' into librem5

This merge pulls input-method and text-input support.
parents 71d11894 67a2040c
Pipeline #1584 passed with stage
in 3 minutes and 10 seconds
......@@ -25,4 +25,4 @@ tasks:
ninja
- clang: |
cd wlroots/build-clang
ninja
ninja scan-build
......@@ -5,10 +5,8 @@ end_of_line = lf
insert_final_newline = true
charset = utf-8
indent_style = tab
indent_size = 4
trim_trailing_whitespace = true
[*.xml]
indent_style = space
indent_size = 2
tab_width = 8
......@@ -30,8 +30,8 @@ development tools - or any subset of these features you like, because all of
them work independently of one another and freely compose with anything you want
to implement yourself.
**Status**: prior to 1.0 the API is not stable, but we've done most of the work
and various projects are using wlroots to build Wayland compositors with.
Check out our [wiki](https://github.com/swaywm/wlroots/wiki/Getting-started) to
get started with wlroots.
wlroots is developed under the direction of the
[sway](https://github.com/swaywm/sway) project. A variety of wrapper libraries
......@@ -74,9 +74,6 @@ Run these commands:
meson build
ninja -C build
On FreeBSD, you need to pass an extra flag to prevent a linking error:
`meson build -D b_lundef=false`.
Install like so:
sudo ninja -C build install
......@@ -86,7 +83,8 @@ Install like so:
wlroots comes with a test compositor called rootston, which demonstrates the
features of the library and is used as a testbed for the development of the
library. It may also be useful as a reference for understanding how to use
various wlroots features.
various wlroots features, but it's not considered a production-quality codebase
and is not designed for daily use.
If you followed the build instructions above the rootston executable can be
found at `./build/rootston/rootston`. To use it, refer to the example config at
......
......@@ -15,6 +15,7 @@
#include <wlr/backend/wayland.h>
#include <wlr/config.h>
#include <wlr/util/log.h>
#include "backend/multi.h"
/* WLR_HAS_X11_BACKEND needs to be after wlr/config.h */
#ifdef WLR_HAS_X11_BACKEND
......@@ -56,6 +57,20 @@ struct wlr_renderer *wlr_backend_get_renderer(struct wlr_backend *backend) {
return NULL;
}
struct wlr_session *wlr_backend_get_session(struct wlr_backend *backend) {
if (backend->impl->get_session) {
return backend->impl->get_session(backend);
}
return NULL;
}
clockid_t wlr_backend_get_presentation_clock(struct wlr_backend *backend) {
if (backend->impl->get_presentation_clock) {
return backend->impl->get_presentation_clock(backend);
}
return CLOCK_MONOTONIC;
}
static size_t parse_outputs_env(const char *name) {
const char *outputs_str = getenv(name);
if (outputs_str == NULL) {
......@@ -158,10 +173,12 @@ static struct wlr_backend *attempt_backend_by_name(struct wl_display *display,
return attempt_headless_backend(display, create_renderer_func);
} else if (strcmp(name, "drm") == 0 || strcmp(name, "libinput") == 0) {
// DRM and libinput need a session
*session = wlr_session_create(display);
if (!*session) {
wlr_log(WLR_ERROR, "failed to start a session");
return NULL;
*session = wlr_session_create(display);
if (!*session) {
wlr_log(WLR_ERROR, "failed to start a session");
return NULL;
}
}
if (strcmp(name, "libinput") == 0) {
......@@ -178,13 +195,12 @@ static struct wlr_backend *attempt_backend_by_name(struct wl_display *display,
struct wlr_backend *wlr_backend_autocreate(struct wl_display *display,
wlr_renderer_create_func_t create_renderer_func) {
struct wlr_backend *backend = wlr_multi_backend_create(display);
struct wlr_multi_backend *multi = (struct wlr_multi_backend *)backend;
if (!backend) {
wlr_log(WLR_ERROR, "could not allocate multibackend");
return NULL;
}
struct wlr_session *session = NULL;
char *names = getenv("WLR_BACKENDS");
if (names) {
names = strdup(names);
......@@ -197,12 +213,12 @@ struct wlr_backend *wlr_backend_autocreate(struct wl_display *display,
char *saveptr;
char *name = strtok_r(names, ",", &saveptr);
while (name != NULL) {
struct wlr_backend *subbackend =
attempt_backend_by_name(display, backend, &session, name, create_renderer_func);
struct wlr_backend *subbackend = attempt_backend_by_name(display,
backend, &multi->session, name, create_renderer_func);
if (subbackend == NULL) {
wlr_log(WLR_ERROR, "failed to start backend '%s'", name);
wlr_backend_destroy(backend);
wlr_session_destroy(session);
wlr_session_destroy(multi->session);
free(names);
return NULL;
}
......@@ -210,7 +226,7 @@ struct wlr_backend *wlr_backend_autocreate(struct wl_display *display,
if (!wlr_multi_backend_add(backend, subbackend)) {
wlr_log(WLR_ERROR, "failed to add backend '%s'", name);
wlr_backend_destroy(backend);
wlr_session_destroy(session);
wlr_session_destroy(multi->session);
free(names);
return NULL;
}
......@@ -245,29 +261,30 @@ struct wlr_backend *wlr_backend_autocreate(struct wl_display *display,
#endif
// Attempt DRM+libinput
session = wlr_session_create(display);
if (!session) {
multi->session = wlr_session_create(display);
if (!multi->session) {
wlr_log(WLR_ERROR, "Failed to start a DRM session");
wlr_backend_destroy(backend);
return NULL;
}
struct wlr_backend *libinput = wlr_libinput_backend_create(display, session);
struct wlr_backend *libinput = wlr_libinput_backend_create(display,
multi->session);
if (!libinput) {
wlr_log(WLR_ERROR, "Failed to start libinput backend");
wlr_backend_destroy(backend);
wlr_session_destroy(session);
wlr_session_destroy(multi->session);
return NULL;
}
wlr_multi_backend_add(backend, libinput);
struct wlr_backend *primary_drm =
attempt_drm_backend(display, backend, session, create_renderer_func);
struct wlr_backend *primary_drm = attempt_drm_backend(display, backend,
multi->session, create_renderer_func);
if (!primary_drm) {
wlr_log(WLR_ERROR, "Failed to open any DRM device");
wlr_backend_destroy(libinput);
wlr_backend_destroy(backend);
wlr_session_destroy(session);
wlr_session_destroy(multi->session);
return NULL;
}
......
......@@ -104,7 +104,8 @@ static bool atomic_crtc_pageflip(struct wlr_drm_backend *drm,
drmModeDestroyPropertyBlob(drm->fd, crtc->mode_id);
}
if (drmModeCreatePropertyBlob(drm->fd, mode, sizeof(*mode), &crtc->mode_id)) {
if (drmModeCreatePropertyBlob(drm->fd, mode, sizeof(*mode),
&crtc->mode_id)) {
wlr_log_errno(WLR_ERROR, "Unable to create property blob");
return false;
}
......@@ -120,6 +121,10 @@ static bool atomic_crtc_pageflip(struct wlr_drm_backend *drm,
struct atomic atom;
atomic_begin(crtc, &atom);
atomic_add(&atom, conn->id, conn->props.crtc_id, crtc->id);
if (mode != NULL && conn->props.link_status != 0) {
atomic_add(&atom, conn->id, conn->props.link_status,
DRM_MODE_LINK_STATUS_GOOD);
}
atomic_add(&atom, crtc->id, crtc->props.mode_id, crtc->mode_id);
atomic_add(&atom, crtc->id, crtc->props.active, 1);
set_plane_props(&atom, crtc->primary, crtc->id, fb_id, true);
......@@ -129,6 +134,9 @@ static bool atomic_crtc_pageflip(struct wlr_drm_backend *drm,
static bool atomic_conn_enable(struct wlr_drm_backend *drm,
struct wlr_drm_connector *conn, bool enable) {
struct wlr_drm_crtc *crtc = conn->crtc;
if (crtc == NULL) {
return !enable;
}
struct atomic atom;
atomic_begin(crtc, &atom);
......@@ -197,14 +205,14 @@ static bool atomic_crtc_move_cursor(struct wlr_drm_backend *drm,
}
static bool atomic_crtc_set_gamma(struct wlr_drm_backend *drm,
struct wlr_drm_crtc *crtc, uint16_t *r, uint16_t *g, uint16_t *b,
uint32_t size) {
struct wlr_drm_crtc *crtc, size_t size,
uint16_t *r, uint16_t *g, uint16_t *b) {
// Fallback to legacy gamma interface when gamma properties are not available
// (can happen on older intel gpu's that support gamma but not degamma)
// TEMP: This is broken on AMDGPU. Always fallback to legacy until they get
// it fixed. Ref https://bugs.freedesktop.org/show_bug.cgi?id=107459
if (crtc->props.gamma_lut == 0 || true) {
return legacy_iface.crtc_set_gamma(drm, crtc, r, g, b, size);
return legacy_iface.crtc_set_gamma(drm, crtc, size, r, g, b);
}
struct drm_color_lut *gamma = malloc(size * sizeof(struct drm_color_lut));
......@@ -213,7 +221,7 @@ static bool atomic_crtc_set_gamma(struct wlr_drm_backend *drm,
return false;
}
for (uint32_t i = 0; i < size; i++) {
for (size_t i = 0; i < size; i++) {
gamma[i].red = r[i];
gamma[i].green = g[i];
gamma[i].blue = b[i];
......@@ -237,21 +245,20 @@ static bool atomic_crtc_set_gamma(struct wlr_drm_backend *drm,
return atomic_end(drm->fd, &atom);
}
static uint32_t atomic_crtc_get_gamma_size(struct wlr_drm_backend *drm,
static size_t atomic_crtc_get_gamma_size(struct wlr_drm_backend *drm,
struct wlr_drm_crtc *crtc) {
uint64_t gamma_lut_size;
if (crtc->props.gamma_lut_size == 0) {
return legacy_iface.crtc_get_gamma_size(drm, crtc);
}
uint64_t gamma_lut_size;
if (!get_drm_prop(drm->fd, crtc->id, crtc->props.gamma_lut_size,
&gamma_lut_size)) {
&gamma_lut_size)) {
wlr_log(WLR_ERROR, "Unable to get gamma lut size");
return 0;
}
return (uint32_t)gamma_lut_size;
return (size_t)gamma_lut_size;
}
const struct wlr_drm_interface atomic_iface = {
......
......@@ -15,8 +15,14 @@
#include "backend/drm/drm.h"
#include "util/signal.h"
struct wlr_drm_backend *get_drm_backend_from_backend(
struct wlr_backend *wlr_backend) {
assert(wlr_backend_is_drm(wlr_backend));
return (struct wlr_drm_backend *)wlr_backend;
}
static bool backend_start(struct wlr_backend *backend) {
struct wlr_drm_backend *drm = (struct wlr_drm_backend *)backend;
struct wlr_drm_backend *drm = get_drm_backend_from_backend(backend);
scan_drm_connectors(drm);
return true;
}
......@@ -26,7 +32,7 @@ static void backend_destroy(struct wlr_backend *backend) {
return;
}
struct wlr_drm_backend *drm = (struct wlr_drm_backend *)backend;
struct wlr_drm_backend *drm = get_drm_backend_from_backend(backend);
restore_drm_outputs(drm);
......@@ -50,7 +56,7 @@ static void backend_destroy(struct wlr_backend *backend) {
static struct wlr_renderer *backend_get_renderer(
struct wlr_backend *backend) {
struct wlr_drm_backend *drm = (struct wlr_drm_backend *)backend;
struct wlr_drm_backend *drm = get_drm_backend_from_backend(backend);
if (drm->parent) {
return drm->parent->renderer.wlr_rend;
......@@ -59,10 +65,16 @@ static struct wlr_renderer *backend_get_renderer(
}
}
static clockid_t backend_get_presentation_clock(struct wlr_backend *backend) {
struct wlr_drm_backend *drm = get_drm_backend_from_backend(backend);
return drm->clock;
}
static struct wlr_backend_impl backend_impl = {
.start = backend_start,
.destroy = backend_destroy,
.get_renderer = backend_get_renderer,
.get_presentation_clock = backend_get_presentation_clock,
};
bool wlr_backend_is_drm(struct wlr_backend *b) {
......@@ -95,6 +107,16 @@ static void session_signal(struct wl_listener *listener, void *data) {
(plane && plane->cursor_enabled) ? plane->cursor_bo : NULL);
drm->iface->crtc_move_cursor(drm, conn->crtc, conn->cursor_x,
conn->cursor_y);
if (conn->crtc->gamma_table != NULL) {
size_t size = conn->crtc->gamma_table_size;
uint16_t *r = conn->crtc->gamma_table;
uint16_t *g = conn->crtc->gamma_table + size;
uint16_t *b = conn->crtc->gamma_table + 2 * size;
drm->iface->crtc_set_gamma(drm, conn->crtc, size, r, g, b);
} else {
set_drm_connector_gamma(&conn->output, 0, NULL, NULL, NULL);
}
}
} else {
wlr_log(WLR_INFO, "DRM fd paused");
......@@ -141,7 +163,9 @@ struct wlr_backend *wlr_drm_backend_create(struct wl_display *display,
wl_list_init(&drm->outputs);
drm->fd = gpu_fd;
drm->parent = (struct wlr_drm_backend *)parent;
if (parent != NULL) {
drm->parent = get_drm_backend_from_backend(parent);
}
drm->drm_invalidated.notify = drm_invalidated;
wlr_session_signal_add(session, gpu_fd, &drm->drm_invalidated);
......@@ -185,8 +209,3 @@ error_fd:
free(drm);
return NULL;
}
struct wlr_session *wlr_drm_backend_get_session(struct wlr_backend *backend) {
struct wlr_drm_backend *drm = (struct wlr_drm_backend *)backend;
return drm->session;
}
This diff is collapsed.
......@@ -39,7 +39,10 @@ bool legacy_crtc_set_cursor(struct wlr_drm_backend *drm,
}
if (!bo) {
drmModeSetCursor(drm->fd, crtc->id, 0, 0, 0);
if (drmModeSetCursor(drm->fd, crtc->id, 0, 0, 0)) {
wlr_log_errno(WLR_DEBUG, "Failed to clear hardware cursor");
return false;
}
return true;
}
......@@ -60,14 +63,14 @@ bool legacy_crtc_move_cursor(struct wlr_drm_backend *drm,
}
bool legacy_crtc_set_gamma(struct wlr_drm_backend *drm,
struct wlr_drm_crtc *crtc, uint16_t *r, uint16_t *g, uint16_t *b,
uint32_t size) {
return !drmModeCrtcSetGamma(drm->fd, crtc->id, size, r, g, b);
struct wlr_drm_crtc *crtc, size_t size,
uint16_t *r, uint16_t *g, uint16_t *b) {
return !drmModeCrtcSetGamma(drm->fd, crtc->id, (uint32_t)size, r, g, b);
}
uint32_t legacy_crtc_get_gamma_size(struct wlr_drm_backend *drm,
size_t legacy_crtc_get_gamma_size(struct wlr_drm_backend *drm,
struct wlr_drm_crtc *crtc) {
return crtc->legacy_crtc->gamma_size;
return (size_t)crtc->legacy_crtc->gamma_size;
}
const struct wlr_drm_interface legacy_iface = {
......
......@@ -19,9 +19,10 @@ struct prop_info {
static const struct prop_info connector_info[] = {
#define INDEX(name) (offsetof(union wlr_drm_connector_props, name) / sizeof(uint32_t))
{ "CRTC_ID", INDEX(crtc_id) },
{ "DPMS", INDEX(dpms) },
{ "EDID", INDEX(edid) },
{ "CRTC_ID", INDEX(crtc_id) },
{ "DPMS", INDEX(dpms) },
{ "EDID", INDEX(edid) },
{ "link-status", INDEX(link_status) },
#undef INDEX
};
......@@ -87,7 +88,8 @@ static bool scan_properties(int fd, uint32_t id, uint32_t type, uint32_t *result
return true;
}
bool get_drm_connector_props(int fd, uint32_t id, union wlr_drm_connector_props *out) {
bool get_drm_connector_props(int fd, uint32_t id,
union wlr_drm_connector_props *out) {
return scan_properties(fd, id, DRM_MODE_OBJECT_CONNECTOR, out->props,
connector_info, sizeof(connector_info) / sizeof(connector_info[0]));
}
......@@ -103,7 +105,8 @@ bool get_drm_plane_props(int fd, uint32_t id, union wlr_drm_plane_props *out) {
}
bool get_drm_prop(int fd, uint32_t obj, uint32_t prop, uint64_t *ret) {
drmModeObjectProperties *props = drmModeObjectGetProperties(fd, obj, DRM_MODE_OBJECT_ANY);
drmModeObjectProperties *props =
drmModeObjectGetProperties(fd, obj, DRM_MODE_OBJECT_ANY);
if (!props) {
return false;
}
......
......@@ -32,21 +32,30 @@ static const char *get_manufacturer(uint16_t id) {
case ID('A', 'A', 'A'): return "Avolites Ltd";
case ID('A', 'C', 'I'): return "Ancor Communications Inc";
case ID('A', 'C', 'R'): return "Acer Technologies";
case ID('A', 'D', 'A'): return "Addi-Data GmbH";
case ID('A', 'P', 'P'): return "Apple Computer Inc";
case ID('A', 'S', 'K'): return "Ask A/S";
case ID('A', 'V', 'T'): return "Avtek (Electronics) Pty Ltd";
case ID('B', 'N', 'O'): return "Bang & Olufsen";
case ID('C', 'M', 'N'): return "Chimei Innolux Corporation";
case ID('C', 'M', 'O'): return "Chi Mei Optoelectronics corp.";
case ID('C', 'R', 'O'): return "Extraordinary Technologies PTY Limited";
case ID('D', 'E', 'L'): return "Dell Inc.";
case ID('D', 'G', 'C'): return "Data General Corporation";
case ID('D', 'O', 'N'): return "DENON, Ltd.";
case ID('E', 'N', 'C'): return "Eizo Nanao Corporation";
case ID('E', 'P', 'H'): return "Epiphan Systems Inc.";
case ID('E', 'X', 'P'): return "Data Export Corporation";
case ID('F', 'N', 'I'): return "Funai Electric Co., Ltd.";
case ID('F', 'U', 'S'): return "Fujitsu Siemens Computers GmbH";
case ID('G', 'S', 'M'): return "Goldstar Company Ltd";
case ID('H', 'I', 'Q'): return "Kaohsiung Opto Electronics Americas, Inc.";
case ID('H', 'S', 'D'): return "HannStar Display Corp";
case ID('H', 'T', 'C'): return "Hitachi Ltd";
case ID('H', 'W', 'P'): return "Hewlett Packard";
case ID('I', 'N', 'T'): return "Interphase Corporation";
case ID('I', 'N', 'X'): return "Communications Supply Corporation (A division of WESCO)";
case ID('I', 'T', 'E'): return "Integrated Tech Express Inc";
case ID('I', 'V', 'M'): return "Iiyama North America";
case ID('L', 'E', 'N'): return "Lenovo Group Limited";
case ID('M', 'A', 'X'): return "Rogen Tech Distribution Inc";
......@@ -55,6 +64,7 @@ static const char *get_manufacturer(uint16_t id) {
case ID('M', 'T', 'C'): return "Mars-Tech Corporation";
case ID('M', 'T', 'X'): return "Matrox";
case ID('N', 'E', 'C'): return "NEC Corporation";
case ID('N', 'E', 'X'): return "Nexgen Mediatech Inc.";
case ID('O', 'N', 'K'): return "ONKYO Corporation";
case ID('O', 'R', 'N'): return "ORION ELECTRIC CO., LTD.";
case ID('O', 'T', 'M'): return "Optoma Corporation";
......@@ -63,15 +73,24 @@ static const char *get_manufacturer(uint16_t id) {
case ID('P', 'I', 'O'): return "Pioneer Electronic Corporation";
case ID('P', 'N', 'R'): return "Planar Systems, Inc.";
case ID('Q', 'D', 'S'): return "Quanta Display Inc.";
case ID('R', 'A', 'T'): return "Rent-A-Tech";
case ID('R', 'E', 'N'): return "Renesas Technology Corp.";
case ID('S', 'A', 'M'): return "Samsung Electric Company";
case ID('S', 'A', 'N'): return "Sanyo Electric Co., Ltd.";
case ID('S', 'E', 'C'): return "Seiko Epson Corporation";
case ID('S', 'H', 'P'): return "Sharp Corporation";
case ID('S', 'I', 'I'): return "Silicon Image, Inc.";
case ID('S', 'N', 'Y'): return "Sony";
case ID('S', 'T', 'D'): return "STD Computer Inc";
case ID('S', 'V', 'S'): return "SVSI";
case ID('S', 'Y', 'N'): return "Synaptics Inc";
case ID('T', 'C', 'L'): return "Technical Concepts Ltd";
case ID('T', 'O', 'P'): return "Orion Communications Co., Ltd.";
case ID('T', 'S', 'B'): return "Toshiba America Info Systems Inc";
case ID('T', 'S', 'T'): return "Transtream Inc";
case ID('U', 'N', 'K'): return "Unknown";
case ID('V', 'E', 'S'): return "Vestel Elektronik Sanayi ve Ticaret A. S.";
case ID('V', 'I', 'T'): return "Visitech AS";
case ID('V', 'I', 'Z'): return "VIZIO, Inc";
case ID('V', 'S', 'C'): return "ViewSonic Corporation";
case ID('Y', 'M', 'H'): return "Yamaha Corporation";
......@@ -223,14 +242,12 @@ struct match_state {
static bool match_obj_(struct match_state *st, size_t skips, size_t score, size_t replaced, size_t i) {
// Finished
if (i >= st->num_res) {
if (score > st->score || (score == st->score && replaced < st->replaced)) {
if (score > st->score ||
(score == st->score && replaced < st->replaced)) {
st->score = score;
st->replaced = replaced;
memcpy(st->best, st->res, sizeof(st->best[0]) * st->num_res);
if (st->score == st->num_objs && st->replaced == 0) {
st->exit_early = true;
}
st->exit_early = (st->score == st->num_res - skips
|| st->score == st->num_objs)
&& st->replaced == 0;
......@@ -246,41 +263,53 @@ static bool match_obj_(struct match_state *st, size_t skips, size_t score, size_
return match_obj_(st, skips + 1, score, replaced, i + 1);
}
bool has_best = false;
/*
* Attempt to use the current solution first, to try and avoid
* recalculating everything
*/
if (st->orig[i] != UNMATCHED && !is_taken(i, st->res, st->orig[i])) {
st->res[i] = st->orig[i];
if (match_obj_(st, skips, score + 1, replaced, i + 1)) {
return true;
size_t obj_score = st->objs[st->res[i]] != 0 ? 1 : 0;
if (match_obj_(st, skips, score + obj_score, replaced, i + 1)) {
has_best = true;
}
}
if (st->orig[i] == UNMATCHED) {
st->res[i] = UNMATCHED;
if (match_obj_(st, skips, score, replaced, i + 1)) {
has_best = true;
}
}
if (st->exit_early) {
return true;
}
if (st->orig[i] != UNMATCHED) {
++replaced;
}
bool is_best = false;
for (st->res[i] = 0; st->res[i] < st->num_objs; ++st->res[i]) {
for (size_t candidate = 0; candidate < st->num_objs; ++candidate) {
// We tried this earlier
if (st->res[i] == st->orig[i]) {
if (candidate == st->orig[i]) {
continue;
}
// Not compatible
if (!(st->objs[st->res[i]] & (1 << i))) {
if (!(st->objs[candidate] & (1 << i))) {
continue;
}
// Already taken
if (is_taken(i, st->res, st->res[i])) {
if (is_taken(i, st->res, candidate)) {
continue;
}
if (match_obj_(st, skips, score + 1, replaced, i + 1)) {
is_best = true;
st->res[i] = candidate;
size_t obj_score = st->objs[candidate] != 0 ? 1 : 0;
if (match_obj_(st, skips, score + obj_score, replaced, i + 1)) {
has_best = true;
}
if (st->exit_early) {
......@@ -288,7 +317,7 @@ static bool match_obj_(struct match_state *st, size_t skips, size_t score, size_
}
}
if (is_best) {
if (has_best) {
return true;
}
......@@ -301,6 +330,9 @@ size_t match_obj(size_t num_objs, const uint32_t objs[static restrict num_objs],
size_t num_res, const uint32_t res[static restrict num_res],
uint32_t out[static restrict num_res]) {
uint32_t solution[num_res];
for (size_t i = 0; i < num_res; ++i) {
solution[i] = UNMATCHED;
}
struct match_state st = {
.num_objs = num_objs,
......
#include "util/signal.h"
#include <assert.h>
#include <stdlib.h>
#include <wlr/interfaces/wlr_input_device.h>
#include <wlr/interfaces/wlr_output.h>
......@@ -7,10 +7,17 @@
#include <wlr/util/log.h>
#include "backend/headless.h"
#include "glapi.h"
#include "util/signal.h"
struct wlr_headless_backend *headless_backend_from_backend(
struct wlr_backend *wlr_backend) {
assert(wlr_backend_is_headless(wlr_backend));
return (struct wlr_headless_backend *)wlr_backend;
}
static bool backend_start(struct wlr_backend *wlr_backend) {
struct wlr_headless_backend *backend =
(struct wlr_headless_backend *)wlr_backend;
headless_backend_from_backend(wlr_backend);
wlr_log(WLR_INFO, "Starting headless backend");
struct wlr_headless_output *output;
......@@ -34,7 +41,7 @@ static bool backend_start(struct wlr_backend *wlr_backend) {
static void backend_destroy(struct wlr_backend *wlr_backend) {
struct wlr_headless_backend *backend =
(struct wlr_headless_backend *)wlr_backend;
headless_backend_from_backend(wlr_backend);
if (!wlr_backend) {
return;
}
......@@ -62,7 +69,7 @@ static void backend_destroy(struct wlr_backend *wlr_backend) {
static struct wlr_renderer *backend_get_renderer(
struct wlr_backend *wlr_backend) {
struct wlr_headless_backend *backend =
(struct wlr_headless_backend *)wlr_backend;
headless_backend_from_backend(wlr_backend);
return backend->renderer;
}