[RFC xserver 13/16] modesetting: Use atomic modesetting to configure output/CRTCs
Daniel Stone
daniels at collabora.com
Thu Jun 8 18:43:39 UTC 2017
From: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
Signed-off-by: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
Signed-off-by: Daniel Stone <daniels at collabora.com>
---
hw/xfree86/drivers/modesetting/drmmode_display.c | 504 ++++++++++++++++++-----
hw/xfree86/drivers/modesetting/drmmode_display.h | 41 +-
hw/xfree86/drivers/modesetting/pageflip.c | 105 ++---
3 files changed, 456 insertions(+), 194 deletions(-)
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c
index 432383ecc..958cfc2c7 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.c
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.c
@@ -262,6 +262,205 @@ drmmode_prop_info_free(drmmode_prop_info_ptr info, int num_props)
free(info[i].enum_values);
}
+#ifdef GLAMOR_HAS_DRM_ATOMIC
+static int
+plane_add_prop(drmModeAtomicReq *req, drmmode_crtc_private_ptr drmmode_crtc,
+ enum drmmode_plane_property prop, uint64_t val)
+{
+ drmmode_prop_info_ptr info = &drmmode_crtc->props_plane[prop];
+ int ret;
+
+ if (!info)
+ return -1;
+
+ ret = drmModeAtomicAddProperty(req, drmmode_crtc->plane_id,
+ 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->mode_output->connector_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, 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;
+ drmmode_ptr drmmode = drmmode_crtc->drmmode;
+ int output_count = 0;
+ uint32_t *output_ids = NULL;
+ drmModeModeInfo kmode;
+ int i, ret = 0;
+
+ xf86DrvMsg(crtc->scrn->scrnIndex, X_INFO,
+ "Setting fb %u at (%i, %i)\n", fb_id, x, y);
+
+ if (mode)
+ drmmode_ConvertToKMode(crtc->scrn, &kmode, mode);
+
+#ifdef GLAMOR_HAS_DRM_ATOMIC
+ if (ms->atomic_modeset) {
+ drmModeAtomicReq *req = drmModeAtomicAlloc();
+
+ 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);
+
+ if (ret == 0)
+ ret = drmModeAtomicCommit(ms->fd, req, flags, data);
+
+ drmModeAtomicFree(req);
+ return ret;
+ }
+#endif
+
+ if (!mode)
+ 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->mode_output->connector_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;
+}
+
+
int
drmmode_bo_destroy(drmmode_ptr drmmode, drmmode_bo *bo)
{
@@ -272,17 +471,9 @@ drmmode_bo_destroy(drmmode_ptr drmmode, drmmode_bo *bo)
gbm_bo_destroy(bo->gbm);
bo->gbm = NULL;
}
- if (bo->num_planes > 0) {
- int i;
-
- for (i = 0; i < bo->num_planes; i++) {
- struct drm_gem_close gem_close = { .handle = bo->handles[i] };
- if (!gem_close.handle)
- continue;
- (void) drmIoctl(drmmode->fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
- }
- bo->num_planes = 0;
- }
+ for (i = 0; i < bo->num_planes; i++)
+ close(bo->fds[i]);
+ bo->num_planes = 0;
#endif
if (bo->dumb) {
@@ -347,10 +538,56 @@ drmmode_bo_map(drmmode_ptr drmmode, drmmode_bo *bo)
return bo->dumb->ptr;
}
+int
+drmmode_bo_import(drmmode_ptr drmmode, drmmode_bo *bo,
+ uint32_t *fb_id)
+{
+ if (bo->num_planes > 0) {
+#ifdef GBM_BO_WITH_MODIFIERS
+ int i, ret;
+ uint32_t handles[4];
+
+ memset(handles, 0, sizeof(handles));
+
+ for (i = 0; i < bo->num_planes; i++) {
+ ret = drmPrimeFDToHandle(drmmode->fd, bo->fds[i], &handles[i]);
+ if (ret != 0) //XXX close handles on error
+ return ret;
+ }
+ ret = drmModeAddFB2WithModifiers(drmmode->fd, bo->width, bo->height,
+ bo->format, handles, bo->strides,
+ bo->offsets, bo->modifiers, fb_id,
+ DRM_MODE_FB_MODIFIERS);
+
+ for (i = 0; i < bo->num_planes; i++) {
+ struct drm_gem_close gem_close = { .handle = handles[i] };
+ if (!gem_close.handle)
+ continue;
+ (void) drmIoctl(drmmode->fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
+ }
+
+ return ret;
+#else
+ xf86DrvMsg(drmmode->scrn->scrnIndex, X_ERROR,
+ "Multi-plane and modified buffers are not supported\n");
+#endif
+ } else {
+ return drmModeAddFB(drmmode->fd, bo->width, bo->height,
+ drmmode->scrn->depth, drmmode->scrn->bitsPerPixel,
+ drmmode_bo_get_pitch(bo),
+ drmmode_bo_get_handle(bo), fb_id);
+ }
+
+ return -1;
+}
+
static Bool
drmmode_create_bo(drmmode_ptr drmmode, drmmode_bo *bo,
unsigned width, unsigned height, unsigned bpp)
{
+ bo->width = width;
+ bo->height = height;
+
#ifdef GLAMOR_HAS_GBM
if (drmmode->glamor) {
bo->gbm = gbm_bo_create(drmmode->gbm, width, height,
@@ -786,124 +1023,93 @@ 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;
+ uint32_t flags = 0; //XXX
saved_mode = crtc->mode;
saved_x = crtc->x;
saved_y = crtc->y;
saved_rotation = crtc->rotation;
- if (mode) {
- crtc->mode = *mode;
- crtc->x = x;
- crtc->y = y;
- crtc->rotation = rotation;
- }
-
- output_ids = calloc(sizeof(uint32_t), xf86_config->num_output);
- if (!output_ids) {
- ret = FALSE;
+ if (!mode)
goto done;
- }
- if (mode) {
- for (i = 0; i < xf86_config->num_output; i++) {
- xf86OutputPtr output = xf86_config->output[i];
- drmmode_output_private_ptr drmmode_output;
+ crtc->mode = *mode;
+ crtc->x = x;
+ crtc->y = y;
+ crtc->rotation = rotation;
- if (output->crtc != crtc)
- continue;
+ if (!xf86CrtcRotate(crtc)) {
+ goto done;
+ }
+ crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green,
+ crtc->gamma_blue, crtc->gamma_size);
- drmmode_output = output->driver_private;
- if (drmmode_output->output_id == -1)
- continue;
- output_ids[output_count] =
- drmmode_output->mode_output->connector_id;
- output_count++;
- }
+ fb_id = drmmode->fb_id;
+ if (drmmode_crtc->prime_pixmap) {
+ if (!drmmode->reverse_prime_offload_mode) {
+ msPixmapPrivPtr ppriv =
+ msGetPixmapPriv(drmmode, drmmode_crtc->prime_pixmap);
+ fb_id = ppriv->fb_id;
+ x = 0;
+ } else
+ x = drmmode_crtc->prime_pixmap_x;
+ y = 0;
+ }
+ else if (drmmode_crtc->rotate_fb_id) {
+ fb_id = drmmode_crtc->rotate_fb_id;
+ x = y = 0;
+ }
- if (!xf86CrtcRotate(crtc)) {
+ if (fb_id == 0) {
+ ret = drmmode_bo_import(drmmode, &drmmode->front_bo,
+ &drmmode->fb_id);
+ if (ret < 0) {
+ ErrorF("failed to add fb %d\n", ret);
+ ret = FALSE;
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) {
- msPixmapPrivPtr ppriv =
- msGetPixmapPriv(drmmode, drmmode_crtc->prime_pixmap);
- fb_id = ppriv->fb_id;
- x = 0;
- } else
- x = drmmode_crtc->prime_pixmap_x;
- y = 0;
- }
- else if (drmmode_crtc->rotate_fb_id) {
- fb_id = drmmode_crtc->rotate_fb_id;
- x = y = 0;
- }
-
- 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);
- if (ret < 0) {
- ErrorF("failed to add fb %d\n", ret);
- ret = FALSE;
- goto done;
- }
- fb_id = drmmode->fb_id;
- }
+ }
- if (drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
- fb_id, x, y, output_ids, output_count, &kmode)) {
- xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
- "failed to set mode: %s\n", strerror(errno));
- ret = FALSE;
- goto done;
- } else
- ret = TRUE;
+ 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;
+ goto done;
+ } else
+ ret = TRUE;
- if (crtc->scrn->pScreen)
- xf86CrtcSetScreenSubpixelOrder(crtc->scrn->pScreen);
+ if (crtc->scrn->pScreen)
+ xf86CrtcSetScreenSubpixelOrder(crtc->scrn->pScreen);
- drmmode_crtc->need_modeset = FALSE;
- crtc->funcs->dpms(crtc, DPMSModeOn);
+ drmmode_crtc->need_modeset = FALSE;
+ crtc->funcs->dpms(crtc, DPMSModeOn);
- if (drmmode_crtc->prime_pixmap_back)
- drmmode_InitSharedPixmapFlipping(crtc, drmmode);
+ if (drmmode_crtc->prime_pixmap_back)
+ drmmode_InitSharedPixmapFlipping(crtc, drmmode);
- /* go through all the outputs and force DPMS them back on? */
- for (i = 0; i < xf86_config->num_output; i++) {
- xf86OutputPtr output = xf86_config->output[i];
- drmmode_output_private_ptr drmmode_output;
+ /* go through all the outputs and force DPMS them back on? */
+ 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;
+ if (output->crtc != crtc)
+ continue;
- drmmode_output = output->driver_private;
- if (drmmode_output->output_id == -1)
- continue;
- output->funcs->dpms(output, DPMSModeOn);
- }
+ drmmode_output = output->driver_private;
+ if (drmmode_output->output_id == -1)
+ continue;
+ output->funcs->dpms(output, DPMSModeOn);
}
done:
@@ -915,8 +1121,6 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
} else
crtc->active = TRUE;
- free(output_ids);
-
return ret;
}
@@ -1174,6 +1378,7 @@ drmmode_shadow_allocate(xf86CrtcPtr crtc, int width, int height)
return NULL;
}
+ // XXX
ret = drmModeAddFB(drmmode->fd, width, height, crtc->scrn->depth,
drmmode->kbpp,
drmmode_bo_get_pitch(&drmmode_crtc->rotate_bo),
@@ -1283,9 +1488,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 = {
@@ -1363,6 +1574,8 @@ drmmode_crtc_create_planes(xf86CrtcPtr crtc, int num)
},
[DRMMODE_PLANE_FB_ID] = { .name = "FB_ID", },
[DRMMODE_PLANE_CRTC_ID] = { .name = "CRTC_ID", },
+ [DRMMODE_PLANE_SRC_X] = { .name = "SRC_X", },
+ [DRMMODE_PLANE_SRC_Y] = { .name = "SRC_Y", },
};
drmmode_prop_info_rec tmp_props[DRMMODE_PLANE__COUNT];
@@ -1448,17 +1661,39 @@ 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
/* Hide any cursors which may be active from previous users */
drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 0, 0, 0);
@@ -1468,10 +1703,6 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, MS_LOGLEVEL_DEBUG,
"Allocated crtc nr. %d to this screen.\n", num);
-#ifdef GLAMOR_HAS_DRM_ATOMIC
- drmmode_crtc_create_planes(crtc, num);
-#endif
-
return 1;
}
@@ -1633,13 +1864,28 @@ drmmode_output_get_modes(xf86OutputPtr output)
drmmode_ptr drmmode = drmmode_output->drmmode;
int i;
DisplayModePtr Modes = NULL, Mode;
- drmModePropertyPtr props;
xf86MonPtr mon = NULL;
+#ifdef GLAMOR_HAS_DRM_ATOMIC
+ drmModeObjectPropertiesPtr props;
+ uint32_t id;
+#else
+ drmModePropertyPtr props;
+#endif
if (!koutput)
return NULL;
+#ifdef GLAMOR_HAS_DRM_ATOMIC
+ props = drmModeObjectGetProperties(drmmode->fd,
+ drmmode_output->mode_output->connector_id,
+ DRM_MODE_OBJECT_CONNECTOR);
+ id = drmmode_prop_get_value(&drmmode_output->props_connector[DRMMODE_CONNECTOR_EDID],
+ props, 0);
+ if (id)
+ drmmode_output->edid_blob = drmModeGetPropertyBlob(drmmode->fd, id);
+#else
/* look for an EDID property */
+
for (i = 0; i < koutput->count_props; i++) {
props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
if (props && (props->flags & DRM_MODE_PROP_BLOB)) {
@@ -1653,6 +1899,7 @@ drmmode_output_get_modes(xf86OutputPtr output)
drmModeFreeProperty(props);
}
}
+#endif
if (drmmode_output->edid_blob) {
mon = xf86InterpretEDID(output->scrn->scrnIndex,
@@ -1706,13 +1953,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;
@@ -2032,25 +2285,35 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r
drmModeConnectorPtr koutput;
drmModeEncoderPtr *kencoders = NULL;
drmmode_output_private_ptr drmmode_output;
- drmModePropertyPtr props;
char name[32];
int i;
drmModePropertyBlobPtr path_blob = NULL;
+ drmModePropertyPtr path_props;
const char *s;
+#ifdef GLAMOR_HAS_DRM_ATOMIC
+ drmModeObjectPropertiesPtr props;
+ static const drmmode_prop_info_rec connector_props[] = {
+ [DRMMODE_CONNECTOR_PATH] = { .name = "PATH" },
+ [DRMMODE_CONNECTOR_EDID] = { .name = "EDID" },
+ [DRMMODE_CONNECTOR_DPMS] = { .name = "DPMS" },
+ [DRMMODE_CONNECTOR_CRTC_ID] = { .name = "CRTC_ID", },
+ };
+#endif
+
koutput =
drmModeGetConnector(drmmode->fd, mode_res->connectors[num]);
if (!koutput)
return 0;
for (i = 0; i < koutput->count_props; i++) {
- props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
- if (props && (props->flags & DRM_MODE_PROP_BLOB)) {
- if (!strcmp(props->name, "PATH")) {
+ path_props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
+ if (path_props && (path_props->flags & DRM_MODE_PROP_BLOB)) {
+ if (!strcmp(path_props->name, "PATH")) {
path_blob = drmModeGetPropertyBlob(drmmode->fd, koutput->prop_values[i]);
- drmModeFreeProperty(props);
+ drmModeFreeProperty(path_props);
break;
}
- drmModeFreeProperty(props);
+ drmModeFreeProperty(path_props);
}
}
@@ -2129,6 +2392,17 @@ 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->mode_output->connector_id,
+ DRM_MODE_OBJECT_CONNECTOR);
+ drmmode_prop_info_update(drmmode, drmmode_output->props_connector,
+ DRMMODE_CONNECTOR__COUNT, props);
+#else
for (i = 0; i < koutput->count_props; i++) {
props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
if (props && (props->flags & DRM_MODE_PROP_ENUM)) {
@@ -2140,6 +2414,7 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r
drmModeFreeProperty(props);
}
}
+#endif
if (dynamic)
output->randr_output = RROutputCreate(xf86ScrnToScreen(pScrn), output->name, strlen(output->name), output);
@@ -2431,6 +2706,7 @@ drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode, Bool set_hw)
/* Skip disabled CRTCs */
if (!crtc->enabled) {
if (set_hw) {
+ // XXX Should we use the atomic API?
drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
0, 0, 0, NULL, 0, NULL);
}
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.h b/hw/xfree86/drivers/modesetting/drmmode_display.h
index 32d335d05..cb7e27d1e 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.h
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.h
@@ -40,6 +40,8 @@ enum drmmode_plane_property {
DRMMODE_PLANE_TYPE = 0,
DRMMODE_PLANE_FB_ID,
DRMMODE_PLANE_CRTC_ID,
+ DRMMODE_PLANE_SRC_X,
+ DRMMODE_PLANE_SRC_Y,
DRMMODE_PLANE__COUNT
};
@@ -50,12 +52,32 @@ enum drmmode_plane_type {
DRMMODE_PLANE_TYPE__COUNT
};
+enum drmmode_connector_property {
+ DRMMODE_CONNECTOR_PATH,
+ DRMMODE_CONNECTOR_EDID,
+ DRMMODE_CONNECTOR_DPMS,
+ 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; // XXX use everywhere?
+ uint32_t height;
struct dumb_bo *dumb;
#ifdef GLAMOR_HAS_GBM
struct gbm_bo *gbm;
int num_planes;
- uint32_t handles[4];
+ int fds[4];
+ uint32_t format;
+ uint32_t strides[4];
+ uint32_t offsets[4];
+ uint64_t modifiers[4];
#endif
} drmmode_bo;
@@ -115,6 +137,12 @@ typedef struct {
} 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;
uint32_t vblank_pipe;
@@ -123,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;
@@ -146,6 +176,7 @@ typedef struct {
/** @} */
Bool need_modeset;
+ struct xorg_list mode_list;
Bool enable_flipping;
Bool flipping_active;
@@ -166,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;
@@ -195,6 +228,8 @@ extern DevPrivateKeyRec msPixmapPrivateKeyRec;
#define msGetPixmapPriv(drmmode, p) ((msPixmapPrivPtr)dixGetPrivateAddr(&(p)->devPrivates, &(drmmode)->pixmapPrivateKeyRec))
+int drmmode_bo_import(drmmode_ptr drmmode, drmmode_bo *bo,
+ uint32_t *fb_id);
int drmmode_bo_destroy(drmmode_ptr drmmode, drmmode_bo *bo);
uint32_t drmmode_bo_get_pitch(drmmode_bo *bo);
uint32_t drmmode_bo_get_handle(drmmode_bo *bo);
@@ -228,6 +263,10 @@ void drmmode_get_default_bpp(ScrnInfoPtr pScrn, drmmode_ptr drmmmode,
int *depth, int *bpp);
void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode);
+
+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
#define DRM_CAP_DUMB_PREFERRED_DEPTH 3
#endif
diff --git a/hw/xfree86/drivers/modesetting/pageflip.c b/hw/xfree86/drivers/modesetting/pageflip.c
index 546de8758..1f795138c 100644
--- a/hw/xfree86/drivers/modesetting/pageflip.c
+++ b/hw/xfree86/drivers/modesetting/pageflip.c
@@ -24,6 +24,7 @@
#include "dix-config.h"
#endif
+#include <unistd.h>
#include <xserver_poll.h>
#include <xf86drm.h>
@@ -159,49 +160,17 @@ ms_pageflip_abort(void *data)
ms_pageflip_free(flip);
}
-#ifdef GLAMOR_HAS_DRM_ATOMIC
-static int
-plane_add_prop(drmModeAtomicReq *req, drmmode_crtc_private_ptr drmmode_crtc,
- enum drmmode_plane_property prop, uint64_t val)
-{
- drmmode_prop_info_ptr info = &drmmode_crtc->props_plane[prop];
- int ret;
-
- if (!info)
- return -1;
-
- ret = drmModeAtomicAddProperty(req, drmmode_crtc->plane_id,
- info->prop_id, val);
- return (ret <= 0) ? -1 : 0;
-}
-#endif
-
static Bool
-do_queue_flip_on_crtc(modesettingPtr ms, drmmode_crtc_private_ptr drmmode_crtc,
+do_queue_flip_on_crtc(modesettingPtr ms, xf86CrtcPtr crtc,
uint32_t flags, uint32_t seq)
{
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
#ifdef GLAMOR_HAS_DRM_ATOMIC
if (ms->atomic_modeset) {
- drmModeAtomicReq *req = drmModeAtomicAlloc();
- int ret = 0;
-
- if (!req)
- return 1;
-
- /* XXX CRTC and connector properties are set non-atomically */
-
- ret |= plane_add_prop(req, drmmode_crtc, DRMMODE_PLANE_FB_ID,
- ms->drmmode.fb_id);
- ret |= plane_add_prop(req, drmmode_crtc, DRMMODE_PLANE_CRTC_ID,
- drmmode_crtc->mode_crtc->crtc_id);
-
flags |= DRM_MODE_ATOMIC_NONBLOCK;
- if (ret == 0)
- ret = drmModeAtomicCommit(ms->fd, req, flags,
- (void *) (uintptr_t) seq);
-
- drmModeAtomicFree(req);
- return ret;
+ return drmmode_crtc_set_fb(crtc, NULL, ms->drmmode.fb_id, 0, 0, flags,
+ (void *) (uintptr_t) seq);
}
#endif
@@ -244,7 +213,7 @@ queue_flip_on_crtc(ScreenPtr screen, xf86CrtcPtr crtc,
/* take a reference on flipdata for use in flip */
flipdata->flip_count++;
- while (do_queue_flip_on_crtc(ms, drmmode_crtc, flags, seq)) {
+ while (do_queue_flip_on_crtc(ms, crtc, flags, seq)) {
err = errno;
/* We may have failed because the event queue was full. Flush it
* and retry. If there was nothing to flush, then we failed for
@@ -284,39 +253,34 @@ ms_do_pageflip(ScreenPtr screen,
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
drmmode_bo new_front_bo;
uint32_t flags;
- int i, fds[4];
- uint32_t format;
- uint32_t strides[4];
- uint32_t offsets[4];
- uint64_t modifier, modifiers[4];
+ int i;
+ uint64_t modifier;
struct ms_flipdata *flipdata;
glamor_block_handler(screen);
new_front_bo.num_planes = 0;
new_front_bo.gbm = NULL;
for (i = 0; i < 4; i++) {
- new_front_bo.handles[i] = 0;
- strides[i] = 0;
- offsets[i] = 0;
- modifiers[i] = 0;
+ new_front_bo.strides[i] = 0;
+ new_front_bo.offsets[i] = 0;
+ new_front_bo.modifiers[i] = 0;
}
#ifdef GBM_BO_WITH_MODIFIERS
- new_front_bo.num_planes = glamor_dmabuf_from_pixmap(new_front, fds,
- strides, offsets,
- &format, &modifier);
+ new_front_bo.num_planes = glamor_dmabuf_from_pixmap(new_front,
+ new_front_bo.fds,
+ new_front_bo.strides,
+ new_front_bo.offsets,
+ &new_front_bo.format,
+ &modifier);
for (i = 0; i < new_front_bo.num_planes; i++) {
- modifiers[i] = modifier;
- if (drmPrimeFDToHandle(ms->fd, fds[i], &new_front_bo.handles[i]) != 0) {
- drmmode_bo_destroy(&ms->drmmode, &new_front_bo);
- return FALSE;
- }
+ new_front_bo.modifiers[i] = modifier;
+ new_front_bo.fds[i] = dup(new_front_bo.fds[i]);
}
#endif
- if (new_front_bo.num_planes == 0) {
+ if (new_front_bo.num_planes == 0)
new_front_bo.gbm = glamor_gbm_bo_from_pixmap(screen, new_front);
- }
new_front_bo.dumb = NULL;
if (!new_front_bo.gbm && new_front_bo.num_planes == 0) {
@@ -350,28 +314,11 @@ ms_do_pageflip(ScreenPtr screen,
/* Create a new handle for the back buffer */
flipdata->old_fb_id = ms->drmmode.fb_id;
- if (new_front_bo.num_planes > 0 || modifier != 0) {
- // XXX ifdef
-#ifdef GBM_BO_WITH_MODIFIERS
- if (drmModeAddFB2WithModifiers(ms->fd, scrn->virtualX, scrn->virtualY,
- format, new_front_bo.handles, strides,
- offsets, modifiers, &ms->drmmode.fb_id,
- DRM_MODE_FB_MODIFIERS)) {
-
- goto error_out;
- }
-#else
- xf86DrvMsg(scrn->scrnIndex, X_ERROR,
- "Multi-plane and modified buffers are not supported\n");
-#endif
- } else {
- if (drmModeAddFB(ms->fd, scrn->virtualX, scrn->virtualY,
- scrn->depth, scrn->bitsPerPixel,
- drmmode_bo_get_pitch(&new_front_bo),
- drmmode_bo_get_handle(&new_front_bo), &ms->drmmode.fb_id)) {
- goto error_out;
- }
- }
+ new_front_bo.width = new_front->drawable.width;
+ new_front_bo.height = new_front->drawable.height;
+ if (drmmode_bo_import(&ms->drmmode, &new_front_bo,
+ &ms->drmmode.fb_id))
+ goto error_out;
flags = DRM_MODE_PAGE_FLIP_EVENT;
if (async)
--
2.13.0
More information about the xorg-devel
mailing list