modesetting: Use atomic modesetting to configure output/CRTCs

To make sure we also use the same primary plane and to avoid
mixing uses of two APIs, it is better to always use the atomic
modesetting API when possible.

v2: Don't use mode_output->connector_id

Signed-off-by: Louis-Francis Ratté-Boulianne <lfrb@collabora.com>
Reviewed-by: Daniel Stone <daniels@collabora.com>
Acked-by: Keith Packard <keithp@keithp.com>
Reviewed-by: Adam Jackson <ajax@redhat.com>
This commit is contained in:
Louis-Francis Ratté-Boulianne 2018-02-28 01:19:39 +00:00 committed by Adam Jackson
parent 2f807c2324
commit 9817c14f6a
4 changed files with 252 additions and 45 deletions

View File

@ -267,16 +267,100 @@ plane_add_prop(drmModeAtomicReq *req, drmmode_crtc_private_ptr drmmode_crtc,
info->prop_id, val);
return (ret <= 0) ? -1 : 0;
}
static int
crtc_add_prop(drmModeAtomicReq *req, drmmode_crtc_private_ptr drmmode_crtc,
enum drmmode_crtc_property prop, uint64_t val)
{
drmmode_prop_info_ptr info = &drmmode_crtc->props[prop];
int ret;
if (!info)
return -1;
ret = drmModeAtomicAddProperty(req, drmmode_crtc->mode_crtc->crtc_id,
info->prop_id, val);
return (ret <= 0) ? -1 : 0;
}
static int
connector_add_prop(drmModeAtomicReq *req, drmmode_output_private_ptr drmmode_output,
enum drmmode_connector_property prop, uint64_t val)
{
drmmode_prop_info_ptr info = &drmmode_output->props_connector[prop];
int ret;
if (!info)
return -1;
ret = drmModeAtomicAddProperty(req, drmmode_output->output_id,
info->prop_id, val);
return (ret <= 0) ? -1 : 0;
}
static int
drmmode_CompareKModes(drmModeModeInfo * kmode, drmModeModeInfo * other)
{
return memcmp(kmode, other, sizeof(*kmode));
}
static int
drm_mode_ensure_blob(xf86CrtcPtr crtc, drmModeModeInfo mode_info)
{
modesettingPtr ms = modesettingPTR(crtc->scrn);
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
drmmode_mode_ptr mode;
int ret;
if (drmmode_crtc->current_mode &&
drmmode_CompareKModes(&drmmode_crtc->current_mode->mode_info, &mode_info) == 0)
return 0;
mode = calloc(sizeof(drmmode_mode_rec), 1);
if (!mode)
return -1;
mode->mode_info = mode_info;
ret = drmModeCreatePropertyBlob(ms->fd,
&mode->mode_info,
sizeof(mode->mode_info),
&mode->blob_id);
drmmode_crtc->current_mode = mode;
xorg_list_add(&mode->entry, &drmmode_crtc->mode_list);
return ret;
}
static void
drm_mode_destroy(xf86CrtcPtr crtc, drmmode_mode_ptr mode)
{
modesettingPtr ms = modesettingPTR(crtc->scrn);
if (mode->blob_id)
drmModeDestroyPropertyBlob(ms->fd, mode->blob_id);
xorg_list_del(&mode->entry);
free(mode);
}
#endif
static void
drmmode_ConvertToKMode(ScrnInfoPtr scrn,
drmModeModeInfo * kmode, DisplayModePtr mode);
int
drmmode_crtc_set_fb(xf86CrtcPtr crtc, uint32_t fb_id,
drmmode_crtc_set_fb(xf86CrtcPtr crtc, DisplayModePtr mode, uint32_t fb_id,
int x, int y, uint32_t flags, void *data)
{
modesettingPtr ms = modesettingPTR(crtc->scrn);
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
int ret = 0;
drmmode_ptr drmmode = drmmode_crtc->drmmode;
int output_count = 0;
uint32_t *output_ids = NULL;
drmModeModeInfo kmode;
int i, ret = 0;
if (mode)
drmmode_ConvertToKMode(crtc->scrn, &kmode, mode);
#ifdef GLAMOR_HAS_DRM_ATOMIC
if (ms->atomic_modeset) {
@ -285,12 +369,56 @@ drmmode_crtc_set_fb(xf86CrtcPtr crtc, uint32_t fb_id,
if (!req)
return 1;
if (mode) {
ret = drm_mode_ensure_blob(crtc, kmode);
for (i = 0; i < xf86_config->num_output; i++) {
xf86OutputPtr output = xf86_config->output[i];
drmmode_output_private_ptr drmmode_output;
if (output->crtc != crtc)
continue;
drmmode_output = output->driver_private;
if (drmmode_output->output_id == -1)
continue;
if (drmmode_output->dpms == DPMSModeOn) {
ret |= crtc_add_prop(req, drmmode_crtc,
DRMMODE_CRTC_ACTIVE, 1);
ret |= crtc_add_prop(req, drmmode_crtc,
DRMMODE_CRTC_MODE_ID,
drmmode_crtc->current_mode->blob_id);
ret |= connector_add_prop(req, drmmode_output,
DRMMODE_CONNECTOR_CRTC_ID,
drmmode_crtc->mode_crtc->crtc_id);
} else {
ret |= crtc_add_prop(req, drmmode_crtc,
DRMMODE_CRTC_ACTIVE, 0);
ret |= crtc_add_prop(req, drmmode_crtc,
DRMMODE_CRTC_MODE_ID, 0);
ret |= connector_add_prop(req, drmmode_output,
DRMMODE_CONNECTOR_CRTC_ID, 0);
}
}
}
ret |= plane_add_prop(req, drmmode_crtc, DRMMODE_PLANE_FB_ID,
fb_id);
ret |= plane_add_prop(req, drmmode_crtc, DRMMODE_PLANE_CRTC_ID,
drmmode_crtc->mode_crtc->crtc_id);
ret |= plane_add_prop(req, drmmode_crtc, DRMMODE_PLANE_SRC_X, x);
ret |= plane_add_prop(req, drmmode_crtc, DRMMODE_PLANE_SRC_Y, y);
ret |= plane_add_prop(req, drmmode_crtc, DRMMODE_PLANE_SRC_X, x << 16);
ret |= plane_add_prop(req, drmmode_crtc, DRMMODE_PLANE_SRC_Y, y << 16);
ret |= plane_add_prop(req, drmmode_crtc, DRMMODE_PLANE_SRC_W,
drmmode->front_bo.width << 16);
ret |= plane_add_prop(req, drmmode_crtc, DRMMODE_PLANE_SRC_H,
drmmode->front_bo.height << 16);
ret |= plane_add_prop(req, drmmode_crtc, DRMMODE_PLANE_CRTC_X, 0);
ret |= plane_add_prop(req, drmmode_crtc, DRMMODE_PLANE_CRTC_Y, 0);
ret |= plane_add_prop(req, drmmode_crtc, DRMMODE_PLANE_CRTC_W,
drmmode->front_bo.width);
ret |= plane_add_prop(req, drmmode_crtc, DRMMODE_PLANE_CRTC_H,
drmmode->front_bo.height);
if (ret == 0)
ret = drmModeAtomicCommit(ms->fd, req, flags, data);
@ -300,7 +428,29 @@ drmmode_crtc_set_fb(xf86CrtcPtr crtc, uint32_t fb_id,
}
#endif
return 0;
output_ids = calloc(sizeof(uint32_t), xf86_config->num_output);
if (!output_ids)
return -1;
for (i = 0; i < xf86_config->num_output; i++) {
xf86OutputPtr output = xf86_config->output[i];
drmmode_output_private_ptr drmmode_output;
if (output->crtc != crtc)
continue;
drmmode_output = output->driver_private;
if (drmmode_output->output_id == -1)
continue;
output_ids[output_count] = drmmode_output->output_id;
output_count++;
}
ret = drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
fb_id, x, y, output_ids, output_count, &kmode);
free(output_ids);
return ret;
}
@ -858,23 +1008,16 @@ static Bool
drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
Rotation rotation, int x, int y)
{
ScrnInfoPtr pScrn = crtc->scrn;
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
drmmode_ptr drmmode = drmmode_crtc->drmmode;
int saved_x, saved_y;
Rotation saved_rotation;
DisplayModeRec saved_mode;
uint32_t *output_ids = NULL;
int output_count = 0;
Bool ret = TRUE;
int i;
uint32_t fb_id = 0;
drmModeModeInfo kmode;
output_ids = calloc(sizeof(uint32_t), xf86_config->num_output);
if (!output_ids)
return FALSE;
uint32_t flags = 0;
saved_mode = crtc->mode;
saved_x = crtc->x;
@ -887,29 +1030,13 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
crtc->y = y;
crtc->rotation = rotation;
for (i = 0; i < xf86_config->num_output; i++) {
xf86OutputPtr output = xf86_config->output[i];
drmmode_output_private_ptr drmmode_output;
if (output->crtc != crtc)
continue;
drmmode_output = output->driver_private;
if (drmmode_output->output_id == -1)
continue;
output_ids[output_count] =
drmmode_output->mode_output->connector_id;
output_count++;
}
if (!xf86CrtcRotate(crtc)) {
goto done;
}
crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green,
crtc->gamma_blue, crtc->gamma_size);
drmmode_ConvertToKMode(crtc->scrn, &kmode, mode);
fb_id = drmmode->fb_id;
if (drmmode_crtc->prime_pixmap) {
if (!drmmode->reverse_prime_offload_mode) {
@ -927,12 +1054,8 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
}
if (fb_id == 0) {
ret = drmModeAddFB(drmmode->fd,
pScrn->virtualX, pScrn->virtualY,
pScrn->depth, drmmode->kbpp,
drmmode_bo_get_pitch(&drmmode->front_bo),
drmmode_bo_get_handle(&drmmode->front_bo),
&drmmode->fb_id);
ret = drmmode_bo_import(drmmode, &drmmode->front_bo,
&drmmode->fb_id);
if (ret < 0) {
ErrorF("failed to add fb %d\n", ret);
ret = FALSE;
@ -941,8 +1064,8 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
fb_id = drmmode->fb_id;
}
if (drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
fb_id, x, y, output_ids, output_count, &kmode)) {
flags |= DRM_MODE_ATOMIC_ALLOW_MODESET;
if (drmmode_crtc_set_fb(crtc, mode, fb_id, x, y, flags, NULL)) {
xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
"failed to set mode: %s\n", strerror(errno));
ret = FALSE;
@ -983,8 +1106,6 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
} else
crtc->active = TRUE;
free(output_ids);
return ret;
}
@ -1355,9 +1476,15 @@ drmmode_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
static void
drmmode_crtc_destroy(xf86CrtcPtr crtc)
{
#ifdef GLAMOR_HAS_DRM_ATOMIC
drmmode_mode_ptr iterator, next;
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
drmmode_prop_info_free(drmmode_crtc->props_plane, DRMMODE_PLANE__COUNT);
xorg_list_for_each_entry_safe(iterator, next, &drmmode_crtc->mode_list, entry) {
drm_mode_destroy(crtc, iterator);
}
#endif
}
static const xf86CrtcFuncsRec drmmode_crtc_funcs = {
@ -1437,6 +1564,12 @@ drmmode_crtc_create_planes(xf86CrtcPtr crtc, int num)
[DRMMODE_PLANE_CRTC_ID] = { .name = "CRTC_ID", },
[DRMMODE_PLANE_SRC_X] = { .name = "SRC_X", },
[DRMMODE_PLANE_SRC_Y] = { .name = "SRC_Y", },
[DRMMODE_PLANE_SRC_W] = { .name = "SRC_W", },
[DRMMODE_PLANE_SRC_H] = { .name = "SRC_H", },
[DRMMODE_PLANE_CRTC_X] = { .name = "CRTC_X", },
[DRMMODE_PLANE_CRTC_Y] = { .name = "CRTC_Y", },
[DRMMODE_PLANE_CRTC_W] = { .name = "CRTC_W", },
[DRMMODE_PLANE_CRTC_H] = { .name = "CRTC_H", },
};
drmmode_prop_info_rec tmp_props[DRMMODE_PLANE__COUNT];
@ -1524,19 +1657,37 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res
xf86CrtcPtr crtc;
drmmode_crtc_private_ptr drmmode_crtc;
modesettingEntPtr ms_ent = ms_ent_priv(pScrn);
#ifdef GLAMOR_HAS_DRM_ATOMIC
drmModeObjectPropertiesPtr props;
static const drmmode_prop_info_rec crtc_props[] = {
[DRMMODE_CRTC_ACTIVE] = { .name = "ACTIVE" },
[DRMMODE_CRTC_MODE_ID] = { .name = "MODE_ID" },
};
#endif
crtc = xf86CrtcCreate(pScrn, &drmmode_crtc_funcs);
if (crtc == NULL)
return 0;
drmmode_crtc = xnfcalloc(sizeof(drmmode_crtc_private_rec), 1);
crtc->driver_private = drmmode_crtc;
drmmode_crtc->mode_crtc =
drmModeGetCrtc(drmmode->fd, mode_res->crtcs[num]);
drmmode_crtc->drmmode = drmmode;
drmmode_crtc->vblank_pipe = drmmode_crtc_vblank_pipe(num);
crtc->driver_private = drmmode_crtc;
xorg_list_init(&drmmode_crtc->mode_list);
#ifdef GLAMOR_HAS_DRM_ATOMIC
props = drmModeObjectGetProperties(drmmode->fd, mode_res->crtcs[num],
DRM_MODE_OBJECT_CRTC);
if (!props || !drmmode_prop_info_copy(drmmode_crtc->props, crtc_props,
DRMMODE_CRTC__COUNT, 0)) {
xf86CrtcDestroy(crtc);
return 0;
}
drmmode_prop_info_update(drmmode, drmmode_crtc->props,
DRMMODE_CRTC__COUNT, props);
drmModeFreeObjectProperties(props);
drmmode_crtc_create_planes(crtc, num);
#endif
@ -1680,6 +1831,7 @@ koutput_get_prop_idx(int fd, drmModeConnectorPtr koutput,
return idx;
}
#ifndef GLAMOR_HAS_DRM_ATOMIC
static int
koutput_get_prop_id(int fd, drmModeConnectorPtr koutput,
int type, const char *name)
@ -1688,6 +1840,7 @@ koutput_get_prop_id(int fd, drmModeConnectorPtr koutput,
return (idx > -1) ? koutput->props[idx] : -1;
}
#endif
static drmModePropertyBlobPtr
koutput_get_prop_blob(int fd, drmModeConnectorPtr koutput, const char *name)
@ -1859,13 +2012,19 @@ drmmode_output_dpms(xf86OutputPtr output, int mode)
drmmode_output_private_ptr drmmode_output = output->driver_private;
xf86CrtcPtr crtc = output->crtc;
drmModeConnectorPtr koutput = drmmode_output->mode_output;
#ifndef GLAMOR_HAS_DRM_ATOMIC
drmmode_ptr drmmode = drmmode_output->drmmode;
#endif
if (!koutput)
return;
#ifdef GLAMOR_HAS_DRM_ATOMIC
drmmode_output->dpms = mode;
#else
drmModeConnectorSetProperty(drmmode->fd, koutput->connector_id,
drmmode_output->dpms_enum_id, mode);
#endif
if (crtc) {
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
@ -2214,6 +2373,13 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r
Bool nonDesktop = FALSE;
drmModePropertyBlobPtr path_blob = NULL;
const char *s;
#ifdef GLAMOR_HAS_DRM_ATOMIC
drmModeObjectPropertiesPtr props;
static const drmmode_prop_info_rec connector_props[] = {
[DRMMODE_CONNECTOR_CRTC_ID] = { .name = "CRTC_ID", },
};
#endif
koutput =
drmModeGetConnector(drmmode->fd, mode_res->connectors[num]);
if (!koutput)
@ -2301,8 +2467,20 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r
/* work out the possible clones later */
output->possible_clones = 0;
#ifdef GLAMOR_HAS_DRM_ATOMIC
if (!drmmode_prop_info_copy(drmmode_output->props_connector, connector_props,
DRMMODE_CONNECTOR__COUNT, 0)) {
goto out_free_encoders;
}
props = drmModeObjectGetProperties(drmmode->fd,
drmmode_output->output_id,
DRM_MODE_OBJECT_CONNECTOR);
drmmode_prop_info_update(drmmode, drmmode_output->props_connector,
DRMMODE_CONNECTOR__COUNT, props);
#else
drmmode_output->dpms_enum_id =
koutput_get_prop_id(drmmode->fd, koutput, DRM_MODE_PROP_ENUM, "DPMS");
#endif
if (dynamic)
output->randr_output = RROutputCreate(xf86ScrnToScreen(pScrn), output->name, strlen(output->name), output);

View File

@ -42,6 +42,12 @@ enum drmmode_plane_property {
DRMMODE_PLANE_CRTC_ID,
DRMMODE_PLANE_SRC_X,
DRMMODE_PLANE_SRC_Y,
DRMMODE_PLANE_SRC_W,
DRMMODE_PLANE_SRC_H,
DRMMODE_PLANE_CRTC_X,
DRMMODE_PLANE_CRTC_Y,
DRMMODE_PLANE_CRTC_W,
DRMMODE_PLANE_CRTC_H,
DRMMODE_PLANE__COUNT
};
@ -52,6 +58,17 @@ enum drmmode_plane_type {
DRMMODE_PLANE_TYPE__COUNT
};
enum drmmode_connector_property {
DRMMODE_CONNECTOR_CRTC_ID,
DRMMODE_CONNECTOR__COUNT
};
enum drmmode_crtc_property {
DRMMODE_CRTC_ACTIVE,
DRMMODE_CRTC_MODE_ID,
DRMMODE_CRTC__COUNT
};
typedef struct {
uint32_t width;
uint32_t height;
@ -119,6 +136,12 @@ typedef struct {
drmmode_prop_enum_info_rec *enum_values;
} drmmode_prop_info_rec, *drmmode_prop_info_ptr;
typedef struct {
drmModeModeInfo mode_info;
uint32_t blob_id;
struct xorg_list entry;
} drmmode_mode_rec, *drmmode_mode_ptr;
typedef struct {
drmmode_ptr drmmode;
drmModeCrtcPtr mode_crtc;
@ -128,8 +151,10 @@ typedef struct {
Bool cursor_up;
uint16_t lut_r[256], lut_g[256], lut_b[256];
drmmode_prop_info_rec props[DRMMODE_CRTC__COUNT];
drmmode_prop_info_rec props_plane[DRMMODE_PLANE__COUNT];
uint32_t plane_id;
drmmode_mode_ptr current_mode;
drmmode_bo rotate_bo;
unsigned rotate_fb_id;
@ -151,6 +176,7 @@ typedef struct {
/** @} */
Bool need_modeset;
struct xorg_list mode_list;
Bool enable_flipping;
Bool flipping_active;
@ -171,8 +197,10 @@ typedef struct {
drmModePropertyBlobPtr edid_blob;
drmModePropertyBlobPtr tile_blob;
int dpms_enum_id;
int dpms;
int num_props;
drmmode_prop_ptr props;
drmmode_prop_info_rec props_connector[DRMMODE_CONNECTOR__COUNT];
int enc_mask;
int enc_clone_mask;
} drmmode_output_private_rec, *drmmode_output_private_ptr;
@ -242,7 +270,7 @@ void drmmode_get_default_bpp(ScrnInfoPtr pScrn, drmmode_ptr drmmmode,
void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode);
int drmmode_crtc_set_fb(xf86CrtcPtr crtc, uint32_t fb_id,
int drmmode_crtc_set_fb(xf86CrtcPtr crtc, DisplayModePtr mode, uint32_t fb_id,
int x, int y, uint32_t flags, void *data);
#ifndef DRM_CAP_DUMB_PREFERRED_DEPTH

View File

@ -168,7 +168,7 @@ do_queue_flip_on_crtc(modesettingPtr ms, xf86CrtcPtr crtc,
#ifdef GLAMOR_HAS_DRM_ATOMIC
if (ms->atomic_modeset) {
flags |= DRM_MODE_ATOMIC_NONBLOCK;
return drmmode_crtc_set_fb(crtc, ms->drmmode.fb_id, 0, 0, flags,
return drmmode_crtc_set_fb(crtc, NULL, ms->drmmode.fb_id, 0, 0, flags,
(void *) (uintptr_t) seq);
}
#endif

View File

@ -248,7 +248,8 @@ ms_present_check_flip(RRCrtcPtr crtc,
return FALSE;
/* Check stride, can't change that on flip */
if (pixmap->devKind != drmmode_bo_get_pitch(&ms->drmmode.front_bo))
if (!ms->atomic_modeset &&
pixmap->devKind != drmmode_bo_get_pitch(&ms->drmmode.front_bo))
return FALSE;
/* Make sure there's a bo we can get to */