DRM resource initalisation
This commit is contained in:
parent
601bbad5d8
commit
7b772e1a4b
|
@ -12,8 +12,8 @@
|
||||||
#include <wlr/interfaces/wlr_output.h>
|
#include <wlr/interfaces/wlr_output.h>
|
||||||
#include <wlr/util/list.h>
|
#include <wlr/util/list.h>
|
||||||
#include <wlr/util/log.h>
|
#include <wlr/util/log.h>
|
||||||
#include "backend/udev.h"
|
#include <backend/udev.h>
|
||||||
#include "backend/drm.h"
|
#include "drm.h"
|
||||||
|
|
||||||
static bool wlr_drm_backend_init(struct wlr_backend_state *state) {
|
static bool wlr_drm_backend_init(struct wlr_backend_state *state) {
|
||||||
wlr_drm_scan_connectors(state);
|
wlr_drm_scan_connectors(state);
|
||||||
|
@ -131,6 +131,15 @@ struct wlr_backend *wlr_drm_backend_create(struct wl_display *display,
|
||||||
state->session_signal.notify = session_signal;
|
state->session_signal.notify = session_signal;
|
||||||
wl_signal_add(&session->session_signal, &state->session_signal);
|
wl_signal_add(&session->session_signal, &state->session_signal);
|
||||||
|
|
||||||
|
if (drmSetClientCap(state->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1)) {
|
||||||
|
wlr_log(L_INFO, "DRM universal planes unsupported");
|
||||||
|
}
|
||||||
|
if (drmSetClientCap(state->fd, DRM_CLIENT_CAP_ATOMIC, 1)) {
|
||||||
|
wlr_log(L_INFO, "Atomic modesetting unsupported");
|
||||||
|
}
|
||||||
|
|
||||||
|
wlr_drm_init_resources(state);
|
||||||
|
|
||||||
// TODO: what is the difference between the per-output renderer and this
|
// TODO: what is the difference between the per-output renderer and this
|
||||||
// one?
|
// one?
|
||||||
if (!wlr_drm_renderer_init(&state->renderer, state->fd)) {
|
if (!wlr_drm_renderer_init(&state->renderer, state->fd)) {
|
||||||
|
|
|
@ -49,10 +49,10 @@ static const struct prop_info plane_info[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static int cmp_prop_info(const void *arg1, const void *arg2) {
|
static int cmp_prop_info(const void *arg1, const void *arg2) {
|
||||||
const struct prop_info *a = arg1;
|
const char *key = arg1;
|
||||||
const struct prop_info *b = arg2;
|
const struct prop_info *elem = arg2;
|
||||||
|
|
||||||
return strcmp(a->name, b->name);
|
return strcmp(key, elem->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool scan_properties(int fd, uint32_t id, uint32_t type, uint32_t *result,
|
static bool scan_properties(int fd, uint32_t id, uint32_t type, uint32_t *result,
|
||||||
|
@ -97,3 +97,47 @@ 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,
|
return scan_properties(fd, id, DRM_MODE_OBJECT_PLANE, out->props,
|
||||||
plane_info, sizeof(plane_info) / sizeof(plane_info[0]));
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These types contain the property ids for several DRM objects.
|
* These types contain the property ids for several DRM objects.
|
||||||
* See https://01.org/linuxgraphics/gfx-docs/drm/drm-kms-properties.html
|
* See https://01.org/linuxgraphics/gfx-docs/drm/gpu/drm-kms.html#kms-properties
|
||||||
* for more details.
|
* for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -56,4 +56,7 @@ bool wlr_drm_get_connector_props(int fd, uint32_t id, union wlr_drm_connector_pr
|
||||||
bool wlr_drm_get_crtc_props(int fd, uint32_t id, union wlr_drm_crtc_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_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
|
#endif
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
#include <wlr/backend/interface.h>
|
#include <wlr/backend/interface.h>
|
||||||
#include <wlr/interfaces/wlr_output.h>
|
#include <wlr/interfaces/wlr_output.h>
|
||||||
#include <wlr/util/log.h>
|
#include <wlr/util/log.h>
|
||||||
#include "backend/drm.h"
|
#include "drm.h"
|
||||||
|
|
||||||
static const char *conn_name[] = {
|
static const char *conn_name[] = {
|
||||||
[DRM_MODE_CONNECTOR_Unknown] = "Unknown",
|
[DRM_MODE_CONNECTOR_Unknown] = "Unknown",
|
||||||
|
@ -37,6 +37,137 @@ static const char *conn_name[] = {
|
||||||
[DRM_MODE_CONNECTOR_DSI] = "DSI",
|
[DRM_MODE_CONNECTOR_DSI] = "DSI",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int cmp_plane(const void *arg1, const void *arg2)
|
||||||
|
{
|
||||||
|
const struct wlr_drm_plane *a = arg1;
|
||||||
|
const struct wlr_drm_plane *b = arg2;
|
||||||
|
|
||||||
|
return (int)a->type - (int)b->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool init_planes(struct wlr_backend_state *drm)
|
||||||
|
{
|
||||||
|
drmModePlaneRes *plane_res = drmModeGetPlaneResources(drm->fd);
|
||||||
|
if (!plane_res) {
|
||||||
|
wlr_log_errno(L_ERROR, "Failed to get DRM plane resources");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
wlr_log(L_INFO, "Found %"PRIu32" DRM planes", plane_res->count_planes);
|
||||||
|
|
||||||
|
if (plane_res->count_planes == 0) {
|
||||||
|
drmModeFreePlaneResources(plane_res);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t num_planes = plane_res->count_planes;
|
||||||
|
struct wlr_drm_plane *planes = calloc(num_planes, sizeof(*planes));
|
||||||
|
if (!planes) {
|
||||||
|
wlr_log_errno(L_ERROR, "Allocation failed");
|
||||||
|
goto error_res;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t num_overlay = 0;
|
||||||
|
size_t num_primary = 0;
|
||||||
|
size_t num_cursor = 0;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < num_planes; ++i) {
|
||||||
|
struct wlr_drm_plane *p = &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;
|
||||||
|
}
|
||||||
|
|
||||||
|
p->id = plane->plane_id;
|
||||||
|
p->possible_crtcs = plane->possible_crtcs;
|
||||||
|
uint64_t 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;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case DRM_PLANE_TYPE_OVERLAY:
|
||||||
|
++num_overlay;
|
||||||
|
break;
|
||||||
|
case DRM_PLANE_TYPE_PRIMARY:
|
||||||
|
++num_primary;
|
||||||
|
break;
|
||||||
|
case DRM_PLANE_TYPE_CURSOR:
|
||||||
|
++num_cursor;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
drmModeFreePlane(plane);
|
||||||
|
}
|
||||||
|
|
||||||
|
wlr_log(L_INFO, "(%zu overlay, %zu primary, %zu cursor)",
|
||||||
|
num_overlay, num_primary, num_cursor);
|
||||||
|
|
||||||
|
qsort(planes, num_planes, sizeof(*planes), cmp_plane);
|
||||||
|
|
||||||
|
drm->num_planes = num_planes;
|
||||||
|
drm->num_overlay_planes = num_overlay;
|
||||||
|
drm->num_primary_planes = num_primary;
|
||||||
|
drm->num_cursor_planes = num_cursor;
|
||||||
|
|
||||||
|
drm->planes = planes;
|
||||||
|
drm->overlay_planes = planes;
|
||||||
|
drm->primary_planes = planes + num_overlay;
|
||||||
|
drm->cursor_planes = planes + num_overlay + num_primary;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
error_planes:
|
||||||
|
free(planes);
|
||||||
|
error_res:
|
||||||
|
drmModeFreePlaneResources(plane_res);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wlr_drm_init_resources(struct wlr_backend_state *drm) {
|
||||||
|
drmModeRes *res = drmModeGetResources(drm->fd);
|
||||||
|
if (!res) {
|
||||||
|
wlr_log_errno(L_ERROR, "Failed to get DRM resources");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
wlr_log(L_INFO, "Found %d DRM CRTCs", res->count_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 < drm->num_crtcs; ++i) {
|
||||||
|
struct wlr_drm_crtc *crtc = &drm->crtcs[i];
|
||||||
|
crtc->id = res->crtcs[i];
|
||||||
|
wlr_drm_get_crtc_props(drm->fd, crtc->id, &crtc->props);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!init_planes(drm)) {
|
||||||
|
goto error_crtcs;
|
||||||
|
}
|
||||||
|
|
||||||
|
drmModeFreeResources(res);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
error_crtcs:
|
||||||
|
free(drm->crtcs);
|
||||||
|
error_res:
|
||||||
|
drmModeFreeResources(res);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool wlr_drm_renderer_init(struct wlr_drm_renderer *renderer, int fd) {
|
bool wlr_drm_renderer_init(struct wlr_drm_renderer *renderer, int fd) {
|
||||||
renderer->gbm = gbm_create_device(fd);
|
renderer->gbm = gbm_create_device(fd);
|
||||||
if (!renderer->gbm) {
|
if (!renderer->gbm) {
|
||||||
|
|
|
@ -14,8 +14,37 @@
|
||||||
#include <wlr/backend/drm.h>
|
#include <wlr/backend/drm.h>
|
||||||
#include <wlr/util/list.h>
|
#include <wlr/util/list.h>
|
||||||
|
|
||||||
#include "backend/egl.h"
|
#include <backend/egl.h>
|
||||||
#include "backend/udev.h"
|
#include <backend/udev.h>
|
||||||
|
#include "drm-properties.h"
|
||||||
|
|
||||||
|
struct wlr_drm_plane {
|
||||||
|
uint32_t type;
|
||||||
|
uint32_t id;
|
||||||
|
uint32_t fb_id;
|
||||||
|
|
||||||
|
uint32_t possible_crtcs;
|
||||||
|
|
||||||
|
int32_t x, y;
|
||||||
|
uint32_t width, height;
|
||||||
|
|
||||||
|
struct gbm_surface *gbm;
|
||||||
|
EGLSurface egl;
|
||||||
|
|
||||||
|
struct gbm_bo *front;
|
||||||
|
struct gbm_bo *back;
|
||||||
|
|
||||||
|
union wlr_drm_plane_props props;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wlr_drm_crtc {
|
||||||
|
uint32_t id;
|
||||||
|
struct wlr_drm_plane *primary;
|
||||||
|
struct wlr_drm_plane *overlay;
|
||||||
|
struct wlr_drm_plane *cursor;
|
||||||
|
|
||||||
|
union wlr_drm_crtc_props props;
|
||||||
|
};
|
||||||
|
|
||||||
struct wlr_drm_renderer {
|
struct wlr_drm_renderer {
|
||||||
int fd;
|
int fd;
|
||||||
|
@ -30,6 +59,18 @@ struct wlr_backend_state {
|
||||||
int fd;
|
int fd;
|
||||||
dev_t dev;
|
dev_t dev;
|
||||||
|
|
||||||
|
size_t num_crtcs;
|
||||||
|
struct wlr_drm_crtc *crtcs;
|
||||||
|
size_t num_planes;
|
||||||
|
struct wlr_drm_plane *planes;
|
||||||
|
|
||||||
|
size_t num_overlay_planes;
|
||||||
|
struct wlr_drm_plane *overlay_planes;
|
||||||
|
size_t num_primary_planes;
|
||||||
|
struct wlr_drm_plane *primary_planes;
|
||||||
|
size_t num_cursor_planes;
|
||||||
|
struct wlr_drm_plane *cursor_planes;
|
||||||
|
|
||||||
struct wlr_backend *backend;
|
struct wlr_backend *backend;
|
||||||
struct wl_display *display;
|
struct wl_display *display;
|
||||||
struct wl_event_source *drm_event;
|
struct wl_event_source *drm_event;
|
||||||
|
@ -83,6 +124,7 @@ struct wlr_output_state {
|
||||||
bool cleanup;
|
bool cleanup;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool wlr_drm_init_resources(struct wlr_backend_state *drm);
|
||||||
void wlr_drm_output_cleanup(struct wlr_output_state *output, bool restore);
|
void wlr_drm_output_cleanup(struct wlr_output_state *output, bool restore);
|
||||||
|
|
||||||
void wlr_drm_scan_connectors(struct wlr_backend_state *state);
|
void wlr_drm_scan_connectors(struct wlr_backend_state *state);
|
Loading…
Reference in New Issue