summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMario Kleiner <mario.kleiner.de@gmail.com>2014-06-23 11:13:57 +0200
committerBen Skeggs <bskeggs@redhat.com>2014-08-11 08:38:34 +1000
commitfcf91a275e96f14e49a93dc3f8dd6798cf7d98f3 (patch)
tree6b9139e385482ac608f07c9934f902cc0411f71b
parent29572e44c24613be9dec0c98ff2731e46ce6203b (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.c11
-rw-r--r--src/nouveau_dri2.c25
-rw-r--r--src/nouveau_present.c8
-rw-r--r--src/nv_proto.h1
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 *);