static int nouveau_present_vblank_queue(RRCrtcPtr rrcrtc, uint64_t event_id, uint64_t msc) { xf86CrtcPtr crtc = rrcrtc->devPrivate; NVPtr pNv = NVPTR(crtc->scrn); drmVBlank args; struct nouveau_present_vblank *event; void *token; int ret; event = drmmode_event_queue(crtc->scrn, event_id, sizeof(*event), nouveau_present_vblank, &token); if (!event) return BadAlloc; event->msc = msc; args.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT; args.request.type |= drmmode_head(crtc) << DRM_VBLANK_HIGH_CRTC_SHIFT; args.request.sequence = msc; args.request.signal = (unsigned long)token; while ((ret = drmWaitVBlank(pNv->dev->fd, &args)) != 0) { if (errno != EBUSY || drmmode_event_flush(crtc->scrn) < 0) return BadAlloc; } return Success; }
static int nouveau_present_ust_msc(RRCrtcPtr rrcrtc, uint64_t *ust, uint64_t *msc) { xf86CrtcPtr crtc = rrcrtc->devPrivate; NVPtr pNv = NVPTR(crtc->scrn); drmVBlank args; int ret; args.request.type = DRM_VBLANK_RELATIVE; args.request.type |= drmmode_head(crtc) << DRM_VBLANK_HIGH_CRTC_SHIFT; args.request.sequence = 0, args.request.signal = 0, ret = drmWaitVBlank(pNv->dev->fd, &args); if (ret) { *ust = *msc = 0; return BadMatch; } *ust = (CARD64)args.reply.tval_sec * 1000000 + args.reply.tval_usec; *msc = args.reply.sequence; return Success; }
static int nouveau_wait_vblank(DrawablePtr draw, int type, CARD64 msc, CARD64 *pmsc, CARD64 *pust, void *data) { ScrnInfoPtr scrn = xf86ScreenToScrn(draw->pScreen); NVPtr pNv = NVPTR(scrn); xf86CrtcPtr crtc; drmVBlank vbl; struct dri2_vblank *event = NULL; void *token = NULL; int ret; int head; /* Select crtc which shows the largest part of the drawable */ crtc = nouveau_pick_best_crtc(scrn, FALSE, draw->x, draw->y, draw->width, draw->height); if (!crtc) { 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, sizeof(*event), nouveau_dri2_vblank_handler, &token); if (!event) return -ENOMEM; event->s = data; } /* Map xf86CrtcPtr to drmWaitVBlank compatible display head index. */ head = drmmode_head(crtc); if (head == 1) type |= DRM_VBLANK_SECONDARY; else if (head > 1) #ifdef 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", head); #endif vbl.request.type = type; vbl.request.sequence = msc; vbl.request.signal = (unsigned long)token; ret = drmWaitVBlank(pNv->dev->fd, &vbl); if (ret) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Wait for VBlank failed: %s\n", strerror(errno)); if (event) drmmode_event_abort(scrn, dri2_sequence--, false); return ret; } if (pmsc) *pmsc = vbl.reply.sequence; if (pust) *pust = (CARD64)vbl.reply.tval_sec * 1000000 + vbl.reply.tval_usec; return 0; }