From c8a8ff66f2bdeab0623c11c1c381b52bc41fbf0d Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Sat, 26 Aug 2017 16:55:38 +1200 Subject: Removed unused fields --- backend/drm/backend.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'backend') diff --git a/backend/drm/backend.c b/backend/drm/backend.c index 8d562007..c394ed65 100644 --- a/backend/drm/backend.c +++ b/backend/drm/backend.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -119,12 +118,6 @@ struct wlr_backend *wlr_drm_backend_create(struct wl_display *display, backend->fd = gpu_fd; - struct stat st; - if (fstat(backend->fd, &st) < 0) { - wlr_log_errno(L_ERROR, "Stat failed"); - } - backend->dev = st.st_rdev; - backend->drm_invalidated.notify = drm_invalidated; wlr_session_signal_add(session, gpu_fd, &backend->drm_invalidated); -- cgit v1.2.3 From 610b0493ac4a3bbde44378adf855c7202b1e59c4 Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Sat, 30 Sep 2017 19:03:34 +1300 Subject: Rename files to remove pointless drm prefix --- backend/drm/backend.c | 2 +- backend/drm/drm-atomic.c | 188 ------------------------ backend/drm/drm-legacy.c | 65 --------- backend/drm/drm-properties.c | 145 ------------------- backend/drm/drm-util.c | 303 --------------------------------------- backend/drm/drm.c | 14 +- backend/drm/iface_atomic.c | 188 ++++++++++++++++++++++++ backend/drm/iface_legacy.c | 65 +++++++++ backend/drm/properties.c | 145 +++++++++++++++++++ backend/drm/util.c | 303 +++++++++++++++++++++++++++++++++++++++ backend/meson.build | 8 +- include/backend/drm-properties.h | 67 --------- include/backend/drm-util.h | 39 ----- include/backend/drm.h | 186 ------------------------ include/backend/drm/drm.h | 186 ++++++++++++++++++++++++ include/backend/drm/properties.h | 67 +++++++++ include/backend/drm/util.h | 39 +++++ 17 files changed, 1005 insertions(+), 1005 deletions(-) delete mode 100644 backend/drm/drm-atomic.c delete mode 100644 backend/drm/drm-legacy.c delete mode 100644 backend/drm/drm-properties.c delete mode 100644 backend/drm/drm-util.c create mode 100644 backend/drm/iface_atomic.c create mode 100644 backend/drm/iface_legacy.c create mode 100644 backend/drm/properties.c create mode 100644 backend/drm/util.c delete mode 100644 include/backend/drm-properties.h delete mode 100644 include/backend/drm-util.h delete mode 100644 include/backend/drm.h create mode 100644 include/backend/drm/drm.h create mode 100644 include/backend/drm/properties.h create mode 100644 include/backend/drm/util.h (limited to 'backend') diff --git a/backend/drm/backend.c b/backend/drm/backend.c index c394ed65..e046cea6 100644 --- a/backend/drm/backend.c +++ b/backend/drm/backend.c @@ -12,7 +12,7 @@ #include #include #include -#include "backend/drm.h" +#include "backend/drm/drm.h" static bool wlr_drm_backend_start(struct wlr_backend *_backend) { struct wlr_drm_backend *backend = (struct wlr_drm_backend *)_backend; diff --git a/backend/drm/drm-atomic.c b/backend/drm/drm-atomic.c deleted file mode 100644 index 16c9c5c3..00000000 --- a/backend/drm/drm-atomic.c +++ /dev/null @@ -1,188 +0,0 @@ -#include -#include -#include -#include -#include "backend/drm.h" -#include "backend/drm-util.h" - -struct atomic { - drmModeAtomicReq *req; - int cursor; - bool failed; -}; - -static void atomic_begin(struct wlr_drm_crtc *crtc, struct atomic *atom) { - if (!crtc->atomic) { - crtc->atomic = drmModeAtomicAlloc(); - if (!crtc->atomic) { - wlr_log_errno(L_ERROR, "Allocation failed"); - atom->failed = true; - return; - } - } - - atom->req = crtc->atomic; - atom->cursor = drmModeAtomicGetCursor(atom->req); - atom->failed = false; -} - -static bool atomic_end(int drm_fd, struct atomic *atom) { - if (atom->failed) { - return false; - } - - uint32_t flags = DRM_MODE_ATOMIC_TEST_ONLY | DRM_MODE_ATOMIC_NONBLOCK; - - if (drmModeAtomicCommit(drm_fd, atom->req, flags, NULL)) { - wlr_log_errno(L_ERROR, "Atomic test failed"); - drmModeAtomicSetCursor(atom->req, atom->cursor); - return false; - } - - return true; -} - -static bool atomic_commit(int drm_fd, struct atomic *atom, - struct wlr_drm_output *output, uint32_t flag, bool modeset) { - if (atom->failed) { - return false; - } - - uint32_t flags = DRM_MODE_PAGE_FLIP_EVENT | flag; - - int ret = drmModeAtomicCommit(drm_fd, atom->req, flags, output); - if (ret) { - wlr_log_errno(L_ERROR, "%s: Atomic commit failed (%s)", - output->output.name, modeset ? "modeset" : "pageflip"); - - // Try to commit without new changes - drmModeAtomicSetCursor(atom->req, atom->cursor); - if (drmModeAtomicCommit(drm_fd, atom->req, flags, output)) { - wlr_log_errno(L_ERROR, "%s: Atomic commit failed (%s)", - output->output.name, modeset ? "modeset" : "pageflip"); - } - } - - drmModeAtomicSetCursor(atom->req, 0); - - return !ret; -} - -static inline void atomic_add(struct atomic *atom, uint32_t id, uint32_t prop, uint64_t val) { - if (!atom->failed && drmModeAtomicAddProperty(atom->req, id, prop, val) < 0) { - wlr_log_errno(L_ERROR, "Failed to add atomic DRM property"); - atom->failed = true; - } -} - -static void set_plane_props(struct atomic *atom, struct wlr_drm_plane *plane, - uint32_t crtc_id, uint32_t fb_id, bool set_crtc_xy) { - uint32_t id = plane->id; - const union wlr_drm_plane_props *props = &plane->props; - - // The src_* properties are in 16.16 fixed point - atomic_add(atom, id, props->src_x, 0); - atomic_add(atom, id, props->src_y, 0); - atomic_add(atom, id, props->src_w, plane->width << 16); - atomic_add(atom, id, props->src_h, plane->height << 16); - atomic_add(atom, id, props->crtc_w, plane->width); - atomic_add(atom, id, props->crtc_h, plane->height); - atomic_add(atom, id, props->fb_id, fb_id); - atomic_add(atom, id, props->crtc_id, crtc_id); - if (set_crtc_xy) { - atomic_add(atom, id, props->crtc_x, 0); - atomic_add(atom, id, props->crtc_y, 0); - } -} - -static bool atomic_crtc_pageflip(struct wlr_drm_backend *backend, - struct wlr_drm_output *output, - struct wlr_drm_crtc *crtc, - uint32_t fb_id, drmModeModeInfo *mode) { - if (mode) { - if (crtc->mode_id) { - drmModeDestroyPropertyBlob(backend->fd, crtc->mode_id); - } - - if (drmModeCreatePropertyBlob(backend->fd, mode, sizeof(*mode), &crtc->mode_id)) { - wlr_log_errno(L_ERROR, "Unable to create property blob"); - return false; - } - } - - struct atomic atom; - - atomic_begin(crtc, &atom); - atomic_add(&atom, output->connector, output->props.crtc_id, crtc->id); - 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); - return atomic_commit(backend->fd, &atom, output, - mode ? DRM_MODE_ATOMIC_ALLOW_MODESET : DRM_MODE_ATOMIC_NONBLOCK, - mode); -} - -static void atomic_conn_enable(struct wlr_drm_backend *backend, - struct wlr_drm_output *output, bool enable) { - struct wlr_drm_crtc *crtc = output->crtc; - struct atomic atom; - - atomic_begin(crtc, &atom); - atomic_add(&atom, crtc->id, crtc->props.active, enable); - atomic_end(backend->fd, &atom); -} - -bool legacy_crtc_set_cursor(struct wlr_drm_backend *backend, - struct wlr_drm_crtc *crtc, struct gbm_bo *bo); - -static bool atomic_crtc_set_cursor(struct wlr_drm_backend *backend, - struct wlr_drm_crtc *crtc, struct gbm_bo *bo) { - if (!crtc || !crtc->cursor) { - return true; - } - - struct wlr_drm_plane *plane = crtc->cursor; - // We can't use atomic operations on fake planes - if (plane->id == 0) { - return legacy_crtc_set_cursor(backend, crtc, bo); - } - - struct atomic atom; - - atomic_begin(crtc, &atom); - - if (bo) { - set_plane_props(&atom, plane, crtc->id, get_fb_for_bo(bo), false); - } else { - atomic_add(&atom, plane->id, plane->props.fb_id, 0); - atomic_add(&atom, plane->id, plane->props.crtc_id, 0); - } - - return atomic_end(backend->fd, &atom); -} - -bool legacy_crtc_move_cursor(struct wlr_drm_backend *backend, - struct wlr_drm_crtc *crtc, int x, int y); - -static bool atomic_crtc_move_cursor(struct wlr_drm_backend *backend, - struct wlr_drm_crtc *crtc, int x, int y) { - struct wlr_drm_plane *plane = crtc->cursor; - // We can't use atomic operations on fake planes - if (plane->id == 0) { - return legacy_crtc_move_cursor(backend, crtc, x, y); - } - - struct atomic atom; - - atomic_begin(crtc, &atom); - atomic_add(&atom, plane->id, plane->props.crtc_x, x); - atomic_add(&atom, plane->id, plane->props.crtc_y, y); - return atomic_end(backend->fd, &atom); -} - -const struct wlr_drm_interface atomic_iface = { - .conn_enable = atomic_conn_enable, - .crtc_pageflip = atomic_crtc_pageflip, - .crtc_set_cursor = atomic_crtc_set_cursor, - .crtc_move_cursor = atomic_crtc_move_cursor, -}; diff --git a/backend/drm/drm-legacy.c b/backend/drm/drm-legacy.c deleted file mode 100644 index 9b7cd301..00000000 --- a/backend/drm/drm-legacy.c +++ /dev/null @@ -1,65 +0,0 @@ -#include -#include -#include -#include -#include "backend/drm.h" -#include "backend/drm-util.h" - -static bool legacy_crtc_pageflip(struct wlr_drm_backend *backend, - struct wlr_drm_output *output, struct wlr_drm_crtc *crtc, - uint32_t fb_id, drmModeModeInfo *mode) { - if (mode) { - if (drmModeSetCrtc(backend->fd, crtc->id, fb_id, 0, 0, - &output->connector, 1, mode)) { - wlr_log_errno(L_ERROR, "%s: Failed to set CRTC", output->output.name); - return false; - } - } - - if (drmModePageFlip(backend->fd, crtc->id, fb_id, DRM_MODE_PAGE_FLIP_EVENT, output)) { - wlr_log_errno(L_ERROR, "%s: Failed to page flip", output->output.name); - return false; - } - - return true; -} - -static void legacy_conn_enable(struct wlr_drm_backend *backend, - struct wlr_drm_output *output, bool enable) { - drmModeConnectorSetProperty(backend->fd, output->connector, output->props.dpms, - enable ? DRM_MODE_DPMS_ON : DRM_MODE_DPMS_OFF); -} - -bool legacy_crtc_set_cursor(struct wlr_drm_backend *backend, - struct wlr_drm_crtc *crtc, struct gbm_bo *bo) { - if (!crtc || !crtc->cursor) { - return true; - } - - if (!bo) { - drmModeSetCursor(backend->fd, crtc->id, 0, 0, 0); - return true; - } - - struct wlr_drm_plane *plane = crtc->cursor; - - if (drmModeSetCursor(backend->fd, crtc->id, gbm_bo_get_handle(bo).u32, - plane->width, plane->height)) { - wlr_log_errno(L_ERROR, "Failed to set hardware cursor"); - return false; - } - - return true; -} - -bool legacy_crtc_move_cursor(struct wlr_drm_backend *backend, - struct wlr_drm_crtc *crtc, int x, int y) { - return !drmModeMoveCursor(backend->fd, crtc->id, x, y); -} - -const struct wlr_drm_interface legacy_iface = { - .conn_enable = legacy_conn_enable, - .crtc_pageflip = legacy_crtc_pageflip, - .crtc_set_cursor = legacy_crtc_set_cursor, - .crtc_move_cursor = legacy_crtc_move_cursor, -}; diff --git a/backend/drm/drm-properties.c b/backend/drm/drm-properties.c deleted file mode 100644 index ef24476f..00000000 --- a/backend/drm/drm-properties.c +++ /dev/null @@ -1,145 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include "backend/drm-properties.h" - -/* - * Creates a mapping between property names and an array index where to store - * the ids. The prop_info arrays must be sorted by name, as bsearch is used to - * search them. - */ -struct prop_info { - const char *name; - size_t index; -}; - -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) }, -#undef INDEX -}; - -static const struct prop_info crtc_info[] = { -#define INDEX(name) (offsetof(union wlr_drm_crtc_props, name) / sizeof(uint32_t)) - { "ACTIVE", INDEX(active) }, - { "MODE_ID", INDEX(mode_id) }, - { "rotation", INDEX(rotation) }, - { "scaling mode", INDEX(scaling_mode) }, -#undef INDEX -}; - -static const struct prop_info plane_info[] = { -#define INDEX(name) (offsetof(union wlr_drm_plane_props, name) / sizeof(uint32_t)) - { "CRTC_H", INDEX(crtc_h) }, - { "CRTC_ID", INDEX(crtc_id) }, - { "CRTC_W", INDEX(crtc_w) }, - { "CRTC_X", INDEX(crtc_x) }, - { "CRTC_Y", INDEX(crtc_y) }, - { "FB_ID", INDEX(fb_id) }, - { "SRC_H", INDEX(src_h) }, - { "SRC_W", INDEX(src_w) }, - { "SRC_X", INDEX(src_x) }, - { "SRC_Y", INDEX(src_y) }, - { "type", INDEX(type) }, -#undef INDEX -}; - -static int cmp_prop_info(const void *arg1, const void *arg2) { - const char *key = arg1; - const struct prop_info *elem = arg2; - - return strcmp(key, elem->name); -} - -static bool scan_properties(int fd, uint32_t id, uint32_t type, uint32_t *result, - const struct prop_info *info, size_t info_len) { - drmModeObjectProperties *props = drmModeObjectGetProperties(fd, id, type); - if (!props) { - wlr_log_errno(L_ERROR, "Failed to get DRM object properties"); - return false; - } - - for (uint32_t i = 0; i < props->count_props; ++i) { - drmModePropertyRes *prop = drmModeGetProperty(fd, props->props[i]); - if (!prop) { - wlr_log_errno(L_ERROR, "Failed to get DRM object property"); - continue; - } - - const struct prop_info *p = - bsearch(prop->name, info, info_len, sizeof(info[0]), cmp_prop_info); - if (p) { - result[p->index] = prop->prop_id; - } - - drmModeFreeProperty(prop); - } - - drmModeFreeObjectProperties(props); - return true; -} - -bool wlr_drm_get_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])); -} - -bool wlr_drm_get_crtc_props(int fd, uint32_t id, union wlr_drm_crtc_props *out) { - return scan_properties(fd, id, DRM_MODE_OBJECT_CRTC, out->props, - crtc_info, sizeof(crtc_info) / sizeof(crtc_info[0])); -} - -bool wlr_drm_get_plane_props(int fd, uint32_t id, union wlr_drm_plane_props *out) { - return scan_properties(fd, id, DRM_MODE_OBJECT_PLANE, out->props, - plane_info, sizeof(plane_info) / sizeof(plane_info[0])); -} - -bool wlr_drm_get_prop(int fd, uint32_t obj, uint32_t prop, uint64_t *ret) { - drmModeObjectProperties *props = drmModeObjectGetProperties(fd, obj, DRM_MODE_OBJECT_ANY); - if (!props) { - return false; - } - - bool found = false; - - for (uint32_t i = 0; i < props->count_props; ++i) { - if (props->props[i] == prop) { - *ret = props->prop_values[i]; - found = true; - break; - } - } - - drmModeFreeObjectProperties(props); - return found; -} - -void *wlr_drm_get_prop_blob(int fd, uint32_t obj, uint32_t prop, size_t *ret_len) { - uint64_t blob_id; - if (!wlr_drm_get_prop(fd, obj, prop, &blob_id)) { - return NULL; - } - - drmModePropertyBlobRes *blob = drmModeGetPropertyBlob(fd, blob_id); - if (!blob) { - return NULL; - } - - void *ptr = malloc(blob->length); - if (!ptr) { - drmModeFreePropertyBlob(blob); - return NULL; - } - - memcpy(ptr, blob->data, blob->length); - *ret_len = blob->length; - - drmModeFreePropertyBlob(blob); - return ptr; -} diff --git a/backend/drm/drm-util.c b/backend/drm/drm-util.c deleted file mode 100644 index 0f8ee18c..00000000 --- a/backend/drm/drm-util.c +++ /dev/null @@ -1,303 +0,0 @@ -#include -#include -#include -#include -#include -#include "backend/drm-util.h" -#include - -int32_t calculate_refresh_rate(drmModeModeInfo *mode) { - int32_t refresh = (mode->clock * 1000000LL / mode->htotal + - mode->vtotal / 2) / mode->vtotal; - - if (mode->flags & DRM_MODE_FLAG_INTERLACE) { - refresh *= 2; - } - - if (mode->flags & DRM_MODE_FLAG_DBLSCAN) { - refresh /= 2; - } - - if (mode->vscan > 1) { - refresh /= mode->vscan; - } - - return refresh; -} - -// Constructed from http://edid.tv/manufacturer -static const char *get_manufacturer(uint16_t id) { -#define ID(a, b, c) ((a & 0x1f) << 10) | ((b & 0x1f) << 5) | (c & 0x1f) - switch (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', 'P', 'P'): return "Apple Computer Inc"; - 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', '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('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', 'W', 'P'): return "Hewlett Packard"; - case ID('I', 'N', 'T'): return "Interphase Corporation"; - 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"; - case ID('M', 'E', 'G'): return "Abeam Tech Ltd"; - case ID('M', 'E', 'I'): return "Panasonic Industry Company"; - 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('O', 'N', 'K'): return "ONKYO Corporation"; - case ID('O', 'R', 'N'): return "ORION ELECTRIC CO., LTD."; - case ID('O', 'T', 'M'): return "Optoma Corporation"; - case ID('O', 'V', 'R'): return "Oculus VR, Inc."; - case ID('P', 'H', 'L'): return "Philips Consumer Electronics Company"; - 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('S', 'A', 'M'): return "Samsung Electric Company"; - 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('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', 'I', 'Z'): return "VIZIO, Inc"; - case ID('V', 'S', 'C'): return "ViewSonic Corporation"; - case ID('Y', 'M', 'H'): return "Yamaha Corporation"; - default: return "Unknown"; - } -#undef ID -} - -/* See https://en.wikipedia.org/wiki/Extended_Display_Identification_Data for layout of EDID data. - * We don't parse the EDID properly. We just expect to receive valid data. - */ -void parse_edid(struct wlr_output *restrict output, size_t len, const uint8_t *data) { - if (!data || len < 128) { - snprintf(output->make, sizeof(output->make), ""); - snprintf(output->model, sizeof(output->model), ""); - return; - } - - uint16_t id = (data[8] << 8) | data[9]; - snprintf(output->make, sizeof(output->make), "%s", get_manufacturer(id)); - - output->phys_width = ((data[68] & 0xf0) << 4) | data[66]; - output->phys_height = ((data[68] & 0x0f) << 8) | data[67]; - - for (size_t i = 72; i <= 108; i += 18) { - uint16_t flag = (data[i] << 8) | data[i + 1]; - if (flag == 0 && data[i + 3] == 0xFC) { - sprintf(output->model, "%.13s", &data[i + 5]); - - // Monitor names are terminated by newline if they're too short - char *nl = strchr(output->model, '\n'); - if (nl) { - *nl = '\0'; - } - - break; - } - } -} - -const char *conn_get_name(uint32_t type_id) { - switch (type_id) { - case DRM_MODE_CONNECTOR_Unknown: return "Unknown"; - case DRM_MODE_CONNECTOR_VGA: return "VGA"; - case DRM_MODE_CONNECTOR_DVII: return "DVI-I"; - case DRM_MODE_CONNECTOR_DVID: return "DVI-D"; - case DRM_MODE_CONNECTOR_DVIA: return "DVI-A"; - case DRM_MODE_CONNECTOR_Composite: return "Composite"; - case DRM_MODE_CONNECTOR_SVIDEO: return "SVIDEO"; - case DRM_MODE_CONNECTOR_LVDS: return "LVDS"; - case DRM_MODE_CONNECTOR_Component: return "Component"; - case DRM_MODE_CONNECTOR_9PinDIN: return "DIN"; - case DRM_MODE_CONNECTOR_DisplayPort: return "DP"; - case DRM_MODE_CONNECTOR_HDMIA: return "HDMI-A"; - case DRM_MODE_CONNECTOR_HDMIB: return "HDMI-B"; - case DRM_MODE_CONNECTOR_TV: return "TV"; - case DRM_MODE_CONNECTOR_eDP: return "eDP"; - case DRM_MODE_CONNECTOR_VIRTUAL: return "Virtual"; - case DRM_MODE_CONNECTOR_DSI: return "DSI"; - default: return "Unknown"; - } -} - -static void free_fb(struct gbm_bo *bo, void *data) { - uint32_t id = (uintptr_t)data; - - if (id) { - struct gbm_device *gbm = gbm_bo_get_device(bo); - drmModeRmFB(gbm_device_get_fd(gbm), id); - } -} - -uint32_t get_fb_for_bo(struct gbm_bo *bo) { - uint32_t id = (uintptr_t)gbm_bo_get_user_data(bo); - if (id) { - return id; - } - - struct gbm_device *gbm = gbm_bo_get_device(bo); - - int fd = gbm_device_get_fd(gbm); - uint32_t width = gbm_bo_get_width(bo); - uint32_t height = gbm_bo_get_height(bo); - uint32_t handles[4] = {gbm_bo_get_handle(bo).u32}; - uint32_t pitches[4] = {gbm_bo_get_stride(bo)}; - uint32_t offsets[4] = {gbm_bo_get_offset(bo, 0)}; - uint32_t format = gbm_bo_get_format(bo); - - if (drmModeAddFB2(fd, width, height, format, handles, pitches, offsets, &id, 0)) { - wlr_log_errno(L_ERROR, "Unable to add DRM framebuffer"); - } - - gbm_bo_set_user_data(bo, (void *)(uintptr_t)id, free_fb); - - return id; -} - -static inline bool is_taken(size_t n, const uint32_t arr[static n], uint32_t key) { - for (size_t i = 0; i < n; ++i) { - if (arr[i] == key) { - return true; - } - } - return false; -} - -/* - * Store all of the non-recursive state in a struct, so we aren't literally - * passing 12 arguments to a function. - */ -struct match_state { - const size_t num_objs; - const uint32_t *restrict objs; - const size_t num_res; - size_t score; - size_t replaced; - uint32_t *restrict res; - uint32_t *restrict best; - const uint32_t *restrict orig; - bool exit_early; -}; - -/* - * skips: The number of SKIP elements encountered so far. - * score: The number of resources we've matched so far. - * replaced: The number of changes from the original solution. - * i: The index of the current element. - * - * This tries to match a solution as close to st->orig as it can. - * - * Returns whether we've set a new best element with this solution. - */ -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)) { - 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; - - return true; - } else { - return false; - } - } - - if (st->orig[i] == SKIP) { - st->res[i] = SKIP; - return match_obj_(st, skips + 1, score, replaced, i + 1); - } - - /* - * 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; - } - } - - if (st->orig[i] != UNMATCHED) { - ++replaced; - } - - bool is_best = false; - for (st->res[i] = 0; st->res[i] < st->num_objs; ++st->res[i]) { - // We tried this earlier - if (st->res[i] == st->orig[i]) { - continue; - } - - // Not compatable - if (!(st->objs[st->res[i]] & (1 << i))) { - continue; - } - - // Already taken - if (is_taken(i, st->res, st->res[i])) { - continue; - } - - if (match_obj_(st, skips, score + 1, replaced, i + 1)) { - is_best = true; - } - - if (st->exit_early) { - return true; - } - } - - if (is_best) { - return true; - } - - // Maybe this resource can't be matched - st->res[i] = UNMATCHED; - return match_obj_(st, skips, score, replaced, i + 1); -} - -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]; - - struct match_state st = { - .num_objs = num_objs, - .num_res = num_res, - .score = 0, - .replaced = SIZE_MAX, - .objs = objs, - .res = solution, - .best = out, - .orig = res, - .exit_early = false, - }; - - match_obj_(&st, 0, 0, 0, 0); - return st.score; -} diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 1a656172..cba41023 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -20,12 +20,12 @@ #include #include #include -#include "backend/drm.h" -#include "backend/drm-util.h" +#include "backend/drm/drm.h" +#include "backend/drm/util.h" bool wlr_drm_check_features(struct wlr_drm_backend *backend) { - extern const struct wlr_drm_interface legacy_iface; - extern const struct wlr_drm_interface atomic_iface; + extern const struct wlr_drm_interface iface_legacy; + extern const struct wlr_drm_interface iface_atomic; if (drmSetClientCap(backend->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1)) { wlr_log(L_ERROR, "DRM universal planes unsupported"); @@ -34,13 +34,13 @@ bool wlr_drm_check_features(struct wlr_drm_backend *backend) { if (getenv("WLR_DRM_NO_ATOMIC")) { wlr_log(L_DEBUG, "WLR_DRM_NO_ATOMIC set, forcing legacy DRM interface"); - backend->iface = &legacy_iface; + backend->iface = &iface_legacy; } else if (drmSetClientCap(backend->fd, DRM_CLIENT_CAP_ATOMIC, 1)) { wlr_log(L_DEBUG, "Atomic modesetting unsupported, using legacy DRM interface"); - backend->iface = &legacy_iface; + backend->iface = &iface_legacy; } else { wlr_log(L_DEBUG, "Using atomic DRM interface"); - backend->iface = &atomic_iface; + backend->iface = &iface_atomic; } return true; diff --git a/backend/drm/iface_atomic.c b/backend/drm/iface_atomic.c new file mode 100644 index 00000000..5bb2da9b --- /dev/null +++ b/backend/drm/iface_atomic.c @@ -0,0 +1,188 @@ +#include +#include +#include +#include +#include "backend/drm/drm.h" +#include "backend/drm/util.h" + +struct atomic { + drmModeAtomicReq *req; + int cursor; + bool failed; +}; + +static void atomic_begin(struct wlr_drm_crtc *crtc, struct atomic *atom) { + if (!crtc->atomic) { + crtc->atomic = drmModeAtomicAlloc(); + if (!crtc->atomic) { + wlr_log_errno(L_ERROR, "Allocation failed"); + atom->failed = true; + return; + } + } + + atom->req = crtc->atomic; + atom->cursor = drmModeAtomicGetCursor(atom->req); + atom->failed = false; +} + +static bool atomic_end(int drm_fd, struct atomic *atom) { + if (atom->failed) { + return false; + } + + uint32_t flags = DRM_MODE_ATOMIC_TEST_ONLY | DRM_MODE_ATOMIC_NONBLOCK; + + if (drmModeAtomicCommit(drm_fd, atom->req, flags, NULL)) { + wlr_log_errno(L_ERROR, "Atomic test failed"); + drmModeAtomicSetCursor(atom->req, atom->cursor); + return false; + } + + return true; +} + +static bool atomic_commit(int drm_fd, struct atomic *atom, + struct wlr_drm_output *output, uint32_t flag, bool modeset) { + if (atom->failed) { + return false; + } + + uint32_t flags = DRM_MODE_PAGE_FLIP_EVENT | flag; + + int ret = drmModeAtomicCommit(drm_fd, atom->req, flags, output); + if (ret) { + wlr_log_errno(L_ERROR, "%s: Atomic commit failed (%s)", + output->output.name, modeset ? "modeset" : "pageflip"); + + // Try to commit without new changes + drmModeAtomicSetCursor(atom->req, atom->cursor); + if (drmModeAtomicCommit(drm_fd, atom->req, flags, output)) { + wlr_log_errno(L_ERROR, "%s: Atomic commit failed (%s)", + output->output.name, modeset ? "modeset" : "pageflip"); + } + } + + drmModeAtomicSetCursor(atom->req, 0); + + return !ret; +} + +static inline void atomic_add(struct atomic *atom, uint32_t id, uint32_t prop, uint64_t val) { + if (!atom->failed && drmModeAtomicAddProperty(atom->req, id, prop, val) < 0) { + wlr_log_errno(L_ERROR, "Failed to add atomic DRM property"); + atom->failed = true; + } +} + +static void set_plane_props(struct atomic *atom, struct wlr_drm_plane *plane, + uint32_t crtc_id, uint32_t fb_id, bool set_crtc_xy) { + uint32_t id = plane->id; + const union wlr_drm_plane_props *props = &plane->props; + + // The src_* properties are in 16.16 fixed point + atomic_add(atom, id, props->src_x, 0); + atomic_add(atom, id, props->src_y, 0); + atomic_add(atom, id, props->src_w, plane->width << 16); + atomic_add(atom, id, props->src_h, plane->height << 16); + atomic_add(atom, id, props->crtc_w, plane->width); + atomic_add(atom, id, props->crtc_h, plane->height); + atomic_add(atom, id, props->fb_id, fb_id); + atomic_add(atom, id, props->crtc_id, crtc_id); + if (set_crtc_xy) { + atomic_add(atom, id, props->crtc_x, 0); + atomic_add(atom, id, props->crtc_y, 0); + } +} + +static bool atomic_crtc_pageflip(struct wlr_drm_backend *backend, + struct wlr_drm_output *output, + struct wlr_drm_crtc *crtc, + uint32_t fb_id, drmModeModeInfo *mode) { + if (mode) { + if (crtc->mode_id) { + drmModeDestroyPropertyBlob(backend->fd, crtc->mode_id); + } + + if (drmModeCreatePropertyBlob(backend->fd, mode, sizeof(*mode), &crtc->mode_id)) { + wlr_log_errno(L_ERROR, "Unable to create property blob"); + return false; + } + } + + struct atomic atom; + + atomic_begin(crtc, &atom); + atomic_add(&atom, output->connector, output->props.crtc_id, crtc->id); + 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); + return atomic_commit(backend->fd, &atom, output, + mode ? DRM_MODE_ATOMIC_ALLOW_MODESET : DRM_MODE_ATOMIC_NONBLOCK, + mode); +} + +static void atomic_conn_enable(struct wlr_drm_backend *backend, + struct wlr_drm_output *output, bool enable) { + struct wlr_drm_crtc *crtc = output->crtc; + struct atomic atom; + + atomic_begin(crtc, &atom); + atomic_add(&atom, crtc->id, crtc->props.active, enable); + atomic_end(backend->fd, &atom); +} + +bool legacy_crtc_set_cursor(struct wlr_drm_backend *backend, + struct wlr_drm_crtc *crtc, struct gbm_bo *bo); + +static bool atomic_crtc_set_cursor(struct wlr_drm_backend *backend, + struct wlr_drm_crtc *crtc, struct gbm_bo *bo) { + if (!crtc || !crtc->cursor) { + return true; + } + + struct wlr_drm_plane *plane = crtc->cursor; + // We can't use atomic operations on fake planes + if (plane->id == 0) { + return legacy_crtc_set_cursor(backend, crtc, bo); + } + + struct atomic atom; + + atomic_begin(crtc, &atom); + + if (bo) { + set_plane_props(&atom, plane, crtc->id, get_fb_for_bo(bo), false); + } else { + atomic_add(&atom, plane->id, plane->props.fb_id, 0); + atomic_add(&atom, plane->id, plane->props.crtc_id, 0); + } + + return atomic_end(backend->fd, &atom); +} + +bool legacy_crtc_move_cursor(struct wlr_drm_backend *backend, + struct wlr_drm_crtc *crtc, int x, int y); + +static bool atomic_crtc_move_cursor(struct wlr_drm_backend *backend, + struct wlr_drm_crtc *crtc, int x, int y) { + struct wlr_drm_plane *plane = crtc->cursor; + // We can't use atomic operations on fake planes + if (plane->id == 0) { + return legacy_crtc_move_cursor(backend, crtc, x, y); + } + + struct atomic atom; + + atomic_begin(crtc, &atom); + atomic_add(&atom, plane->id, plane->props.crtc_x, x); + atomic_add(&atom, plane->id, plane->props.crtc_y, y); + return atomic_end(backend->fd, &atom); +} + +const struct wlr_drm_interface iface_atomic = { + .conn_enable = atomic_conn_enable, + .crtc_pageflip = atomic_crtc_pageflip, + .crtc_set_cursor = atomic_crtc_set_cursor, + .crtc_move_cursor = atomic_crtc_move_cursor, +}; diff --git a/backend/drm/iface_legacy.c b/backend/drm/iface_legacy.c new file mode 100644 index 00000000..856e9060 --- /dev/null +++ b/backend/drm/iface_legacy.c @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#include "backend/drm/drm.h" +#include "backend/drm/util.h" + +static bool legacy_crtc_pageflip(struct wlr_drm_backend *backend, + struct wlr_drm_output *output, struct wlr_drm_crtc *crtc, + uint32_t fb_id, drmModeModeInfo *mode) { + if (mode) { + if (drmModeSetCrtc(backend->fd, crtc->id, fb_id, 0, 0, + &output->connector, 1, mode)) { + wlr_log_errno(L_ERROR, "%s: Failed to set CRTC", output->output.name); + return false; + } + } + + if (drmModePageFlip(backend->fd, crtc->id, fb_id, DRM_MODE_PAGE_FLIP_EVENT, output)) { + wlr_log_errno(L_ERROR, "%s: Failed to page flip", output->output.name); + return false; + } + + return true; +} + +static void legacy_conn_enable(struct wlr_drm_backend *backend, + struct wlr_drm_output *output, bool enable) { + drmModeConnectorSetProperty(backend->fd, output->connector, output->props.dpms, + enable ? DRM_MODE_DPMS_ON : DRM_MODE_DPMS_OFF); +} + +bool legacy_crtc_set_cursor(struct wlr_drm_backend *backend, + struct wlr_drm_crtc *crtc, struct gbm_bo *bo) { + if (!crtc || !crtc->cursor) { + return true; + } + + if (!bo) { + drmModeSetCursor(backend->fd, crtc->id, 0, 0, 0); + return true; + } + + struct wlr_drm_plane *plane = crtc->cursor; + + if (drmModeSetCursor(backend->fd, crtc->id, gbm_bo_get_handle(bo).u32, + plane->width, plane->height)) { + wlr_log_errno(L_ERROR, "Failed to set hardware cursor"); + return false; + } + + return true; +} + +bool legacy_crtc_move_cursor(struct wlr_drm_backend *backend, + struct wlr_drm_crtc *crtc, int x, int y) { + return !drmModeMoveCursor(backend->fd, crtc->id, x, y); +} + +const struct wlr_drm_interface iface_legacy = { + .conn_enable = legacy_conn_enable, + .crtc_pageflip = legacy_crtc_pageflip, + .crtc_set_cursor = legacy_crtc_set_cursor, + .crtc_move_cursor = legacy_crtc_move_cursor, +}; diff --git a/backend/drm/properties.c b/backend/drm/properties.c new file mode 100644 index 00000000..5bec3243 --- /dev/null +++ b/backend/drm/properties.c @@ -0,0 +1,145 @@ +#include +#include +#include +#include +#include +#include +#include +#include "backend/drm/properties.h" + +/* + * Creates a mapping between property names and an array index where to store + * the ids. The prop_info arrays must be sorted by name, as bsearch is used to + * search them. + */ +struct prop_info { + const char *name; + size_t index; +}; + +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) }, +#undef INDEX +}; + +static const struct prop_info crtc_info[] = { +#define INDEX(name) (offsetof(union wlr_drm_crtc_props, name) / sizeof(uint32_t)) + { "ACTIVE", INDEX(active) }, + { "MODE_ID", INDEX(mode_id) }, + { "rotation", INDEX(rotation) }, + { "scaling mode", INDEX(scaling_mode) }, +#undef INDEX +}; + +static const struct prop_info plane_info[] = { +#define INDEX(name) (offsetof(union wlr_drm_plane_props, name) / sizeof(uint32_t)) + { "CRTC_H", INDEX(crtc_h) }, + { "CRTC_ID", INDEX(crtc_id) }, + { "CRTC_W", INDEX(crtc_w) }, + { "CRTC_X", INDEX(crtc_x) }, + { "CRTC_Y", INDEX(crtc_y) }, + { "FB_ID", INDEX(fb_id) }, + { "SRC_H", INDEX(src_h) }, + { "SRC_W", INDEX(src_w) }, + { "SRC_X", INDEX(src_x) }, + { "SRC_Y", INDEX(src_y) }, + { "type", INDEX(type) }, +#undef INDEX +}; + +static int cmp_prop_info(const void *arg1, const void *arg2) { + const char *key = arg1; + const struct prop_info *elem = arg2; + + return strcmp(key, elem->name); +} + +static bool scan_properties(int fd, uint32_t id, uint32_t type, uint32_t *result, + const struct prop_info *info, size_t info_len) { + drmModeObjectProperties *props = drmModeObjectGetProperties(fd, id, type); + if (!props) { + wlr_log_errno(L_ERROR, "Failed to get DRM object properties"); + return false; + } + + for (uint32_t i = 0; i < props->count_props; ++i) { + drmModePropertyRes *prop = drmModeGetProperty(fd, props->props[i]); + if (!prop) { + wlr_log_errno(L_ERROR, "Failed to get DRM object property"); + continue; + } + + const struct prop_info *p = + bsearch(prop->name, info, info_len, sizeof(info[0]), cmp_prop_info); + if (p) { + result[p->index] = prop->prop_id; + } + + drmModeFreeProperty(prop); + } + + drmModeFreeObjectProperties(props); + return true; +} + +bool wlr_drm_get_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])); +} + +bool wlr_drm_get_crtc_props(int fd, uint32_t id, union wlr_drm_crtc_props *out) { + return scan_properties(fd, id, DRM_MODE_OBJECT_CRTC, out->props, + crtc_info, sizeof(crtc_info) / sizeof(crtc_info[0])); +} + +bool wlr_drm_get_plane_props(int fd, uint32_t id, union wlr_drm_plane_props *out) { + return scan_properties(fd, id, DRM_MODE_OBJECT_PLANE, out->props, + plane_info, sizeof(plane_info) / sizeof(plane_info[0])); +} + +bool wlr_drm_get_prop(int fd, uint32_t obj, uint32_t prop, uint64_t *ret) { + drmModeObjectProperties *props = drmModeObjectGetProperties(fd, obj, DRM_MODE_OBJECT_ANY); + if (!props) { + return false; + } + + bool found = false; + + for (uint32_t i = 0; i < props->count_props; ++i) { + if (props->props[i] == prop) { + *ret = props->prop_values[i]; + found = true; + break; + } + } + + drmModeFreeObjectProperties(props); + return found; +} + +void *wlr_drm_get_prop_blob(int fd, uint32_t obj, uint32_t prop, size_t *ret_len) { + uint64_t blob_id; + if (!wlr_drm_get_prop(fd, obj, prop, &blob_id)) { + return NULL; + } + + drmModePropertyBlobRes *blob = drmModeGetPropertyBlob(fd, blob_id); + if (!blob) { + return NULL; + } + + void *ptr = malloc(blob->length); + if (!ptr) { + drmModeFreePropertyBlob(blob); + return NULL; + } + + memcpy(ptr, blob->data, blob->length); + *ret_len = blob->length; + + drmModeFreePropertyBlob(blob); + return ptr; +} diff --git a/backend/drm/util.c b/backend/drm/util.c new file mode 100644 index 00000000..656c070a --- /dev/null +++ b/backend/drm/util.c @@ -0,0 +1,303 @@ +#include +#include +#include +#include +#include +#include "backend/drm/util.h" +#include + +int32_t calculate_refresh_rate(drmModeModeInfo *mode) { + int32_t refresh = (mode->clock * 1000000LL / mode->htotal + + mode->vtotal / 2) / mode->vtotal; + + if (mode->flags & DRM_MODE_FLAG_INTERLACE) { + refresh *= 2; + } + + if (mode->flags & DRM_MODE_FLAG_DBLSCAN) { + refresh /= 2; + } + + if (mode->vscan > 1) { + refresh /= mode->vscan; + } + + return refresh; +} + +// Constructed from http://edid.tv/manufacturer +static const char *get_manufacturer(uint16_t id) { +#define ID(a, b, c) ((a & 0x1f) << 10) | ((b & 0x1f) << 5) | (c & 0x1f) + switch (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', 'P', 'P'): return "Apple Computer Inc"; + 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', '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('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', 'W', 'P'): return "Hewlett Packard"; + case ID('I', 'N', 'T'): return "Interphase Corporation"; + 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"; + case ID('M', 'E', 'G'): return "Abeam Tech Ltd"; + case ID('M', 'E', 'I'): return "Panasonic Industry Company"; + 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('O', 'N', 'K'): return "ONKYO Corporation"; + case ID('O', 'R', 'N'): return "ORION ELECTRIC CO., LTD."; + case ID('O', 'T', 'M'): return "Optoma Corporation"; + case ID('O', 'V', 'R'): return "Oculus VR, Inc."; + case ID('P', 'H', 'L'): return "Philips Consumer Electronics Company"; + 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('S', 'A', 'M'): return "Samsung Electric Company"; + 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('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', 'I', 'Z'): return "VIZIO, Inc"; + case ID('V', 'S', 'C'): return "ViewSonic Corporation"; + case ID('Y', 'M', 'H'): return "Yamaha Corporation"; + default: return "Unknown"; + } +#undef ID +} + +/* See https://en.wikipedia.org/wiki/Extended_Display_Identification_Data for layout of EDID data. + * We don't parse the EDID properly. We just expect to receive valid data. + */ +void parse_edid(struct wlr_output *restrict output, size_t len, const uint8_t *data) { + if (!data || len < 128) { + snprintf(output->make, sizeof(output->make), ""); + snprintf(output->model, sizeof(output->model), ""); + return; + } + + uint16_t id = (data[8] << 8) | data[9]; + snprintf(output->make, sizeof(output->make), "%s", get_manufacturer(id)); + + output->phys_width = ((data[68] & 0xf0) << 4) | data[66]; + output->phys_height = ((data[68] & 0x0f) << 8) | data[67]; + + for (size_t i = 72; i <= 108; i += 18) { + uint16_t flag = (data[i] << 8) | data[i + 1]; + if (flag == 0 && data[i + 3] == 0xFC) { + sprintf(output->model, "%.13s", &data[i + 5]); + + // Monitor names are terminated by newline if they're too short + char *nl = strchr(output->model, '\n'); + if (nl) { + *nl = '\0'; + } + + break; + } + } +} + +const char *conn_get_name(uint32_t type_id) { + switch (type_id) { + case DRM_MODE_CONNECTOR_Unknown: return "Unknown"; + case DRM_MODE_CONNECTOR_VGA: return "VGA"; + case DRM_MODE_CONNECTOR_DVII: return "DVI-I"; + case DRM_MODE_CONNECTOR_DVID: return "DVI-D"; + case DRM_MODE_CONNECTOR_DVIA: return "DVI-A"; + case DRM_MODE_CONNECTOR_Composite: return "Composite"; + case DRM_MODE_CONNECTOR_SVIDEO: return "SVIDEO"; + case DRM_MODE_CONNECTOR_LVDS: return "LVDS"; + case DRM_MODE_CONNECTOR_Component: return "Component"; + case DRM_MODE_CONNECTOR_9PinDIN: return "DIN"; + case DRM_MODE_CONNECTOR_DisplayPort: return "DP"; + case DRM_MODE_CONNECTOR_HDMIA: return "HDMI-A"; + case DRM_MODE_CONNECTOR_HDMIB: return "HDMI-B"; + case DRM_MODE_CONNECTOR_TV: return "TV"; + case DRM_MODE_CONNECTOR_eDP: return "eDP"; + case DRM_MODE_CONNECTOR_VIRTUAL: return "Virtual"; + case DRM_MODE_CONNECTOR_DSI: return "DSI"; + default: return "Unknown"; + } +} + +static void free_fb(struct gbm_bo *bo, void *data) { + uint32_t id = (uintptr_t)data; + + if (id) { + struct gbm_device *gbm = gbm_bo_get_device(bo); + drmModeRmFB(gbm_device_get_fd(gbm), id); + } +} + +uint32_t get_fb_for_bo(struct gbm_bo *bo) { + uint32_t id = (uintptr_t)gbm_bo_get_user_data(bo); + if (id) { + return id; + } + + struct gbm_device *gbm = gbm_bo_get_device(bo); + + int fd = gbm_device_get_fd(gbm); + uint32_t width = gbm_bo_get_width(bo); + uint32_t height = gbm_bo_get_height(bo); + uint32_t handles[4] = {gbm_bo_get_handle(bo).u32}; + uint32_t pitches[4] = {gbm_bo_get_stride(bo)}; + uint32_t offsets[4] = {gbm_bo_get_offset(bo, 0)}; + uint32_t format = gbm_bo_get_format(bo); + + if (drmModeAddFB2(fd, width, height, format, handles, pitches, offsets, &id, 0)) { + wlr_log_errno(L_ERROR, "Unable to add DRM framebuffer"); + } + + gbm_bo_set_user_data(bo, (void *)(uintptr_t)id, free_fb); + + return id; +} + +static inline bool is_taken(size_t n, const uint32_t arr[static n], uint32_t key) { + for (size_t i = 0; i < n; ++i) { + if (arr[i] == key) { + return true; + } + } + return false; +} + +/* + * Store all of the non-recursive state in a struct, so we aren't literally + * passing 12 arguments to a function. + */ +struct match_state { + const size_t num_objs; + const uint32_t *restrict objs; + const size_t num_res; + size_t score; + size_t replaced; + uint32_t *restrict res; + uint32_t *restrict best; + const uint32_t *restrict orig; + bool exit_early; +}; + +/* + * skips: The number of SKIP elements encountered so far. + * score: The number of resources we've matched so far. + * replaced: The number of changes from the original solution. + * i: The index of the current element. + * + * This tries to match a solution as close to st->orig as it can. + * + * Returns whether we've set a new best element with this solution. + */ +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)) { + 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; + + return true; + } else { + return false; + } + } + + if (st->orig[i] == SKIP) { + st->res[i] = SKIP; + return match_obj_(st, skips + 1, score, replaced, i + 1); + } + + /* + * 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; + } + } + + if (st->orig[i] != UNMATCHED) { + ++replaced; + } + + bool is_best = false; + for (st->res[i] = 0; st->res[i] < st->num_objs; ++st->res[i]) { + // We tried this earlier + if (st->res[i] == st->orig[i]) { + continue; + } + + // Not compatable + if (!(st->objs[st->res[i]] & (1 << i))) { + continue; + } + + // Already taken + if (is_taken(i, st->res, st->res[i])) { + continue; + } + + if (match_obj_(st, skips, score + 1, replaced, i + 1)) { + is_best = true; + } + + if (st->exit_early) { + return true; + } + } + + if (is_best) { + return true; + } + + // Maybe this resource can't be matched + st->res[i] = UNMATCHED; + return match_obj_(st, skips, score, replaced, i + 1); +} + +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]; + + struct match_state st = { + .num_objs = num_objs, + .num_res = num_res, + .score = 0, + .replaced = SIZE_MAX, + .objs = objs, + .res = solution, + .best = out, + .orig = res, + .exit_early = false, + }; + + match_obj_(&st, 0, 0, 0, 0); + return st.score; +} diff --git a/backend/meson.build b/backend/meson.build index 9e3b6fed..630bc284 100644 --- a/backend/meson.build +++ b/backend/meson.build @@ -5,10 +5,10 @@ backend_files = files( 'session/session.c', 'drm/backend.c', 'drm/drm.c', - 'drm/drm-atomic.c', - 'drm/drm-legacy.c', - 'drm/drm-properties.c', - 'drm/drm-util.c', + 'drm/iface_atomic.c', + 'drm/iface_legacy.c', + 'drm/properties.c', + 'drm/util.c', 'libinput/backend.c', 'libinput/events.c', 'libinput/keyboard.c', diff --git a/include/backend/drm-properties.h b/include/backend/drm-properties.h deleted file mode 100644 index 7de386ea..00000000 --- a/include/backend/drm-properties.h +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef BACKEND_DRM_PROPERTIES_H -#define BACKEND_DRM_PROPERTIES_H - -#include -#include - -/* - * These types contain the property ids for several DRM objects. - * See https://01.org/linuxgraphics/gfx-docs/drm/gpu/drm-kms.html#kms-properties - * for more details. - */ - -union wlr_drm_connector_props { - struct { - uint32_t edid; - uint32_t dpms; - - // atomic-modesetting only - - uint32_t crtc_id; - }; - uint32_t props[3]; -}; - -union wlr_drm_crtc_props { - struct { - // Neither of these are guranteed to exist - uint32_t rotation; - uint32_t scaling_mode; - - // atomic-modesetting only - - uint32_t active; - uint32_t mode_id; - }; - uint32_t props[4]; -}; - -union wlr_drm_plane_props { - struct { - uint32_t type; - uint32_t rotation; // Not guranteed to exist - - // atomic-modesetting only - - uint32_t src_x; - uint32_t src_y; - uint32_t src_w; - uint32_t src_h; - uint32_t crtc_x; - uint32_t crtc_y; - uint32_t crtc_w; - uint32_t crtc_h; - uint32_t fb_id; - uint32_t crtc_id; - }; - uint32_t props[12]; -}; - -bool wlr_drm_get_connector_props(int fd, uint32_t id, union wlr_drm_connector_props *out); -bool wlr_drm_get_crtc_props(int fd, uint32_t id, union wlr_drm_crtc_props *out); -bool wlr_drm_get_plane_props(int fd, uint32_t id, union wlr_drm_plane_props *out); - -bool wlr_drm_get_prop(int fd, uint32_t obj, uint32_t prop, uint64_t *ret); -void *wlr_drm_get_prop_blob(int fd, uint32_t obj, uint32_t prop, size_t *ret_len); - -#endif diff --git a/include/backend/drm-util.h b/include/backend/drm-util.h deleted file mode 100644 index 6818b4db..00000000 --- a/include/backend/drm-util.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef BACKEND_DRM_UTIL_H -#define BACKEND_DRM_UTIL_H - -#include -#include -#include -#include - -// Calculates a more accurate refresh rate (mHz) than what mode itself provides -int32_t calculate_refresh_rate(drmModeModeInfo *mode); -// Populates the make/model/phys_{width,height} of output from the edid data -void parse_edid(struct wlr_output *restrict output, size_t len, const uint8_t *data); -// Returns the string representation of a DRM output type -const char *conn_get_name(uint32_t type_id); -// Returns the DRM framebuffer id for a gbm_bo -uint32_t get_fb_for_bo(struct gbm_bo *bo); - -// Part of match_obj -enum { - UNMATCHED = (uint32_t)-1, - SKIP = (uint32_t)-2, -}; - -/* - * Tries to match some DRM objects with some other DRM resource. - * e.g. Match CRTCs with Encoders, CRTCs with Planes. - * - * objs contains a bit array which resources it can be matched with. - * e.g. Bit 0 set means can be matched with res[0] - * - * res contains an index of which objs it is matched with or UNMATCHED. - * - * This solution is left in out. - * Returns the total number of matched solutions. - */ -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]); -#endif diff --git a/include/backend/drm.h b/include/backend/drm.h deleted file mode 100644 index 6987b0bc..00000000 --- a/include/backend/drm.h +++ /dev/null @@ -1,186 +0,0 @@ -#ifndef BACKEND_DRM_H -#define BACKEND_DRM_H - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "drm-properties.h" - -struct wlr_drm_plane { - uint32_t type; - uint32_t id; - - uint32_t possible_crtcs; - - uint32_t width, height; - - struct gbm_surface *gbm; - EGLSurface egl; - - struct gbm_bo *front; - struct gbm_bo *back; - - // Only used by cursor - float matrix[16]; - struct wlr_renderer *wlr_rend; - struct wlr_texture *wlr_tex; - struct gbm_bo *cursor_bo; - - union wlr_drm_plane_props props; -}; - -struct wlr_drm_crtc { - uint32_t id; - uint32_t mode_id; // atomic modesetting only - drmModeAtomicReq *atomic; - - union { - struct { - struct wlr_drm_plane *overlay; - struct wlr_drm_plane *primary; - struct wlr_drm_plane *cursor; - }; - struct wlr_drm_plane *planes[3]; - }; - - union wlr_drm_crtc_props props; - - struct wl_list connectors; -}; - -struct wlr_drm_connector { - struct wlr_output *base; - uint32_t id; - struct wlr_drm_crtc *crtc; - - union wlr_drm_connector_props props; - - struct wl_list link; -}; - -struct wlr_drm_renderer { - int fd; - struct gbm_device *gbm; - struct wlr_egl egl; -}; - -bool wlr_drm_renderer_init(struct wlr_drm_renderer *renderer, int fd); -void wlr_drm_renderer_free(struct wlr_drm_renderer *renderer); - -struct wlr_drm_interface; - -struct wlr_drm_backend { - struct wlr_backend backend; - - const struct wlr_drm_interface *iface; - - int fd; - - size_t num_crtcs; - struct wlr_drm_crtc *crtcs; - size_t num_planes; - struct wlr_drm_plane *planes; - - union { - struct { - size_t num_overlay_planes; - size_t num_primary_planes; - size_t num_cursor_planes; - }; - size_t num_type_planes[3]; - }; - - union { - struct { - struct wlr_drm_plane *overlay_planes; - struct wlr_drm_plane *primary_planes; - struct wlr_drm_plane *cursor_planes; - }; - struct wlr_drm_plane *type_planes[3]; - }; - - struct wl_display *display; - struct wl_event_source *drm_event; - - struct wl_listener session_signal; - struct wl_listener drm_invalidated; - - list_t *outputs; - - struct wlr_drm_renderer renderer; - struct wlr_session *session; -}; - -enum wlr_drm_output_state { - WLR_DRM_OUTPUT_DISCONNECTED, - WLR_DRM_OUTPUT_NEEDS_MODESET, - WLR_DRM_OUTPUT_CLEANUP, - WLR_DRM_OUTPUT_CONNECTED, -}; - -struct wlr_drm_output_mode { - struct wlr_output_mode wlr_mode; - drmModeModeInfo mode; -}; - -struct wlr_drm_output { - struct wlr_output output; - - enum wlr_drm_output_state state; - uint32_t connector; - - struct wlr_drm_crtc *crtc; - uint32_t possible_crtc; - - union wlr_drm_connector_props props; - - uint32_t width; - uint32_t height; - - drmModeCrtc *old_crtc; - - struct wlr_drm_renderer *renderer; - - bool pageflip_pending; - struct wl_event_source *retry_pageflip; -}; - -// Used to provide atomic or legacy DRM functions -struct wlr_drm_interface { - // Enable or disable DPMS for output - void (*conn_enable)(struct wlr_drm_backend *backend, - struct wlr_drm_output *output, bool enable); - // Pageflip on crtc. If mode is non-NULL perform a full modeset using it. - bool (*crtc_pageflip)(struct wlr_drm_backend *backend, - struct wlr_drm_output *output, struct wlr_drm_crtc *crtc, - uint32_t fb_id, drmModeModeInfo *mode); - // Enable the cursor buffer on crtc. Set bo to NULL to disable - bool (*crtc_set_cursor)(struct wlr_drm_backend *backend, - struct wlr_drm_crtc *crtc, struct gbm_bo *bo); - // Move the cursor on crtc - bool (*crtc_move_cursor)(struct wlr_drm_backend *backend, - struct wlr_drm_crtc *crtc, int x, int y); -}; - -bool wlr_drm_check_features(struct wlr_drm_backend *drm); -bool wlr_drm_resources_init(struct wlr_drm_backend *drm); -void wlr_drm_resources_free(struct wlr_drm_backend *drm); -void wlr_drm_restore_outputs(struct wlr_drm_backend *drm); -void wlr_drm_output_cleanup(struct wlr_drm_output *output); -void wlr_drm_scan_connectors(struct wlr_drm_backend *state); -int wlr_drm_event(int fd, uint32_t mask, void *data); - -void wlr_drm_output_start_renderer(struct wlr_drm_output *output); - -#endif diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h new file mode 100644 index 00000000..43838495 --- /dev/null +++ b/include/backend/drm/drm.h @@ -0,0 +1,186 @@ +#ifndef BACKEND_DRM_DRM_H +#define BACKEND_DRM_DRM_H + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "properties.h" + +struct wlr_drm_plane { + uint32_t type; + uint32_t id; + + uint32_t possible_crtcs; + + uint32_t width, height; + + struct gbm_surface *gbm; + EGLSurface egl; + + struct gbm_bo *front; + struct gbm_bo *back; + + // Only used by cursor + float matrix[16]; + struct wlr_renderer *wlr_rend; + struct wlr_texture *wlr_tex; + struct gbm_bo *cursor_bo; + + union wlr_drm_plane_props props; +}; + +struct wlr_drm_crtc { + uint32_t id; + uint32_t mode_id; // atomic modesetting only + drmModeAtomicReq *atomic; + + union { + struct { + struct wlr_drm_plane *overlay; + struct wlr_drm_plane *primary; + struct wlr_drm_plane *cursor; + }; + struct wlr_drm_plane *planes[3]; + }; + + union wlr_drm_crtc_props props; + + struct wl_list connectors; +}; + +struct wlr_drm_connector { + struct wlr_output *base; + uint32_t id; + struct wlr_drm_crtc *crtc; + + union wlr_drm_connector_props props; + + struct wl_list link; +}; + +struct wlr_drm_renderer { + int fd; + struct gbm_device *gbm; + struct wlr_egl egl; +}; + +bool wlr_drm_renderer_init(struct wlr_drm_renderer *renderer, int fd); +void wlr_drm_renderer_free(struct wlr_drm_renderer *renderer); + +struct wlr_drm_interface; + +struct wlr_drm_backend { + struct wlr_backend backend; + + const struct wlr_drm_interface *iface; + + int fd; + + size_t num_crtcs; + struct wlr_drm_crtc *crtcs; + size_t num_planes; + struct wlr_drm_plane *planes; + + union { + struct { + size_t num_overlay_planes; + size_t num_primary_planes; + size_t num_cursor_planes; + }; + size_t num_type_planes[3]; + }; + + union { + struct { + struct wlr_drm_plane *overlay_planes; + struct wlr_drm_plane *primary_planes; + struct wlr_drm_plane *cursor_planes; + }; + struct wlr_drm_plane *type_planes[3]; + }; + + struct wl_display *display; + struct wl_event_source *drm_event; + + struct wl_listener session_signal; + struct wl_listener drm_invalidated; + + list_t *outputs; + + struct wlr_drm_renderer renderer; + struct wlr_session *session; +}; + +enum wlr_drm_output_state { + WLR_DRM_OUTPUT_DISCONNECTED, + WLR_DRM_OUTPUT_NEEDS_MODESET, + WLR_DRM_OUTPUT_CLEANUP, + WLR_DRM_OUTPUT_CONNECTED, +}; + +struct wlr_drm_output_mode { + struct wlr_output_mode wlr_mode; + drmModeModeInfo mode; +}; + +struct wlr_drm_output { + struct wlr_output output; + + enum wlr_drm_output_state state; + uint32_t connector; + + struct wlr_drm_crtc *crtc; + uint32_t possible_crtc; + + union wlr_drm_connector_props props; + + uint32_t width; + uint32_t height; + + drmModeCrtc *old_crtc; + + struct wlr_drm_renderer *renderer; + + bool pageflip_pending; + struct wl_event_source *retry_pageflip; +}; + +// Used to provide atomic or legacy DRM functions +struct wlr_drm_interface { + // Enable or disable DPMS for output + void (*conn_enable)(struct wlr_drm_backend *backend, + struct wlr_drm_output *output, bool enable); + // Pageflip on crtc. If mode is non-NULL perform a full modeset using it. + bool (*crtc_pageflip)(struct wlr_drm_backend *backend, + struct wlr_drm_output *output, struct wlr_drm_crtc *crtc, + uint32_t fb_id, drmModeModeInfo *mode); + // Enable the cursor buffer on crtc. Set bo to NULL to disable + bool (*crtc_set_cursor)(struct wlr_drm_backend *backend, + struct wlr_drm_crtc *crtc, struct gbm_bo *bo); + // Move the cursor on crtc + bool (*crtc_move_cursor)(struct wlr_drm_backend *backend, + struct wlr_drm_crtc *crtc, int x, int y); +}; + +bool wlr_drm_check_features(struct wlr_drm_backend *drm); +bool wlr_drm_resources_init(struct wlr_drm_backend *drm); +void wlr_drm_resources_free(struct wlr_drm_backend *drm); +void wlr_drm_restore_outputs(struct wlr_drm_backend *drm); +void wlr_drm_output_cleanup(struct wlr_drm_output *output); +void wlr_drm_scan_connectors(struct wlr_drm_backend *state); +int wlr_drm_event(int fd, uint32_t mask, void *data); + +void wlr_drm_output_start_renderer(struct wlr_drm_output *output); + +#endif diff --git a/include/backend/drm/properties.h b/include/backend/drm/properties.h new file mode 100644 index 00000000..7de386ea --- /dev/null +++ b/include/backend/drm/properties.h @@ -0,0 +1,67 @@ +#ifndef BACKEND_DRM_PROPERTIES_H +#define BACKEND_DRM_PROPERTIES_H + +#include +#include + +/* + * These types contain the property ids for several DRM objects. + * See https://01.org/linuxgraphics/gfx-docs/drm/gpu/drm-kms.html#kms-properties + * for more details. + */ + +union wlr_drm_connector_props { + struct { + uint32_t edid; + uint32_t dpms; + + // atomic-modesetting only + + uint32_t crtc_id; + }; + uint32_t props[3]; +}; + +union wlr_drm_crtc_props { + struct { + // Neither of these are guranteed to exist + uint32_t rotation; + uint32_t scaling_mode; + + // atomic-modesetting only + + uint32_t active; + uint32_t mode_id; + }; + uint32_t props[4]; +}; + +union wlr_drm_plane_props { + struct { + uint32_t type; + uint32_t rotation; // Not guranteed to exist + + // atomic-modesetting only + + uint32_t src_x; + uint32_t src_y; + uint32_t src_w; + uint32_t src_h; + uint32_t crtc_x; + uint32_t crtc_y; + uint32_t crtc_w; + uint32_t crtc_h; + uint32_t fb_id; + uint32_t crtc_id; + }; + uint32_t props[12]; +}; + +bool wlr_drm_get_connector_props(int fd, uint32_t id, union wlr_drm_connector_props *out); +bool wlr_drm_get_crtc_props(int fd, uint32_t id, union wlr_drm_crtc_props *out); +bool wlr_drm_get_plane_props(int fd, uint32_t id, union wlr_drm_plane_props *out); + +bool wlr_drm_get_prop(int fd, uint32_t obj, uint32_t prop, uint64_t *ret); +void *wlr_drm_get_prop_blob(int fd, uint32_t obj, uint32_t prop, size_t *ret_len); + +#endif diff --git a/include/backend/drm/util.h b/include/backend/drm/util.h new file mode 100644 index 00000000..6818b4db --- /dev/null +++ b/include/backend/drm/util.h @@ -0,0 +1,39 @@ +#ifndef BACKEND_DRM_UTIL_H +#define BACKEND_DRM_UTIL_H + +#include +#include +#include +#include + +// Calculates a more accurate refresh rate (mHz) than what mode itself provides +int32_t calculate_refresh_rate(drmModeModeInfo *mode); +// Populates the make/model/phys_{width,height} of output from the edid data +void parse_edid(struct wlr_output *restrict output, size_t len, const uint8_t *data); +// Returns the string representation of a DRM output type +const char *conn_get_name(uint32_t type_id); +// Returns the DRM framebuffer id for a gbm_bo +uint32_t get_fb_for_bo(struct gbm_bo *bo); + +// Part of match_obj +enum { + UNMATCHED = (uint32_t)-1, + SKIP = (uint32_t)-2, +}; + +/* + * Tries to match some DRM objects with some other DRM resource. + * e.g. Match CRTCs with Encoders, CRTCs with Planes. + * + * objs contains a bit array which resources it can be matched with. + * e.g. Bit 0 set means can be matched with res[0] + * + * res contains an index of which objs it is matched with or UNMATCHED. + * + * This solution is left in out. + * Returns the total number of matched solutions. + */ +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]); +#endif -- cgit v1.2.3 From d0708b1a3a3fb9fd3a073d6c5406b26e8bf617e9 Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Sat, 30 Sep 2017 19:11:41 +1300 Subject: Split DRM internal interface to its own header --- backend/drm/drm.c | 4 +--- backend/drm/iface_atomic.c | 1 + backend/drm/iface_legacy.c | 1 + include/backend/drm/drm.h | 18 +----------------- include/backend/drm/iface.h | 35 +++++++++++++++++++++++++++++++++++ 5 files changed, 39 insertions(+), 20 deletions(-) create mode 100644 include/backend/drm/iface.h (limited to 'backend') diff --git a/backend/drm/drm.c b/backend/drm/drm.c index cba41023..40a6f37b 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -21,12 +21,10 @@ #include #include #include "backend/drm/drm.h" +#include "backend/drm/iface.h" #include "backend/drm/util.h" bool wlr_drm_check_features(struct wlr_drm_backend *backend) { - extern const struct wlr_drm_interface iface_legacy; - extern const struct wlr_drm_interface iface_atomic; - if (drmSetClientCap(backend->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1)) { wlr_log(L_ERROR, "DRM universal planes unsupported"); return false; diff --git a/backend/drm/iface_atomic.c b/backend/drm/iface_atomic.c index 5bb2da9b..75a3c33a 100644 --- a/backend/drm/iface_atomic.c +++ b/backend/drm/iface_atomic.c @@ -3,6 +3,7 @@ #include #include #include "backend/drm/drm.h" +#include "backend/drm/iface.h" #include "backend/drm/util.h" struct atomic { diff --git a/backend/drm/iface_legacy.c b/backend/drm/iface_legacy.c index 856e9060..110b38b5 100644 --- a/backend/drm/iface_legacy.c +++ b/backend/drm/iface_legacy.c @@ -3,6 +3,7 @@ #include #include #include "backend/drm/drm.h" +#include "backend/drm/iface.h" #include "backend/drm/util.h" static bool legacy_crtc_pageflip(struct wlr_drm_backend *backend, diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h index 43838495..c57493f3 100644 --- a/include/backend/drm/drm.h +++ b/include/backend/drm/drm.h @@ -15,6 +15,7 @@ #include #include +#include "iface.h" #include "properties.h" struct wlr_drm_plane { @@ -156,23 +157,6 @@ struct wlr_drm_output { struct wl_event_source *retry_pageflip; }; -// Used to provide atomic or legacy DRM functions -struct wlr_drm_interface { - // Enable or disable DPMS for output - void (*conn_enable)(struct wlr_drm_backend *backend, - struct wlr_drm_output *output, bool enable); - // Pageflip on crtc. If mode is non-NULL perform a full modeset using it. - bool (*crtc_pageflip)(struct wlr_drm_backend *backend, - struct wlr_drm_output *output, struct wlr_drm_crtc *crtc, - uint32_t fb_id, drmModeModeInfo *mode); - // Enable the cursor buffer on crtc. Set bo to NULL to disable - bool (*crtc_set_cursor)(struct wlr_drm_backend *backend, - struct wlr_drm_crtc *crtc, struct gbm_bo *bo); - // Move the cursor on crtc - bool (*crtc_move_cursor)(struct wlr_drm_backend *backend, - struct wlr_drm_crtc *crtc, int x, int y); -}; - bool wlr_drm_check_features(struct wlr_drm_backend *drm); bool wlr_drm_resources_init(struct wlr_drm_backend *drm); void wlr_drm_resources_free(struct wlr_drm_backend *drm); diff --git a/include/backend/drm/iface.h b/include/backend/drm/iface.h new file mode 100644 index 00000000..cf77f4d4 --- /dev/null +++ b/include/backend/drm/iface.h @@ -0,0 +1,35 @@ +#ifndef BACKEND_DRM_IFACE_H +#define BACKEND_DRM_IFACE_H + +#include +#include + +#include +#include +#include + +struct wlr_drm_backend; +struct wlr_drm_output; +struct wlr_drm_crtc; + +// Used to provide atomic or legacy DRM functions +struct wlr_drm_interface { + // Enable or disable DPMS for output + void (*conn_enable)(struct wlr_drm_backend *backend, + struct wlr_drm_output *output, bool enable); + // Pageflip on crtc. If mode is non-NULL perform a full modeset using it. + bool (*crtc_pageflip)(struct wlr_drm_backend *backend, + struct wlr_drm_output *output, struct wlr_drm_crtc *crtc, + uint32_t fb_id, drmModeModeInfo *mode); + // Enable the cursor buffer on crtc. Set bo to NULL to disable + bool (*crtc_set_cursor)(struct wlr_drm_backend *backend, + struct wlr_drm_crtc *crtc, struct gbm_bo *bo); + // Move the cursor on crtc + bool (*crtc_move_cursor)(struct wlr_drm_backend *backend, + struct wlr_drm_crtc *crtc, int x, int y); +}; + +extern const struct wlr_drm_interface iface_atomic; +extern const struct wlr_drm_interface iface_legacy; + +#endif -- cgit v1.2.3 From 096249a2a1dc604b062a6fef6c4ca56065724d79 Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Sat, 30 Sep 2017 20:52:58 +1300 Subject: Split DRM rendering to its own file --- backend/drm/backend.c | 2 +- backend/drm/drm.c | 161 +++++------------------------------------ backend/drm/iface_atomic.c | 8 +- backend/drm/iface_legacy.c | 2 +- backend/drm/renderer.c | 126 ++++++++++++++++++++++++++++++++ backend/meson.build | 1 + include/backend/drm/drm.h | 20 +---- include/backend/drm/renderer.h | 47 ++++++++++++ 8 files changed, 202 insertions(+), 165 deletions(-) create mode 100644 backend/drm/renderer.c create mode 100644 include/backend/drm/renderer.h (limited to 'backend') diff --git a/backend/drm/backend.c b/backend/drm/backend.c index e046cea6..95c86bb1 100644 --- a/backend/drm/backend.c +++ b/backend/drm/backend.c @@ -33,7 +33,7 @@ static void wlr_drm_backend_destroy(struct wlr_backend *_backend) { wlr_output_destroy(&output->output); } - wlr_drm_renderer_free(&backend->renderer); + wlr_drm_renderer_finish(&backend->renderer); wlr_drm_resources_free(backend); wlr_session_close_file(backend->session, backend->fd); wl_event_source_remove(backend->drm_event); diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 40a6f37b..05a050e6 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -173,121 +173,9 @@ void wlr_drm_resources_free(struct wlr_drm_backend *backend) { free(backend->planes); } -bool wlr_drm_renderer_init(struct wlr_drm_renderer *renderer, int fd) { - renderer->gbm = gbm_create_device(fd); - if (!renderer->gbm) { - wlr_log(L_ERROR, "Failed to create GBM device: %s", strerror(errno)); - return false; - } - - if (!wlr_egl_init(&renderer->egl, EGL_PLATFORM_GBM_MESA, - GBM_FORMAT_ARGB8888, renderer->gbm)) { - gbm_device_destroy(renderer->gbm); - return false; - } - - renderer->fd = fd; - return true; -} - -void wlr_drm_renderer_free(struct wlr_drm_renderer *renderer) { - if (!renderer) { - return; - } - - wlr_egl_free(&renderer->egl); - gbm_device_destroy(renderer->gbm); -} - -static bool wlr_drm_plane_renderer_init(struct wlr_drm_renderer *renderer, - struct wlr_drm_plane *plane, uint32_t width, uint32_t height, uint32_t format, uint32_t flags) { - if (plane->width == width && plane->height == height) { - return true; - } - - plane->width = width; - plane->height = height; - - plane->gbm = gbm_surface_create(renderer->gbm, width, height, - format, GBM_BO_USE_RENDERING | flags); - if (!plane->gbm) { - wlr_log_errno(L_ERROR, "Failed to create GBM surface for plane"); - return false; - } - - plane->egl = wlr_egl_create_surface(&renderer->egl, plane->gbm); - if (plane->egl == EGL_NO_SURFACE) { - wlr_log(L_ERROR, "Failed to create EGL surface for plane"); - return false; - } - - return true; -} - -static void wlr_drm_plane_renderer_free(struct wlr_drm_renderer *renderer, - struct wlr_drm_plane *plane) { - if (!renderer || !plane) { - return; - } - - eglMakeCurrent(renderer->egl.display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - - if (plane->front) { - gbm_surface_release_buffer(plane->gbm, plane->front); - } - if (plane->back) { - gbm_surface_release_buffer(plane->gbm, plane->back); - } - - if (plane->egl) { - eglDestroySurface(renderer->egl.display, plane->egl); - } - if (plane->gbm) { - gbm_surface_destroy(plane->gbm); - } - - if (plane->wlr_tex) { - wlr_texture_destroy(plane->wlr_tex); - } - if (plane->wlr_rend) { - wlr_renderer_destroy(plane->wlr_rend); - } - if (plane->cursor_bo) { - gbm_bo_destroy(plane->cursor_bo); - } - - plane->width = 0; - plane->height = 0; - plane->egl = EGL_NO_SURFACE; - plane->gbm = NULL; - plane->front = NULL; - plane->back = NULL; - plane->wlr_rend = NULL; - plane->wlr_tex = NULL; - plane->cursor_bo = NULL; -} - -static void wlr_drm_plane_make_current(struct wlr_drm_renderer *renderer, - struct wlr_drm_plane *plane) { - eglMakeCurrent(renderer->egl.display, plane->egl, plane->egl, - renderer->egl.context); -} - -static void wlr_drm_plane_swap_buffers(struct wlr_drm_renderer *renderer, - struct wlr_drm_plane *plane) { - if (plane->front) { - gbm_surface_release_buffer(plane->gbm, plane->front); - } - - eglSwapBuffers(renderer->egl.display, plane->egl); - - plane->front = plane->back; - plane->back = gbm_surface_lock_front_buffer(plane->gbm); -} - static void wlr_drm_output_make_current(struct wlr_output *_output) { struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - wlr_drm_plane_make_current(output->renderer, output->crtc->primary); + wlr_drm_surface_make_current(output->renderer, &output->crtc->primary->surf); } static void wlr_drm_output_swap_buffers(struct wlr_output *_output) { @@ -298,9 +186,8 @@ static void wlr_drm_output_swap_buffers(struct wlr_output *_output) { struct wlr_drm_crtc *crtc = output->crtc; struct wlr_drm_plane *plane = crtc->primary; - wlr_drm_plane_swap_buffers(renderer, plane); - - uint32_t fb_id = get_fb_for_bo(plane->back); + struct gbm_bo *bo = wlr_drm_surface_swap_buffers(renderer, &plane->surf); + uint32_t fb_id = get_fb_for_bo(bo); if (backend->iface->crtc_pageflip(backend, output, crtc, fb_id, NULL)) { output->pageflip_pending = true; @@ -338,17 +225,7 @@ void wlr_drm_output_start_renderer(struct wlr_drm_output *output) { struct wlr_drm_crtc *crtc = output->crtc; struct wlr_drm_plane *plane = crtc->primary; - struct gbm_bo *bo = plane->front; - if (!bo) { - // Render a black frame to start the rendering loop - wlr_drm_plane_make_current(renderer, plane); - glViewport(0, 0, plane->width, plane->height); - glClearColor(0.0, 0.0, 0.0, 1.0); - glClear(GL_COLOR_BUFFER_BIT); - wlr_drm_plane_swap_buffers(renderer, plane); - - bo = plane->back; - } + struct gbm_bo *bo = wlr_drm_surface_get_front(renderer, &plane->surf); struct wlr_drm_output_mode *_mode = (struct wlr_drm_output_mode *)output->output.current_mode; @@ -415,8 +292,10 @@ static void realloc_planes(struct wlr_drm_backend *backend, const uint32_t *crtc struct wlr_drm_plane *new = &backend->type_planes[type][crtc_res[i]]; if (*old != new) { - wlr_drm_plane_renderer_free(&backend->renderer, *old); - wlr_drm_plane_renderer_free(&backend->renderer, new); + if (*old) { + wlr_drm_surface_finish(&backend->renderer, &(*old)->surf); + } + wlr_drm_surface_finish(&backend->renderer, &new->surf); *old = new; } } @@ -547,7 +426,7 @@ static bool wlr_drm_output_set_mode(struct wlr_output *_output, continue; } - if (!wlr_drm_plane_renderer_init(&backend->renderer, crtc->primary, + if (!wlr_drm_surface_init(&backend->renderer, &crtc->primary->surf, mode->width, mode->height, GBM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT)) { wlr_log(L_ERROR, "Failed to initalise renderer for plane"); @@ -598,7 +477,7 @@ static bool wlr_drm_output_set_cursor(struct wlr_output *_output, crtc->cursor = plane; } - if (!plane->gbm) { + if (!plane->surf.gbm) { int ret; uint64_t w, h; ret = drmGetCap(backend->fd, DRM_CAP_CURSOR_WIDTH, &w); @@ -611,7 +490,7 @@ static bool wlr_drm_output_set_cursor(struct wlr_output *_output, return false; } - if (!wlr_drm_plane_renderer_init(renderer, plane, w, h, GBM_FORMAT_ARGB8888, 0)) { + if (!wlr_drm_surface_init(renderer, &plane->surf, w, h, GBM_FORMAT_ARGB8888, 0)) { wlr_log(L_ERROR, "Cannot allocate cursor resources"); return false; } @@ -625,7 +504,7 @@ static bool wlr_drm_output_set_cursor(struct wlr_output *_output, // OpenGL will read the pixels out upside down, // so we need to flip the image vertically - wlr_matrix_texture(plane->matrix, plane->width, plane->height, + wlr_matrix_texture(plane->matrix, plane->surf.width, plane->surf.height, output->output.transform ^ WL_OUTPUT_TRANSFORM_FLIPPED_180); // TODO the image needs to be rotated depending on the output rotation @@ -653,12 +532,12 @@ static bool wlr_drm_output_set_cursor(struct wlr_output *_output, return false; } - wlr_drm_plane_make_current(renderer, plane); + wlr_drm_surface_make_current(renderer, &plane->surf); wlr_texture_upload_pixels(plane->wlr_tex, WL_SHM_FORMAT_ARGB8888, stride, width, height, buf); - glViewport(0, 0, plane->width, plane->height); + glViewport(0, 0, plane->surf.width, plane->surf.height); glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT); @@ -668,10 +547,10 @@ static bool wlr_drm_output_set_cursor(struct wlr_output *_output, glFinish(); glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, bo_stride); - glReadPixels(0, 0, plane->width, plane->height, GL_BGRA_EXT, GL_UNSIGNED_BYTE, bo_data); + glReadPixels(0, 0, plane->surf.width, plane->surf.height, GL_BGRA_EXT, GL_UNSIGNED_BYTE, bo_data); glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0); - wlr_drm_plane_swap_buffers(renderer, plane); + wlr_drm_surface_swap_buffers(renderer, &plane->surf); gbm_bo_unmap(bo, bo_data); @@ -914,9 +793,9 @@ static void page_flip_handler(int fd, unsigned seq, } struct wlr_drm_plane *plane = output->crtc->primary; - if (plane->front) { - gbm_surface_release_buffer(plane->gbm, plane->front); - plane->front = NULL; + if (plane->surf.front) { + gbm_surface_release_buffer(plane->surf.gbm, plane->surf.front); + plane->surf.front = NULL; } if (backend->session->active) { @@ -987,7 +866,7 @@ void wlr_drm_output_cleanup(struct wlr_drm_output *output) { case WLR_DRM_OUTPUT_CLEANUP:; struct wlr_drm_crtc *crtc = output->crtc; for (int i = 0; i < 3; ++i) { - wlr_drm_plane_renderer_free(renderer, crtc->planes[i]); + wlr_drm_surface_finish(renderer, &crtc->planes[i]->surf); if (crtc->planes[i] && crtc->planes[i]->id == 0) { free(crtc->planes[i]); crtc->planes[i] = NULL; diff --git a/backend/drm/iface_atomic.c b/backend/drm/iface_atomic.c index 75a3c33a..ce5de091 100644 --- a/backend/drm/iface_atomic.c +++ b/backend/drm/iface_atomic.c @@ -84,10 +84,10 @@ static void set_plane_props(struct atomic *atom, struct wlr_drm_plane *plane, // The src_* properties are in 16.16 fixed point atomic_add(atom, id, props->src_x, 0); atomic_add(atom, id, props->src_y, 0); - atomic_add(atom, id, props->src_w, plane->width << 16); - atomic_add(atom, id, props->src_h, plane->height << 16); - atomic_add(atom, id, props->crtc_w, plane->width); - atomic_add(atom, id, props->crtc_h, plane->height); + atomic_add(atom, id, props->src_w, plane->surf.width << 16); + atomic_add(atom, id, props->src_h, plane->surf.height << 16); + atomic_add(atom, id, props->crtc_w, plane->surf.width); + atomic_add(atom, id, props->crtc_h, plane->surf.height); atomic_add(atom, id, props->fb_id, fb_id); atomic_add(atom, id, props->crtc_id, crtc_id); if (set_crtc_xy) { diff --git a/backend/drm/iface_legacy.c b/backend/drm/iface_legacy.c index 110b38b5..e320af93 100644 --- a/backend/drm/iface_legacy.c +++ b/backend/drm/iface_legacy.c @@ -45,7 +45,7 @@ bool legacy_crtc_set_cursor(struct wlr_drm_backend *backend, struct wlr_drm_plane *plane = crtc->cursor; if (drmModeSetCursor(backend->fd, crtc->id, gbm_bo_get_handle(bo).u32, - plane->width, plane->height)) { + plane->surf.width, plane->surf.height)) { wlr_log_errno(L_ERROR, "Failed to set hardware cursor"); return false; } diff --git a/backend/drm/renderer.c b/backend/drm/renderer.c new file mode 100644 index 00000000..8afc6dca --- /dev/null +++ b/backend/drm/renderer.c @@ -0,0 +1,126 @@ +#include + +#include +#include +#include +#include + +#include +#include +#include "backend/drm/drm.h" + +bool wlr_drm_renderer_init(struct wlr_drm_renderer *renderer, int fd) { + renderer->gbm = gbm_create_device(fd); + if (!renderer->gbm) { + wlr_log(L_ERROR, "Failed to create GBM device"); + return false; + } + + if (!wlr_egl_init(&renderer->egl, EGL_PLATFORM_GBM_MESA, + GBM_FORMAT_ARGB8888, renderer->gbm)) { + gbm_device_destroy(renderer->gbm); + return false; + } + + renderer->fd = fd; + return true; +} + +void wlr_drm_renderer_finish(struct wlr_drm_renderer *renderer) { + if (!renderer) { + return; + } + + wlr_egl_free(&renderer->egl); + gbm_device_destroy(renderer->gbm); +} + +bool wlr_drm_surface_init(struct wlr_drm_renderer *renderer, + struct wlr_drm_surface *surf, uint32_t width, uint32_t height, + uint32_t format, uint32_t flags) { + if (surf->width == width && surf->height == height) { + return true; + } + + surf->width = width; + surf->height = height; + + surf->gbm = gbm_surface_create(renderer->gbm, width, height, + format, GBM_BO_USE_RENDERING | flags); + if (!surf->gbm) { + wlr_log_errno(L_ERROR, "Failed to create GBM surface"); + goto error_zero; + } + + surf->egl = wlr_egl_create_surface(&renderer->egl, surf->gbm); + if (surf->egl == EGL_NO_SURFACE) { + wlr_log(L_ERROR, "Failed to create EGL surface"); + goto error_gbm; + } + + return true; + +error_gbm: + gbm_surface_destroy(surf->gbm); +error_zero: + memset(surf, 0, sizeof(*surf)); + return false; +} + +void wlr_drm_surface_finish(struct wlr_drm_renderer *renderer, + struct wlr_drm_surface *surf) { + if (!renderer || !surf || !surf->gbm) { + return; + } + + eglMakeCurrent(renderer->egl.display, EGL_NO_SURFACE, EGL_NO_SURFACE, + EGL_NO_CONTEXT); + + if (surf->front) { + gbm_surface_release_buffer(surf->gbm, surf->front); + } + if (surf->back) { + gbm_surface_release_buffer(surf->gbm, surf->back); + } + + if (surf->egl) { + eglDestroySurface(renderer->egl.display, surf->egl); + } + if (surf->gbm) { + gbm_surface_destroy(surf->gbm); + } + + memset(surf, 0, sizeof(*surf)); +} + +void wlr_drm_surface_make_current(struct wlr_drm_renderer *renderer, + struct wlr_drm_surface *surf) { + eglMakeCurrent(renderer->egl.display, surf->egl, surf->egl, + renderer->egl.context); +} + +struct gbm_bo *wlr_drm_surface_swap_buffers(struct wlr_drm_renderer *renderer, + struct wlr_drm_surface *surf) { + if (surf->front) { + gbm_surface_release_buffer(surf->gbm, surf->front); + } + + eglSwapBuffers(renderer->egl.display, surf->egl); + + surf->front = surf->back; + surf->back = gbm_surface_lock_front_buffer(surf->gbm); + return surf->back; +} + +struct gbm_bo *wlr_drm_surface_get_front(struct wlr_drm_renderer *renderer, + struct wlr_drm_surface *surf) { + if (surf->front) { + return surf->front; + } + + wlr_drm_surface_make_current(renderer, surf); + glViewport(0, 0, surf->width, surf->height); + glClearColor(0.0, 0.0, 0.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + return wlr_drm_surface_swap_buffers(renderer, surf); +} diff --git a/backend/meson.build b/backend/meson.build index 630bc284..caf2c8b0 100644 --- a/backend/meson.build +++ b/backend/meson.build @@ -8,6 +8,7 @@ backend_files = files( 'drm/iface_atomic.c', 'drm/iface_legacy.c', 'drm/properties.c', + 'drm/renderer.c', 'drm/util.c', 'libinput/backend.c', 'libinput/events.c', diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h index c57493f3..b13cb5e7 100644 --- a/include/backend/drm/drm.h +++ b/include/backend/drm/drm.h @@ -17,6 +17,7 @@ #include "iface.h" #include "properties.h" +#include "renderer.h" struct wlr_drm_plane { uint32_t type; @@ -24,13 +25,7 @@ struct wlr_drm_plane { uint32_t possible_crtcs; - uint32_t width, height; - - struct gbm_surface *gbm; - EGLSurface egl; - - struct gbm_bo *front; - struct gbm_bo *back; + struct wlr_drm_surface surf; // Only used by cursor float matrix[16]; @@ -70,17 +65,6 @@ struct wlr_drm_connector { struct wl_list link; }; -struct wlr_drm_renderer { - int fd; - struct gbm_device *gbm; - struct wlr_egl egl; -}; - -bool wlr_drm_renderer_init(struct wlr_drm_renderer *renderer, int fd); -void wlr_drm_renderer_free(struct wlr_drm_renderer *renderer); - -struct wlr_drm_interface; - struct wlr_drm_backend { struct wlr_backend backend; diff --git a/include/backend/drm/renderer.h b/include/backend/drm/renderer.h new file mode 100644 index 00000000..bbcf4f0c --- /dev/null +++ b/include/backend/drm/renderer.h @@ -0,0 +1,47 @@ +#ifndef BACKEND_DRM_RENDERER_H +#define BACKEND_DRM_RENDERER_H + +#include +#include + +#include +#include + +struct wlr_drm_renderer { + int fd; + struct gbm_device *gbm; + struct wlr_egl egl; +}; + +struct wlr_drm_surface { + uint32_t width; + uint32_t height; + + struct gbm_surface *gbm; + EGLSurface egl; + + struct gbm_bo *front; + struct gbm_bo *back; +}; + +bool wlr_drm_renderer_init(struct wlr_drm_renderer *renderer, int fd); + +void wlr_drm_renderer_finish(struct wlr_drm_renderer *renderer); + +bool wlr_drm_surface_init(struct wlr_drm_renderer *renderer, + struct wlr_drm_surface *surf, uint32_t width, uint32_t height, + uint32_t format, uint32_t flags); + +void wlr_drm_surface_finish(struct wlr_drm_renderer *renderer, + struct wlr_drm_surface *surf); + +void wlr_drm_surface_make_current(struct wlr_drm_renderer *renderer, + struct wlr_drm_surface *surf); + +struct gbm_bo *wlr_drm_surface_swap_buffers(struct wlr_drm_renderer *renderer, + struct wlr_drm_surface *surf); + +struct gbm_bo *wlr_drm_surface_get_front(struct wlr_drm_renderer *renderer, + struct wlr_drm_surface *surf); + +#endif -- cgit v1.2.3 From ec5b95e08f7549fc3628d9790d62f22d8b975300 Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Sat, 30 Sep 2017 22:01:59 +1300 Subject: Add pointer to backend from DRM outputs --- backend/drm/drm.c | 38 ++++++++++++++------------------------ include/backend/drm/drm.h | 3 +-- 2 files changed, 15 insertions(+), 26 deletions(-) (limited to 'backend') diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 05a050e6..96feba15 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -175,14 +175,13 @@ void wlr_drm_resources_free(struct wlr_drm_backend *backend) { static void wlr_drm_output_make_current(struct wlr_output *_output) { struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - wlr_drm_surface_make_current(output->renderer, &output->crtc->primary->surf); + wlr_drm_surface_make_current(&output->drm->renderer, &output->crtc->primary->surf); } static void wlr_drm_output_swap_buffers(struct wlr_output *_output) { struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - struct wlr_drm_backend *backend = - wl_container_of(output->renderer, backend, renderer); - struct wlr_drm_renderer *renderer = output->renderer; + struct wlr_drm_backend *backend = output->drm; + struct wlr_drm_renderer *renderer = &backend->renderer; struct wlr_drm_crtc *crtc = output->crtc; struct wlr_drm_plane *plane = crtc->primary; @@ -200,8 +199,7 @@ static void wlr_drm_output_swap_buffers(struct wlr_output *_output) { static void wlr_drm_output_set_gamma(struct wlr_output *_output, uint16_t size, uint16_t *r, uint16_t *g, uint16_t *b) { struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - struct wlr_drm_backend *backend = - wl_container_of(output->renderer, backend, renderer); + struct wlr_drm_backend *backend = output->drm; drmModeCrtcSetGamma(backend->fd, output->crtc->id, size, r, g, b); } @@ -219,9 +217,8 @@ void wlr_drm_output_start_renderer(struct wlr_drm_output *output) { return; } - struct wlr_drm_backend *backend = - wl_container_of(output->renderer, backend, renderer); - struct wlr_drm_renderer *renderer = output->renderer; + struct wlr_drm_backend *backend = output->drm; + struct wlr_drm_renderer *renderer = &backend->renderer; struct wlr_drm_crtc *crtc = output->crtc; struct wlr_drm_plane *plane = crtc->primary; @@ -240,8 +237,7 @@ void wlr_drm_output_start_renderer(struct wlr_drm_output *output) { static void wlr_drm_output_enable(struct wlr_output *_output, bool enable) { struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - struct wlr_drm_backend *backend = - wl_container_of(output->renderer, backend, renderer); + struct wlr_drm_backend *backend = output->drm; if (output->state != WLR_DRM_OUTPUT_CONNECTED) { return; } @@ -367,8 +363,7 @@ static void realloc_crtcs(struct wlr_drm_backend *backend, static bool wlr_drm_output_set_mode(struct wlr_output *_output, struct wlr_output_mode *mode) { struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - struct wlr_drm_backend *backend - = wl_container_of(output->renderer, backend, renderer); + struct wlr_drm_backend *backend = output->drm; wlr_log(L_INFO, "Modesetting '%s' with '%ux%u@%u mHz'", output->output.name, mode->width, mode->height, mode->refresh); @@ -457,9 +452,8 @@ static void wlr_drm_output_transform(struct wlr_output *output, static bool wlr_drm_output_set_cursor(struct wlr_output *_output, const uint8_t *buf, int32_t stride, uint32_t width, uint32_t height) { struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - struct wlr_drm_backend *backend - = wl_container_of(output->renderer, backend, renderer); - struct wlr_drm_renderer *renderer = output->renderer; + struct wlr_drm_backend *backend = output->drm; + struct wlr_drm_renderer *renderer = &backend->renderer; struct wlr_drm_crtc *crtc = output->crtc; struct wlr_drm_plane *plane = crtc->cursor; @@ -560,8 +554,7 @@ static bool wlr_drm_output_set_cursor(struct wlr_output *_output, static bool wlr_drm_output_move_cursor(struct wlr_output *_output, int x, int y) { struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - struct wlr_drm_backend *backend = - wl_container_of(output->renderer, backend, renderer); + struct wlr_drm_backend *backend = output->drm; int width, height, tmp; wlr_output_effective_resolution(_output, &width, &height); @@ -678,7 +671,6 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *backend) { output); - output->renderer = &backend->renderer; output->state = WLR_DRM_OUTPUT_DISCONNECTED; output->connector = conn->connector_id; @@ -784,8 +776,7 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *backend) { static void page_flip_handler(int fd, unsigned seq, unsigned tv_sec, unsigned tv_usec, void *user) { struct wlr_drm_output *output = user; - struct wlr_drm_backend *backend = - wl_container_of(output->renderer, backend, renderer); + struct wlr_drm_backend *backend = output->drm; output->pageflip_pending = false; if (output->state != WLR_DRM_OUTPUT_CONNECTED) { @@ -857,9 +848,8 @@ void wlr_drm_output_cleanup(struct wlr_drm_output *output) { return; } - struct wlr_drm_renderer *renderer = output->renderer; - struct wlr_drm_backend *backend = - wl_container_of(renderer, backend, renderer); + struct wlr_drm_backend *backend = output->drm; + struct wlr_drm_renderer *renderer = &backend->renderer; switch (output->state) { case WLR_DRM_OUTPUT_CONNECTED: diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h index b13cb5e7..6f1abc00 100644 --- a/include/backend/drm/drm.h +++ b/include/backend/drm/drm.h @@ -121,6 +121,7 @@ struct wlr_drm_output_mode { struct wlr_drm_output { struct wlr_output output; + struct wlr_drm_backend *drm; enum wlr_drm_output_state state; uint32_t connector; @@ -135,8 +136,6 @@ struct wlr_drm_output { drmModeCrtc *old_crtc; - struct wlr_drm_renderer *renderer; - bool pageflip_pending; struct wl_event_source *retry_pageflip; }; -- cgit v1.2.3 From 22e77d919570c0a8d4a84878c377db8fa9a0edfb Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Sat, 30 Sep 2017 22:22:26 +1300 Subject: Rename backend to drm --- backend/drm/backend.c | 97 ++++++++-------- backend/drm/drm.c | 262 ++++++++++++++++++++++---------------------- backend/drm/iface_atomic.c | 28 ++--- backend/drm/iface_legacy.c | 20 ++-- include/backend/drm/iface.h | 18 +-- 5 files changed, 210 insertions(+), 215 deletions(-) (limited to 'backend') diff --git a/backend/drm/backend.c b/backend/drm/backend.c index 95c86bb1..f634eee6 100644 --- a/backend/drm/backend.c +++ b/backend/drm/backend.c @@ -14,36 +14,37 @@ #include #include "backend/drm/drm.h" -static bool wlr_drm_backend_start(struct wlr_backend *_backend) { - struct wlr_drm_backend *backend = (struct wlr_drm_backend *)_backend; - wlr_drm_scan_connectors(backend); +static bool wlr_drm_backend_start(struct wlr_backend *backend) { + struct wlr_drm_backend *drm = (struct wlr_drm_backend *)backend; + wlr_drm_scan_connectors(drm); return true; } -static void wlr_drm_backend_destroy(struct wlr_backend *_backend) { - if (!_backend) { +static void wlr_drm_backend_destroy(struct wlr_backend *backend) { + if (!backend) { return; } - struct wlr_drm_backend *backend = (struct wlr_drm_backend *)_backend; - wlr_drm_restore_outputs(backend); + struct wlr_drm_backend *drm = (struct wlr_drm_backend *)backend; + + wlr_drm_restore_outputs(drm); - for (size_t i = 0; backend->outputs && i < backend->outputs->length; ++i) { - struct wlr_drm_output *output = backend->outputs->items[i]; + for (size_t i = 0; drm->outputs && i < drm->outputs->length; ++i) { + struct wlr_drm_output *output = drm->outputs->items[i]; wlr_output_destroy(&output->output); } - wlr_drm_renderer_finish(&backend->renderer); - wlr_drm_resources_free(backend); - wlr_session_close_file(backend->session, backend->fd); - wl_event_source_remove(backend->drm_event); - list_free(backend->outputs); - free(backend); + wlr_drm_renderer_finish(&drm->renderer); + wlr_drm_resources_free(drm); + wlr_session_close_file(drm->session, drm->fd); + wl_event_source_remove(drm->drm_event); + list_free(drm->outputs); + free(drm); } static struct wlr_egl *wlr_drm_backend_get_egl(struct wlr_backend *_backend) { - struct wlr_drm_backend *backend = (struct wlr_drm_backend *)_backend; - return &backend->renderer.egl; + struct wlr_drm_backend *drm = (struct wlr_drm_backend *)_backend; + return &drm->renderer.egl; } static struct wlr_backend_impl backend_impl = { @@ -57,15 +58,14 @@ bool wlr_backend_is_drm(struct wlr_backend *b) { } static void session_signal(struct wl_listener *listener, void *data) { - struct wlr_drm_backend *backend = - wl_container_of(listener, backend, session_signal); + struct wlr_drm_backend *drm = wl_container_of(listener, drm, session_signal); struct wlr_session *session = data; if (session->active) { wlr_log(L_INFO, "DRM fd resumed"); - for (size_t i = 0; i < backend->outputs->length; ++i) { - struct wlr_drm_output *output = backend->outputs->items[i]; + for (size_t i = 0; i < drm->outputs->length; ++i) { + struct wlr_drm_output *output = drm->outputs->items[i]; wlr_drm_output_start_renderer(output); if (!output->crtc) { @@ -73,7 +73,7 @@ static void session_signal(struct wl_listener *listener, void *data) { } struct wlr_drm_plane *plane = output->crtc->cursor; - backend->iface->crtc_set_cursor(backend, output->crtc, + drm->iface->crtc_set_cursor(drm, output->crtc, plane ? plane->cursor_bo : NULL); } } else { @@ -82,14 +82,13 @@ static void session_signal(struct wl_listener *listener, void *data) { } static void drm_invalidated(struct wl_listener *listener, void *data) { - struct wlr_drm_backend *backend = - wl_container_of(listener, backend, drm_invalidated); + struct wlr_drm_backend *drm = wl_container_of(listener, drm, drm_invalidated); - char *name = drmGetDeviceNameFromFd2(backend->fd); + char *name = drmGetDeviceNameFromFd2(drm->fd); wlr_log(L_DEBUG, "%s invalidated", name); free(name); - wlr_drm_scan_connectors(backend); + wlr_drm_scan_connectors(drm); } struct wlr_backend *wlr_drm_backend_create(struct wl_display *display, @@ -102,63 +101,63 @@ struct wlr_backend *wlr_drm_backend_create(struct wl_display *display, free(name); drmFreeVersion(version); - struct wlr_drm_backend *backend = calloc(1, sizeof(struct wlr_drm_backend)); - if (!backend) { + struct wlr_drm_backend *drm = calloc(1, sizeof(struct wlr_drm_backend)); + if (!drm) { wlr_log_errno(L_ERROR, "Allocation failed"); return NULL; } - wlr_backend_init(&backend->backend, &backend_impl); + wlr_backend_init(&drm->backend, &backend_impl); - backend->session = session; - backend->outputs = list_create(); - if (!backend->outputs) { + drm->session = session; + drm->outputs = list_create(); + if (!drm->outputs) { wlr_log(L_ERROR, "Failed to allocate list"); goto error_backend; } - backend->fd = gpu_fd; + drm->fd = gpu_fd; - backend->drm_invalidated.notify = drm_invalidated; - wlr_session_signal_add(session, gpu_fd, &backend->drm_invalidated); + drm->drm_invalidated.notify = drm_invalidated; + wlr_session_signal_add(session, gpu_fd, &drm->drm_invalidated); - backend->display = display; + drm->display = display; struct wl_event_loop *event_loop = wl_display_get_event_loop(display); - backend->drm_event = wl_event_loop_add_fd(event_loop, backend->fd, + drm->drm_event = wl_event_loop_add_fd(event_loop, drm->fd, WL_EVENT_READABLE, wlr_drm_event, NULL); - if (!backend->drm_event) { + if (!drm->drm_event) { wlr_log(L_ERROR, "Failed to create DRM event source"); goto error_fd; } - backend->session_signal.notify = session_signal; - wl_signal_add(&session->session_signal, &backend->session_signal); + drm->session_signal.notify = session_signal; + wl_signal_add(&session->session_signal, &drm->session_signal); - if (!wlr_drm_check_features(backend)) { + if (!wlr_drm_check_features(drm)) { goto error_event; } - if (!wlr_drm_resources_init(backend)) { + if (!wlr_drm_resources_init(drm)) { goto error_event; } - if (!wlr_drm_renderer_init(&backend->renderer, backend->fd)) { + if (!wlr_drm_renderer_init(&drm->renderer, drm->fd)) { wlr_log(L_ERROR, "Failed to initialize renderer"); goto error_event; } - if (!wlr_egl_bind_display(&backend->renderer.egl, display)) { + if (!wlr_egl_bind_display(&drm->renderer.egl, display)) { wlr_log(L_INFO, "Failed to bind egl/wl display: %s", egl_error()); } - return &backend->backend; + return &drm->backend; error_event: - wl_event_source_remove(backend->drm_event); + wl_event_source_remove(drm->drm_event); error_fd: - wlr_session_close_file(backend->session, backend->fd); - list_free(backend->outputs); + wlr_session_close_file(drm->session, drm->fd); + list_free(drm->outputs); error_backend: - free(backend); + free(drm); return NULL; } diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 96feba15..a50216cb 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -24,21 +24,21 @@ #include "backend/drm/iface.h" #include "backend/drm/util.h" -bool wlr_drm_check_features(struct wlr_drm_backend *backend) { - if (drmSetClientCap(backend->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1)) { +bool wlr_drm_check_features(struct wlr_drm_backend *drm) { + if (drmSetClientCap(drm->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1)) { wlr_log(L_ERROR, "DRM universal planes unsupported"); return false; } if (getenv("WLR_DRM_NO_ATOMIC")) { wlr_log(L_DEBUG, "WLR_DRM_NO_ATOMIC set, forcing legacy DRM interface"); - backend->iface = &iface_legacy; - } else if (drmSetClientCap(backend->fd, DRM_CLIENT_CAP_ATOMIC, 1)) { + drm->iface = &iface_legacy; + } else if (drmSetClientCap(drm->fd, DRM_CLIENT_CAP_ATOMIC, 1)) { wlr_log(L_DEBUG, "Atomic modesetting unsupported, using legacy DRM interface"); - backend->iface = &iface_legacy; + drm->iface = &iface_legacy; } else { wlr_log(L_DEBUG, "Using atomic DRM interface"); - backend->iface = &iface_atomic; + drm->iface = &iface_atomic; } return true; @@ -51,8 +51,8 @@ static int cmp_plane(const void *arg1, const void *arg2) { return (int)a->type - (int)b->type; } -static bool init_planes(struct wlr_drm_backend *backend) { - drmModePlaneRes *plane_res = drmModeGetPlaneResources(backend->fd); +static bool init_planes(struct wlr_drm_backend *drm) { + drmModePlaneRes *plane_res = drmModeGetPlaneResources(drm->fd); if (!plane_res) { wlr_log_errno(L_ERROR, "Failed to get DRM plane resources"); return false; @@ -65,17 +65,17 @@ static bool init_planes(struct wlr_drm_backend *backend) { return true; } - backend->num_planes = plane_res->count_planes; - backend->planes = calloc(backend->num_planes, sizeof(*backend->planes)); - if (!backend->planes) { + drm->num_planes = plane_res->count_planes; + drm->planes = calloc(drm->num_planes, sizeof(*drm->planes)); + if (!drm->planes) { wlr_log_errno(L_ERROR, "Allocation failed"); goto error_res; } - for (size_t i = 0; i < backend->num_planes; ++i) { - struct wlr_drm_plane *p = &backend->planes[i]; + for (size_t i = 0; i < drm->num_planes; ++i) { + struct wlr_drm_plane *p = &drm->planes[i]; - drmModePlane *plane = drmModeGetPlane(backend->fd, plane_res->planes[i]); + drmModePlane *plane = drmModeGetPlane(drm->fd, plane_res->planes[i]); if (!plane) { wlr_log_errno(L_ERROR, "Failed to get DRM plane"); goto error_planes; @@ -85,44 +85,43 @@ static bool init_planes(struct wlr_drm_backend *backend) { p->possible_crtcs = plane->possible_crtcs; uint64_t type; - if (!wlr_drm_get_plane_props(backend->fd, p->id, &p->props) || - !wlr_drm_get_prop(backend->fd, p->id, p->props.type, &type)) { + if (!wlr_drm_get_plane_props(drm->fd, p->id, &p->props) || + !wlr_drm_get_prop(drm->fd, p->id, p->props.type, &type)) { drmModeFreePlane(plane); goto error_planes; } p->type = type; - backend->num_type_planes[type]++; + drm->num_type_planes[type]++; drmModeFreePlane(plane); } wlr_log(L_INFO, "(%zu overlay, %zu primary, %zu cursor)", - backend->num_overlay_planes, - backend->num_primary_planes, - backend->num_cursor_planes); + drm->num_overlay_planes, + drm->num_primary_planes, + drm->num_cursor_planes); - qsort(backend->planes, backend->num_planes, - sizeof(*backend->planes), cmp_plane); + qsort(drm->planes, drm->num_planes, sizeof(*drm->planes), cmp_plane); - backend->overlay_planes = backend->planes; - backend->primary_planes = backend->overlay_planes - + backend->num_overlay_planes; - backend->cursor_planes = backend->primary_planes - + backend->num_primary_planes; + drm->overlay_planes = drm->planes; + drm->primary_planes = drm->overlay_planes + + drm->num_overlay_planes; + drm->cursor_planes = drm->primary_planes + + drm->num_primary_planes; drmModeFreePlaneResources(plane_res); return true; error_planes: - free(backend->planes); + free(drm->planes); error_res: drmModeFreePlaneResources(plane_res); return false; } -bool wlr_drm_resources_init(struct wlr_drm_backend *backend) { - drmModeRes *res = drmModeGetResources(backend->fd); +bool wlr_drm_resources_init(struct wlr_drm_backend *drm) { + drmModeRes *res = drmModeGetResources(drm->fd); if (!res) { wlr_log_errno(L_ERROR, "Failed to get DRM resources"); return false; @@ -130,20 +129,20 @@ bool wlr_drm_resources_init(struct wlr_drm_backend *backend) { wlr_log(L_INFO, "Found %d DRM CRTCs", res->count_crtcs); - backend->num_crtcs = res->count_crtcs; - backend->crtcs = calloc(backend->num_crtcs, sizeof(backend->crtcs[0])); - if (!backend->crtcs) { + drm->num_crtcs = res->count_crtcs; + drm->crtcs = calloc(drm->num_crtcs, sizeof(drm->crtcs[0])); + if (!drm->crtcs) { wlr_log_errno(L_ERROR, "Allocation failed"); goto error_res; } - for (size_t i = 0; i < backend->num_crtcs; ++i) { - struct wlr_drm_crtc *crtc = &backend->crtcs[i]; + for (size_t i = 0; i < drm->num_crtcs; ++i) { + struct wlr_drm_crtc *crtc = &drm->crtcs[i]; crtc->id = res->crtcs[i]; - wlr_drm_get_crtc_props(backend->fd, crtc->id, &crtc->props); + wlr_drm_get_crtc_props(drm->fd, crtc->id, &crtc->props); } - if (!init_planes(backend)) { + if (!init_planes(drm)) { goto error_crtcs; } @@ -152,25 +151,26 @@ bool wlr_drm_resources_init(struct wlr_drm_backend *backend) { return true; error_crtcs: - free(backend->crtcs); + free(drm->crtcs); error_res: drmModeFreeResources(res); return false; } -void wlr_drm_resources_free(struct wlr_drm_backend *backend) { - if (!backend) { +void wlr_drm_resources_free(struct wlr_drm_backend *drm) { + if (!drm) { return; } - for (size_t i = 0; i < backend->num_crtcs; ++i) { - struct wlr_drm_crtc *crtc = &backend->crtcs[i]; + + for (size_t i = 0; i < drm->num_crtcs; ++i) { + struct wlr_drm_crtc *crtc = &drm->crtcs[i]; drmModeAtomicFree(crtc->atomic); if (crtc->mode_id) { - drmModeDestroyPropertyBlob(backend->fd, crtc->mode_id); + drmModeDestroyPropertyBlob(drm->fd, crtc->mode_id); } } - free(backend->crtcs); - free(backend->planes); + free(drm->crtcs); + free(drm->planes); } static void wlr_drm_output_make_current(struct wlr_output *_output) { @@ -180,15 +180,15 @@ static void wlr_drm_output_make_current(struct wlr_output *_output) { static void wlr_drm_output_swap_buffers(struct wlr_output *_output) { struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - struct wlr_drm_backend *backend = output->drm; - struct wlr_drm_renderer *renderer = &backend->renderer; + struct wlr_drm_backend *drm = output->drm; + struct wlr_drm_crtc *crtc = output->crtc; struct wlr_drm_plane *plane = crtc->primary; - struct gbm_bo *bo = wlr_drm_surface_swap_buffers(renderer, &plane->surf); + struct gbm_bo *bo = wlr_drm_surface_swap_buffers(&drm->renderer, &plane->surf); uint32_t fb_id = get_fb_for_bo(bo); - if (backend->iface->crtc_pageflip(backend, output, crtc, fb_id, NULL)) { + if (drm->iface->crtc_pageflip(drm, output, crtc, fb_id, NULL)) { output->pageflip_pending = true; } else { wl_event_source_timer_update(output->retry_pageflip, @@ -199,8 +199,7 @@ static void wlr_drm_output_swap_buffers(struct wlr_output *_output) { static void wlr_drm_output_set_gamma(struct wlr_output *_output, uint16_t size, uint16_t *r, uint16_t *g, uint16_t *b) { struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - struct wlr_drm_backend *backend = output->drm; - drmModeCrtcSetGamma(backend->fd, output->crtc->id, size, r, g, b); + drmModeCrtcSetGamma(output->drm->fd, output->crtc->id, size, r, g, b); } static uint16_t wlr_drm_output_get_gamma_size(struct wlr_output *_output) { @@ -217,17 +216,16 @@ void wlr_drm_output_start_renderer(struct wlr_drm_output *output) { return; } - struct wlr_drm_backend *backend = output->drm; - struct wlr_drm_renderer *renderer = &backend->renderer; + struct wlr_drm_backend *drm = output->drm; struct wlr_drm_crtc *crtc = output->crtc; struct wlr_drm_plane *plane = crtc->primary; - struct gbm_bo *bo = wlr_drm_surface_get_front(renderer, &plane->surf); + struct gbm_bo *bo = wlr_drm_surface_get_front(&drm->renderer, &plane->surf); struct wlr_drm_output_mode *_mode = (struct wlr_drm_output_mode *)output->output.current_mode; drmModeModeInfo *mode = &_mode->mode; - if (backend->iface->crtc_pageflip(backend, output, crtc, get_fb_for_bo(bo), mode)) { + if (drm->iface->crtc_pageflip(drm, output, crtc, get_fb_for_bo(bo), mode)) { output->pageflip_pending = true; } else { wl_event_source_timer_update(output->retry_pageflip, @@ -237,82 +235,81 @@ void wlr_drm_output_start_renderer(struct wlr_drm_output *output) { static void wlr_drm_output_enable(struct wlr_output *_output, bool enable) { struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - struct wlr_drm_backend *backend = output->drm; if (output->state != WLR_DRM_OUTPUT_CONNECTED) { return; } - backend->iface->conn_enable(backend, output, enable); + struct wlr_drm_backend *drm = output->drm; + drm->iface->conn_enable(drm, output, enable); if (enable) { wlr_drm_output_start_renderer(output); } } -static void realloc_planes(struct wlr_drm_backend *backend, const uint32_t *crtc_in) { +static void realloc_planes(struct wlr_drm_backend *drm, const uint32_t *crtc_in) { // overlay, primary, cursor for (int type = 0; type < 3; ++type) { - if (backend->num_type_planes[type] == 0) { + if (drm->num_type_planes[type] == 0) { continue; } - uint32_t possible[backend->num_type_planes[type]]; - uint32_t crtc[backend->num_crtcs]; - uint32_t crtc_res[backend->num_crtcs]; + uint32_t possible[drm->num_type_planes[type]]; + uint32_t crtc[drm->num_crtcs]; + uint32_t crtc_res[drm->num_crtcs]; - for (size_t i = 0; i < backend->num_type_planes[type]; ++i) { - possible[i] = backend->type_planes[type][i].possible_crtcs; + for (size_t i = 0; i < drm->num_type_planes[type]; ++i) { + possible[i] = drm->type_planes[type][i].possible_crtcs; } - for (size_t i = 0; i < backend->num_crtcs; ++i) { + for (size_t i = 0; i < drm->num_crtcs; ++i) { if (crtc_in[i] == UNMATCHED) { crtc[i] = SKIP; - } else if (backend->crtcs[i].planes[type]) { - crtc[i] = backend->crtcs[i].planes[type] - - backend->type_planes[type]; + } else if (drm->crtcs[i].planes[type]) { + crtc[i] = drm->crtcs[i].planes[type] + - drm->type_planes[type]; } else { crtc[i] = UNMATCHED; } } - match_obj(backend->num_type_planes[type], possible, - backend->num_crtcs, crtc, crtc_res); + match_obj(drm->num_type_planes[type], possible, + drm->num_crtcs, crtc, crtc_res); - for (size_t i = 0; i < backend->num_crtcs; ++i) { + for (size_t i = 0; i < drm->num_crtcs; ++i) { if (crtc_res[i] == UNMATCHED || crtc_res[i] == SKIP) { continue; } - struct wlr_drm_crtc *c = &backend->crtcs[i]; + struct wlr_drm_crtc *c = &drm->crtcs[i]; struct wlr_drm_plane **old = &c->planes[type]; - struct wlr_drm_plane *new = &backend->type_planes[type][crtc_res[i]]; + struct wlr_drm_plane *new = &drm->type_planes[type][crtc_res[i]]; if (*old != new) { if (*old) { - wlr_drm_surface_finish(&backend->renderer, &(*old)->surf); + wlr_drm_surface_finish(&drm->renderer, &(*old)->surf); } - wlr_drm_surface_finish(&backend->renderer, &new->surf); + wlr_drm_surface_finish(&drm->renderer, &new->surf); *old = new; } } } } -static void realloc_crtcs(struct wlr_drm_backend *backend, - struct wlr_drm_output *output) { - uint32_t crtc[backend->num_crtcs]; - uint32_t crtc_res[backend->num_crtcs]; - uint32_t possible_crtc[backend->outputs->length]; +static void realloc_crtcs(struct wlr_drm_backend *drm, struct wlr_drm_output *output) { + uint32_t crtc[drm->num_crtcs]; + uint32_t crtc_res[drm->num_crtcs]; + uint32_t possible_crtc[drm->outputs->length]; - for (size_t i = 0; i < backend->num_crtcs; ++i) { + for (size_t i = 0; i < drm->num_crtcs; ++i) { crtc[i] = UNMATCHED; } memset(possible_crtc, 0, sizeof(possible_crtc)); ssize_t index = -1; - for (size_t i = 0; i < backend->outputs->length; ++i) { - struct wlr_drm_output *o = backend->outputs->items[i]; + for (size_t i = 0; i < drm->outputs->length; ++i) { + struct wlr_drm_output *o = drm->outputs->items[i]; if (o == output) { index = i; } @@ -322,16 +319,16 @@ static void realloc_crtcs(struct wlr_drm_backend *backend, } possible_crtc[i] = o->possible_crtc; - crtc[o->crtc - backend->crtcs] = i; + crtc[o->crtc - drm->crtcs] = i; } assert(index != -1); possible_crtc[index] = output->possible_crtc; - match_obj(backend->outputs->length, possible_crtc, - backend->num_crtcs, crtc, crtc_res); + match_obj(drm->outputs->length, possible_crtc, + drm->num_crtcs, crtc, crtc_res); bool matched = false; - for (size_t i = 0; i < backend->num_crtcs; ++i) { + for (size_t i = 0; i < drm->num_crtcs; ++i) { // We don't want any of the current monitors to be deactivated. if (crtc[i] != UNMATCHED && crtc_res[i] == UNMATCHED) { return; @@ -346,29 +343,29 @@ static void realloc_crtcs(struct wlr_drm_backend *backend, return; } - for (size_t i = 0; i < backend->num_crtcs; ++i) { + for (size_t i = 0; i < drm->num_crtcs; ++i) { if (crtc_res[i] == UNMATCHED) { continue; } if (crtc_res[i] != crtc[i]) { - struct wlr_drm_output *o = backend->outputs->items[crtc_res[i]]; - o->crtc = &backend->crtcs[i]; + struct wlr_drm_output *o = drm->outputs->items[crtc_res[i]]; + o->crtc = &drm->crtcs[i]; } } - realloc_planes(backend, crtc_res); + realloc_planes(drm, crtc_res); } static bool wlr_drm_output_set_mode(struct wlr_output *_output, struct wlr_output_mode *mode) { struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - struct wlr_drm_backend *backend = output->drm; + struct wlr_drm_backend *drm = output->drm; wlr_log(L_INFO, "Modesetting '%s' with '%ux%u@%u mHz'", output->output.name, mode->width, mode->height, mode->refresh); - drmModeConnector *conn = drmModeGetConnector(backend->fd, output->connector); + drmModeConnector *conn = drmModeGetConnector(drm->fd, output->connector); if (!conn) { wlr_log_errno(L_ERROR, "Failed to get DRM connector"); goto error_output; @@ -381,7 +378,7 @@ static bool wlr_drm_output_set_mode(struct wlr_output *_output, drmModeEncoder *enc = NULL; for (int i = 0; !enc && i < conn->count_encoders; ++i) { - enc = drmModeGetEncoder(backend->fd, conn->encoders[i]); + enc = drmModeGetEncoder(drm->fd, conn->encoders[i]); } if (!enc) { @@ -390,7 +387,7 @@ static bool wlr_drm_output_set_mode(struct wlr_output *_output, } output->possible_crtc = enc->possible_crtcs; - realloc_crtcs(backend, output); + realloc_crtcs(drm, output); if (!output->crtc) { wlr_log(L_ERROR, "Unable to match %s with a CRTC", output->output.name); @@ -399,10 +396,10 @@ static bool wlr_drm_output_set_mode(struct wlr_output *_output, struct wlr_drm_crtc *crtc = output->crtc; wlr_log(L_DEBUG, "%s: crtc=%ju ovr=%jd pri=%jd cur=%jd", output->output.name, - crtc - backend->crtcs, - crtc->overlay ? crtc->overlay - backend->overlay_planes : -1, - crtc->primary ? crtc->primary - backend->primary_planes : -1, - crtc->cursor ? crtc->cursor - backend->cursor_planes : -1); + crtc - drm->crtcs, + crtc->overlay ? crtc->overlay - drm->overlay_planes : -1, + crtc->primary ? crtc->primary - drm->primary_planes : -1, + crtc->cursor ? crtc->cursor - drm->cursor_planes : -1); output->state = WLR_DRM_OUTPUT_CONNECTED; output->width = output->output.width = mode->width; @@ -412,8 +409,8 @@ static bool wlr_drm_output_set_mode(struct wlr_output *_output, // Since realloc_crtcs can deallocate planes on OTHER outputs, // we actually need to reinitalise all of them - for (size_t i = 0; i < backend->outputs->length; ++i) { - struct wlr_drm_output *output = backend->outputs->items[i]; + for (size_t i = 0; i < drm->outputs->length; ++i) { + struct wlr_drm_output *output = drm->outputs->items[i]; struct wlr_output_mode *mode = output->output.current_mode; struct wlr_drm_crtc *crtc = output->crtc; @@ -421,7 +418,7 @@ static bool wlr_drm_output_set_mode(struct wlr_output *_output, continue; } - if (!wlr_drm_surface_init(&backend->renderer, &crtc->primary->surf, + if (!wlr_drm_surface_init(&drm->renderer, &crtc->primary->surf, mode->width, mode->height, GBM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT)) { wlr_log(L_ERROR, "Failed to initalise renderer for plane"); @@ -452,13 +449,13 @@ static void wlr_drm_output_transform(struct wlr_output *output, static bool wlr_drm_output_set_cursor(struct wlr_output *_output, const uint8_t *buf, int32_t stride, uint32_t width, uint32_t height) { struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - struct wlr_drm_backend *backend = output->drm; - struct wlr_drm_renderer *renderer = &backend->renderer; + struct wlr_drm_backend *drm = output->drm; + struct wlr_drm_renderer *renderer = &drm->renderer; struct wlr_drm_crtc *crtc = output->crtc; struct wlr_drm_plane *plane = crtc->cursor; if (!buf) { - return backend->iface->crtc_set_cursor(backend, crtc, NULL); + return drm->iface->crtc_set_cursor(drm, crtc, NULL); } // We don't have a real cursor plane, so we make a fake one @@ -474,9 +471,9 @@ static bool wlr_drm_output_set_cursor(struct wlr_output *_output, if (!plane->surf.gbm) { int ret; uint64_t w, h; - ret = drmGetCap(backend->fd, DRM_CAP_CURSOR_WIDTH, &w); + ret = drmGetCap(drm->fd, DRM_CAP_CURSOR_WIDTH, &w); w = ret ? 64 : w; - ret = drmGetCap(backend->fd, DRM_CAP_CURSOR_HEIGHT, &h); + ret = drmGetCap(drm->fd, DRM_CAP_CURSOR_HEIGHT, &h); h = ret ? 64 : h; if (width > w || height > h) { @@ -503,7 +500,7 @@ static bool wlr_drm_output_set_cursor(struct wlr_output *_output, // TODO the image needs to be rotated depending on the output rotation - plane->wlr_rend = wlr_gles2_renderer_create(&backend->backend); + plane->wlr_rend = wlr_gles2_renderer_create(&drm->backend); if (!plane->wlr_rend) { return false; } @@ -548,13 +545,13 @@ static bool wlr_drm_output_set_cursor(struct wlr_output *_output, gbm_bo_unmap(bo, bo_data); - return backend->iface->crtc_set_cursor(backend, crtc, bo); + return drm->iface->crtc_set_cursor(drm, crtc, bo); } static bool wlr_drm_output_move_cursor(struct wlr_output *_output, int x, int y) { struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - struct wlr_drm_backend *backend = output->drm; + struct wlr_drm_backend *drm = output->drm; int width, height, tmp; wlr_output_effective_resolution(_output, &width, &height); @@ -580,7 +577,7 @@ static bool wlr_drm_output_move_cursor(struct wlr_output *_output, break; } - return backend->iface->crtc_move_cursor(backend, output->crtc, x, y); + return drm->iface->crtc_move_cursor(drm, output->crtc, x, y); } static void wlr_drm_output_destroy(struct wlr_output *_output) { @@ -632,22 +629,22 @@ static const int32_t subpixel_map[] = { [DRM_MODE_SUBPIXEL_NONE] = WL_OUTPUT_SUBPIXEL_NONE, }; -void wlr_drm_scan_connectors(struct wlr_drm_backend *backend) { +void wlr_drm_scan_connectors(struct wlr_drm_backend *drm) { wlr_log(L_INFO, "Scanning DRM connectors"); - drmModeRes *res = drmModeGetResources(backend->fd); + drmModeRes *res = drmModeGetResources(drm->fd); if (!res) { wlr_log_errno(L_ERROR, "Failed to get DRM resources"); return; } - size_t seen_len = backend->outputs->length; + size_t seen_len = drm->outputs->length; // +1 so it can never be 0 bool seen[seen_len + 1]; memset(seen, 0, sizeof(seen)); for (int i = 0; i < res->count_connectors; ++i) { - drmModeConnector *conn = drmModeGetConnector(backend->fd, + drmModeConnector *conn = drmModeGetConnector(drm->fd, res->connectors[i]); if (!conn) { wlr_log_errno(L_ERROR, "Failed to get DRM connector"); @@ -655,7 +652,7 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *backend) { } struct wlr_drm_output *output; - int index = list_seq_find(backend->outputs, find_id, &conn->connector_id); + int index = list_seq_find(drm->outputs, find_id, &conn->connector_id); if (index == -1) { output = calloc(1, sizeof(*output)); @@ -666,7 +663,7 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *backend) { } wlr_output_init(&output->output, &output_impl); - struct wl_event_loop *ev = wl_display_get_event_loop(backend->display); + struct wl_event_loop *ev = wl_display_get_event_loop(drm->display); output->retry_pageflip = wl_event_loop_add_timer(ev, retry_pageflip, output); @@ -674,10 +671,10 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *backend) { output->state = WLR_DRM_OUTPUT_DISCONNECTED; output->connector = conn->connector_id; - drmModeEncoder *curr_enc = drmModeGetEncoder(backend->fd, + drmModeEncoder *curr_enc = drmModeGetEncoder(drm->fd, conn->encoder_id); if (curr_enc) { - output->old_crtc = drmModeGetCrtc(backend->fd, curr_enc->crtc_id); + output->old_crtc = drmModeGetCrtc(drm->fd, curr_enc->crtc_id); drmModeFreeEncoder(curr_enc); } @@ -688,26 +685,26 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *backend) { conn_get_name(conn->connector_type), conn->connector_type_id); - wlr_drm_get_connector_props(backend->fd, + wlr_drm_get_connector_props(drm->fd, output->connector, &output->props); size_t edid_len = 0; - uint8_t *edid = wlr_drm_get_prop_blob(backend->fd, + uint8_t *edid = wlr_drm_get_prop_blob(drm->fd, output->connector, output->props.edid, &edid_len); parse_edid(&output->output, edid_len, edid); free(edid); - if (list_add(backend->outputs, output) == -1) { + if (list_add(drm->outputs, output) == -1) { wlr_log_errno(L_ERROR, "Allocation failed"); drmModeFreeConnector(conn); wl_event_source_remove(output->retry_pageflip); free(output); continue; } - wlr_output_create_global(&output->output, backend->display); + wlr_output_create_global(&output->output, drm->display); wlr_log(L_INFO, "Found display '%s'", output->output.name); } else { - output = backend->outputs->items[index]; + output = drm->outputs->items[index]; seen[index] = true; } @@ -742,7 +739,7 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *backend) { output->state = WLR_DRM_OUTPUT_NEEDS_MODESET; wlr_log(L_INFO, "Sending modesetting signal for '%s'", output->output.name); - wl_signal_emit(&backend->backend.events.output_add, &output->output); + wl_signal_emit(&drm->backend.events.output_add, &output->output); } else if (output->state == WLR_DRM_OUTPUT_CONNECTED && conn->connection != DRM_MODE_CONNECTED) { @@ -760,7 +757,7 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *backend) { continue; } - struct wlr_drm_output *output = backend->outputs->items[i]; + struct wlr_drm_output *output = drm->outputs->items[i]; wlr_log(L_INFO, "'%s' disappeared", output->output.name); wlr_drm_output_cleanup(output); @@ -769,14 +766,14 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *backend) { wl_event_source_remove(output->retry_pageflip); free(output); - list_del(backend->outputs, i); + list_del(drm->outputs, i); } } static void page_flip_handler(int fd, unsigned seq, unsigned tv_sec, unsigned tv_usec, void *user) { struct wlr_drm_output *output = user; - struct wlr_drm_backend *backend = output->drm; + struct wlr_drm_backend *drm = output->drm; output->pageflip_pending = false; if (output->state != WLR_DRM_OUTPUT_CONNECTED) { @@ -789,7 +786,7 @@ static void page_flip_handler(int fd, unsigned seq, plane->surf.front = NULL; } - if (backend->session->active) { + if (drm->session->active) { wl_signal_emit(&output->output.events.frame, &output->output); } } @@ -848,15 +845,14 @@ void wlr_drm_output_cleanup(struct wlr_drm_output *output) { return; } - struct wlr_drm_backend *backend = output->drm; - struct wlr_drm_renderer *renderer = &backend->renderer; + struct wlr_drm_backend *drm = output->drm; switch (output->state) { case WLR_DRM_OUTPUT_CONNECTED: case WLR_DRM_OUTPUT_CLEANUP:; struct wlr_drm_crtc *crtc = output->crtc; for (int i = 0; i < 3; ++i) { - wlr_drm_surface_finish(renderer, &crtc->planes[i]->surf); + wlr_drm_surface_finish(&drm->renderer, &crtc->planes[i]->surf); if (crtc->planes[i] && crtc->planes[i]->id == 0) { free(crtc->planes[i]); crtc->planes[i] = NULL; @@ -869,7 +865,7 @@ void wlr_drm_output_cleanup(struct wlr_drm_output *output) { case WLR_DRM_OUTPUT_NEEDS_MODESET: wlr_log(L_INFO, "Emmiting destruction signal for '%s'", output->output.name); - wl_signal_emit(&backend->backend.events.output_remove, &output->output); + wl_signal_emit(&drm->backend.events.output_remove, &output->output); break; case WLR_DRM_OUTPUT_DISCONNECTED: break; diff --git a/backend/drm/iface_atomic.c b/backend/drm/iface_atomic.c index ce5de091..7e506fe7 100644 --- a/backend/drm/iface_atomic.c +++ b/backend/drm/iface_atomic.c @@ -96,16 +96,16 @@ static void set_plane_props(struct atomic *atom, struct wlr_drm_plane *plane, } } -static bool atomic_crtc_pageflip(struct wlr_drm_backend *backend, +static bool atomic_crtc_pageflip(struct wlr_drm_backend *drm, struct wlr_drm_output *output, struct wlr_drm_crtc *crtc, uint32_t fb_id, drmModeModeInfo *mode) { if (mode) { if (crtc->mode_id) { - drmModeDestroyPropertyBlob(backend->fd, crtc->mode_id); + drmModeDestroyPropertyBlob(drm->fd, crtc->mode_id); } - if (drmModeCreatePropertyBlob(backend->fd, mode, sizeof(*mode), &crtc->mode_id)) { + if (drmModeCreatePropertyBlob(drm->fd, mode, sizeof(*mode), &crtc->mode_id)) { wlr_log_errno(L_ERROR, "Unable to create property blob"); return false; } @@ -118,25 +118,25 @@ static bool atomic_crtc_pageflip(struct wlr_drm_backend *backend, 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); - return atomic_commit(backend->fd, &atom, output, + return atomic_commit(drm->fd, &atom, output, mode ? DRM_MODE_ATOMIC_ALLOW_MODESET : DRM_MODE_ATOMIC_NONBLOCK, mode); } -static void atomic_conn_enable(struct wlr_drm_backend *backend, +static void atomic_conn_enable(struct wlr_drm_backend *drm, struct wlr_drm_output *output, bool enable) { struct wlr_drm_crtc *crtc = output->crtc; struct atomic atom; atomic_begin(crtc, &atom); atomic_add(&atom, crtc->id, crtc->props.active, enable); - atomic_end(backend->fd, &atom); + atomic_end(drm->fd, &atom); } -bool legacy_crtc_set_cursor(struct wlr_drm_backend *backend, +bool legacy_crtc_set_cursor(struct wlr_drm_backend *drm, struct wlr_drm_crtc *crtc, struct gbm_bo *bo); -static bool atomic_crtc_set_cursor(struct wlr_drm_backend *backend, +static bool atomic_crtc_set_cursor(struct wlr_drm_backend *drm, struct wlr_drm_crtc *crtc, struct gbm_bo *bo) { if (!crtc || !crtc->cursor) { return true; @@ -145,7 +145,7 @@ static bool atomic_crtc_set_cursor(struct wlr_drm_backend *backend, struct wlr_drm_plane *plane = crtc->cursor; // We can't use atomic operations on fake planes if (plane->id == 0) { - return legacy_crtc_set_cursor(backend, crtc, bo); + return legacy_crtc_set_cursor(drm, crtc, bo); } struct atomic atom; @@ -159,18 +159,18 @@ static bool atomic_crtc_set_cursor(struct wlr_drm_backend *backend, atomic_add(&atom, plane->id, plane->props.crtc_id, 0); } - return atomic_end(backend->fd, &atom); + return atomic_end(drm->fd, &atom); } -bool legacy_crtc_move_cursor(struct wlr_drm_backend *backend, +bool legacy_crtc_move_cursor(struct wlr_drm_backend *drm, struct wlr_drm_crtc *crtc, int x, int y); -static bool atomic_crtc_move_cursor(struct wlr_drm_backend *backend, +static bool atomic_crtc_move_cursor(struct wlr_drm_backend *drm, struct wlr_drm_crtc *crtc, int x, int y) { struct wlr_drm_plane *plane = crtc->cursor; // We can't use atomic operations on fake planes if (plane->id == 0) { - return legacy_crtc_move_cursor(backend, crtc, x, y); + return legacy_crtc_move_cursor(drm, crtc, x, y); } struct atomic atom; @@ -178,7 +178,7 @@ static bool atomic_crtc_move_cursor(struct wlr_drm_backend *backend, atomic_begin(crtc, &atom); atomic_add(&atom, plane->id, plane->props.crtc_x, x); atomic_add(&atom, plane->id, plane->props.crtc_y, y); - return atomic_end(backend->fd, &atom); + return atomic_end(drm->fd, &atom); } const struct wlr_drm_interface iface_atomic = { diff --git a/backend/drm/iface_legacy.c b/backend/drm/iface_legacy.c index e320af93..ffa8157b 100644 --- a/backend/drm/iface_legacy.c +++ b/backend/drm/iface_legacy.c @@ -6,18 +6,18 @@ #include "backend/drm/iface.h" #include "backend/drm/util.h" -static bool legacy_crtc_pageflip(struct wlr_drm_backend *backend, +static bool legacy_crtc_pageflip(struct wlr_drm_backend *drm, struct wlr_drm_output *output, struct wlr_drm_crtc *crtc, uint32_t fb_id, drmModeModeInfo *mode) { if (mode) { - if (drmModeSetCrtc(backend->fd, crtc->id, fb_id, 0, 0, + if (drmModeSetCrtc(drm->fd, crtc->id, fb_id, 0, 0, &output->connector, 1, mode)) { wlr_log_errno(L_ERROR, "%s: Failed to set CRTC", output->output.name); return false; } } - if (drmModePageFlip(backend->fd, crtc->id, fb_id, DRM_MODE_PAGE_FLIP_EVENT, output)) { + if (drmModePageFlip(drm->fd, crtc->id, fb_id, DRM_MODE_PAGE_FLIP_EVENT, output)) { wlr_log_errno(L_ERROR, "%s: Failed to page flip", output->output.name); return false; } @@ -25,26 +25,26 @@ static bool legacy_crtc_pageflip(struct wlr_drm_backend *backend, return true; } -static void legacy_conn_enable(struct wlr_drm_backend *backend, +static void legacy_conn_enable(struct wlr_drm_backend *drm, struct wlr_drm_output *output, bool enable) { - drmModeConnectorSetProperty(backend->fd, output->connector, output->props.dpms, + drmModeConnectorSetProperty(drm->fd, output->connector, output->props.dpms, enable ? DRM_MODE_DPMS_ON : DRM_MODE_DPMS_OFF); } -bool legacy_crtc_set_cursor(struct wlr_drm_backend *backend, +bool legacy_crtc_set_cursor(struct wlr_drm_backend *drm, struct wlr_drm_crtc *crtc, struct gbm_bo *bo) { if (!crtc || !crtc->cursor) { return true; } if (!bo) { - drmModeSetCursor(backend->fd, crtc->id, 0, 0, 0); + drmModeSetCursor(drm->fd, crtc->id, 0, 0, 0); return true; } struct wlr_drm_plane *plane = crtc->cursor; - if (drmModeSetCursor(backend->fd, crtc->id, gbm_bo_get_handle(bo).u32, + if (drmModeSetCursor(drm->fd, crtc->id, gbm_bo_get_handle(bo).u32, plane->surf.width, plane->surf.height)) { wlr_log_errno(L_ERROR, "Failed to set hardware cursor"); return false; @@ -53,9 +53,9 @@ bool legacy_crtc_set_cursor(struct wlr_drm_backend *backend, return true; } -bool legacy_crtc_move_cursor(struct wlr_drm_backend *backend, +bool legacy_crtc_move_cursor(struct wlr_drm_backend *drm, struct wlr_drm_crtc *crtc, int x, int y) { - return !drmModeMoveCursor(backend->fd, crtc->id, x, y); + return !drmModeMoveCursor(drm->fd, crtc->id, x, y); } const struct wlr_drm_interface iface_legacy = { diff --git a/include/backend/drm/iface.h b/include/backend/drm/iface.h index cf77f4d4..291b9a30 100644 --- a/include/backend/drm/iface.h +++ b/include/backend/drm/iface.h @@ -15,18 +15,18 @@ struct wlr_drm_crtc; // Used to provide atomic or legacy DRM functions struct wlr_drm_interface { // Enable or disable DPMS for output - void (*conn_enable)(struct wlr_drm_backend *backend, - struct wlr_drm_output *output, bool enable); + void (*conn_enable)(struct wlr_drm_backend *drm, + struct wlr_drm_output *output, bool enable); // Pageflip on crtc. If mode is non-NULL perform a full modeset using it. - bool (*crtc_pageflip)(struct wlr_drm_backend *backend, - struct wlr_drm_output *output, struct wlr_drm_crtc *crtc, - uint32_t fb_id, drmModeModeInfo *mode); + bool (*crtc_pageflip)(struct wlr_drm_backend *drm, + struct wlr_drm_output *output, struct wlr_drm_crtc *crtc, + uint32_t fb_id, drmModeModeInfo *mode); // Enable the cursor buffer on crtc. Set bo to NULL to disable - bool (*crtc_set_cursor)(struct wlr_drm_backend *backend, - struct wlr_drm_crtc *crtc, struct gbm_bo *bo); + bool (*crtc_set_cursor)(struct wlr_drm_backend *drm, + struct wlr_drm_crtc *crtc, struct gbm_bo *bo); // Move the cursor on crtc - bool (*crtc_move_cursor)(struct wlr_drm_backend *backend, - struct wlr_drm_crtc *crtc, int x, int y); + bool (*crtc_move_cursor)(struct wlr_drm_backend *drm, + struct wlr_drm_crtc *crtc, int x, int y); }; extern const struct wlr_drm_interface iface_atomic; -- cgit v1.2.3 From 4101b897000602caf04aba8a10c1b4a4b229f4d6 Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Sat, 30 Sep 2017 23:31:08 +1300 Subject: Rename wlr_drm_output to wlr_drm_connector --- backend/drm/backend.c | 14 +- backend/drm/drm.c | 422 ++++++++++++++++++++++---------------------- backend/drm/iface_atomic.c | 20 +-- backend/drm/iface_legacy.c | 14 +- include/backend/drm/drm.h | 34 ++-- include/backend/drm/iface.h | 8 +- 6 files changed, 252 insertions(+), 260 deletions(-) (limited to 'backend') diff --git a/backend/drm/backend.c b/backend/drm/backend.c index f634eee6..442e5d0e 100644 --- a/backend/drm/backend.c +++ b/backend/drm/backend.c @@ -30,8 +30,8 @@ static void wlr_drm_backend_destroy(struct wlr_backend *backend) { wlr_drm_restore_outputs(drm); for (size_t i = 0; drm->outputs && i < drm->outputs->length; ++i) { - struct wlr_drm_output *output = drm->outputs->items[i]; - wlr_output_destroy(&output->output); + struct wlr_drm_connector *conn = drm->outputs->items[i]; + wlr_output_destroy(&conn->output); } wlr_drm_renderer_finish(&drm->renderer); @@ -65,15 +65,15 @@ static void session_signal(struct wl_listener *listener, void *data) { wlr_log(L_INFO, "DRM fd resumed"); for (size_t i = 0; i < drm->outputs->length; ++i) { - struct wlr_drm_output *output = drm->outputs->items[i]; - wlr_drm_output_start_renderer(output); + struct wlr_drm_connector *conn = drm->outputs->items[i]; + wlr_drm_connector_start_renderer(conn); - if (!output->crtc) { + if (!conn->crtc) { continue; } - struct wlr_drm_plane *plane = output->crtc->cursor; - drm->iface->crtc_set_cursor(drm, output->crtc, + struct wlr_drm_plane *plane = conn->crtc->cursor; + drm->iface->crtc_set_cursor(drm, conn->crtc, plane ? plane->cursor_bo : NULL); } } else { diff --git a/backend/drm/drm.c b/backend/drm/drm.c index a50216cb..676f5f7b 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -173,77 +173,73 @@ void wlr_drm_resources_free(struct wlr_drm_backend *drm) { free(drm->planes); } -static void wlr_drm_output_make_current(struct wlr_output *_output) { - struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - wlr_drm_surface_make_current(&output->drm->renderer, &output->crtc->primary->surf); +static void wlr_drm_connector_make_current(struct wlr_output *output) { + struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output; + wlr_drm_surface_make_current(&conn->drm->renderer, &conn->crtc->primary->surf); } -static void wlr_drm_output_swap_buffers(struct wlr_output *_output) { - struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - struct wlr_drm_backend *drm = output->drm; +static void wlr_drm_connector_swap_buffers(struct wlr_output *output) { + struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output; + struct wlr_drm_backend *drm = conn->drm; - struct wlr_drm_crtc *crtc = output->crtc; + struct wlr_drm_crtc *crtc = conn->crtc; struct wlr_drm_plane *plane = crtc->primary; struct gbm_bo *bo = wlr_drm_surface_swap_buffers(&drm->renderer, &plane->surf); uint32_t fb_id = get_fb_for_bo(bo); - if (drm->iface->crtc_pageflip(drm, output, crtc, fb_id, NULL)) { - output->pageflip_pending = true; + if (drm->iface->crtc_pageflip(drm, conn, crtc, fb_id, NULL)) { + conn->pageflip_pending = true; } else { - wl_event_source_timer_update(output->retry_pageflip, - 1000.0f / output->output.current_mode->refresh); + wl_event_source_timer_update(conn->retry_pageflip, + 1000.0f / conn->output.current_mode->refresh); } } -static void wlr_drm_output_set_gamma(struct wlr_output *_output, +static void wlr_drm_connector_set_gamma(struct wlr_output *output, uint16_t size, uint16_t *r, uint16_t *g, uint16_t *b) { - struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - drmModeCrtcSetGamma(output->drm->fd, output->crtc->id, size, r, g, b); + struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output; + drmModeCrtcSetGamma(conn->drm->fd, conn->crtc->id, size, r, g, b); } -static uint16_t wlr_drm_output_get_gamma_size(struct wlr_output *_output) { - struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - drmModeCrtc *crtc = output->old_crtc; - if (!crtc) { - return 0; - } - return crtc->gamma_size; +static uint16_t wlr_drm_connector_get_gamma_size(struct wlr_output *output) { + struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output; + drmModeCrtc *crtc = conn->old_crtc; + return crtc ? crtc->gamma_size : 0; } -void wlr_drm_output_start_renderer(struct wlr_drm_output *output) { - if (output->state != WLR_DRM_OUTPUT_CONNECTED) { +void wlr_drm_connector_start_renderer(struct wlr_drm_connector *conn) { + if (conn->state != WLR_DRM_CONN_CONNECTED) { return; } - struct wlr_drm_backend *drm = output->drm; - struct wlr_drm_crtc *crtc = output->crtc; + struct wlr_drm_backend *drm = conn->drm; + struct wlr_drm_crtc *crtc = conn->crtc; struct wlr_drm_plane *plane = crtc->primary; struct gbm_bo *bo = wlr_drm_surface_get_front(&drm->renderer, &plane->surf); + uint32_t fb_id = get_fb_for_bo(bo); - struct wlr_drm_output_mode *_mode = - (struct wlr_drm_output_mode *)output->output.current_mode; - drmModeModeInfo *mode = &_mode->mode; - if (drm->iface->crtc_pageflip(drm, output, crtc, get_fb_for_bo(bo), mode)) { - output->pageflip_pending = true; + struct wlr_drm_mode *mode = (struct wlr_drm_mode *)conn->output.current_mode; + if (drm->iface->crtc_pageflip(drm, conn, crtc, fb_id, &mode->drm_mode)) { + conn->pageflip_pending = true; } else { - wl_event_source_timer_update(output->retry_pageflip, - 1000.0f / output->output.current_mode->refresh); + wl_event_source_timer_update(conn->retry_pageflip, + 1000.0f / conn->output.current_mode->refresh); } } -static void wlr_drm_output_enable(struct wlr_output *_output, bool enable) { - struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - if (output->state != WLR_DRM_OUTPUT_CONNECTED) { +static void wlr_drm_connector_enable(struct wlr_output *output, bool enable) { + struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output; + if (conn->state != WLR_DRM_CONN_CONNECTED) { return; } - struct wlr_drm_backend *drm = output->drm; - drm->iface->conn_enable(drm, output, enable); + struct wlr_drm_backend *drm = conn->drm; + drm->iface->conn_enable(drm, conn, enable); if (enable) { - wlr_drm_output_start_renderer(output); + wlr_drm_connector_start_renderer(conn); } } @@ -296,7 +292,7 @@ static void realloc_planes(struct wlr_drm_backend *drm, const uint32_t *crtc_in) } } -static void realloc_crtcs(struct wlr_drm_backend *drm, struct wlr_drm_output *output) { +static void realloc_crtcs(struct wlr_drm_backend *drm, struct wlr_drm_connector *conn) { uint32_t crtc[drm->num_crtcs]; uint32_t crtc_res[drm->num_crtcs]; uint32_t possible_crtc[drm->outputs->length]; @@ -309,23 +305,23 @@ static void realloc_crtcs(struct wlr_drm_backend *drm, struct wlr_drm_output *ou ssize_t index = -1; for (size_t i = 0; i < drm->outputs->length; ++i) { - struct wlr_drm_output *o = drm->outputs->items[i]; - if (o == output) { + struct wlr_drm_connector *c = drm->outputs->items[i]; + if (c == conn) { index = i; } - if (o->state != WLR_DRM_OUTPUT_CONNECTED) { + if (c->state != WLR_DRM_CONN_CONNECTED) { continue; } - possible_crtc[i] = o->possible_crtc; - crtc[o->crtc - drm->crtcs] = i; + possible_crtc[i] = c->possible_crtc; + crtc[c->crtc - drm->crtcs] = i; } assert(index != -1); - possible_crtc[index] = output->possible_crtc; - match_obj(drm->outputs->length, possible_crtc, - drm->num_crtcs, crtc, crtc_res); + possible_crtc[index] = conn->possible_crtc; + match_obj(drm->outputs->length, possible_crtc, drm->num_crtcs, + crtc, crtc_res); bool matched = false; for (size_t i = 0; i < drm->num_crtcs; ++i) { @@ -349,36 +345,29 @@ static void realloc_crtcs(struct wlr_drm_backend *drm, struct wlr_drm_output *ou } if (crtc_res[i] != crtc[i]) { - struct wlr_drm_output *o = drm->outputs->items[crtc_res[i]]; - o->crtc = &drm->crtcs[i]; + struct wlr_drm_connector *c = drm->outputs->items[crtc_res[i]]; + c->crtc = &drm->crtcs[i]; } } realloc_planes(drm, crtc_res); } -static bool wlr_drm_output_set_mode(struct wlr_output *_output, - struct wlr_output_mode *mode) { - struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - struct wlr_drm_backend *drm = output->drm; - - wlr_log(L_INFO, "Modesetting '%s' with '%ux%u@%u mHz'", output->output.name, - mode->width, mode->height, mode->refresh); - - drmModeConnector *conn = drmModeGetConnector(drm->fd, output->connector); +static uint32_t get_possible_crtcs(int fd, uint32_t conn_id) { + drmModeConnector *conn = drmModeGetConnector(fd, conn_id); if (!conn) { wlr_log_errno(L_ERROR, "Failed to get DRM connector"); - goto error_output; + return 0; } if (conn->connection != DRM_MODE_CONNECTED || conn->count_modes == 0) { - wlr_log(L_ERROR, "%s is not connected", output->output.name); - goto error_output; + wlr_log(L_ERROR, "Output is not connected"); + goto error_conn; } drmModeEncoder *enc = NULL; for (int i = 0; !enc && i < conn->count_encoders; ++i) { - enc = drmModeGetEncoder(drm->fd, conn->encoders[i]); + enc = drmModeGetEncoder(fd, conn->encoders[i]); } if (!enc) { @@ -386,35 +375,58 @@ static bool wlr_drm_output_set_mode(struct wlr_output *_output, goto error_conn; } - output->possible_crtc = enc->possible_crtcs; - realloc_crtcs(drm, output); + uint32_t ret = enc->possible_crtcs; + drmModeFreeEncoder(enc); + drmModeFreeConnector(conn); + return ret; - if (!output->crtc) { - wlr_log(L_ERROR, "Unable to match %s with a CRTC", output->output.name); - goto error_enc; +error_conn: + drmModeFreeConnector(conn); + return 0; +} + +static bool wlr_drm_connector_set_mode(struct wlr_output *output, + struct wlr_output_mode *mode) { + struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output; + struct wlr_drm_backend *drm = conn->drm; + + wlr_log(L_INFO, "Modesetting '%s' with '%ux%u@%u mHz'", conn->output.name, + mode->width, mode->height, mode->refresh); + + wlr_log(L_DEBUG, "%p %p", conn, drm); + conn->possible_crtc = get_possible_crtcs(drm->fd, conn->id); + if (conn->possible_crtc == 0) { + goto error_conn; } - struct wlr_drm_crtc *crtc = output->crtc; - wlr_log(L_DEBUG, "%s: crtc=%ju ovr=%jd pri=%jd cur=%jd", output->output.name, + realloc_crtcs(drm, conn); + + if (!conn->crtc) { + wlr_log(L_ERROR, "Unable to match %s with a CRTC", conn->output.name); + goto error_conn; + } + + struct wlr_drm_crtc *crtc = conn->crtc; + wlr_log(L_DEBUG, "%s: crtc=%ju ovr=%jd pri=%jd cur=%jd", conn->output.name, crtc - drm->crtcs, crtc->overlay ? crtc->overlay - drm->overlay_planes : -1, crtc->primary ? crtc->primary - drm->primary_planes : -1, crtc->cursor ? crtc->cursor - drm->cursor_planes : -1); - output->state = WLR_DRM_OUTPUT_CONNECTED; - output->width = output->output.width = mode->width; - output->height = output->output.height = mode->height; - output->output.current_mode = mode; - wl_signal_emit(&output->output.events.resolution, &output->output); + conn->state = WLR_DRM_CONN_CONNECTED; + conn->output.width = mode->width; + conn->output.height = mode->height; + conn->output.current_mode = mode; + wl_signal_emit(&conn->output.events.resolution, &conn->output); // Since realloc_crtcs can deallocate planes on OTHER outputs, // we actually need to reinitalise all of them for (size_t i = 0; i < drm->outputs->length; ++i) { - struct wlr_drm_output *output = drm->outputs->items[i]; - struct wlr_output_mode *mode = output->output.current_mode; - struct wlr_drm_crtc *crtc = output->crtc; + struct wlr_drm_connector *conn = drm->outputs->items[i]; + struct wlr_output_mode *mode = conn->output.current_mode; + struct wlr_drm_crtc *crtc = conn->crtc; - if (output->state != WLR_DRM_OUTPUT_CONNECTED) { + if (conn->state != WLR_DRM_CONN_CONNECTED) { continue; } @@ -422,36 +434,31 @@ static bool wlr_drm_output_set_mode(struct wlr_output *_output, mode->width, mode->height, GBM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT)) { wlr_log(L_ERROR, "Failed to initalise renderer for plane"); - goto error_enc; + goto error_conn; } - wlr_drm_output_start_renderer(output); + wlr_drm_connector_start_renderer(conn); } - drmModeFreeEncoder(enc); - drmModeFreeConnector(conn); return true; -error_enc: - drmModeFreeEncoder(enc); error_conn: - drmModeFreeConnector(conn); -error_output: - wlr_drm_output_cleanup(output); + wlr_drm_connector_cleanup(conn); return false; } -static void wlr_drm_output_transform(struct wlr_output *output, +static void wlr_drm_connector_transform(struct wlr_output *output, enum wl_output_transform transform) { output->transform = transform; } -static bool wlr_drm_output_set_cursor(struct wlr_output *_output, +static bool wlr_drm_connector_set_cursor(struct wlr_output *output, const uint8_t *buf, int32_t stride, uint32_t width, uint32_t height) { - struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - struct wlr_drm_backend *drm = output->drm; + struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output; + struct wlr_drm_backend *drm = conn->drm; struct wlr_drm_renderer *renderer = &drm->renderer; - struct wlr_drm_crtc *crtc = output->crtc; + + struct wlr_drm_crtc *crtc = conn->crtc; struct wlr_drm_plane *plane = crtc->cursor; if (!buf) { @@ -496,7 +503,7 @@ static bool wlr_drm_output_set_cursor(struct wlr_output *_output, // OpenGL will read the pixels out upside down, // so we need to flip the image vertically wlr_matrix_texture(plane->matrix, plane->surf.width, plane->surf.height, - output->output.transform ^ WL_OUTPUT_TRANSFORM_FLIPPED_180); + conn->output.transform ^ WL_OUTPUT_TRANSFORM_FLIPPED_180); // TODO the image needs to be rotated depending on the output rotation @@ -548,15 +555,15 @@ static bool wlr_drm_output_set_cursor(struct wlr_output *_output, return drm->iface->crtc_set_cursor(drm, crtc, bo); } -static bool wlr_drm_output_move_cursor(struct wlr_output *_output, +static bool wlr_drm_connector_move_cursor(struct wlr_output *output, int x, int y) { - struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - struct wlr_drm_backend *drm = output->drm; + struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output; + struct wlr_drm_backend *drm = conn->drm; int width, height, tmp; - wlr_output_effective_resolution(_output, &width, &height); + wlr_output_effective_resolution(output, &width, &height); - switch (_output->transform) { + switch (output->transform) { case WL_OUTPUT_TRANSFORM_NORMAL: // nothing to do break; @@ -573,51 +580,45 @@ static bool wlr_drm_output_move_cursor(struct wlr_output *_output, default: // TODO other transformations wlr_log(L_ERROR, "TODO: handle surface to crtc for transformation = %d", - _output->transform); + output->transform); break; } - return drm->iface->crtc_move_cursor(drm, output->crtc, x, y); + return drm->iface->crtc_move_cursor(drm, conn->crtc, x, y); } -static void wlr_drm_output_destroy(struct wlr_output *_output) { - struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - wlr_drm_output_cleanup(output); - wl_event_source_remove(output->retry_pageflip); - free(output); +static void wlr_drm_connector_destroy(struct wlr_output *output) { + struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output; + wlr_drm_connector_cleanup(conn); + wl_event_source_remove(conn->retry_pageflip); + free(conn); } static struct wlr_output_impl output_impl = { - .enable = wlr_drm_output_enable, - .set_mode = wlr_drm_output_set_mode, - .transform = wlr_drm_output_transform, - .set_cursor = wlr_drm_output_set_cursor, - .move_cursor = wlr_drm_output_move_cursor, - .destroy = wlr_drm_output_destroy, - .make_current = wlr_drm_output_make_current, - .swap_buffers = wlr_drm_output_swap_buffers, - .set_gamma = wlr_drm_output_set_gamma, - .get_gamma_size = wlr_drm_output_get_gamma_size, + .enable = wlr_drm_connector_enable, + .set_mode = wlr_drm_connector_set_mode, + .transform = wlr_drm_connector_transform, + .set_cursor = wlr_drm_connector_set_cursor, + .move_cursor = wlr_drm_connector_move_cursor, + .destroy = wlr_drm_connector_destroy, + .make_current = wlr_drm_connector_make_current, + .swap_buffers = wlr_drm_connector_swap_buffers, + .set_gamma = wlr_drm_connector_set_gamma, + .get_gamma_size = wlr_drm_connector_get_gamma_size, }; static int retry_pageflip(void *data) { - struct wlr_drm_output *output = data; - wlr_log(L_INFO, "%s: Retrying pageflip", output->output.name); - wlr_drm_output_start_renderer(output); + struct wlr_drm_connector *conn = data; + wlr_log(L_INFO, "%s: Retrying pageflip", conn->output.name); + wlr_drm_connector_start_renderer(conn); return 0; } static int find_id(const void *item, const void *cmp_to) { - const struct wlr_drm_output *output = item; + const struct wlr_drm_connector *conn = item; const uint32_t *id = cmp_to; - if (output->connector < *id) { - return -1; - } else if (output->connector > *id) { - return 1; - } else { - return 0; - } + return (int)conn->id - (int)*id; } static const int32_t subpixel_map[] = { @@ -644,110 +645,111 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *drm) { memset(seen, 0, sizeof(seen)); for (int i = 0; i < res->count_connectors; ++i) { - drmModeConnector *conn = drmModeGetConnector(drm->fd, + drmModeConnector *drm_conn = drmModeGetConnector(drm->fd, res->connectors[i]); - if (!conn) { + if (!drm_conn) { wlr_log_errno(L_ERROR, "Failed to get DRM connector"); continue; } - struct wlr_drm_output *output; - int index = list_seq_find(drm->outputs, find_id, &conn->connector_id); + struct wlr_drm_connector *wlr_conn; + int index = list_seq_find(drm->outputs, find_id, &drm_conn->connector_id); if (index == -1) { - output = calloc(1, sizeof(*output)); - if (!output) { + wlr_conn = calloc(1, sizeof(*wlr_conn)); + if (!wlr_conn) { wlr_log_errno(L_ERROR, "Allocation failed"); - drmModeFreeConnector(conn); + drmModeFreeConnector(drm_conn); continue; } - wlr_output_init(&output->output, &output_impl); + wlr_output_init(&wlr_conn->output, &output_impl); struct wl_event_loop *ev = wl_display_get_event_loop(drm->display); - output->retry_pageflip = wl_event_loop_add_timer(ev, retry_pageflip, - output); + wlr_conn->retry_pageflip = wl_event_loop_add_timer(ev, retry_pageflip, + wlr_conn); - output->state = WLR_DRM_OUTPUT_DISCONNECTED; - output->connector = conn->connector_id; + wlr_conn->drm = drm; + wlr_conn->state = WLR_DRM_CONN_DISCONNECTED; + wlr_conn->id = drm_conn->connector_id; drmModeEncoder *curr_enc = drmModeGetEncoder(drm->fd, - conn->encoder_id); + drm_conn->encoder_id); if (curr_enc) { - output->old_crtc = drmModeGetCrtc(drm->fd, curr_enc->crtc_id); + wlr_conn->old_crtc = drmModeGetCrtc(drm->fd, curr_enc->crtc_id); drmModeFreeEncoder(curr_enc); } - output->output.phys_width = conn->mmWidth; - output->output.phys_height = conn->mmHeight; - output->output.subpixel = subpixel_map[conn->subpixel]; - snprintf(output->output.name, sizeof(output->output.name), "%s-%"PRIu32, - conn_get_name(conn->connector_type), - conn->connector_type_id); + wlr_conn->output.phys_width = drm_conn->mmWidth; + wlr_conn->output.phys_height = drm_conn->mmHeight; + wlr_conn->output.subpixel = subpixel_map[drm_conn->subpixel]; + snprintf(wlr_conn->output.name, sizeof(wlr_conn->output.name), + "%s-%"PRIu32, + conn_get_name(drm_conn->connector_type), + drm_conn->connector_type_id); - wlr_drm_get_connector_props(drm->fd, - output->connector, &output->props); + wlr_drm_get_connector_props(drm->fd, wlr_conn->id, &wlr_conn->props); size_t edid_len = 0; uint8_t *edid = wlr_drm_get_prop_blob(drm->fd, - output->connector, output->props.edid, &edid_len); - parse_edid(&output->output, edid_len, edid); + wlr_conn->id, wlr_conn->props.edid, &edid_len); + parse_edid(&wlr_conn->output, edid_len, edid); free(edid); - if (list_add(drm->outputs, output) == -1) { + if (list_add(drm->outputs, wlr_conn) == -1) { wlr_log_errno(L_ERROR, "Allocation failed"); - drmModeFreeConnector(conn); - wl_event_source_remove(output->retry_pageflip); - free(output); + drmModeFreeConnector(drm_conn); + wl_event_source_remove(wlr_conn->retry_pageflip); + free(wlr_conn); continue; } - wlr_output_create_global(&output->output, drm->display); - wlr_log(L_INFO, "Found display '%s'", output->output.name); + wlr_output_create_global(&wlr_conn->output, drm->display); + wlr_log(L_INFO, "Found display '%s'", wlr_conn->output.name); } else { - output = drm->outputs->items[index]; + wlr_conn = drm->outputs->items[index]; seen[index] = true; } - if (output->state == WLR_DRM_OUTPUT_DISCONNECTED && - conn->connection == DRM_MODE_CONNECTED) { + if (wlr_conn->state == WLR_DRM_CONN_DISCONNECTED && + drm_conn->connection == DRM_MODE_CONNECTED) { - wlr_log(L_INFO, "'%s' connected", output->output.name); + wlr_log(L_INFO, "'%s' connected", wlr_conn->output.name); wlr_log(L_INFO, "Detected modes:"); - for (int i = 0; i < conn->count_modes; ++i) { - struct wlr_drm_output_mode *mode = calloc(1, - sizeof(struct wlr_drm_output_mode)); + for (int i = 0; i < drm_conn->count_modes; ++i) { + struct wlr_drm_mode *mode = calloc(1, sizeof(*mode)); if (!mode) { wlr_log_errno(L_ERROR, "Allocation failed"); continue; } - mode->mode = conn->modes[i]; - mode->wlr_mode.width = mode->mode.hdisplay; - mode->wlr_mode.height = mode->mode.vdisplay; - mode->wlr_mode.refresh = calculate_refresh_rate(&mode->mode); + mode->drm_mode = drm_conn->modes[i]; + mode->wlr_mode.width = mode->drm_mode.hdisplay; + mode->wlr_mode.height = mode->drm_mode.vdisplay; + mode->wlr_mode.refresh = calculate_refresh_rate(&mode->drm_mode); wlr_log(L_INFO, " %"PRId32"@%"PRId32"@%"PRId32, mode->wlr_mode.width, mode->wlr_mode.height, mode->wlr_mode.refresh); - if (list_add(output->output.modes, mode) == -1) { + if (list_add(wlr_conn->output.modes, mode) == -1) { wlr_log_errno(L_ERROR, "Allocation failed"); free(mode); continue; } } - output->state = WLR_DRM_OUTPUT_NEEDS_MODESET; - wlr_log(L_INFO, "Sending modesetting signal for '%s'", output->output.name); - wl_signal_emit(&drm->backend.events.output_add, &output->output); - } else if (output->state == WLR_DRM_OUTPUT_CONNECTED && - conn->connection != DRM_MODE_CONNECTED) { + wlr_conn->state = WLR_DRM_CONN_NEEDS_MODESET; + wlr_log(L_INFO, "Sending modesetting signal for '%s'", + wlr_conn->output.name); + wl_signal_emit(&drm->backend.events.output_add, &wlr_conn->output); + } else if (wlr_conn->state == WLR_DRM_CONN_CONNECTED && + drm_conn->connection != DRM_MODE_CONNECTED) { - wlr_log(L_INFO, "'%s' disconnected", output->output.name); - wlr_drm_output_cleanup(output); + wlr_log(L_INFO, "'%s' disconnected", wlr_conn->output.name); + wlr_drm_connector_cleanup(wlr_conn); } - drmModeFreeConnector(conn); + drmModeFreeConnector(drm_conn); } drmModeFreeResources(res); @@ -757,14 +759,14 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *drm) { continue; } - struct wlr_drm_output *output = drm->outputs->items[i]; + struct wlr_drm_connector *conn = drm->outputs->items[i]; - wlr_log(L_INFO, "'%s' disappeared", output->output.name); - wlr_drm_output_cleanup(output); + wlr_log(L_INFO, "'%s' disappeared", conn->output.name); + wlr_drm_connector_cleanup(conn); - drmModeFreeCrtc(output->old_crtc); - wl_event_source_remove(output->retry_pageflip); - free(output); + drmModeFreeCrtc(conn->old_crtc); + wl_event_source_remove(conn->retry_pageflip); + free(conn); list_del(drm->outputs, i); } @@ -772,22 +774,22 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *drm) { static void page_flip_handler(int fd, unsigned seq, unsigned tv_sec, unsigned tv_usec, void *user) { - struct wlr_drm_output *output = user; - struct wlr_drm_backend *drm = output->drm; + struct wlr_drm_connector *conn = user; + struct wlr_drm_backend *drm = conn->drm; - output->pageflip_pending = false; - if (output->state != WLR_DRM_OUTPUT_CONNECTED) { + conn->pageflip_pending = false; + if (conn->state != WLR_DRM_CONN_CONNECTED) { return; } - struct wlr_drm_plane *plane = output->crtc->primary; + struct wlr_drm_plane *plane = conn->crtc->primary; if (plane->surf.front) { gbm_surface_release_buffer(plane->surf.gbm, plane->surf.front); plane->surf.front = NULL; } if (drm->session->active) { - wl_signal_emit(&output->output.events.frame, &output->output); + wl_signal_emit(&conn->output.events.frame, &conn->output); } } @@ -805,9 +807,9 @@ void wlr_drm_restore_outputs(struct wlr_drm_backend *drm) { uint64_t to_close = (1 << drm->outputs->length) - 1; for (size_t i = 0; i < drm->outputs->length; ++i) { - struct wlr_drm_output *output = drm->outputs->items[i]; - if (output->state == WLR_DRM_OUTPUT_CONNECTED) { - output->state = WLR_DRM_OUTPUT_CLEANUP; + struct wlr_drm_connector *conn = drm->outputs->items[i]; + if (conn->state == WLR_DRM_CONN_CONNECTED) { + conn->state = WLR_DRM_CONN_CLEANUP; } } @@ -816,8 +818,8 @@ void wlr_drm_restore_outputs(struct wlr_drm_backend *drm) { while (to_close && time(NULL) < timeout) { wlr_drm_event(drm->fd, 0, NULL); for (size_t i = 0; i < drm->outputs->length; ++i) { - struct wlr_drm_output *output = drm->outputs->items[i]; - if (output->state != WLR_DRM_OUTPUT_CLEANUP || !output->pageflip_pending) { + struct wlr_drm_connector *conn = drm->outputs->items[i]; + if (conn->state != WLR_DRM_CONN_CLEANUP || !conn->pageflip_pending) { to_close &= ~(1 << i); } } @@ -828,29 +830,29 @@ void wlr_drm_restore_outputs(struct wlr_drm_backend *drm) { } for (size_t i = 0; i < drm->outputs->length; ++i) { - struct wlr_drm_output *output = drm->outputs->items[i]; - drmModeCrtc *crtc = output->old_crtc; + struct wlr_drm_connector *conn = drm->outputs->items[i]; + drmModeCrtc *crtc = conn->old_crtc; if (!crtc) { continue; } drmModeSetCrtc(drm->fd, crtc->crtc_id, crtc->buffer_id, crtc->x, crtc->y, - &output->connector, 1, &crtc->mode); + &conn->id, 1, &crtc->mode); drmModeFreeCrtc(crtc); } } -void wlr_drm_output_cleanup(struct wlr_drm_output *output) { - if (!output) { +void wlr_drm_connector_cleanup(struct wlr_drm_connector *conn) { + if (!conn) { return; } - struct wlr_drm_backend *drm = output->drm; + struct wlr_drm_backend *drm = conn->drm; - switch (output->state) { - case WLR_DRM_OUTPUT_CONNECTED: - case WLR_DRM_OUTPUT_CLEANUP:; - struct wlr_drm_crtc *crtc = output->crtc; + switch (conn->state) { + case WLR_DRM_CONN_CONNECTED: + case WLR_DRM_CONN_CLEANUP:; + struct wlr_drm_crtc *crtc = conn->crtc; for (int i = 0; i < 3; ++i) { wlr_drm_surface_finish(&drm->renderer, &crtc->planes[i]->surf); if (crtc->planes[i] && crtc->planes[i]->id == 0) { @@ -859,17 +861,17 @@ void wlr_drm_output_cleanup(struct wlr_drm_output *output) { } } - output->crtc = NULL; - output->possible_crtc = 0; + conn->crtc = NULL; + conn->possible_crtc = 0; /* Fallthrough */ - case WLR_DRM_OUTPUT_NEEDS_MODESET: + case WLR_DRM_CONN_NEEDS_MODESET: wlr_log(L_INFO, "Emmiting destruction signal for '%s'", - output->output.name); - wl_signal_emit(&drm->backend.events.output_remove, &output->output); + conn->output.name); + wl_signal_emit(&drm->backend.events.output_remove, &conn->output); break; - case WLR_DRM_OUTPUT_DISCONNECTED: + case WLR_DRM_CONN_DISCONNECTED: break; } - output->state = WLR_DRM_OUTPUT_DISCONNECTED; + conn->state = WLR_DRM_CONN_DISCONNECTED; } diff --git a/backend/drm/iface_atomic.c b/backend/drm/iface_atomic.c index 7e506fe7..1aef05d1 100644 --- a/backend/drm/iface_atomic.c +++ b/backend/drm/iface_atomic.c @@ -44,23 +44,23 @@ static bool atomic_end(int drm_fd, struct atomic *atom) { } static bool atomic_commit(int drm_fd, struct atomic *atom, - struct wlr_drm_output *output, uint32_t flag, bool modeset) { + struct wlr_drm_connector *conn, uint32_t flag, bool modeset) { if (atom->failed) { return false; } uint32_t flags = DRM_MODE_PAGE_FLIP_EVENT | flag; - int ret = drmModeAtomicCommit(drm_fd, atom->req, flags, output); + int ret = drmModeAtomicCommit(drm_fd, atom->req, flags, conn); if (ret) { wlr_log_errno(L_ERROR, "%s: Atomic commit failed (%s)", - output->output.name, modeset ? "modeset" : "pageflip"); + conn->output.name, modeset ? "modeset" : "pageflip"); // Try to commit without new changes drmModeAtomicSetCursor(atom->req, atom->cursor); - if (drmModeAtomicCommit(drm_fd, atom->req, flags, output)) { + if (drmModeAtomicCommit(drm_fd, atom->req, flags, conn)) { wlr_log_errno(L_ERROR, "%s: Atomic commit failed (%s)", - output->output.name, modeset ? "modeset" : "pageflip"); + conn->output.name, modeset ? "modeset" : "pageflip"); } } @@ -97,7 +97,7 @@ static void set_plane_props(struct atomic *atom, struct wlr_drm_plane *plane, } static bool atomic_crtc_pageflip(struct wlr_drm_backend *drm, - struct wlr_drm_output *output, + struct wlr_drm_connector *conn, struct wlr_drm_crtc *crtc, uint32_t fb_id, drmModeModeInfo *mode) { if (mode) { @@ -114,18 +114,18 @@ static bool atomic_crtc_pageflip(struct wlr_drm_backend *drm, struct atomic atom; atomic_begin(crtc, &atom); - atomic_add(&atom, output->connector, output->props.crtc_id, crtc->id); + atomic_add(&atom, conn->id, conn->props.crtc_id, crtc->id); 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); - return atomic_commit(drm->fd, &atom, output, + return atomic_commit(drm->fd, &atom, conn, mode ? DRM_MODE_ATOMIC_ALLOW_MODESET : DRM_MODE_ATOMIC_NONBLOCK, mode); } static void atomic_conn_enable(struct wlr_drm_backend *drm, - struct wlr_drm_output *output, bool enable) { - struct wlr_drm_crtc *crtc = output->crtc; + struct wlr_drm_connector *conn, bool enable) { + struct wlr_drm_crtc *crtc = conn->crtc; struct atomic atom; atomic_begin(crtc, &atom); diff --git a/backend/drm/iface_legacy.c b/backend/drm/iface_legacy.c index ffa8157b..cf73bb87 100644 --- a/backend/drm/iface_legacy.c +++ b/backend/drm/iface_legacy.c @@ -7,18 +7,18 @@ #include "backend/drm/util.h" static bool legacy_crtc_pageflip(struct wlr_drm_backend *drm, - struct wlr_drm_output *output, struct wlr_drm_crtc *crtc, + struct wlr_drm_connector *conn, struct wlr_drm_crtc *crtc, uint32_t fb_id, drmModeModeInfo *mode) { if (mode) { if (drmModeSetCrtc(drm->fd, crtc->id, fb_id, 0, 0, - &output->connector, 1, mode)) { - wlr_log_errno(L_ERROR, "%s: Failed to set CRTC", output->output.name); + &conn->id, 1, mode)) { + wlr_log_errno(L_ERROR, "%s: Failed to set CRTC", conn->output.name); return false; } } - if (drmModePageFlip(drm->fd, crtc->id, fb_id, DRM_MODE_PAGE_FLIP_EVENT, output)) { - wlr_log_errno(L_ERROR, "%s: Failed to page flip", output->output.name); + if (drmModePageFlip(drm->fd, crtc->id, fb_id, DRM_MODE_PAGE_FLIP_EVENT, conn)) { + wlr_log_errno(L_ERROR, "%s: Failed to page flip", conn->output.name); return false; } @@ -26,8 +26,8 @@ static bool legacy_crtc_pageflip(struct wlr_drm_backend *drm, } static void legacy_conn_enable(struct wlr_drm_backend *drm, - struct wlr_drm_output *output, bool enable) { - drmModeConnectorSetProperty(drm->fd, output->connector, output->props.dpms, + struct wlr_drm_connector *conn, bool enable) { + drmModeConnectorSetProperty(drm->fd, conn->id, conn->props.dpms, enable ? DRM_MODE_DPMS_ON : DRM_MODE_DPMS_OFF); } diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h index 6f1abc00..a3a724bc 100644 --- a/include/backend/drm/drm.h +++ b/include/backend/drm/drm.h @@ -55,16 +55,6 @@ struct wlr_drm_crtc { struct wl_list connectors; }; -struct wlr_drm_connector { - struct wlr_output *base; - uint32_t id; - struct wlr_drm_crtc *crtc; - - union wlr_drm_connector_props props; - - struct wl_list link; -}; - struct wlr_drm_backend { struct wlr_backend backend; @@ -107,24 +97,24 @@ struct wlr_drm_backend { struct wlr_session *session; }; -enum wlr_drm_output_state { - WLR_DRM_OUTPUT_DISCONNECTED, - WLR_DRM_OUTPUT_NEEDS_MODESET, - WLR_DRM_OUTPUT_CLEANUP, - WLR_DRM_OUTPUT_CONNECTED, +enum wlr_drm_connector_state { + WLR_DRM_CONN_DISCONNECTED, + WLR_DRM_CONN_NEEDS_MODESET, + WLR_DRM_CONN_CLEANUP, + WLR_DRM_CONN_CONNECTED, }; -struct wlr_drm_output_mode { +struct wlr_drm_mode { struct wlr_output_mode wlr_mode; - drmModeModeInfo mode; + drmModeModeInfo drm_mode; }; -struct wlr_drm_output { +struct wlr_drm_connector { struct wlr_output output; struct wlr_drm_backend *drm; - enum wlr_drm_output_state state; - uint32_t connector; + enum wlr_drm_connector_state state; + uint32_t id; struct wlr_drm_crtc *crtc; uint32_t possible_crtc; @@ -144,10 +134,10 @@ bool wlr_drm_check_features(struct wlr_drm_backend *drm); bool wlr_drm_resources_init(struct wlr_drm_backend *drm); void wlr_drm_resources_free(struct wlr_drm_backend *drm); void wlr_drm_restore_outputs(struct wlr_drm_backend *drm); -void wlr_drm_output_cleanup(struct wlr_drm_output *output); +void wlr_drm_connector_cleanup(struct wlr_drm_connector *conn); void wlr_drm_scan_connectors(struct wlr_drm_backend *state); int wlr_drm_event(int fd, uint32_t mask, void *data); -void wlr_drm_output_start_renderer(struct wlr_drm_output *output); +void wlr_drm_connector_start_renderer(struct wlr_drm_connector *conn); #endif diff --git a/include/backend/drm/iface.h b/include/backend/drm/iface.h index 291b9a30..db1d7ee1 100644 --- a/include/backend/drm/iface.h +++ b/include/backend/drm/iface.h @@ -9,17 +9,17 @@ #include struct wlr_drm_backend; -struct wlr_drm_output; +struct wlr_drm_connector; struct wlr_drm_crtc; // Used to provide atomic or legacy DRM functions struct wlr_drm_interface { - // Enable or disable DPMS for output + // Enable or disable DPMS for connector void (*conn_enable)(struct wlr_drm_backend *drm, - struct wlr_drm_output *output, bool enable); + struct wlr_drm_connector *conn, bool enable); // Pageflip on crtc. If mode is non-NULL perform a full modeset using it. bool (*crtc_pageflip)(struct wlr_drm_backend *drm, - struct wlr_drm_output *output, struct wlr_drm_crtc *crtc, + struct wlr_drm_connector *conn, struct wlr_drm_crtc *crtc, uint32_t fb_id, drmModeModeInfo *mode); // Enable the cursor buffer on crtc. Set bo to NULL to disable bool (*crtc_set_cursor)(struct wlr_drm_backend *drm, -- cgit v1.2.3 From eaef028976d32e382c4ebcfbb8605a6f40cd22b8 Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Sun, 1 Oct 2017 15:55:25 +1300 Subject: Add renderer pointer inside drm_surface --- backend/drm/drm.c | 20 ++++++++++---------- backend/drm/renderer.c | 33 +++++++++++++++------------------ include/backend/drm/renderer.h | 22 ++++++++-------------- 3 files changed, 33 insertions(+), 42 deletions(-) (limited to 'backend') diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 676f5f7b..5c5ac8cd 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -175,7 +175,7 @@ void wlr_drm_resources_free(struct wlr_drm_backend *drm) { static void wlr_drm_connector_make_current(struct wlr_output *output) { struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output; - wlr_drm_surface_make_current(&conn->drm->renderer, &conn->crtc->primary->surf); + wlr_drm_surface_make_current(&conn->crtc->primary->surf); } static void wlr_drm_connector_swap_buffers(struct wlr_output *output) { @@ -185,7 +185,7 @@ static void wlr_drm_connector_swap_buffers(struct wlr_output *output) { struct wlr_drm_crtc *crtc = conn->crtc; struct wlr_drm_plane *plane = crtc->primary; - struct gbm_bo *bo = wlr_drm_surface_swap_buffers(&drm->renderer, &plane->surf); + struct gbm_bo *bo = wlr_drm_surface_swap_buffers(&plane->surf); uint32_t fb_id = get_fb_for_bo(bo); if (drm->iface->crtc_pageflip(drm, conn, crtc, fb_id, NULL)) { @@ -217,7 +217,7 @@ void wlr_drm_connector_start_renderer(struct wlr_drm_connector *conn) { struct wlr_drm_crtc *crtc = conn->crtc; struct wlr_drm_plane *plane = crtc->primary; - struct gbm_bo *bo = wlr_drm_surface_get_front(&drm->renderer, &plane->surf); + struct gbm_bo *bo = wlr_drm_surface_get_front(&plane->surf); uint32_t fb_id = get_fb_for_bo(bo); struct wlr_drm_mode *mode = (struct wlr_drm_mode *)conn->output.current_mode; @@ -283,9 +283,9 @@ static void realloc_planes(struct wlr_drm_backend *drm, const uint32_t *crtc_in) if (*old != new) { if (*old) { - wlr_drm_surface_finish(&drm->renderer, &(*old)->surf); + wlr_drm_surface_finish(&(*old)->surf); } - wlr_drm_surface_finish(&drm->renderer, &new->surf); + wlr_drm_surface_finish(&new->surf); *old = new; } } @@ -430,7 +430,7 @@ static bool wlr_drm_connector_set_mode(struct wlr_output *output, continue; } - if (!wlr_drm_surface_init(&drm->renderer, &crtc->primary->surf, + if (!wlr_drm_surface_init(&crtc->primary->surf, &drm->renderer, mode->width, mode->height, GBM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT)) { wlr_log(L_ERROR, "Failed to initalise renderer for plane"); @@ -488,7 +488,7 @@ static bool wlr_drm_connector_set_cursor(struct wlr_output *output, return false; } - if (!wlr_drm_surface_init(renderer, &plane->surf, w, h, GBM_FORMAT_ARGB8888, 0)) { + if (!wlr_drm_surface_init(&plane->surf, renderer, w, h, GBM_FORMAT_ARGB8888, 0)) { wlr_log(L_ERROR, "Cannot allocate cursor resources"); return false; } @@ -530,7 +530,7 @@ static bool wlr_drm_connector_set_cursor(struct wlr_output *output, return false; } - wlr_drm_surface_make_current(renderer, &plane->surf); + wlr_drm_surface_make_current(&plane->surf); wlr_texture_upload_pixels(plane->wlr_tex, WL_SHM_FORMAT_ARGB8888, stride, width, height, buf); @@ -548,7 +548,7 @@ static bool wlr_drm_connector_set_cursor(struct wlr_output *output, glReadPixels(0, 0, plane->surf.width, plane->surf.height, GL_BGRA_EXT, GL_UNSIGNED_BYTE, bo_data); glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0); - wlr_drm_surface_swap_buffers(renderer, &plane->surf); + wlr_drm_surface_swap_buffers(&plane->surf); gbm_bo_unmap(bo, bo_data); @@ -854,7 +854,7 @@ void wlr_drm_connector_cleanup(struct wlr_drm_connector *conn) { case WLR_DRM_CONN_CLEANUP:; struct wlr_drm_crtc *crtc = conn->crtc; for (int i = 0; i < 3; ++i) { - wlr_drm_surface_finish(&drm->renderer, &crtc->planes[i]->surf); + wlr_drm_surface_finish(&crtc->planes[i]->surf); if (crtc->planes[i] && crtc->planes[i]->id == 0) { free(crtc->planes[i]); crtc->planes[i] = NULL; diff --git a/backend/drm/renderer.c b/backend/drm/renderer.c index 8afc6dca..e1c6a4bc 100644 --- a/backend/drm/renderer.c +++ b/backend/drm/renderer.c @@ -35,13 +35,14 @@ void wlr_drm_renderer_finish(struct wlr_drm_renderer *renderer) { gbm_device_destroy(renderer->gbm); } -bool wlr_drm_surface_init(struct wlr_drm_renderer *renderer, - struct wlr_drm_surface *surf, uint32_t width, uint32_t height, +bool wlr_drm_surface_init(struct wlr_drm_surface *surf, + struct wlr_drm_renderer *renderer, uint32_t width, uint32_t height, uint32_t format, uint32_t flags) { if (surf->width == width && surf->height == height) { return true; } + surf->renderer = renderer; surf->width = width; surf->height = height; @@ -67,13 +68,12 @@ error_zero: return false; } -void wlr_drm_surface_finish(struct wlr_drm_renderer *renderer, - struct wlr_drm_surface *surf) { - if (!renderer || !surf || !surf->gbm) { +void wlr_drm_surface_finish(struct wlr_drm_surface *surf) { + if (!surf || !surf->renderer) { return; } - eglMakeCurrent(renderer->egl.display, EGL_NO_SURFACE, EGL_NO_SURFACE, + eglMakeCurrent(surf->renderer->egl.display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); if (surf->front) { @@ -84,7 +84,7 @@ void wlr_drm_surface_finish(struct wlr_drm_renderer *renderer, } if (surf->egl) { - eglDestroySurface(renderer->egl.display, surf->egl); + eglDestroySurface(surf->renderer->egl.display, surf->egl); } if (surf->gbm) { gbm_surface_destroy(surf->gbm); @@ -93,34 +93,31 @@ void wlr_drm_surface_finish(struct wlr_drm_renderer *renderer, memset(surf, 0, sizeof(*surf)); } -void wlr_drm_surface_make_current(struct wlr_drm_renderer *renderer, - struct wlr_drm_surface *surf) { - eglMakeCurrent(renderer->egl.display, surf->egl, surf->egl, - renderer->egl.context); +void wlr_drm_surface_make_current(struct wlr_drm_surface *surf) { + eglMakeCurrent(surf->renderer->egl.display, surf->egl, surf->egl, + surf->renderer->egl.context); } -struct gbm_bo *wlr_drm_surface_swap_buffers(struct wlr_drm_renderer *renderer, - struct wlr_drm_surface *surf) { +struct gbm_bo *wlr_drm_surface_swap_buffers(struct wlr_drm_surface *surf) { if (surf->front) { gbm_surface_release_buffer(surf->gbm, surf->front); } - eglSwapBuffers(renderer->egl.display, surf->egl); + eglSwapBuffers(surf->renderer->egl.display, surf->egl); surf->front = surf->back; surf->back = gbm_surface_lock_front_buffer(surf->gbm); return surf->back; } -struct gbm_bo *wlr_drm_surface_get_front(struct wlr_drm_renderer *renderer, - struct wlr_drm_surface *surf) { +struct gbm_bo *wlr_drm_surface_get_front(struct wlr_drm_surface *surf) { if (surf->front) { return surf->front; } - wlr_drm_surface_make_current(renderer, surf); + wlr_drm_surface_make_current(surf); glViewport(0, 0, surf->width, surf->height); glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); - return wlr_drm_surface_swap_buffers(renderer, surf); + return wlr_drm_surface_swap_buffers(surf); } diff --git a/include/backend/drm/renderer.h b/include/backend/drm/renderer.h index bbcf4f0c..9982c25f 100644 --- a/include/backend/drm/renderer.h +++ b/include/backend/drm/renderer.h @@ -14,6 +14,8 @@ struct wlr_drm_renderer { }; struct wlr_drm_surface { + struct wlr_drm_renderer *renderer; + uint32_t width; uint32_t height; @@ -25,23 +27,15 @@ struct wlr_drm_surface { }; bool wlr_drm_renderer_init(struct wlr_drm_renderer *renderer, int fd); - void wlr_drm_renderer_finish(struct wlr_drm_renderer *renderer); -bool wlr_drm_surface_init(struct wlr_drm_renderer *renderer, - struct wlr_drm_surface *surf, uint32_t width, uint32_t height, +bool wlr_drm_surface_init(struct wlr_drm_surface *surf, + struct wlr_drm_renderer *renderer, uint32_t width, uint32_t height, uint32_t format, uint32_t flags); -void wlr_drm_surface_finish(struct wlr_drm_renderer *renderer, - struct wlr_drm_surface *surf); - -void wlr_drm_surface_make_current(struct wlr_drm_renderer *renderer, - struct wlr_drm_surface *surf); - -struct gbm_bo *wlr_drm_surface_swap_buffers(struct wlr_drm_renderer *renderer, - struct wlr_drm_surface *surf); - -struct gbm_bo *wlr_drm_surface_get_front(struct wlr_drm_renderer *renderer, - struct wlr_drm_surface *surf); +void wlr_drm_surface_finish(struct wlr_drm_surface *surf); +void wlr_drm_surface_make_current(struct wlr_drm_surface *surf); +struct gbm_bo *wlr_drm_surface_swap_buffers(struct wlr_drm_surface *surf); +struct gbm_bo *wlr_drm_surface_get_front(struct wlr_drm_surface *surf); #endif -- cgit v1.2.3 From fa3d0ed9295d18405ab65f63f329d3def19509a3 Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Sun, 1 Oct 2017 16:47:05 +1300 Subject: Change wlr_session to open every GPU --- backend/backend.c | 41 ++++++++++++++++++++-------------- backend/drm/backend.c | 4 ++-- backend/session/session.c | 51 +++++++++++++++++++------------------------ include/wlr/backend/session.h | 5 +++-- 4 files changed, 52 insertions(+), 49 deletions(-) (limited to 'backend') diff --git a/backend/backend.c b/backend/backend.c index ec309da4..359df3d1 100644 --- a/backend/backend.c +++ b/backend/backend.c @@ -91,15 +91,9 @@ struct wlr_backend *wlr_backend_autocreate(struct wl_display *display) { return NULL; } - int gpu = wlr_session_find_gpu(session); - if (gpu == -1) { - wlr_log(L_ERROR, "Failed to open DRM device"); - goto error_session; - } - backend = wlr_multi_backend_create(session); if (!backend) { - goto error_gpu; + goto error_session; } struct wlr_backend *libinput = wlr_libinput_backend_create(display, session); @@ -107,21 +101,36 @@ struct wlr_backend *wlr_backend_autocreate(struct wl_display *display) { goto error_multi; } - struct wlr_backend *drm = wlr_drm_backend_create(display, session, gpu); - if (!drm) { - goto error_libinput; + wlr_multi_backend_add(backend, libinput); + + int gpus[8]; + size_t num_gpus = wlr_session_find_gpus(session, 8, gpus); + struct wlr_backend *primary_drm = NULL; + wlr_log(L_INFO, "Found %zu GPUs", num_gpus); + + for (size_t i = 0; i < num_gpus; ++i) { + struct wlr_backend *drm = wlr_drm_backend_create(display, session, gpus[i]); + if (!drm) { + wlr_log(L_ERROR, "Failed to open DRM device"); + continue; + } + + if (!primary_drm) { + primary_drm = drm; + } + + wlr_multi_backend_add(backend, drm); + } + + if (!primary_drm) { + wlr_log(L_ERROR, "Failed to open any DRM device"); + goto error_multi; } - wlr_multi_backend_add(backend, libinput); - wlr_multi_backend_add(backend, drm); return backend; -error_libinput: - wlr_backend_destroy(libinput); error_multi: wlr_backend_destroy(backend); -error_gpu: - wlr_session_close_file(session, gpu); error_session: wlr_session_destroy(session); return NULL; diff --git a/backend/drm/backend.c b/backend/drm/backend.c index 442e5d0e..2d06e5e4 100644 --- a/backend/drm/backend.c +++ b/backend/drm/backend.c @@ -42,8 +42,8 @@ static void wlr_drm_backend_destroy(struct wlr_backend *backend) { free(drm); } -static struct wlr_egl *wlr_drm_backend_get_egl(struct wlr_backend *_backend) { - struct wlr_drm_backend *drm = (struct wlr_drm_backend *)_backend; +static struct wlr_egl *wlr_drm_backend_get_egl(struct wlr_backend *backend) { + struct wlr_drm_backend *drm = (struct wlr_drm_backend *)backend; return &drm->renderer.egl; } diff --git a/backend/session/session.c b/backend/session/session.c index cfa617f6..be79c34d 100644 --- a/backend/session/session.c +++ b/backend/session/session.c @@ -191,18 +191,16 @@ bool wlr_session_change_vt(struct wlr_session *session, unsigned vt) { /* Tests if 'path' is KMS compatible by trying to open it. * It leaves the open device in *fd_out it it succeeds. */ -static bool device_is_kms(struct wlr_session *restrict session, - const char *restrict path, int *restrict fd_out) { - +static int open_if_kms(struct wlr_session *restrict session, const char *restrict path) { int fd; if (!path) { - return false; + return -1; } fd = wlr_session_open_file(session, path); if (fd < 0) { - return false; + return -1; } drmModeRes *res = drmModeGetResources(fd); @@ -216,26 +214,21 @@ static bool device_is_kms(struct wlr_session *restrict session, goto out_res; } - if (*fd_out >= 0) { - wlr_session_close_file(session, *fd_out); - } - - *fd_out = fd; - drmModeFreeResources(res); - return true; + return fd; out_res: drmModeFreeResources(res); out_fd: wlr_session_close_file(session, fd); - return false; + return -1; } /* Tries to find the primary GPU by checking for the "boot_vga" attribute. * If it's not found, it returns the first valid GPU it finds. */ -int wlr_session_find_gpu(struct wlr_session *session) { +size_t wlr_session_find_gpus(struct wlr_session *session, + size_t ret_len, int ret[static ret_len]) { struct udev_enumerate *en = udev_enumerate_new(session->udev); if (!en) { wlr_log(L_ERROR, "Failed to create udev enumeration"); @@ -247,9 +240,13 @@ int wlr_session_find_gpu(struct wlr_session *session) { udev_enumerate_scan_devices(en); struct udev_list_entry *entry; - int fd = -1; + size_t i = 0; udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(en)) { + if (i == ret_len) { + break; + } + bool is_boot_vga = false; const char *path = udev_list_entry_get_name(entry); @@ -258,15 +255,13 @@ int wlr_session_find_gpu(struct wlr_session *session) { continue; } - /* const char *seat = udev_device_get_property_value(dev, "ID_SEAT"); if (!seat) seat = "seat0"; - if (strcmp(session->seat, seat) != 0) { + if (session->seat[0] && strcmp(session->seat, seat) != 0) { udev_device_unref(dev); continue; } - */ // This is owned by 'dev', so we don't need to free it struct udev_device *pci = @@ -279,27 +274,25 @@ int wlr_session_find_gpu(struct wlr_session *session) { } } - // We already have a valid GPU - if (!is_boot_vga && fd >= 0) { - udev_device_unref(dev); - continue; - } - - path = udev_device_get_devnode(dev); - if (!device_is_kms(session, path, &fd)) { + int fd = open_if_kms(session, udev_device_get_devnode(dev)); + if (fd < 0) { udev_device_unref(dev); continue; } udev_device_unref(dev); - // We've found the primary GPU + ret[i] = fd; if (is_boot_vga) { - break; + int tmp = ret[0]; + ret[0] = ret[i]; + ret[i] = tmp; } + + ++i; } udev_enumerate_unref(en); - return fd; + return i; } diff --git a/include/wlr/backend/session.h b/include/wlr/backend/session.h index 52cf13b7..94002bc5 100644 --- a/include/wlr/backend/session.h +++ b/include/wlr/backend/session.h @@ -72,12 +72,13 @@ int wlr_session_open_file(struct wlr_session *session, const char *path); void wlr_session_close_file(struct wlr_session *session, int fd); void wlr_session_signal_add(struct wlr_session *session, int fd, - struct wl_listener *listener); + struct wl_listener *listener); /* * Changes the virtual terminal. */ bool wlr_session_change_vt(struct wlr_session *session, unsigned vt); -int wlr_session_find_gpu(struct wlr_session *session); +size_t wlr_session_find_gpus(struct wlr_session *session, + size_t ret_len, int ret[static ret_len]); #endif -- cgit v1.2.3 From 009c3747a8771bcd441dc9cf95823fe40895f1e0 Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Sun, 1 Oct 2017 19:22:47 +1300 Subject: Multi-GPU DRM --- backend/backend.c | 3 +- backend/drm/backend.c | 4 +- backend/drm/drm.c | 21 ++++---- backend/drm/renderer.c | 117 +++++++++++++++++++++++++++++++++++++++++ include/backend/drm/drm.h | 2 + include/backend/drm/renderer.h | 11 ++++ include/wlr/backend/drm.h | 2 +- include/wlr/render.h | 9 +++- include/wlr/render/interface.h | 4 ++ render/gles2/texture.c | 20 +++++++ render/wlr_texture.c | 5 ++ 11 files changed, 184 insertions(+), 14 deletions(-) (limited to 'backend') diff --git a/backend/backend.c b/backend/backend.c index 359df3d1..d5cd1f70 100644 --- a/backend/backend.c +++ b/backend/backend.c @@ -109,7 +109,8 @@ struct wlr_backend *wlr_backend_autocreate(struct wl_display *display) { wlr_log(L_INFO, "Found %zu GPUs", num_gpus); for (size_t i = 0; i < num_gpus; ++i) { - struct wlr_backend *drm = wlr_drm_backend_create(display, session, gpus[i]); + struct wlr_backend *drm = wlr_drm_backend_create(display, session, + gpus[i], primary_drm); if (!drm) { wlr_log(L_ERROR, "Failed to open DRM device"); continue; diff --git a/backend/drm/backend.c b/backend/drm/backend.c index 2d06e5e4..e3148821 100644 --- a/backend/drm/backend.c +++ b/backend/drm/backend.c @@ -92,8 +92,9 @@ static void drm_invalidated(struct wl_listener *listener, void *data) { } struct wlr_backend *wlr_drm_backend_create(struct wl_display *display, - struct wlr_session *session, int gpu_fd) { + struct wlr_session *session, int gpu_fd, struct wlr_backend *parent) { assert(display && session && gpu_fd >= 0); + assert(!parent || wlr_backend_is_drm(parent)); char *name = drmGetDeviceNameFromFd2(gpu_fd); drmVersion *version = drmGetVersion(gpu_fd); @@ -116,6 +117,7 @@ struct wlr_backend *wlr_drm_backend_create(struct wl_display *display, } drm->fd = gpu_fd; + drm->parent = (struct wlr_drm_backend *)parent; drm->drm_invalidated.notify = drm_invalidated; wlr_session_signal_add(session, gpu_fd, &drm->drm_invalidated); diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 5c5ac8cd..3effa9ff 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -186,6 +186,10 @@ static void wlr_drm_connector_swap_buffers(struct wlr_output *output) { struct wlr_drm_plane *plane = crtc->primary; struct gbm_bo *bo = wlr_drm_surface_swap_buffers(&plane->surf); + if (drm->parent) { + bo = wlr_drm_surface_mgpu_copy(&plane->mgpu_surf, bo); + } + uint32_t fb_id = get_fb_for_bo(bo); if (drm->iface->crtc_pageflip(drm, conn, crtc, fb_id, NULL)) { @@ -217,7 +221,8 @@ void wlr_drm_connector_start_renderer(struct wlr_drm_connector *conn) { struct wlr_drm_crtc *crtc = conn->crtc; struct wlr_drm_plane *plane = crtc->primary; - struct gbm_bo *bo = wlr_drm_surface_get_front(&plane->surf); + struct gbm_bo *bo = wlr_drm_surface_get_front( + drm->parent ? &plane->mgpu_surf : &plane->surf); uint32_t fb_id = get_fb_for_bo(bo); struct wlr_drm_mode *mode = (struct wlr_drm_mode *)conn->output.current_mode; @@ -393,7 +398,6 @@ static bool wlr_drm_connector_set_mode(struct wlr_output *output, wlr_log(L_INFO, "Modesetting '%s' with '%ux%u@%u mHz'", conn->output.name, mode->width, mode->height, mode->refresh); - wlr_log(L_DEBUG, "%p %p", conn, drm); conn->possible_crtc = get_possible_crtcs(drm->fd, conn->id); if (conn->possible_crtc == 0) { goto error_conn; @@ -430,9 +434,8 @@ static bool wlr_drm_connector_set_mode(struct wlr_output *output, continue; } - if (!wlr_drm_surface_init(&crtc->primary->surf, &drm->renderer, - mode->width, mode->height, GBM_FORMAT_XRGB8888, - GBM_BO_USE_SCANOUT)) { + if (!wlr_drm_plane_surfaces_init(crtc->primary, drm, + mode->width, mode->height, GBM_FORMAT_XRGB8888)) { wlr_log(L_ERROR, "Failed to initalise renderer for plane"); goto error_conn; } @@ -782,10 +785,9 @@ static void page_flip_handler(int fd, unsigned seq, return; } - struct wlr_drm_plane *plane = conn->crtc->primary; - if (plane->surf.front) { - gbm_surface_release_buffer(plane->surf.gbm, plane->surf.front); - plane->surf.front = NULL; + wlr_drm_surface_post(&conn->crtc->primary->surf); + if (drm->parent) { + wlr_drm_surface_post(&conn->crtc->primary->mgpu_surf); } if (drm->session->active) { @@ -855,6 +857,7 @@ void wlr_drm_connector_cleanup(struct wlr_drm_connector *conn) { struct wlr_drm_crtc *crtc = conn->crtc; for (int i = 0; i < 3; ++i) { wlr_drm_surface_finish(&crtc->planes[i]->surf); + wlr_drm_surface_finish(&crtc->planes[i]->mgpu_surf); if (crtc->planes[i] && crtc->planes[i]->id == 0) { free(crtc->planes[i]); crtc->planes[i] = NULL; diff --git a/backend/drm/renderer.c b/backend/drm/renderer.c index e1c6a4bc..bcadf17e 100644 --- a/backend/drm/renderer.c +++ b/backend/drm/renderer.c @@ -1,12 +1,18 @@ #include +#include +#include #include #include #include #include +#include #include #include +#include +#include +#include #include "backend/drm/drm.h" bool wlr_drm_renderer_init(struct wlr_drm_renderer *renderer, int fd) { @@ -22,6 +28,9 @@ bool wlr_drm_renderer_init(struct wlr_drm_renderer *renderer, int fd) { return false; } + struct wlr_drm_backend *drm = wl_container_of(renderer, drm, renderer); + renderer->wlr_rend = wlr_gles2_renderer_create(&drm->backend); + renderer->fd = fd; return true; } @@ -121,3 +130,111 @@ struct gbm_bo *wlr_drm_surface_get_front(struct wlr_drm_surface *surf) { glClear(GL_COLOR_BUFFER_BIT); return wlr_drm_surface_swap_buffers(surf); } + +void wlr_drm_surface_post(struct wlr_drm_surface *surf) { + if (surf->front) { + gbm_surface_release_buffer(surf->gbm, surf->front); + surf->front = NULL; + } +} + +struct tex { + struct wlr_egl *egl; + EGLImageKHR img; + struct wlr_texture *tex; +}; + +static void free_eglimage(struct gbm_bo *bo, void *data) { + struct tex *tex = data; + + wlr_egl_destroy_image(tex->egl, tex->img); + wlr_texture_destroy(tex->tex); + free(tex); +} + +static struct wlr_texture *get_tex_for_bo(struct wlr_drm_renderer *renderer, struct gbm_bo *bo) { + struct tex *tex = gbm_bo_get_user_data(bo); + if (tex) { + return tex->tex; + } + + tex = malloc(sizeof(*tex)); + if (!tex) { + wlr_log_errno(L_ERROR, "Allocation failed"); + return NULL; + } + + tex->egl = &renderer->egl; + + int dmabuf_fd = gbm_bo_get_fd(bo); + uint32_t width = gbm_bo_get_width(bo); + uint32_t height = gbm_bo_get_height(bo); + + EGLint attribs[] = { + EGL_WIDTH, width, + EGL_HEIGHT, height, + EGL_LINUX_DRM_FOURCC_EXT, gbm_bo_get_format(bo), + EGL_DMA_BUF_PLANE0_FD_EXT, dmabuf_fd, + EGL_DMA_BUF_PLANE0_OFFSET_EXT, gbm_bo_get_offset(bo, 0), + EGL_DMA_BUF_PLANE0_PITCH_EXT, gbm_bo_get_stride_for_plane(bo, 0), + EGL_IMAGE_PRESERVED_KHR, EGL_FALSE, + EGL_NONE, + }; + + tex->img = renderer->egl.eglCreateImageKHR(renderer->egl.display, EGL_NO_CONTEXT, + EGL_LINUX_DMA_BUF_EXT, NULL, attribs); + if (!tex->img) { + wlr_log(L_ERROR, "Failed to create EGL image: %s", egl_error()); + abort(); + } + + tex->tex = wlr_render_texture_create(renderer->wlr_rend); + wlr_texture_upload_eglimage(tex->tex, tex->img, width, height); + + gbm_bo_set_user_data(bo, tex, free_eglimage); + + return tex->tex; +} + +struct gbm_bo *wlr_drm_surface_mgpu_copy(struct wlr_drm_surface *dest, struct gbm_bo *src) { + wlr_drm_surface_make_current(dest); + + struct wlr_texture *tex = get_tex_for_bo(dest->renderer, src); + + static const float matrix[16] = { + [0] = 2.0f, + [3] = -1.0f, + [5] = 2.0f, + [7] = -1.0f, + [10] = 1.0f, + [15] = 1.0f, + }; + + glViewport(0, 0, dest->width, dest->height); + glClearColor(0.0, 0.0, 0.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + wlr_render_with_matrix(dest->renderer->wlr_rend, tex, &matrix); + + return wlr_drm_surface_swap_buffers(dest); +} + +bool wlr_drm_plane_surfaces_init(struct wlr_drm_plane *plane, struct wlr_drm_backend *drm, + int32_t width, uint32_t height, uint32_t format) { + if (!drm->parent) { + return wlr_drm_surface_init(&plane->surf, &drm->renderer, width, height, + format, GBM_BO_USE_SCANOUT); + } + + if (!wlr_drm_surface_init(&plane->surf, &drm->parent->renderer, + width, height, format, GBM_BO_USE_LINEAR)) { + return false; + } + + if (!wlr_drm_surface_init(&plane->mgpu_surf, &drm->renderer, + width, height, format, GBM_BO_USE_SCANOUT)) { + wlr_drm_surface_finish(&plane->surf); + return false; + } + + return true; +} diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h index a3a724bc..6106a85a 100644 --- a/include/backend/drm/drm.h +++ b/include/backend/drm/drm.h @@ -26,6 +26,7 @@ struct wlr_drm_plane { uint32_t possible_crtcs; struct wlr_drm_surface surf; + struct wlr_drm_surface mgpu_surf; // Only used by cursor float matrix[16]; @@ -58,6 +59,7 @@ struct wlr_drm_crtc { struct wlr_drm_backend { struct wlr_backend backend; + struct wlr_drm_backend *parent; const struct wlr_drm_interface *iface; int fd; diff --git a/include/backend/drm/renderer.h b/include/backend/drm/renderer.h index 9982c25f..8fcf566d 100644 --- a/include/backend/drm/renderer.h +++ b/include/backend/drm/renderer.h @@ -7,10 +7,16 @@ #include #include +#include + +struct wlr_drm_plane; + struct wlr_drm_renderer { int fd; struct gbm_device *gbm; struct wlr_egl egl; + + struct wlr_renderer *wlr_rend; }; struct wlr_drm_surface { @@ -33,9 +39,14 @@ bool wlr_drm_surface_init(struct wlr_drm_surface *surf, struct wlr_drm_renderer *renderer, uint32_t width, uint32_t height, uint32_t format, uint32_t flags); +bool wlr_drm_plane_surfaces_init(struct wlr_drm_plane *plane, struct wlr_drm_backend *drm, + int32_t width, uint32_t height, uint32_t format); + void wlr_drm_surface_finish(struct wlr_drm_surface *surf); void wlr_drm_surface_make_current(struct wlr_drm_surface *surf); struct gbm_bo *wlr_drm_surface_swap_buffers(struct wlr_drm_surface *surf); struct gbm_bo *wlr_drm_surface_get_front(struct wlr_drm_surface *surf); +void wlr_drm_surface_post(struct wlr_drm_surface *surf); +struct gbm_bo *wlr_drm_surface_mgpu_copy(struct wlr_drm_surface *dest, struct gbm_bo *src); #endif diff --git a/include/wlr/backend/drm.h b/include/wlr/backend/drm.h index fa63df0a..b3475703 100644 --- a/include/wlr/backend/drm.h +++ b/include/wlr/backend/drm.h @@ -6,7 +6,7 @@ #include struct wlr_backend *wlr_drm_backend_create(struct wl_display *display, - struct wlr_session *session, int gpu_fd); + struct wlr_session *session, int gpu_fd, struct wlr_backend *parent); bool wlr_backend_is_drm(struct wlr_backend *backend); diff --git a/include/wlr/render.h b/include/wlr/render.h index 325f8c01..2fbfb476 100644 --- a/include/wlr/render.h +++ b/include/wlr/render.h @@ -2,6 +2,8 @@ #define WLR_RENDER_H #include +#include +#include #include #include @@ -93,8 +95,11 @@ bool wlr_texture_upload_shm(struct wlr_texture *tex, uint32_t format, * texture. The wl_resource is not used after this call. * Will fail (return false) if the given resource is no drm buffer. */ - bool wlr_texture_upload_drm(struct wlr_texture *tex, - struct wl_resource *drm_buffer); +bool wlr_texture_upload_drm(struct wlr_texture *tex, + struct wl_resource *drm_buffer); + +bool wlr_texture_upload_eglimage(struct wlr_texture *tex, + EGLImageKHR image, uint32_t width, uint32_t height); /** * Copies a rectangle of pixels from a wl_shm_buffer onto the texture. The diff --git a/include/wlr/render/interface.h b/include/wlr/render/interface.h index e3ba0414..cbe33822 100644 --- a/include/wlr/render/interface.h +++ b/include/wlr/render/interface.h @@ -2,6 +2,8 @@ #define WLR_RENDER_INTERFACE_H #include +#include +#include #include #include #include @@ -45,6 +47,8 @@ struct wlr_texture_impl { int x, int y, int width, int height, struct wl_shm_buffer *shm); bool (*upload_drm)(struct wlr_texture *texture, struct wl_resource *drm_buf); + bool (*upload_eglimage)(struct wlr_texture *texture, EGLImageKHR image, + uint32_t width, uint32_t height); void (*get_matrix)(struct wlr_texture *state, float (*matrix)[16], const float (*projection)[16], int x, int y); void (*get_buffer_size)(struct wlr_texture *texture, diff --git a/render/gles2/texture.c b/render/gles2/texture.c index 98d1a112..5e934aa4 100644 --- a/render/gles2/texture.c +++ b/render/gles2/texture.c @@ -205,6 +205,25 @@ static bool gles2_texture_upload_drm(struct wlr_texture *_tex, return true; } +static bool gles2_texture_upload_eglimage(struct wlr_texture *wlr_tex, + EGLImageKHR image, uint32_t width, uint32_t height) { + struct wlr_gles2_texture *tex = (struct wlr_gles2_texture *)wlr_tex; + + tex->image = image; + tex->pixel_format = &external_pixel_format; + tex->wlr_texture.valid = true; + tex->wlr_texture.width = width; + tex->wlr_texture.height = height; + + gles2_texture_ensure_texture(tex); + + GL_CALL(glActiveTexture(GL_TEXTURE0)); + GL_CALL(glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex->tex_id)); + GL_CALL(glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, tex->image)); + + return true; +} + static void gles2_texture_get_matrix(struct wlr_texture *_texture, float (*matrix)[16], const float (*projection)[16], int x, int y) { struct wlr_gles2_texture *texture = (struct wlr_gles2_texture *)_texture; @@ -270,6 +289,7 @@ static struct wlr_texture_impl wlr_texture_impl = { .upload_shm = gles2_texture_upload_shm, .update_shm = gles2_texture_update_shm, .upload_drm = gles2_texture_upload_drm, + .upload_eglimage = gles2_texture_upload_eglimage, .get_matrix = gles2_texture_get_matrix, .get_buffer_size = gles2_texture_get_buffer_size, .bind = gles2_texture_bind, diff --git a/render/wlr_texture.c b/render/wlr_texture.c index 9faea820..4ce86bdd 100644 --- a/render/wlr_texture.c +++ b/render/wlr_texture.c @@ -48,6 +48,11 @@ bool wlr_texture_upload_drm(struct wlr_texture *texture, return texture->impl->upload_drm(texture, drm_buffer); } +bool wlr_texture_upload_eglimage(struct wlr_texture *texture, + EGLImageKHR image, uint32_t width, uint32_t height) { + return texture->impl->upload_eglimage(texture, image, width, height); +} + void wlr_texture_get_matrix(struct wlr_texture *texture, float (*matrix)[16], const float (*projection)[16], int x, int y) { texture->impl->get_matrix(texture, matrix, projection, x, y); -- cgit v1.2.3 From f6f9c4096544fa64b7814ac55718f1c128c15004 Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Sun, 1 Oct 2017 22:44:24 +1300 Subject: Minor fixes --- backend/drm/backend.c | 2 +- backend/drm/drm.c | 6 +++++- backend/drm/renderer.c | 22 ++++++++++++++++------ include/backend/drm/renderer.h | 4 +++- 4 files changed, 25 insertions(+), 9 deletions(-) (limited to 'backend') diff --git a/backend/drm/backend.c b/backend/drm/backend.c index e3148821..468fca6e 100644 --- a/backend/drm/backend.c +++ b/backend/drm/backend.c @@ -143,7 +143,7 @@ struct wlr_backend *wlr_drm_backend_create(struct wl_display *display, goto error_event; } - if (!wlr_drm_renderer_init(&drm->renderer, drm->fd)) { + if (!wlr_drm_renderer_init(drm, &drm->renderer)) { wlr_log(L_ERROR, "Failed to initialize renderer"); goto error_event; } diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 3effa9ff..ccdc92d9 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -856,9 +856,13 @@ void wlr_drm_connector_cleanup(struct wlr_drm_connector *conn) { case WLR_DRM_CONN_CLEANUP:; struct wlr_drm_crtc *crtc = conn->crtc; for (int i = 0; i < 3; ++i) { + if (!crtc->planes[i]) { + continue; + } + wlr_drm_surface_finish(&crtc->planes[i]->surf); wlr_drm_surface_finish(&crtc->planes[i]->mgpu_surf); - if (crtc->planes[i] && crtc->planes[i]->id == 0) { + if (crtc->planes[i]->id == 0) { free(crtc->planes[i]); crtc->planes[i] = NULL; } diff --git a/backend/drm/renderer.c b/backend/drm/renderer.c index bcadf17e..c5840436 100644 --- a/backend/drm/renderer.c +++ b/backend/drm/renderer.c @@ -15,8 +15,9 @@ #include #include "backend/drm/drm.h" -bool wlr_drm_renderer_init(struct wlr_drm_renderer *renderer, int fd) { - renderer->gbm = gbm_create_device(fd); +bool wlr_drm_renderer_init(struct wlr_drm_backend *drm, + struct wlr_drm_renderer *renderer) { + renderer->gbm = gbm_create_device(drm->fd); if (!renderer->gbm) { wlr_log(L_ERROR, "Failed to create GBM device"); return false; @@ -24,15 +25,23 @@ bool wlr_drm_renderer_init(struct wlr_drm_renderer *renderer, int fd) { if (!wlr_egl_init(&renderer->egl, EGL_PLATFORM_GBM_MESA, GBM_FORMAT_ARGB8888, renderer->gbm)) { - gbm_device_destroy(renderer->gbm); - return false; + goto error_gbm; } - struct wlr_drm_backend *drm = wl_container_of(renderer, drm, renderer); renderer->wlr_rend = wlr_gles2_renderer_create(&drm->backend); + if (!renderer->wlr_rend) { + wlr_log(L_ERROR, "Failed to create WLR renderer"); + goto error_egl; + } - renderer->fd = fd; + renderer->fd = drm->fd; return true; + +error_egl: + wlr_egl_free(&renderer->egl); +error_gbm: + gbm_device_destroy(renderer->gbm); + return false; } void wlr_drm_renderer_finish(struct wlr_drm_renderer *renderer) { @@ -40,6 +49,7 @@ void wlr_drm_renderer_finish(struct wlr_drm_renderer *renderer) { return; } + wlr_renderer_destroy(renderer->wlr_rend); wlr_egl_free(&renderer->egl); gbm_device_destroy(renderer->gbm); } diff --git a/include/backend/drm/renderer.h b/include/backend/drm/renderer.h index 8fcf566d..45127cd0 100644 --- a/include/backend/drm/renderer.h +++ b/include/backend/drm/renderer.h @@ -9,6 +9,7 @@ #include +struct wlr_drm_backend; struct wlr_drm_plane; struct wlr_drm_renderer { @@ -32,7 +33,8 @@ struct wlr_drm_surface { struct gbm_bo *back; }; -bool wlr_drm_renderer_init(struct wlr_drm_renderer *renderer, int fd); +bool wlr_drm_renderer_init(struct wlr_drm_backend *drm, + struct wlr_drm_renderer *renderer); void wlr_drm_renderer_finish(struct wlr_drm_renderer *renderer); bool wlr_drm_surface_init(struct wlr_drm_surface *surf, -- cgit v1.2.3 From f193623ca11c245e9209a8df40115dbe420bbc22 Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Mon, 2 Oct 2017 21:44:33 +1300 Subject: Change iface prefix to suffix --- backend/drm/atomic.c | 189 ++++++++++++++++++++++++++++++++++++++++++++ backend/drm/drm.c | 6 +- backend/drm/iface_atomic.c | 189 -------------------------------------------- backend/drm/iface_legacy.c | 66 ---------------- backend/drm/legacy.c | 66 ++++++++++++++++ backend/meson.build | 4 +- include/backend/drm/iface.h | 4 +- 7 files changed, 262 insertions(+), 262 deletions(-) create mode 100644 backend/drm/atomic.c delete mode 100644 backend/drm/iface_atomic.c delete mode 100644 backend/drm/iface_legacy.c create mode 100644 backend/drm/legacy.c (limited to 'backend') diff --git a/backend/drm/atomic.c b/backend/drm/atomic.c new file mode 100644 index 00000000..e7374a00 --- /dev/null +++ b/backend/drm/atomic.c @@ -0,0 +1,189 @@ +#include +#include +#include +#include +#include "backend/drm/drm.h" +#include "backend/drm/iface.h" +#include "backend/drm/util.h" + +struct atomic { + drmModeAtomicReq *req; + int cursor; + bool failed; +}; + +static void atomic_begin(struct wlr_drm_crtc *crtc, struct atomic *atom) { + if (!crtc->atomic) { + crtc->atomic = drmModeAtomicAlloc(); + if (!crtc->atomic) { + wlr_log_errno(L_ERROR, "Allocation failed"); + atom->failed = true; + return; + } + } + + atom->req = crtc->atomic; + atom->cursor = drmModeAtomicGetCursor(atom->req); + atom->failed = false; +} + +static bool atomic_end(int drm_fd, struct atomic *atom) { + if (atom->failed) { + return false; + } + + uint32_t flags = DRM_MODE_ATOMIC_TEST_ONLY | DRM_MODE_ATOMIC_NONBLOCK; + + if (drmModeAtomicCommit(drm_fd, atom->req, flags, NULL)) { + wlr_log_errno(L_ERROR, "Atomic test failed"); + drmModeAtomicSetCursor(atom->req, atom->cursor); + return false; + } + + return true; +} + +static bool atomic_commit(int drm_fd, struct atomic *atom, + struct wlr_drm_connector *conn, uint32_t flag, bool modeset) { + if (atom->failed) { + return false; + } + + uint32_t flags = DRM_MODE_PAGE_FLIP_EVENT | flag; + + int ret = drmModeAtomicCommit(drm_fd, atom->req, flags, conn); + if (ret) { + wlr_log_errno(L_ERROR, "%s: Atomic commit failed (%s)", + conn->output.name, modeset ? "modeset" : "pageflip"); + + // Try to commit without new changes + drmModeAtomicSetCursor(atom->req, atom->cursor); + if (drmModeAtomicCommit(drm_fd, atom->req, flags, conn)) { + wlr_log_errno(L_ERROR, "%s: Atomic commit failed (%s)", + conn->output.name, modeset ? "modeset" : "pageflip"); + } + } + + drmModeAtomicSetCursor(atom->req, 0); + + return !ret; +} + +static inline void atomic_add(struct atomic *atom, uint32_t id, uint32_t prop, uint64_t val) { + if (!atom->failed && drmModeAtomicAddProperty(atom->req, id, prop, val) < 0) { + wlr_log_errno(L_ERROR, "Failed to add atomic DRM property"); + atom->failed = true; + } +} + +static void set_plane_props(struct atomic *atom, struct wlr_drm_plane *plane, + uint32_t crtc_id, uint32_t fb_id, bool set_crtc_xy) { + uint32_t id = plane->id; + const union wlr_drm_plane_props *props = &plane->props; + + // The src_* properties are in 16.16 fixed point + atomic_add(atom, id, props->src_x, 0); + atomic_add(atom, id, props->src_y, 0); + atomic_add(atom, id, props->src_w, plane->surf.width << 16); + atomic_add(atom, id, props->src_h, plane->surf.height << 16); + atomic_add(atom, id, props->crtc_w, plane->surf.width); + atomic_add(atom, id, props->crtc_h, plane->surf.height); + atomic_add(atom, id, props->fb_id, fb_id); + atomic_add(atom, id, props->crtc_id, crtc_id); + if (set_crtc_xy) { + atomic_add(atom, id, props->crtc_x, 0); + atomic_add(atom, id, props->crtc_y, 0); + } +} + +static bool atomic_crtc_pageflip(struct wlr_drm_backend *drm, + struct wlr_drm_connector *conn, + struct wlr_drm_crtc *crtc, + uint32_t fb_id, drmModeModeInfo *mode) { + if (mode) { + if (crtc->mode_id) { + drmModeDestroyPropertyBlob(drm->fd, crtc->mode_id); + } + + if (drmModeCreatePropertyBlob(drm->fd, mode, sizeof(*mode), &crtc->mode_id)) { + wlr_log_errno(L_ERROR, "Unable to create property blob"); + return false; + } + } + + struct atomic atom; + + atomic_begin(crtc, &atom); + atomic_add(&atom, conn->id, conn->props.crtc_id, crtc->id); + 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); + return atomic_commit(drm->fd, &atom, conn, + mode ? DRM_MODE_ATOMIC_ALLOW_MODESET : DRM_MODE_ATOMIC_NONBLOCK, + mode); +} + +static void atomic_conn_enable(struct wlr_drm_backend *drm, + struct wlr_drm_connector *conn, bool enable) { + struct wlr_drm_crtc *crtc = conn->crtc; + struct atomic atom; + + atomic_begin(crtc, &atom); + atomic_add(&atom, crtc->id, crtc->props.active, enable); + atomic_end(drm->fd, &atom); +} + +bool legacy_crtc_set_cursor(struct wlr_drm_backend *drm, + struct wlr_drm_crtc *crtc, struct gbm_bo *bo); + +static bool atomic_crtc_set_cursor(struct wlr_drm_backend *drm, + struct wlr_drm_crtc *crtc, struct gbm_bo *bo) { + if (!crtc || !crtc->cursor) { + return true; + } + + struct wlr_drm_plane *plane = crtc->cursor; + // We can't use atomic operations on fake planes + if (plane->id == 0) { + return legacy_crtc_set_cursor(drm, crtc, bo); + } + + struct atomic atom; + + atomic_begin(crtc, &atom); + + if (bo) { + set_plane_props(&atom, plane, crtc->id, get_fb_for_bo(bo), false); + } else { + atomic_add(&atom, plane->id, plane->props.fb_id, 0); + atomic_add(&atom, plane->id, plane->props.crtc_id, 0); + } + + return atomic_end(drm->fd, &atom); +} + +bool legacy_crtc_move_cursor(struct wlr_drm_backend *drm, + struct wlr_drm_crtc *crtc, int x, int y); + +static bool atomic_crtc_move_cursor(struct wlr_drm_backend *drm, + struct wlr_drm_crtc *crtc, int x, int y) { + struct wlr_drm_plane *plane = crtc->cursor; + // We can't use atomic operations on fake planes + if (plane->id == 0) { + return legacy_crtc_move_cursor(drm, crtc, x, y); + } + + struct atomic atom; + + atomic_begin(crtc, &atom); + atomic_add(&atom, plane->id, plane->props.crtc_x, x); + atomic_add(&atom, plane->id, plane->props.crtc_y, y); + return atomic_end(drm->fd, &atom); +} + +const struct wlr_drm_interface atomic_iface = { + .conn_enable = atomic_conn_enable, + .crtc_pageflip = atomic_crtc_pageflip, + .crtc_set_cursor = atomic_crtc_set_cursor, + .crtc_move_cursor = atomic_crtc_move_cursor, +}; diff --git a/backend/drm/drm.c b/backend/drm/drm.c index ccdc92d9..1a5fea9f 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -32,13 +32,13 @@ bool wlr_drm_check_features(struct wlr_drm_backend *drm) { if (getenv("WLR_DRM_NO_ATOMIC")) { wlr_log(L_DEBUG, "WLR_DRM_NO_ATOMIC set, forcing legacy DRM interface"); - drm->iface = &iface_legacy; + drm->iface = &legacy_iface; } else if (drmSetClientCap(drm->fd, DRM_CLIENT_CAP_ATOMIC, 1)) { wlr_log(L_DEBUG, "Atomic modesetting unsupported, using legacy DRM interface"); - drm->iface = &iface_legacy; + drm->iface = &legacy_iface; } else { wlr_log(L_DEBUG, "Using atomic DRM interface"); - drm->iface = &iface_atomic; + drm->iface = &atomic_iface; } return true; diff --git a/backend/drm/iface_atomic.c b/backend/drm/iface_atomic.c deleted file mode 100644 index 1aef05d1..00000000 --- a/backend/drm/iface_atomic.c +++ /dev/null @@ -1,189 +0,0 @@ -#include -#include -#include -#include -#include "backend/drm/drm.h" -#include "backend/drm/iface.h" -#include "backend/drm/util.h" - -struct atomic { - drmModeAtomicReq *req; - int cursor; - bool failed; -}; - -static void atomic_begin(struct wlr_drm_crtc *crtc, struct atomic *atom) { - if (!crtc->atomic) { - crtc->atomic = drmModeAtomicAlloc(); - if (!crtc->atomic) { - wlr_log_errno(L_ERROR, "Allocation failed"); - atom->failed = true; - return; - } - } - - atom->req = crtc->atomic; - atom->cursor = drmModeAtomicGetCursor(atom->req); - atom->failed = false; -} - -static bool atomic_end(int drm_fd, struct atomic *atom) { - if (atom->failed) { - return false; - } - - uint32_t flags = DRM_MODE_ATOMIC_TEST_ONLY | DRM_MODE_ATOMIC_NONBLOCK; - - if (drmModeAtomicCommit(drm_fd, atom->req, flags, NULL)) { - wlr_log_errno(L_ERROR, "Atomic test failed"); - drmModeAtomicSetCursor(atom->req, atom->cursor); - return false; - } - - return true; -} - -static bool atomic_commit(int drm_fd, struct atomic *atom, - struct wlr_drm_connector *conn, uint32_t flag, bool modeset) { - if (atom->failed) { - return false; - } - - uint32_t flags = DRM_MODE_PAGE_FLIP_EVENT | flag; - - int ret = drmModeAtomicCommit(drm_fd, atom->req, flags, conn); - if (ret) { - wlr_log_errno(L_ERROR, "%s: Atomic commit failed (%s)", - conn->output.name, modeset ? "modeset" : "pageflip"); - - // Try to commit without new changes - drmModeAtomicSetCursor(atom->req, atom->cursor); - if (drmModeAtomicCommit(drm_fd, atom->req, flags, conn)) { - wlr_log_errno(L_ERROR, "%s: Atomic commit failed (%s)", - conn->output.name, modeset ? "modeset" : "pageflip"); - } - } - - drmModeAtomicSetCursor(atom->req, 0); - - return !ret; -} - -static inline void atomic_add(struct atomic *atom, uint32_t id, uint32_t prop, uint64_t val) { - if (!atom->failed && drmModeAtomicAddProperty(atom->req, id, prop, val) < 0) { - wlr_log_errno(L_ERROR, "Failed to add atomic DRM property"); - atom->failed = true; - } -} - -static void set_plane_props(struct atomic *atom, struct wlr_drm_plane *plane, - uint32_t crtc_id, uint32_t fb_id, bool set_crtc_xy) { - uint32_t id = plane->id; - const union wlr_drm_plane_props *props = &plane->props; - - // The src_* properties are in 16.16 fixed point - atomic_add(atom, id, props->src_x, 0); - atomic_add(atom, id, props->src_y, 0); - atomic_add(atom, id, props->src_w, plane->surf.width << 16); - atomic_add(atom, id, props->src_h, plane->surf.height << 16); - atomic_add(atom, id, props->crtc_w, plane->surf.width); - atomic_add(atom, id, props->crtc_h, plane->surf.height); - atomic_add(atom, id, props->fb_id, fb_id); - atomic_add(atom, id, props->crtc_id, crtc_id); - if (set_crtc_xy) { - atomic_add(atom, id, props->crtc_x, 0); - atomic_add(atom, id, props->crtc_y, 0); - } -} - -static bool atomic_crtc_pageflip(struct wlr_drm_backend *drm, - struct wlr_drm_connector *conn, - struct wlr_drm_crtc *crtc, - uint32_t fb_id, drmModeModeInfo *mode) { - if (mode) { - if (crtc->mode_id) { - drmModeDestroyPropertyBlob(drm->fd, crtc->mode_id); - } - - if (drmModeCreatePropertyBlob(drm->fd, mode, sizeof(*mode), &crtc->mode_id)) { - wlr_log_errno(L_ERROR, "Unable to create property blob"); - return false; - } - } - - struct atomic atom; - - atomic_begin(crtc, &atom); - atomic_add(&atom, conn->id, conn->props.crtc_id, crtc->id); - 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); - return atomic_commit(drm->fd, &atom, conn, - mode ? DRM_MODE_ATOMIC_ALLOW_MODESET : DRM_MODE_ATOMIC_NONBLOCK, - mode); -} - -static void atomic_conn_enable(struct wlr_drm_backend *drm, - struct wlr_drm_connector *conn, bool enable) { - struct wlr_drm_crtc *crtc = conn->crtc; - struct atomic atom; - - atomic_begin(crtc, &atom); - atomic_add(&atom, crtc->id, crtc->props.active, enable); - atomic_end(drm->fd, &atom); -} - -bool legacy_crtc_set_cursor(struct wlr_drm_backend *drm, - struct wlr_drm_crtc *crtc, struct gbm_bo *bo); - -static bool atomic_crtc_set_cursor(struct wlr_drm_backend *drm, - struct wlr_drm_crtc *crtc, struct gbm_bo *bo) { - if (!crtc || !crtc->cursor) { - return true; - } - - struct wlr_drm_plane *plane = crtc->cursor; - // We can't use atomic operations on fake planes - if (plane->id == 0) { - return legacy_crtc_set_cursor(drm, crtc, bo); - } - - struct atomic atom; - - atomic_begin(crtc, &atom); - - if (bo) { - set_plane_props(&atom, plane, crtc->id, get_fb_for_bo(bo), false); - } else { - atomic_add(&atom, plane->id, plane->props.fb_id, 0); - atomic_add(&atom, plane->id, plane->props.crtc_id, 0); - } - - return atomic_end(drm->fd, &atom); -} - -bool legacy_crtc_move_cursor(struct wlr_drm_backend *drm, - struct wlr_drm_crtc *crtc, int x, int y); - -static bool atomic_crtc_move_cursor(struct wlr_drm_backend *drm, - struct wlr_drm_crtc *crtc, int x, int y) { - struct wlr_drm_plane *plane = crtc->cursor; - // We can't use atomic operations on fake planes - if (plane->id == 0) { - return legacy_crtc_move_cursor(drm, crtc, x, y); - } - - struct atomic atom; - - atomic_begin(crtc, &atom); - atomic_add(&atom, plane->id, plane->props.crtc_x, x); - atomic_add(&atom, plane->id, plane->props.crtc_y, y); - return atomic_end(drm->fd, &atom); -} - -const struct wlr_drm_interface iface_atomic = { - .conn_enable = atomic_conn_enable, - .crtc_pageflip = atomic_crtc_pageflip, - .crtc_set_cursor = atomic_crtc_set_cursor, - .crtc_move_cursor = atomic_crtc_move_cursor, -}; diff --git a/backend/drm/iface_legacy.c b/backend/drm/iface_legacy.c deleted file mode 100644 index cf73bb87..00000000 --- a/backend/drm/iface_legacy.c +++ /dev/null @@ -1,66 +0,0 @@ -#include -#include -#include -#include -#include "backend/drm/drm.h" -#include "backend/drm/iface.h" -#include "backend/drm/util.h" - -static bool legacy_crtc_pageflip(struct wlr_drm_backend *drm, - struct wlr_drm_connector *conn, struct wlr_drm_crtc *crtc, - uint32_t fb_id, drmModeModeInfo *mode) { - if (mode) { - if (drmModeSetCrtc(drm->fd, crtc->id, fb_id, 0, 0, - &conn->id, 1, mode)) { - wlr_log_errno(L_ERROR, "%s: Failed to set CRTC", conn->output.name); - return false; - } - } - - if (drmModePageFlip(drm->fd, crtc->id, fb_id, DRM_MODE_PAGE_FLIP_EVENT, conn)) { - wlr_log_errno(L_ERROR, "%s: Failed to page flip", conn->output.name); - return false; - } - - return true; -} - -static void legacy_conn_enable(struct wlr_drm_backend *drm, - struct wlr_drm_connector *conn, bool enable) { - drmModeConnectorSetProperty(drm->fd, conn->id, conn->props.dpms, - enable ? DRM_MODE_DPMS_ON : DRM_MODE_DPMS_OFF); -} - -bool legacy_crtc_set_cursor(struct wlr_drm_backend *drm, - struct wlr_drm_crtc *crtc, struct gbm_bo *bo) { - if (!crtc || !crtc->cursor) { - return true; - } - - if (!bo) { - drmModeSetCursor(drm->fd, crtc->id, 0, 0, 0); - return true; - } - - struct wlr_drm_plane *plane = crtc->cursor; - - if (drmModeSetCursor(drm->fd, crtc->id, gbm_bo_get_handle(bo).u32, - plane->surf.width, plane->surf.height)) { - wlr_log_errno(L_ERROR, "Failed to set hardware cursor"); - return false; - } - - return true; -} - -bool legacy_crtc_move_cursor(struct wlr_drm_backend *drm, - struct wlr_drm_crtc *crtc, int x, int y) { - return !drmModeMoveCursor(drm->fd, crtc->id, x, y); -} - -const struct wlr_drm_interface iface_legacy = { - .conn_enable = legacy_conn_enable, - .crtc_pageflip = legacy_crtc_pageflip, - .crtc_set_cursor = legacy_crtc_set_cursor, - .crtc_move_cursor = legacy_crtc_move_cursor, -}; diff --git a/backend/drm/legacy.c b/backend/drm/legacy.c new file mode 100644 index 00000000..d75eb2cb --- /dev/null +++ b/backend/drm/legacy.c @@ -0,0 +1,66 @@ +#include +#include +#include +#include +#include "backend/drm/drm.h" +#include "backend/drm/iface.h" +#include "backend/drm/util.h" + +static bool legacy_crtc_pageflip(struct wlr_drm_backend *drm, + struct wlr_drm_connector *conn, struct wlr_drm_crtc *crtc, + uint32_t fb_id, drmModeModeInfo *mode) { + if (mode) { + if (drmModeSetCrtc(drm->fd, crtc->id, fb_id, 0, 0, + &conn->id, 1, mode)) { + wlr_log_errno(L_ERROR, "%s: Failed to set CRTC", conn->output.name); + return false; + } + } + + if (drmModePageFlip(drm->fd, crtc->id, fb_id, DRM_MODE_PAGE_FLIP_EVENT, conn)) { + wlr_log_errno(L_ERROR, "%s: Failed to page flip", conn->output.name); + return false; + } + + return true; +} + +static void legacy_conn_enable(struct wlr_drm_backend *drm, + struct wlr_drm_connector *conn, bool enable) { + drmModeConnectorSetProperty(drm->fd, conn->id, conn->props.dpms, + enable ? DRM_MODE_DPMS_ON : DRM_MODE_DPMS_OFF); +} + +bool legacy_crtc_set_cursor(struct wlr_drm_backend *drm, + struct wlr_drm_crtc *crtc, struct gbm_bo *bo) { + if (!crtc || !crtc->cursor) { + return true; + } + + if (!bo) { + drmModeSetCursor(drm->fd, crtc->id, 0, 0, 0); + return true; + } + + struct wlr_drm_plane *plane = crtc->cursor; + + if (drmModeSetCursor(drm->fd, crtc->id, gbm_bo_get_handle(bo).u32, + plane->surf.width, plane->surf.height)) { + wlr_log_errno(L_ERROR, "Failed to set hardware cursor"); + return false; + } + + return true; +} + +bool legacy_crtc_move_cursor(struct wlr_drm_backend *drm, + struct wlr_drm_crtc *crtc, int x, int y) { + return !drmModeMoveCursor(drm->fd, crtc->id, x, y); +} + +const struct wlr_drm_interface legacy_iface = { + .conn_enable = legacy_conn_enable, + .crtc_pageflip = legacy_crtc_pageflip, + .crtc_set_cursor = legacy_crtc_set_cursor, + .crtc_move_cursor = legacy_crtc_move_cursor, +}; diff --git a/backend/meson.build b/backend/meson.build index caf2c8b0..c5c73288 100644 --- a/backend/meson.build +++ b/backend/meson.build @@ -3,10 +3,10 @@ backend_files = files( 'session/direct-ipc.c', 'session/direct.c', 'session/session.c', + 'drm/atomic.c', 'drm/backend.c', 'drm/drm.c', - 'drm/iface_atomic.c', - 'drm/iface_legacy.c', + 'drm/legacy.c', 'drm/properties.c', 'drm/renderer.c', 'drm/util.c', diff --git a/include/backend/drm/iface.h b/include/backend/drm/iface.h index db1d7ee1..bc61eb51 100644 --- a/include/backend/drm/iface.h +++ b/include/backend/drm/iface.h @@ -29,7 +29,7 @@ struct wlr_drm_interface { struct wlr_drm_crtc *crtc, int x, int y); }; -extern const struct wlr_drm_interface iface_atomic; -extern const struct wlr_drm_interface iface_legacy; +extern const struct wlr_drm_interface atomic_iface; +extern const struct wlr_drm_interface legacy_iface; #endif -- cgit v1.2.3 From 6cfe47d1d891d31ef3e13deebbf899af27cadb82 Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Mon, 2 Oct 2017 21:57:14 +1300 Subject: Add explicitly picking GPUs with environment var --- backend/session/session.c | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) (limited to 'backend') diff --git a/backend/session/session.c b/backend/session/session.c index be79c34d..72eb6149 100644 --- a/backend/session/session.c +++ b/backend/session/session.c @@ -1,7 +1,8 @@ +#define _POSIX_C_SOURCE 200809L #include #include -#include #include +#include #include #include #include @@ -224,11 +225,44 @@ out_fd: return -1; } +static size_t explicit_find_gpus(struct wlr_session *session, + size_t ret_len, int ret[static ret_len], const char *str) { + char *gpus = strdup(str); + if (!gpus) { + wlr_log_errno(L_ERROR, "Allocation failed"); + return 0; + } + + size_t i = 0; + char *save; + char *ptr = strtok_r(gpus, ":", &save); + do { + if (i >= ret_len) { + break; + } + + ret[i] = open_if_kms(session, ptr); + if (ret[i] <= 0) { + wlr_log(L_ERROR, "Unable to open %s as DRM device", ptr); + } else { + ++i; + } + } while ((ptr = strtok_r(NULL, ":", &save))); + + free(ptr); + return i; +} + /* Tries to find the primary GPU by checking for the "boot_vga" attribute. * If it's not found, it returns the first valid GPU it finds. */ size_t wlr_session_find_gpus(struct wlr_session *session, size_t ret_len, int ret[static ret_len]) { + const char *explicit = getenv("WLR_DRM_DEVICES"); + if (explicit) { + return explicit_find_gpus(session, ret_len, ret, explicit); + } + struct udev_enumerate *en = udev_enumerate_new(session->udev); if (!en) { wlr_log(L_ERROR, "Failed to create udev enumeration"); -- cgit v1.2.3 From 9ec9edc40d4694dedfd7f00eb9106ce5ed133239 Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Mon, 2 Oct 2017 22:01:09 +1300 Subject: Check for fd failure properly --- backend/session/session.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backend') diff --git a/backend/session/session.c b/backend/session/session.c index 72eb6149..b73952fd 100644 --- a/backend/session/session.c +++ b/backend/session/session.c @@ -242,7 +242,7 @@ static size_t explicit_find_gpus(struct wlr_session *session, } ret[i] = open_if_kms(session, ptr); - if (ret[i] <= 0) { + if (ret[i] < 0) { wlr_log(L_ERROR, "Unable to open %s as DRM device", ptr); } else { ++i; -- cgit v1.2.3