diff options
author | Mario Kleiner <mario.kleiner.de@gmail.com> | 2014-06-23 11:13:57 +0200 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2014-08-11 08:38:34 +1000 |
commit | fcf91a275e96f14e49a93dc3f8dd6798cf7d98f3 (patch) | |
tree | 6b9139e385482ac608f07c9934f902cc0411f71b | |
parent | 29572e44c24613be9dec0c98ff2731e46ce6203b (diff) |
dri2: Fix drmWaitVblank on multi-x-screen configs.
Old mapping of xf86Crtc -> display head index was
too simple and only worked on a single x-screen config.
Introduce a new helper function drmmode_hw_head_index()
which returns proper mapping also for multi x-screens per
gpu and ZaphodHeads setups and other non-standard multi-
display configurations.
Tested on triple-head setup with various ZaphodHead and
server layout combos.
This helper will be also needed for dri3/present code.
Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com>
-rw-r--r-- | src/drmmode_display.c | 11 | ||||
-rw-r--r-- | src/nouveau_dri2.c | 25 | ||||
-rw-r--r-- | src/nouveau_present.c | 8 | ||||
-rw-r--r-- | src/nv_proto.h | 1 |
4 files changed, 33 insertions, 12 deletions
diff --git a/src/drmmode_display.c b/src/drmmode_display.c index 45225ad..501440a 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -59,6 +59,7 @@ typedef struct { typedef struct { drmmode_ptr drmmode; drmModeCrtcPtr mode_crtc; + int hw_crtc_index; struct nouveau_bo *cursor; struct nouveau_bo *rotate_bo; int rotate_pitch; @@ -112,12 +113,19 @@ drmmode_pixmap(PixmapPtr ppix) } int -drmmode_head(xf86CrtcPtr crtc) +drmmode_crtc(xf86CrtcPtr crtc) { drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; return drmmode_crtc->mode_crtc->crtc_id; } +int +drmmode_head(xf86CrtcPtr crtc) +{ + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + return drmmode_crtc->hw_crtc_index; +} + void drmmode_swap(ScrnInfoPtr scrn, uint32_t next, uint32_t *prev) { @@ -754,6 +762,7 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num) drmmode_crtc->mode_crtc = drmModeGetCrtc(drmmode->fd, drmmode->mode_res->crtcs[num]); drmmode_crtc->drmmode = drmmode; + drmmode_crtc->hw_crtc_index = num; ret = nouveau_bo_new(pNv->dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0, 64*64*4, NULL, &drmmode_crtc->cursor); diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c index 7446122..cc16cb1 100644 --- a/src/nouveau_dri2.c +++ b/src/nouveau_dri2.c @@ -466,7 +466,7 @@ dri2_page_flip(DrawablePtr draw, PixmapPtr back, void *priv, flipdata->fd = pNv->dev->fd; for (i = 0; i < config->num_crtc; i++) { - int head = drmmode_head(config->crtc[i]); + int head = drmmode_crtc(config->crtc[i]); void *token; if (!config->crtc[i]->enabled) @@ -565,6 +565,7 @@ nouveau_wait_vblank(DrawablePtr draw, int type, CARD64 msc, CARD64 *pmsc, CARD64 *pust, void *data) { ScrnInfoPtr scrn = xf86ScreenToScrn(draw->pScreen); + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); NVPtr pNv = NVPTR(scrn); int crtcs = nv_window_belongs_to_crtc(scrn, draw->x, draw->y, draw->width, draw->height); @@ -572,6 +573,16 @@ nouveau_wait_vblank(DrawablePtr draw, int type, CARD64 msc, struct dri2_vblank *event = NULL; void *token = NULL; int ret; + int head; + + /* Select crtc with smallest index from bitmask of crtcs */ + crtcs = ffs(crtcs) - 1; + + if (crtcs < 0) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "Wait for VBlank failed: No valid crtc for drawable.\n"); + return -EINVAL; + } if (type & DRM_VBLANK_EVENT) { event = drmmode_event_queue(scrn, ++dri2_sequence, @@ -584,20 +595,20 @@ nouveau_wait_vblank(DrawablePtr draw, int type, CARD64 msc, event->s = data; } - /* Select crtc with smallest index from bitmask of crtcs */ - crtcs = ffs(crtcs) - 1; + /* Map xf86CrtcPtr to drmWaitVBlank compatible display head index. */ + head = drmmode_head(config->crtc[crtcs]); - if (crtcs == 1) + if (head == 1) type |= DRM_VBLANK_SECONDARY; - else if (crtcs > 1) + else if (head > 1) #ifdef DRM_VBLANK_HIGH_CRTC_SHIFT - type |= (crtcs << DRM_VBLANK_HIGH_CRTC_SHIFT) & + type |= (head << DRM_VBLANK_HIGH_CRTC_SHIFT) & DRM_VBLANK_HIGH_CRTC_MASK; #else xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Wait for VBlank failed: Called for CRTC %d > 1, but " "DRM_VBLANK_HIGH_CRTC_SHIFT not defined at build time.\n", - crtcs); + head); #endif vbl.request.type = type; diff --git a/src/nouveau_present.c b/src/nouveau_present.c index 38f2cac..05cd518 100644 --- a/src/nouveau_present.c +++ b/src/nouveau_present.c @@ -250,18 +250,18 @@ nouveau_present_flip_exec(ScrnInfoPtr scrn, uint64_t event_id, int sync, for (i = 0; i < config->num_crtc; i++) { int type = vsync ? 0 : DRM_MODE_PAGE_FLIP_ASYNC; - int head = drmmode_head(config->crtc[i]); + int crtc = drmmode_crtc(config->crtc[i]); void *user = NULL; if (!config->crtc[i]->enabled) continue; - if (token && ((head == sync) || (i == last))) { + if (token && ((crtc == sync) || (i == last))) { type |= DRM_MODE_PAGE_FLIP_EVENT; user = token; } - ret = drmModePageFlip(pNv->dev->fd, head, + ret = drmModePageFlip(pNv->dev->fd, crtc, next_fb, type, user); if (ret == 0 && user) { token = NULL; @@ -288,7 +288,7 @@ nouveau_present_flip_next(RRCrtcPtr rrcrtc, uint64_t event_id, { xf86CrtcPtr crtc = rrcrtc->devPrivate; ScrnInfoPtr scrn = crtc->scrn; - return nouveau_present_flip_exec(scrn, event_id, drmmode_head(crtc), + return nouveau_present_flip_exec(scrn, event_id, drmmode_crtc(crtc), target_msc, pixmap, vsync); } diff --git a/src/nv_proto.h b/src/nv_proto.h index c076461..27354e0 100644 --- a/src/nv_proto.h +++ b/src/nv_proto.h @@ -12,6 +12,7 @@ Bool drmmode_page_flip(DrawablePtr draw, PixmapPtr back, void *priv, void drmmode_screen_init(ScreenPtr pScreen); void drmmode_screen_fini(ScreenPtr pScreen); +int drmmode_crtc(xf86CrtcPtr crtc); int drmmode_head(xf86CrtcPtr crtc); void drmmode_swap(ScrnInfoPtr, uint32_t, uint32_t *); |