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;
}
Exemplo n.º 3
0
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;
}