nouveau_dri2.c revision fda9279d
1#include <sys/types.h>
2#include <sys/stat.h>
3#include <fcntl.h>
4#include <errno.h>
5
6#include "xorg-server.h"
7#include "nv_include.h"
8#ifdef DRI2
9#include "dri2.h"
10#else
11#error "This driver requires a DRI2-enabled X server"
12#endif
13
14#include "xf86drmMode.h"
15
16struct nouveau_dri2_buffer {
17	DRI2BufferRec base;
18	PixmapPtr ppix;
19};
20
21static inline struct nouveau_dri2_buffer *
22nouveau_dri2_buffer(DRI2BufferPtr buf)
23{
24	return (struct nouveau_dri2_buffer *)buf;
25}
26
27static PixmapPtr get_drawable_pixmap(DrawablePtr drawable)
28{
29	if (drawable->type == DRAWABLE_PIXMAP)
30		return (PixmapPtr)drawable;
31	else
32		return (*drawable->pScreen->GetWindowPixmap)((WindowPtr)drawable);
33}
34
35DRI2BufferPtr
36nouveau_dri2_create_buffer2(ScreenPtr pScreen, DrawablePtr pDraw, unsigned int attachment,
37			   unsigned int format)
38{
39	NVPtr pNv = NVPTR(xf86ScreenToScrn(pScreen));
40	struct nouveau_dri2_buffer *nvbuf;
41	struct nouveau_pixmap *nvpix;
42	PixmapPtr ppix = NULL;
43
44	nvbuf = calloc(1, sizeof(*nvbuf));
45	if (!nvbuf)
46		return NULL;
47
48	if (attachment == DRI2BufferFrontLeft) {
49		ppix = get_drawable_pixmap(pDraw);
50		if (pScreen != ppix->drawable.pScreen)
51			ppix = NULL;
52
53		if (pDraw->type == DRAWABLE_WINDOW) {
54#if DRI2INFOREC_VERSION >= 6
55			/* Set initial swap limit on drawable. */
56			DRI2SwapLimit(pDraw, pNv->swap_limit);
57#endif
58		}
59		if (ppix)
60			ppix->refcnt++;
61	} else {
62		int bpp;
63		unsigned int usage_hint = NOUVEAU_CREATE_PIXMAP_TILED;
64
65		/* 'format' is just depth (or 0, or maybe it depends on the caller) */
66		bpp = round_up_pow2(format ? format : pDraw->depth);
67
68		if (attachment == DRI2BufferDepth ||
69		    attachment == DRI2BufferDepthStencil)
70			usage_hint |= NOUVEAU_CREATE_PIXMAP_ZETA;
71		else
72			usage_hint |= NOUVEAU_CREATE_PIXMAP_SCANOUT;
73
74		ppix = pScreen->CreatePixmap(pScreen, pDraw->width,
75					     pDraw->height, bpp,
76					     usage_hint);
77	}
78
79	if (ppix) {
80		pNv->exa_force_cp = TRUE;
81		exaMoveInPixmap(ppix);
82		pNv->exa_force_cp = FALSE;
83
84		nvbuf->base.pitch = ppix->devKind;
85		nvbuf->base.cpp = ppix->drawable.bitsPerPixel / 8;
86	}
87
88	nvbuf->base.attachment = attachment;
89	nvbuf->base.driverPrivate = nvbuf;
90	nvbuf->base.format = format;
91	nvbuf->base.flags = 0;
92	nvbuf->ppix = ppix;
93
94	if (ppix) {
95		nvpix = nouveau_pixmap(ppix);
96		if (!nvpix || !nvpix->bo ||
97		    nouveau_bo_name_get(nvpix->bo, &nvbuf->base.name)) {
98			pScreen->DestroyPixmap(nvbuf->ppix);
99			free(nvbuf);
100			return NULL;
101		}
102	}
103	return &nvbuf->base;
104}
105
106DRI2BufferPtr
107nouveau_dri2_create_buffer(DrawablePtr pDraw, unsigned int attachment,
108			   unsigned int format)
109{
110	return nouveau_dri2_create_buffer2(pDraw->pScreen, pDraw,
111					   attachment, format);
112}
113
114void
115nouveau_dri2_destroy_buffer2(ScreenPtr pScreen, DrawablePtr pDraw, DRI2BufferPtr buf)
116{
117	struct nouveau_dri2_buffer *nvbuf;
118
119	nvbuf = nouveau_dri2_buffer(buf);
120	if (!nvbuf)
121		return;
122
123	if (nvbuf->ppix)
124	    pScreen->DestroyPixmap(nvbuf->ppix);
125	free(nvbuf);
126}
127
128void
129nouveau_dri2_destroy_buffer(DrawablePtr pDraw, DRI2BufferPtr buf)
130{
131	nouveau_dri2_destroy_buffer2(pDraw->pScreen, pDraw, buf);
132}
133
134void
135nouveau_dri2_copy_region2(ScreenPtr pScreen, DrawablePtr pDraw, RegionPtr pRegion,
136			 DRI2BufferPtr pDstBuffer, DRI2BufferPtr pSrcBuffer)
137{
138	struct nouveau_dri2_buffer *src = nouveau_dri2_buffer(pSrcBuffer);
139	struct nouveau_dri2_buffer *dst = nouveau_dri2_buffer(pDstBuffer);
140	NVPtr pNv = NVPTR(xf86ScreenToScrn(pScreen));
141	RegionPtr pCopyClip;
142	GCPtr pGC;
143	DrawablePtr src_draw, dst_draw;
144	Bool translate = FALSE;
145	int off_x = 0, off_y = 0;
146
147	src_draw = &src->ppix->drawable;
148	dst_draw = &dst->ppix->drawable;
149#if 0
150	ErrorF("attachments src %d, dst %d, drawable %p %p pDraw %p\n",
151	       src->base.attachment, dst->base.attachment,
152	       src_draw, dst_draw, pDraw);
153#endif
154	if (src->base.attachment == DRI2BufferFrontLeft)
155		src_draw = pDraw;
156	if (dst->base.attachment == DRI2BufferFrontLeft) {
157#ifdef NOUVEAU_PIXMAP_SHARING
158		if (pDraw->pScreen != pScreen) {
159			dst_draw = DRI2UpdatePrime(pDraw, pDstBuffer);
160			if (!dst_draw)
161				return;
162		}
163		else
164#endif
165			dst_draw = pDraw;
166		if (dst_draw != pDraw)
167			translate = TRUE;
168	}
169
170	if (translate && pDraw->type == DRAWABLE_WINDOW) {
171		PixmapPtr pPix = get_drawable_pixmap(pDraw);
172		off_x = pDraw->x - pPix->screen_x;
173		off_y = pDraw->y - pPix->screen_y;
174	}
175
176	pGC = GetScratchGC(pDraw->depth, pScreen);
177	pCopyClip = REGION_CREATE(pScreen, NULL, 0);
178	REGION_COPY(pScreen, pCopyClip, pRegion);
179
180	if (translate) {
181		REGION_TRANSLATE(pScreen, pCopyClip, off_x, off_y);
182	}
183	pGC->funcs->ChangeClip(pGC, CT_REGION, pCopyClip, 0);
184	ValidateGC(dst_draw, pGC);
185
186	/* If this is a full buffer swap or frontbuffer flush, throttle on
187	 * the previous one.
188	 */
189	if (dst->base.attachment == DRI2BufferFrontLeft &&
190	    REGION_NUM_RECTS(pRegion) == 1) {
191		BoxPtr extents = REGION_EXTENTS(pScreen, pRegion);
192		if (extents->x1 == 0 && extents->y1 == 0 &&
193		    extents->x2 == pDraw->width &&
194		    extents->y2 == pDraw->height) {
195			PixmapPtr fpix = get_drawable_pixmap(dst_draw);
196			struct nouveau_bo *bo = nouveau_pixmap_bo(fpix);
197			if (bo)
198				nouveau_bo_wait(bo, NOUVEAU_BO_RD, pNv->client);
199		}
200	}
201
202	pGC->ops->CopyArea(src_draw, dst_draw, pGC, 0, 0,
203			   pDraw->width, pDraw->height, off_x, off_y);
204
205	FreeScratchGC(pGC);
206}
207
208void
209nouveau_dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion,
210			 DRI2BufferPtr pDstBuffer, DRI2BufferPtr pSrcBuffer)
211{
212    return nouveau_dri2_copy_region2(pDraw->pScreen, pDraw, pRegion,
213				     pDstBuffer, pSrcBuffer);
214}
215
216struct nouveau_dri2_vblank_state {
217	enum {
218		SWAP,
219		BLIT,
220		WAIT
221	} action;
222
223	ClientPtr client;
224	XID draw;
225
226	DRI2BufferPtr dst;
227	DRI2BufferPtr src;
228	DRI2SwapEventPtr func;
229	void *data;
230	unsigned int frame;
231};
232
233struct dri2_vblank {
234	struct nouveau_dri2_vblank_state *s;
235};
236
237static uint64_t dri2_sequence;
238
239static Bool
240update_front(DrawablePtr draw, DRI2BufferPtr front)
241{
242	int r;
243	PixmapPtr pixmap;
244	struct nouveau_dri2_buffer *nvbuf = nouveau_dri2_buffer(front);
245
246	if (draw->type == DRAWABLE_PIXMAP)
247		pixmap = (PixmapPtr)draw;
248	else
249		pixmap = (*draw->pScreen->GetWindowPixmap)((WindowPtr)draw);
250
251	pixmap->refcnt++;
252
253	exaMoveInPixmap(pixmap);
254	r = nouveau_bo_name_get(nouveau_pixmap_bo(pixmap), &front->name);
255	if (r) {
256		(*draw->pScreen->DestroyPixmap)(pixmap);
257		return FALSE;
258	}
259
260	if (nvbuf->ppix)
261		(*draw->pScreen->DestroyPixmap)(nvbuf->ppix);
262
263	front->pitch = pixmap->devKind;
264	front->cpp = pixmap->drawable.bitsPerPixel / 8;
265	nvbuf->ppix = pixmap;
266
267	return TRUE;
268}
269
270static Bool
271can_exchange(DrawablePtr draw, PixmapPtr dst_pix, PixmapPtr src_pix)
272{
273	ScrnInfoPtr scrn = xf86ScreenToScrn(draw->pScreen);
274	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
275	NVPtr pNv = NVPTR(scrn);
276	int i;
277
278	if (!xf86_config->num_crtc)
279		return FALSE;
280
281	for (i = 0; i < xf86_config->num_crtc; i++) {
282		xf86CrtcPtr crtc = xf86_config->crtc[i];
283		if (crtc->enabled && crtc->rotatedData)
284			return FALSE;
285
286	}
287
288	return ((DRI2CanFlip(draw) && pNv->has_pageflip)) &&
289		dst_pix->drawable.width == src_pix->drawable.width &&
290		dst_pix->drawable.height == src_pix->drawable.height &&
291		dst_pix->drawable.bitsPerPixel == src_pix->drawable.bitsPerPixel &&
292		dst_pix->devKind == src_pix->devKind;
293}
294
295static Bool
296can_sync_to_vblank(DrawablePtr draw)
297{
298	ScrnInfoPtr scrn = xf86ScreenToScrn(draw->pScreen);
299	NVPtr pNv = NVPTR(scrn);
300
301	return pNv->glx_vblank &&
302		nv_window_belongs_to_crtc(scrn, draw->x, draw->y,
303					  draw->width, draw->height);
304}
305
306#if DRI2INFOREC_VERSION >= 6
307static Bool
308nouveau_dri2_swap_limit_validate(DrawablePtr draw, int swap_limit)
309{
310	ScrnInfoPtr scrn = xf86ScreenToScrn(draw->pScreen);
311	NVPtr pNv = NVPTR(scrn);
312
313	if ((swap_limit < 1 ) || (swap_limit > pNv->max_swap_limit))
314		return FALSE;
315
316	return TRUE;
317}
318#endif
319
320/* Shall we intentionally violate the OML_sync_control spec to
321 * get some sort of triple-buffering behaviour on a pre 1.12.0
322 * x-server?
323 */
324static Bool violate_oml(DrawablePtr draw)
325{
326	ScrnInfoPtr scrn = xf86ScreenToScrn(draw->pScreen);
327	NVPtr pNv = NVPTR(scrn);
328
329	return (DRI2INFOREC_VERSION < 6) && (pNv->swap_limit > 1);
330}
331
332typedef struct {
333    int fd;
334    unsigned old_fb_id;
335    int flip_count;
336    void *event_data;
337    unsigned int fe_msc;
338    uint64_t fe_ust;
339} dri2_flipdata_rec, *dri2_flipdata_ptr;
340
341typedef struct {
342    dri2_flipdata_ptr flipdata;
343    Bool dispatch_me;
344} dri2_flipevtcarrier_rec, *dri2_flipevtcarrier_ptr;
345
346static void
347nouveau_dri2_flip_event_handler(unsigned int frame, unsigned int tv_sec,
348				unsigned int tv_usec, void *event_data)
349{
350	struct nouveau_dri2_vblank_state *flip = event_data;
351	DrawablePtr draw;
352	ScreenPtr screen;
353	ScrnInfoPtr scrn;
354	int status;
355
356	status = dixLookupDrawable(&draw, flip->draw, serverClient,
357				   M_ANY, DixWriteAccess);
358	if (status != Success) {
359		free(flip);
360		return;
361	}
362
363	screen = draw->pScreen;
364	scrn = xf86ScreenToScrn(screen);
365
366	/* We assume our flips arrive in order, so we don't check the frame */
367	switch (flip->action) {
368	case SWAP:
369		/* Check for too small vblank count of pageflip completion,
370		 * taking wraparound into account. This usually means some
371		 * defective kms pageflip completion, causing wrong (msc, ust)
372		 * return values and possible visual corruption.
373		 * Skip test for frame == 0, as this is a valid constant value
374		 * reported by all Linux kernels at least up to Linux 3.0.
375		 */
376		if ((frame != 0) &&
377		    (frame < flip->frame) && (flip->frame - frame < 5)) {
378			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
379				   "%s: Pageflip has impossible msc %d < target_msc %d\n",
380				   __func__, frame, flip->frame);
381			/* All-Zero values signal failure of (msc, ust)
382			 * timestamping to client.
383			 */
384			frame = tv_sec = tv_usec = 0;
385		}
386
387		DRI2SwapComplete(flip->client, draw, frame, tv_sec, tv_usec,
388				 DRI2_FLIP_COMPLETE, flip->func,
389				 flip->data);
390		break;
391	default:
392		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
393			   "%s: unknown vblank event received\n", __func__);
394		/* Unknown type */
395		break;
396	}
397
398	free(flip);
399}
400
401static void
402nouveau_dri2_flip_handler(void *priv, uint64_t name, uint64_t ust, uint32_t msc)
403{
404	dri2_flipevtcarrier_ptr flipcarrier = priv;
405	dri2_flipdata_ptr flipdata = flipcarrier->flipdata;
406
407	/* Is this the event whose info shall be delivered to higher level? */
408	if (flipcarrier->dispatch_me) {
409		/* Yes: Cache msc, ust for later delivery. */
410		flipdata->fe_msc = msc;
411		flipdata->fe_ust = ust;
412	}
413
414	/* Last crtc completed flip? */
415	flipdata->flip_count--;
416	if (flipdata->flip_count > 0)
417		return;
418
419	/* Release framebuffer */
420	drmModeRmFB(flipdata->fd, flipdata->old_fb_id);
421
422	if (flipdata->event_data == NULL) {
423		free(flipdata);
424		return;
425	}
426
427	/* Deliver cached msc, ust from reference crtc to flip event handler */
428	nouveau_dri2_flip_event_handler(flipdata->fe_msc,
429					flipdata->fe_ust / 1000000,
430					flipdata->fe_ust % 1000000,
431					flipdata->event_data);
432	free(flipdata);
433}
434
435static Bool
436dri2_page_flip(DrawablePtr draw, PixmapPtr back, void *priv,
437			   xf86CrtcPtr ref_crtc)
438{
439	ScrnInfoPtr scrn = xf86ScreenToScrn(draw->pScreen);
440	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
441	NVPtr pNv = NVPTR(scrn);
442	uint32_t next_fb;
443	int emitted = 0;
444	int ret, i;
445	dri2_flipdata_ptr flipdata;
446	dri2_flipevtcarrier_ptr flipcarrier;
447
448	ret = drmModeAddFB(pNv->dev->fd, scrn->virtualX, scrn->virtualY,
449			   scrn->depth, scrn->bitsPerPixel,
450			   scrn->displayWidth * scrn->bitsPerPixel / 8,
451			   nouveau_pixmap(back)->bo->handle, &next_fb);
452	if (ret) {
453		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
454			   "add fb failed: %s\n", strerror(errno));
455		return FALSE;
456	}
457
458	flipdata = calloc(1, sizeof(dri2_flipdata_rec));
459	if (!flipdata) {
460		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
461		"flip queue: data alloc failed.\n");
462		goto error_undo;
463	}
464
465	flipdata->event_data = priv;
466	flipdata->fd = pNv->dev->fd;
467
468	for (i = 0; i < config->num_crtc; i++) {
469		int head = drmmode_crtc(config->crtc[i]);
470		void *token;
471
472		if (!config->crtc[i]->enabled)
473			continue;
474
475		flipdata->flip_count++;
476
477		flipcarrier = drmmode_event_queue(scrn, ++dri2_sequence,
478						  sizeof(*flipcarrier),
479						  nouveau_dri2_flip_handler,
480						  &token);
481		if (!flipcarrier) {
482			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
483				   "flip queue: carrier alloc failed.\n");
484			if (emitted == 0)
485				free(flipdata);
486			goto error_undo;
487		}
488
489		/* Only the reference crtc will finally deliver its page flip
490		 * completion event. All other crtc's events will be discarded.
491		 */
492		flipcarrier->dispatch_me = (config->crtc[i] == ref_crtc);
493		flipcarrier->flipdata = flipdata;
494
495		ret = drmModePageFlip(pNv->dev->fd, head, next_fb,
496				      DRM_MODE_PAGE_FLIP_EVENT, token);
497		if (ret) {
498			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
499				   "flip queue failed: %s\n", strerror(errno));
500			drmmode_event_abort(scrn, dri2_sequence--, false);
501			if (emitted == 0)
502				free(flipdata);
503			goto error_undo;
504		}
505
506		emitted++;
507	}
508
509	/* Will release old fb after all crtc's completed flip. */
510	drmmode_swap(scrn, next_fb, &flipdata->old_fb_id);
511	return TRUE;
512
513error_undo:
514	drmModeRmFB(pNv->dev->fd, next_fb);
515	return FALSE;
516}
517
518static void
519nouveau_dri2_finish_swap(DrawablePtr draw, unsigned int frame,
520			 unsigned int tv_sec, unsigned int tv_usec,
521			 struct nouveau_dri2_vblank_state *s);
522
523static void
524nouveau_dri2_vblank_handler(void *priv, uint64_t name, uint64_t ust, uint32_t frame)
525{
526	struct dri2_vblank *event = priv;
527	struct nouveau_dri2_vblank_state *s = event->s;
528	uint32_t tv_sec  = ust / 1000000;
529	uint32_t tv_usec = ust % 1000000;
530	DrawablePtr draw;
531	int ret;
532
533	ret = dixLookupDrawable(&draw, s->draw, serverClient,
534				M_ANY, DixWriteAccess);
535	if (ret) {
536		free(s);
537		return;
538	}
539
540	switch (s->action) {
541	case SWAP:
542		nouveau_dri2_finish_swap(draw, frame, tv_sec, tv_usec, s);
543#if DRI2INFOREC_VERSION >= 6
544		/* Restore real swap limit on drawable, now that it is safe. */
545		ScrnInfoPtr scrn = xf86ScreenToScrn(draw->pScreen);
546		DRI2SwapLimit(draw, NVPTR(scrn)->swap_limit);
547#endif
548		break;
549
550	case WAIT:
551		DRI2WaitMSCComplete(s->client, draw, frame, tv_sec, tv_usec);
552		free(s);
553		break;
554
555	case BLIT:
556		DRI2SwapComplete(s->client, draw, frame, tv_sec, tv_usec,
557				 DRI2_BLIT_COMPLETE, s->func, s->data);
558		free(s);
559		break;
560	}
561}
562
563static int
564nouveau_wait_vblank(DrawablePtr draw, int type, CARD64 msc,
565		    CARD64 *pmsc, CARD64 *pust, void *data)
566{
567	ScrnInfoPtr scrn = xf86ScreenToScrn(draw->pScreen);
568	NVPtr pNv = NVPTR(scrn);
569	xf86CrtcPtr crtc;
570	drmVBlank vbl;
571	struct dri2_vblank *event = NULL;
572	void *token = NULL;
573	int ret;
574	int head;
575
576	/* Select crtc which shows the largest part of the drawable */
577	crtc = nouveau_pick_best_crtc(scrn, FALSE,
578                                  draw->x, draw->y, draw->width, draw->height);
579
580	if (!crtc) {
581		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
582				   "Wait for VBlank failed: No valid crtc for drawable.\n");
583		return -EINVAL;
584	}
585
586	if (type & DRM_VBLANK_EVENT) {
587		event = drmmode_event_queue(scrn, ++dri2_sequence,
588					    sizeof(*event),
589					    nouveau_dri2_vblank_handler,
590					    &token);
591		if (!event)
592			return -ENOMEM;
593
594		event->s = data;
595	}
596
597	/* Map xf86CrtcPtr to drmWaitVBlank compatible display head index. */
598	head = drmmode_head(crtc);
599
600	if (head == 1)
601		type |= DRM_VBLANK_SECONDARY;
602	else if (head > 1)
603#ifdef DRM_VBLANK_HIGH_CRTC_SHIFT
604		type |= (head << DRM_VBLANK_HIGH_CRTC_SHIFT) &
605				DRM_VBLANK_HIGH_CRTC_MASK;
606#else
607	xf86DrvMsg(scrn->scrnIndex, X_WARNING,
608			   "Wait for VBlank failed: Called for CRTC %d > 1, but "
609			   "DRM_VBLANK_HIGH_CRTC_SHIFT not defined at build time.\n",
610			   head);
611#endif
612
613	vbl.request.type = type;
614	vbl.request.sequence = msc;
615	vbl.request.signal = (unsigned long)token;
616
617	ret = drmWaitVBlank(pNv->dev->fd, &vbl);
618	if (ret) {
619		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
620			   "Wait for VBlank failed: %s\n", strerror(errno));
621		if (event)
622			drmmode_event_abort(scrn, dri2_sequence--, false);
623		return ret;
624	}
625
626	if (pmsc)
627		*pmsc = vbl.reply.sequence;
628	if (pust)
629		*pust = (CARD64)vbl.reply.tval_sec * 1000000 +
630			vbl.reply.tval_usec;
631	return 0;
632}
633
634static void
635nouveau_dri2_finish_swap(DrawablePtr draw, unsigned int frame,
636			 unsigned int tv_sec, unsigned int tv_usec,
637			 struct nouveau_dri2_vblank_state *s)
638{
639	ScrnInfoPtr scrn = xf86ScreenToScrn(draw->pScreen);
640	NVPtr pNv = NVPTR(scrn);
641	PixmapPtr dst_pix;
642	PixmapPtr src_pix = nouveau_dri2_buffer(s->src)->ppix;
643	struct nouveau_bo *dst_bo;
644	struct nouveau_bo *src_bo = nouveau_pixmap_bo(src_pix);
645	struct nouveau_pushbuf *push = pNv->pushbuf;
646	RegionRec reg;
647	int type, ret;
648	Bool front_updated, will_exchange;
649	xf86CrtcPtr ref_crtc;
650
651	REGION_INIT(0, &reg, (&(BoxRec){ 0, 0, draw->width, draw->height }), 0);
652	REGION_TRANSLATE(0, &reg, draw->x, draw->y);
653
654	/* Main crtc for this drawable shall finally deliver pageflip event. */
655	ref_crtc = nouveau_pick_best_crtc(scrn, FALSE, draw->x, draw->y,
656                                      draw->width, draw->height);
657
658	/* Update frontbuffer pixmap and name: Could have changed due to
659	 * window (un)redirection as part of compositing.
660	 */
661	front_updated = update_front(draw, s->dst);
662
663	/* Assign frontbuffer pixmap, after update in update_front() */
664	dst_pix = nouveau_dri2_buffer(s->dst)->ppix;
665	dst_bo = nouveau_pixmap_bo(dst_pix);
666
667	/* Throttle on the previous frame before swapping */
668	nouveau_bo_wait(dst_bo, NOUVEAU_BO_RD, push->client);
669
670	/* Swap by buffer exchange possible? */
671	will_exchange = front_updated && can_exchange(draw, dst_pix, src_pix);
672
673	/* Only emit a wait for vblank pushbuf here if this is a copy-swap, or
674	 * if it is a kms pageflip-swap on an old kernel. Pure exchange swaps
675	 * don't need sync to vblank. kms pageflip-swaps on Linux 3.13+ are
676	 * synced to vblank in the kms driver, so we must not sync here, or
677	 * framerate will be cut in half!
678	 */
679	if (can_sync_to_vblank(draw) &&
680		(!will_exchange ||
681		(!pNv->has_async_pageflip && nouveau_exa_pixmap_is_onscreen(dst_pix)))) {
682		/* Reference the back buffer to sync it to vblank */
683		nouveau_pushbuf_refn(push, &(struct nouveau_pushbuf_refn) {
684					   src_bo,
685					   NOUVEAU_BO_VRAM | NOUVEAU_BO_RD
686				     }, 1);
687
688		if (pNv->Architecture >= NV_FERMI)
689			NVC0SyncToVBlank(dst_pix, REGION_EXTENTS(0, &reg));
690		else
691		if (pNv->Architecture >= NV_TESLA)
692			NV50SyncToVBlank(dst_pix, REGION_EXTENTS(0, &reg));
693		else
694			NV11SyncToVBlank(dst_pix, REGION_EXTENTS(0, &reg));
695
696		nouveau_pushbuf_kick(push, push->channel);
697	}
698
699	if (will_exchange) {
700		type = DRI2_EXCHANGE_COMPLETE;
701		DamageRegionAppend(draw, &reg);
702
703		if (nouveau_exa_pixmap_is_onscreen(dst_pix)) {
704			type = DRI2_FLIP_COMPLETE;
705			ret = dri2_page_flip(draw, src_pix, violate_oml(draw) ?
706					     NULL : s, ref_crtc);
707			if (!ret)
708				goto out;
709		}
710
711		SWAP(s->dst->name, s->src->name);
712		SWAP(nouveau_pixmap(dst_pix)->bo, nouveau_pixmap(src_pix)->bo);
713
714		DamageRegionProcessPending(draw);
715
716		/* If it is a page flip, finish it in the flip event handler. */
717		if ((type == DRI2_FLIP_COMPLETE) && !violate_oml(draw))
718			return;
719	} else {
720		type = DRI2_BLIT_COMPLETE;
721
722		/* Reference the front buffer to let throttling work
723		 * on occluded drawables. */
724		nouveau_pushbuf_refn(push, &(struct nouveau_pushbuf_refn) {
725					   dst_bo,
726					   NOUVEAU_BO_VRAM | NOUVEAU_BO_RD
727				     }, 1);
728
729		REGION_TRANSLATE(0, &reg, -draw->x, -draw->y);
730		nouveau_dri2_copy_region(draw, &reg, s->dst, s->src);
731
732		if (can_sync_to_vblank(draw) && !violate_oml(draw)) {
733			/* Request a vblank event one vblank from now, the most
734			 * likely (optimistic?) time a direct framebuffer blit
735			 * will complete or a desktop compositor will update its
736			 * screen. This defers DRI2SwapComplete() to the earliest
737			 * likely time of real swap completion.
738			 */
739			s->action = BLIT;
740			ret = nouveau_wait_vblank(draw, DRM_VBLANK_EVENT |
741						  DRM_VBLANK_RELATIVE, 1,
742						  NULL, NULL, s);
743			/* Done, if success. Otherwise use fallback below. */
744			if (!ret)
745				return;
746		}
747	}
748
749	/* Special triple-buffering hack for old pre 1.12.0 x-servers used? */
750	if (violate_oml(draw)) {
751		/* Signal to client that swap completion timestamps and counts
752		 * are invalid - they violate the specification.
753		 */
754		frame = tv_sec = tv_usec = 0;
755	}
756
757	/*
758	 * Tell the X server buffers are already swapped even if they're
759	 * not, to prevent it from blocking the client on the next
760	 * GetBuffers request (and let the client do triple-buffering).
761	 *
762	 * XXX - The DRI2SwapLimit() API allowed us to move this to
763	 *	 the flip handler with no FPS hit for page flipped swaps.
764	 *       It is still needed as a fallback for some copy swaps as
765	 *       we lack a method to detect true swap completion for
766	 *       DRI2_BLIT_COMPLETE.
767	 *
768	 *       It is also used if triple-buffering is requested on
769	 *       old x-servers which don't support the DRI2SwapLimit()
770	 *       function.
771	 */
772	DRI2SwapComplete(s->client, draw, frame, tv_sec, tv_usec,
773			 type, s->func, s->data);
774out:
775	free(s);
776}
777
778static Bool
779nouveau_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
780			   DRI2BufferPtr dst, DRI2BufferPtr src,
781			   CARD64 *target_msc, CARD64 divisor, CARD64 remainder,
782			   DRI2SwapEventPtr func, void *data)
783{
784	struct nouveau_dri2_vblank_state *s;
785	CARD64 current_msc, expect_msc;
786	CARD64 current_ust;
787	int ret;
788
789	/* Initialize a swap structure */
790	s = malloc(sizeof(*s));
791	if (!s)
792		return FALSE;
793
794	*s = (struct nouveau_dri2_vblank_state)
795		{ SWAP, client, draw->id, dst, src, func, data, 0 };
796
797	if (can_sync_to_vblank(draw)) {
798		/* Get current sequence and vblank time*/
799		ret = nouveau_wait_vblank(draw, DRM_VBLANK_RELATIVE, 0,
800					  &current_msc, &current_ust, NULL);
801		if (ret)
802			goto fail;
803
804		/* Truncate to match kernel interfaces; means occasional overflow
805		 * misses, but that's generally not a big deal.
806		 */
807		*target_msc &= 0xffffffff;
808		divisor &= 0xffffffff;
809		remainder &= 0xffffffff;
810
811		/* Calculate a swap target if we don't have one */
812		if (current_msc >= *target_msc && divisor)
813			*target_msc = current_msc + divisor
814				- (current_msc - remainder) % divisor;
815
816		/* Avoid underflow of unsigned value below */
817		if (*target_msc == 0)
818			*target_msc = 1;
819
820		/* Swap at next possible vblank requested? */
821		if (current_msc >= *target_msc - 1) {
822			/* Special case: Need to swap at next vblank.
823			 * Schedule swap immediately, bypassing the kernel
824			 * vblank event mechanism to avoid a dangerous race
825			 * between the client and the x-server vblank event
826			 * dispatch in the main x-server dispatch loop when
827			 * the swap_limit is set to 2 for triple-buffering.
828			 *
829			 * This also optimizes for the common case of swap
830			 * at next vblank, avoiding vblank dispatch delay.
831			 */
832			s->frame = 1 + ((unsigned int) current_msc & 0xffffffff);
833			*target_msc = 1 + current_msc;
834			nouveau_dri2_finish_swap(draw, current_msc,
835						 (unsigned int) (current_ust / 1000000),
836						 (unsigned int) (current_ust % 1000000),
837						 s);
838			return TRUE;
839		}
840
841		/* This is a swap in the future, ie. the vblank event will
842		 * only get dispatched at least 2 vblanks into the future.
843		 */
844
845#if DRI2INFOREC_VERSION >= 6
846		/* On XOrg 1.12+ we need to temporarily lower the swaplimit to 1,
847		 * so that DRI2GetBuffersWithFormat() requests from the client get
848		 * deferred in the x-server until the vblank event has been
849		 * dispatched to us and nouveau_dri2_finish_swap() is done. If
850		 * we wouldn't do this, DRI2GetBuffersWithFormat() would operate
851		 * on wrong (pre-swap) buffers, and cause a segfault later on in
852		 * nouveau_dri2_finish_swap(). Our vblank event handler will restore
853		 * the old swaplimit immediately after nouveau_dri2_finish_swap()
854		 * is done, so we still get 1 video refresh cycle worth of triple-
855		 * buffering, because the client can start rendering again 1 cycle
856		 * before the pending swap is completed.
857		 *
858		 * The same race would happen for the "swap at next vblank" case,
859		 * but the special case "swap immediately" code above prevents this.
860		 */
861		DRI2SwapLimit(draw, 1);
862#endif
863
864		/* Request a vblank event one frame before the target */
865		ret = nouveau_wait_vblank(draw, DRM_VBLANK_ABSOLUTE |
866					  DRM_VBLANK_EVENT,
867					  max(current_msc, *target_msc - 1),
868					  &expect_msc, NULL, s);
869		if (ret)
870			goto fail;
871		s->frame = 1 + ((unsigned int) expect_msc & 0xffffffff);
872		*target_msc = 1 + expect_msc;
873	} else {
874		/* We can't/don't want to sync to vblank, just swap. */
875		nouveau_dri2_finish_swap(draw, 0, 0, 0, s);
876	}
877
878	return TRUE;
879
880fail:
881	free(s);
882	return FALSE;
883}
884
885static Bool
886nouveau_dri2_schedule_wait(ClientPtr client, DrawablePtr draw,
887			   CARD64 target_msc, CARD64 divisor, CARD64 remainder)
888{
889	struct nouveau_dri2_vblank_state *s;
890	CARD64 current_msc;
891	int ret;
892
893	/* Truncate to match kernel interfaces; means occasional overflow
894	 * misses, but that's generally not a big deal.
895	 */
896	target_msc &= 0xffffffff;
897	divisor &= 0xffffffff;
898	remainder &= 0xffffffff;
899
900	if (!can_sync_to_vblank(draw)) {
901		DRI2WaitMSCComplete(client, draw, target_msc, 0, 0);
902		return TRUE;
903	}
904
905	/* Initialize a vblank structure */
906	s = malloc(sizeof(*s));
907	if (!s)
908		return FALSE;
909
910	*s = (struct nouveau_dri2_vblank_state) { WAIT, client, draw->id };
911
912	/* Get current sequence */
913	ret = nouveau_wait_vblank(draw, DRM_VBLANK_RELATIVE, 0,
914				  &current_msc, NULL, NULL);
915	if (ret)
916		goto fail;
917
918	/* Calculate a wait target if we don't have one */
919	if (current_msc >= target_msc && divisor)
920		target_msc = current_msc + divisor
921			- (current_msc - remainder) % divisor;
922
923	/* Request a vblank event */
924	ret = nouveau_wait_vblank(draw, DRM_VBLANK_ABSOLUTE |
925				  DRM_VBLANK_EVENT,
926				  max(current_msc, target_msc),
927				  NULL, NULL, s);
928	if (ret)
929		goto fail;
930
931	DRI2BlockClient(client, draw);
932	return TRUE;
933fail:
934	free(s);
935	return FALSE;
936}
937
938static Bool
939nouveau_dri2_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc)
940{
941	int ret;
942
943	if (!can_sync_to_vblank(draw)) {
944		*ust = 0;
945		*msc = 0;
946		return TRUE;
947	}
948
949	/* Get current sequence */
950	ret = nouveau_wait_vblank(draw, DRM_VBLANK_RELATIVE, 0, msc, ust, NULL);
951	if (ret)
952		return FALSE;
953
954	return TRUE;
955}
956
957Bool
958nouveau_dri2_init(ScreenPtr pScreen)
959{
960	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
961	NVPtr pNv = NVPTR(pScrn);
962	DRI2InfoRec dri2 = { 0 };
963	const char *drivernames[2][2] = {
964		{ "nouveau", "nouveau" },
965		{ "nouveau_vieux", "nouveau_vieux" }
966	};
967
968	if (pNv->AccelMethod != EXA)
969		return FALSE;
970
971	if (pNv->Architecture >= NV_ARCH_30)
972		dri2.driverNames = drivernames[0];
973	else
974		dri2.driverNames = drivernames[1];
975	dri2.numDrivers = 2;
976	dri2.driverName = dri2.driverNames[0];
977
978	dri2.fd = pNv->dev->fd;
979	dri2.deviceName = pNv->drm_device_name;
980
981	dri2.version = DRI2INFOREC_VERSION;
982	dri2.CreateBuffer = nouveau_dri2_create_buffer;
983	dri2.DestroyBuffer = nouveau_dri2_destroy_buffer;
984	dri2.CopyRegion = nouveau_dri2_copy_region;
985	dri2.ScheduleSwap = nouveau_dri2_schedule_swap;
986	dri2.ScheduleWaitMSC = nouveau_dri2_schedule_wait;
987	dri2.GetMSC = nouveau_dri2_get_msc;
988
989#if DRI2INFOREC_VERSION >= 6
990	dri2.SwapLimitValidate = nouveau_dri2_swap_limit_validate;
991#endif
992
993#if DRI2INFOREC_VERSION >= 7
994	dri2.version = 7;
995	dri2.GetParam = NULL;
996#endif
997
998#if DRI2INFOREC_VERSION >= 9
999	dri2.version = 9;
1000	dri2.CreateBuffer2 = nouveau_dri2_create_buffer2;
1001	dri2.DestroyBuffer2 = nouveau_dri2_destroy_buffer2;
1002	dri2.CopyRegion2 = nouveau_dri2_copy_region2;
1003#endif
1004	return DRI2ScreenInit(pScreen, &dri2);
1005}
1006
1007void
1008nouveau_dri2_fini(ScreenPtr pScreen)
1009{
1010	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1011	NVPtr pNv = NVPTR(pScrn);
1012	if (pNv->AccelMethod == EXA)
1013		DRI2CloseScreen(pScreen);
1014}
1015