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 v3: Only use the new properties cache for atomic modesetting as to not conflict with the newish properties fetcher/helper Signed-off-by: Louis-Francis Ratté-Boulianne <l...@collabora.com> Reviewed-by: Daniel Stone <dani...@collabora.com> --- hw/xfree86/drivers/modesetting/drmmode_display.c | 264 +++++++++++++++++++---- hw/xfree86/drivers/modesetting/drmmode_display.h | 32 ++- hw/xfree86/drivers/modesetting/pageflip.c | 2 +- hw/xfree86/drivers/modesetting/present.c | 3 +- 4 files changed, 256 insertions(+), 45 deletions(-) diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c index b8393b1ea..30e3b05db 100644 --- a/hw/xfree86/drivers/modesetting/drmmode_display.c +++ b/hw/xfree86/drivers/modesetting/drmmode_display.c @@ -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; } @@ -857,23 +1007,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; @@ -886,29 +1029,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) { @@ -926,12 +1053,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; @@ -940,8 +1063,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; @@ -982,8 +1105,6 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, } else crtc->active = TRUE; - free(output_ids); - return ret; } @@ -1354,9 +1475,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 = { @@ -1434,6 +1561,14 @@ 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_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]; @@ -1521,19 +1656,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 @@ -1677,6 +1830,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) @@ -1685,6 +1839,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) @@ -1856,13 +2011,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; @@ -2187,6 +2348,13 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r int i; 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) @@ -2269,8 +2437,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); diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.h b/hw/xfree86/drivers/modesetting/drmmode_display.h index 1641706b6..fcb13a491 100644 --- a/hw/xfree86/drivers/modesetting/drmmode_display.h +++ b/hw/xfree86/drivers/modesetting/drmmode_display.h @@ -40,6 +40,14 @@ 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_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 }; @@ -50,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; @@ -114,6 +133,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; @@ -123,8 +148,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 +173,7 @@ typedef struct { /** @} */ Bool need_modeset; + struct xorg_list mode_list; Bool enable_flipping; Bool flipping_active; @@ -166,8 +194,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; @@ -231,7 +261,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 diff --git a/hw/xfree86/drivers/modesetting/pageflip.c b/hw/xfree86/drivers/modesetting/pageflip.c index 027ebfe42..26738f928 100644 --- a/hw/xfree86/drivers/modesetting/pageflip.c +++ b/hw/xfree86/drivers/modesetting/pageflip.c @@ -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 diff --git a/hw/xfree86/drivers/modesetting/present.c b/hw/xfree86/drivers/modesetting/present.c index c01be3486..4a01d19ea 100644 --- a/hw/xfree86/drivers/modesetting/present.c +++ b/hw/xfree86/drivers/modesetting/present.c @@ -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 */ -- 2.14.3 _______________________________________________ xorg-devel@lists.x.org: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: https://lists.x.org/mailman/listinfo/xorg-devel