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