amdgpu_dri2.c revision 504d986f
1/*
2 * Copyright 2008 Kristian Høgsberg
3 * Copyright 2008 Jérôme Glisse
4 *
5 * All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining
8 * a copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation on the rights to use, copy, modify, merge,
11 * publish, distribute, sublicense, and/or sell copies of the Software,
12 * and to permit persons to whom the Software is furnished to do so,
13 * subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial
17 * portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22 * NON-INFRINGEMENT.  IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
23 * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
27 */
28#ifdef HAVE_CONFIG_H
29#include "config.h"
30#endif
31
32#include "amdgpu_drv.h"
33#include "amdgpu_dri2.h"
34#include "amdgpu_glamor.h"
35#include "amdgpu_video.h"
36#include "amdgpu_pixmap.h"
37
38#ifdef DRI2
39
40#include <sys/ioctl.h>
41#include <sys/types.h>
42#include <sys/stat.h>
43#include <fcntl.h>
44#include <errno.h>
45
46#include <gbm.h>
47
48#include "amdgpu_bo_helper.h"
49#include "amdgpu_version.h"
50
51#include "amdgpu_list.h"
52
53#include <xf86Priv.h>
54
55#if DRI2INFOREC_VERSION >= 9
56#define USE_DRI2_PRIME
57#endif
58
59#define FALLBACK_SWAP_DELAY 16
60
61typedef DRI2BufferPtr BufferPtr;
62
63struct dri2_buffer_priv {
64	PixmapPtr pixmap;
65	unsigned int attachment;
66	unsigned int refcnt;
67};
68
69struct dri2_window_priv {
70	xf86CrtcPtr crtc;
71	int vblank_delta;
72};
73
74static DevPrivateKeyRec dri2_window_private_key_rec;
75#define dri2_window_private_key (&dri2_window_private_key_rec)
76
77#define get_dri2_window_priv(window) \
78	((struct dri2_window_priv*) \
79	 dixLookupPrivate(&(window)->devPrivates, dri2_window_private_key))
80
81/* Get GEM flink name for a pixmap */
82static Bool
83amdgpu_get_flink_name(AMDGPUEntPtr pAMDGPUEnt, PixmapPtr pixmap, uint32_t *name)
84{
85	struct amdgpu_buffer *bo = amdgpu_get_pixmap_bo(pixmap);
86	struct drm_gem_flink flink;
87
88	if (bo && !(bo->flags & AMDGPU_BO_FLAGS_GBM) &&
89	    amdgpu_bo_export(bo->bo.amdgpu,
90			     amdgpu_bo_handle_type_gem_flink_name,
91			     name) == 0)
92		return TRUE;
93
94	if (!amdgpu_pixmap_get_handle(pixmap, &flink.handle) ||
95	    ioctl(pAMDGPUEnt->fd, DRM_IOCTL_GEM_FLINK, &flink) < 0)
96		return FALSE;
97	*name = flink.name;
98	return TRUE;
99}
100
101static BufferPtr
102amdgpu_dri2_create_buffer2(ScreenPtr pScreen,
103			   DrawablePtr drawable,
104			   unsigned int attachment, unsigned int format)
105{
106	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
107	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
108	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
109	BufferPtr buffers;
110	struct dri2_buffer_priv *privates;
111	PixmapPtr pixmap;
112	unsigned front_width;
113	unsigned aligned_width = drawable->width;
114	unsigned height = drawable->height;
115	Bool is_glamor_pixmap = FALSE;
116	int depth;
117	int cpp;
118
119	if (format) {
120		depth = format;
121
122		switch (depth) {
123		case 15:
124			cpp = 2;
125			break;
126		case 24:
127			cpp = 4;
128			break;
129		default:
130			cpp = depth / 8;
131		}
132	} else {
133		depth = drawable->depth;
134		cpp = drawable->bitsPerPixel / 8;
135	}
136
137	front_width = pScreen->GetScreenPixmap(pScreen)->drawable.width;
138
139	pixmap = NULL;
140
141	if (attachment == DRI2BufferFrontLeft) {
142		uint32_t handle;
143
144		pixmap = get_drawable_pixmap(drawable);
145		if (pScreen != pixmap->drawable.pScreen)
146			pixmap = NULL;
147		else if (info->use_glamor && !amdgpu_pixmap_get_handle(pixmap, &handle)) {
148			is_glamor_pixmap = TRUE;
149			aligned_width = pixmap->drawable.width;
150			height = pixmap->drawable.height;
151			pixmap = NULL;
152		} else
153			pixmap->refcnt++;
154	}
155
156	if (!pixmap && (is_glamor_pixmap || attachment != DRI2BufferFrontLeft)) {
157		if (aligned_width == front_width)
158			aligned_width = pScrn->virtualX;
159
160		pixmap = (*pScreen->CreatePixmap) (pScreen,
161						   aligned_width,
162						   height,
163						   depth,
164						   AMDGPU_CREATE_PIXMAP_DRI2);
165	}
166
167	buffers = calloc(1, sizeof *buffers);
168	if (buffers == NULL)
169		goto error;
170
171	if (pixmap) {
172		if (is_glamor_pixmap) {
173			pixmap = amdgpu_glamor_set_pixmap_bo(drawable, pixmap);
174			pixmap->refcnt++;
175		}
176
177		if (!amdgpu_get_flink_name(pAMDGPUEnt, pixmap, &buffers->name))
178			goto error;
179	}
180
181	privates = calloc(1, sizeof(struct dri2_buffer_priv));
182	if (privates == NULL)
183		goto error;
184
185	buffers->attachment = attachment;
186	if (pixmap) {
187		buffers->pitch = pixmap->devKind;
188		buffers->cpp = cpp;
189	}
190	buffers->driverPrivate = privates;
191	buffers->format = format;
192	buffers->flags = 0;	/* not tiled */
193	privates->pixmap = pixmap;
194	privates->attachment = attachment;
195	privates->refcnt = 1;
196
197	return buffers;
198
199error:
200	free(buffers);
201	if (pixmap)
202		(*pScreen->DestroyPixmap) (pixmap);
203	return NULL;
204}
205
206DRI2BufferPtr
207amdgpu_dri2_create_buffer(DrawablePtr pDraw, unsigned int attachment,
208			  unsigned int format)
209{
210	return amdgpu_dri2_create_buffer2(pDraw->pScreen, pDraw,
211					  attachment, format);
212}
213
214static void
215amdgpu_dri2_destroy_buffer2(ScreenPtr pScreen,
216			    DrawablePtr drawable, BufferPtr buffers)
217{
218	if (buffers) {
219		struct dri2_buffer_priv *private = buffers->driverPrivate;
220
221		/* Trying to free an already freed buffer is unlikely to end well */
222		if (private->refcnt == 0) {
223			ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen);
224
225			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
226				   "Attempted to destroy previously destroyed buffer.\
227 This is a programming error\n");
228			return;
229		}
230
231		private->refcnt--;
232		if (private->refcnt == 0) {
233			if (private->pixmap)
234				(*pScreen->DestroyPixmap) (private->pixmap);
235
236			free(buffers->driverPrivate);
237			free(buffers);
238		}
239	}
240}
241
242void amdgpu_dri2_destroy_buffer(DrawablePtr pDraw, DRI2BufferPtr buf)
243{
244	amdgpu_dri2_destroy_buffer2(pDraw->pScreen, pDraw, buf);
245}
246
247static inline PixmapPtr GetDrawablePixmap(DrawablePtr drawable)
248{
249	if (drawable->type == DRAWABLE_PIXMAP)
250		return (PixmapPtr) drawable;
251	else {
252		struct _Window *pWin = (struct _Window *)drawable;
253		return drawable->pScreen->GetWindowPixmap(pWin);
254	}
255}
256
257static void
258amdgpu_dri2_copy_region2(ScreenPtr pScreen,
259			 DrawablePtr drawable,
260			 RegionPtr region,
261			 BufferPtr dest_buffer, BufferPtr src_buffer)
262{
263	struct dri2_buffer_priv *src_private = src_buffer->driverPrivate;
264	struct dri2_buffer_priv *dst_private = dest_buffer->driverPrivate;
265	DrawablePtr src_drawable;
266	DrawablePtr dst_drawable;
267	RegionPtr copy_clip;
268	GCPtr gc;
269	Bool translate = FALSE;
270	int off_x = 0, off_y = 0;
271
272	src_drawable = &src_private->pixmap->drawable;
273	dst_drawable = &dst_private->pixmap->drawable;
274
275	if (src_private->attachment == DRI2BufferFrontLeft) {
276#ifdef USE_DRI2_PRIME
277		if (drawable->pScreen != pScreen) {
278			src_drawable = DRI2UpdatePrime(drawable, src_buffer);
279			if (!src_drawable)
280				return;
281		} else
282#endif
283			src_drawable = drawable;
284	}
285	if (dst_private->attachment == DRI2BufferFrontLeft) {
286#ifdef USE_DRI2_PRIME
287		if (drawable->pScreen != pScreen) {
288			dst_drawable = DRI2UpdatePrime(drawable, dest_buffer);
289			if (!dst_drawable)
290				return;
291			if (dst_drawable != drawable)
292				translate = TRUE;
293		} else
294#endif
295			dst_drawable = drawable;
296	}
297
298	if (translate && drawable->type == DRAWABLE_WINDOW) {
299		PixmapPtr pPix = GetDrawablePixmap(drawable);
300
301		off_x = drawable->x - pPix->screen_x;
302		off_y = drawable->y - pPix->screen_y;
303	}
304	gc = GetScratchGC(dst_drawable->depth, pScreen);
305	copy_clip = REGION_CREATE(pScreen, NULL, 0);
306	REGION_COPY(pScreen, copy_clip, region);
307
308	if (translate) {
309		REGION_TRANSLATE(pScreen, copy_clip, off_x, off_y);
310	}
311
312	(*gc->funcs->ChangeClip) (gc, CT_REGION, copy_clip, 0);
313	ValidateGC(dst_drawable, gc);
314
315	(*gc->ops->CopyArea) (src_drawable, dst_drawable, gc,
316			      0, 0, drawable->width, drawable->height, off_x,
317			      off_y);
318
319	FreeScratchGC(gc);
320}
321
322void
323amdgpu_dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion,
324			DRI2BufferPtr pDstBuffer, DRI2BufferPtr pSrcBuffer)
325{
326	return amdgpu_dri2_copy_region2(pDraw->pScreen, pDraw, pRegion,
327					pDstBuffer, pSrcBuffer);
328}
329
330enum DRI2FrameEventType {
331	DRI2_SWAP,
332	DRI2_FLIP,
333	DRI2_WAITMSC,
334};
335
336typedef struct _DRI2FrameEvent {
337	XID drawable_id;
338	ClientPtr client;
339	enum DRI2FrameEventType type;
340	unsigned frame;
341	xf86CrtcPtr crtc;
342	OsTimerPtr timer;
343	uintptr_t drm_queue_seq;
344
345	/* for swaps & flips only */
346	DRI2SwapEventPtr event_complete;
347	void *event_data;
348	DRI2BufferPtr front;
349	DRI2BufferPtr back;
350} DRI2FrameEventRec, *DRI2FrameEventPtr;
351
352static int DRI2InfoCnt;
353
354static void amdgpu_dri2_ref_buffer(BufferPtr buffer)
355{
356	struct dri2_buffer_priv *private = buffer->driverPrivate;
357	private->refcnt++;
358}
359
360static void amdgpu_dri2_unref_buffer(BufferPtr buffer)
361{
362	if (buffer) {
363		struct dri2_buffer_priv *private = buffer->driverPrivate;
364		amdgpu_dri2_destroy_buffer(&(private->pixmap->drawable),
365					   buffer);
366	}
367}
368
369static void
370amdgpu_dri2_client_state_changed(CallbackListPtr * ClientStateCallback,
371				 pointer data, pointer calldata)
372{
373	NewClientInfoRec *clientinfo = calldata;
374	ClientPtr pClient = clientinfo->client;
375
376	switch (pClient->clientState) {
377	case ClientStateRetained:
378	case ClientStateGone:
379		amdgpu_drm_abort_client(pClient);
380		break;
381	default:
382		break;
383	}
384}
385
386/*
387 * Get current frame count delta for the specified drawable and CRTC
388 */
389static uint32_t amdgpu_get_msc_delta(DrawablePtr pDraw, xf86CrtcPtr crtc)
390{
391	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
392
393	if (pDraw && pDraw->type == DRAWABLE_WINDOW)
394		return drmmode_crtc->interpolated_vblanks +
395			get_dri2_window_priv((WindowPtr)pDraw)->vblank_delta;
396
397	return drmmode_crtc->interpolated_vblanks;
398}
399
400/*
401 * Get current frame count and timestamp of the specified CRTC
402 */
403static Bool amdgpu_dri2_get_crtc_msc(xf86CrtcPtr crtc, CARD64 *ust, CARD64 *msc)
404{
405	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
406
407	if (!amdgpu_crtc_is_enabled(crtc) ||
408	    drmmode_crtc_get_ust_msc(crtc, ust, msc) != Success) {
409		/* CRTC is not running, extrapolate MSC and timestamp */
410		ScrnInfoPtr scrn = crtc->scrn;
411		AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
412		CARD64 now, delta_t, delta_seq;
413
414		if (!drmmode_crtc->dpms_last_ust)
415			return FALSE;
416
417		if (drmmode_get_current_ust(pAMDGPUEnt->fd, &now) != 0) {
418			xf86DrvMsg(scrn->scrnIndex, X_ERROR,
419				   "%s cannot get current time\n", __func__);
420			return FALSE;
421		}
422
423		delta_t = now - drmmode_crtc->dpms_last_ust;
424		delta_seq = delta_t * drmmode_crtc->dpms_last_fps;
425		delta_seq /= 1000000;
426		*ust = drmmode_crtc->dpms_last_ust;
427		delta_t = delta_seq * 1000000;
428		delta_t /= drmmode_crtc->dpms_last_fps;
429		*ust += delta_t;
430		*msc = drmmode_crtc->dpms_last_seq;
431		*msc += delta_seq;
432	}
433
434	*msc += drmmode_crtc->interpolated_vblanks;
435
436	return TRUE;
437}
438
439static
440xf86CrtcPtr amdgpu_dri2_drawable_crtc(DrawablePtr pDraw, Bool consider_disabled)
441{
442	ScreenPtr pScreen = pDraw->pScreen;
443	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
444	xf86CrtcPtr crtc = amdgpu_pick_best_crtc(pScrn, consider_disabled,
445						 pDraw->x, pDraw->x + pDraw->width,
446						 pDraw->y, pDraw->y + pDraw->height);
447
448	if (crtc && pDraw->type == DRAWABLE_WINDOW) {
449		struct dri2_window_priv *priv = get_dri2_window_priv((WindowPtr)pDraw);
450
451		if (priv->crtc && priv->crtc != crtc) {
452			CARD64 ust, mscold, mscnew;
453
454			if (amdgpu_dri2_get_crtc_msc(priv->crtc, &ust, &mscold) &&
455			    amdgpu_dri2_get_crtc_msc(crtc, &ust, &mscnew))
456				priv->vblank_delta += mscold - mscnew;
457		}
458
459		priv->crtc = crtc;
460	}
461
462	return crtc;
463}
464
465static void
466amdgpu_dri2_flip_event_abort(xf86CrtcPtr crtc, void *event_data)
467{
468	AMDGPUInfoPtr info = AMDGPUPTR(crtc->scrn);
469
470	info->drmmode.dri2_flipping = FALSE;
471	free(event_data);
472}
473
474static void
475amdgpu_dri2_flip_event_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec,
476			       void *event_data)
477{
478	DRI2FrameEventPtr flip = event_data;
479	ScrnInfoPtr scrn = crtc->scrn;
480	unsigned tv_sec, tv_usec;
481	DrawablePtr drawable;
482	ScreenPtr screen;
483	int status;
484	PixmapPtr pixmap;
485
486	status = dixLookupDrawable(&drawable, flip->drawable_id, serverClient,
487				   M_ANY, DixWriteAccess);
488	if (status != Success)
489		goto abort;
490
491	frame += amdgpu_get_msc_delta(drawable, crtc);
492
493	screen = scrn->pScreen;
494	pixmap = screen->GetScreenPixmap(screen);
495	xf86DrvMsgVerb(scrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
496		       "%s:%d fevent[%p] width %d pitch %d (/4 %d)\n",
497		       __func__, __LINE__, flip, pixmap->drawable.width,
498		       pixmap->devKind, pixmap->devKind / 4);
499
500	tv_sec = usec / 1000000;
501	tv_usec = usec % 1000000;
502
503	/* We assume our flips arrive in order, so we don't check the frame */
504	switch (flip->type) {
505	case DRI2_SWAP:
506		/* Check for too small vblank count of pageflip completion, taking wraparound
507		 * into account. This usually means some defective kms pageflip completion,
508		 * causing wrong (msc, ust) return values and possible visual corruption.
509		 */
510		if ((frame < flip->frame) && (flip->frame - frame < 5)) {
511			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
512				   "%s: Pageflip completion event has impossible msc %u < target_msc %u\n",
513				   __func__, frame, flip->frame);
514			/* All-Zero values signal failure of (msc, ust) timestamping to client. */
515			frame = tv_sec = tv_usec = 0;
516		}
517
518		DRI2SwapComplete(flip->client, drawable, frame, tv_sec, tv_usec,
519				 DRI2_FLIP_COMPLETE, flip->event_complete,
520				 flip->event_data);
521		break;
522	default:
523		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
524			   "%s: unknown vblank event received\n", __func__);
525		/* Unknown type */
526		break;
527	}
528
529abort:
530	amdgpu_dri2_flip_event_abort(crtc, event_data);
531}
532
533static Bool
534amdgpu_dri2_schedule_flip(xf86CrtcPtr crtc, ClientPtr client,
535			  DrawablePtr draw, DRI2BufferPtr front,
536			  DRI2BufferPtr back, DRI2SwapEventPtr func,
537			  void *data, unsigned int target_msc)
538{
539	ScrnInfoPtr scrn = crtc->scrn;
540	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
541	struct dri2_buffer_priv *back_priv;
542	DRI2FrameEventPtr flip_info;
543	int ref_crtc_hw_id = drmmode_get_crtc_id(crtc);
544
545	flip_info = calloc(1, sizeof(DRI2FrameEventRec));
546	if (!flip_info)
547		return FALSE;
548
549	flip_info->drawable_id = draw->id;
550	flip_info->client = client;
551	flip_info->type = DRI2_SWAP;
552	flip_info->event_complete = func;
553	flip_info->event_data = data;
554	flip_info->frame = target_msc;
555	flip_info->crtc = crtc;
556
557	xf86DrvMsgVerb(scrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
558		       "%s:%d fevent[%p]\n", __func__, __LINE__, flip_info);
559
560	/* Page flip the full screen buffer */
561	back_priv = back->driverPrivate;
562	if (amdgpu_do_pageflip(scrn, client, back_priv->pixmap,
563			       AMDGPU_DRM_QUEUE_ID_DEFAULT, flip_info,
564			       ref_crtc_hw_id,
565			       amdgpu_dri2_flip_event_handler,
566			       amdgpu_dri2_flip_event_abort, FLIP_VSYNC)) {
567		info->drmmode.dri2_flipping = TRUE;
568		return TRUE;
569	}
570	return FALSE;
571}
572
573static Bool update_front(DrawablePtr draw, DRI2BufferPtr front)
574{
575	ScreenPtr screen = draw->pScreen;
576	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
577	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
578	PixmapPtr pixmap = get_drawable_pixmap(draw);
579	struct dri2_buffer_priv *priv = front->driverPrivate;
580
581	if (!amdgpu_get_flink_name(pAMDGPUEnt, pixmap, &front->name))
582		return FALSE;
583
584	(*draw->pScreen->DestroyPixmap) (priv->pixmap);
585	front->pitch = pixmap->devKind;
586	front->cpp = pixmap->drawable.bitsPerPixel / 8;
587	priv->pixmap = pixmap;
588	pixmap->refcnt++;
589
590	return TRUE;
591}
592
593static Bool
594can_exchange(ScrnInfoPtr pScrn, DrawablePtr draw,
595	     DRI2BufferPtr front, DRI2BufferPtr back)
596{
597	struct dri2_buffer_priv *front_priv = front->driverPrivate;
598	struct dri2_buffer_priv *back_priv = back->driverPrivate;
599	PixmapPtr front_pixmap;
600	PixmapPtr back_pixmap = back_priv->pixmap;
601	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
602	int i;
603
604	for (i = 0; i < xf86_config->num_crtc; i++) {
605		xf86CrtcPtr crtc = xf86_config->crtc[i];
606		drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
607
608		if (crtc->enabled &&
609		    (crtc->rotatedData || drmmode_crtc->scanout[0].bo))
610			return FALSE;
611	}
612
613	if (!update_front(draw, front))
614		return FALSE;
615
616	front_pixmap = front_priv->pixmap;
617
618	if (front_pixmap->drawable.width != back_pixmap->drawable.width)
619		return FALSE;
620
621	if (front_pixmap->drawable.height != back_pixmap->drawable.height)
622		return FALSE;
623
624	if (front_pixmap->drawable.bitsPerPixel !=
625	    back_pixmap->drawable.bitsPerPixel)
626		return FALSE;
627
628	if (front_pixmap->devKind != back_pixmap->devKind)
629		return FALSE;
630
631	return TRUE;
632}
633
634static Bool
635can_flip(ScrnInfoPtr pScrn, DrawablePtr draw,
636	 DRI2BufferPtr front, DRI2BufferPtr back)
637{
638	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
639
640	return draw->type == DRAWABLE_WINDOW &&
641	    info->allowPageFlip &&
642	    !info->hwcursor_disabled &&
643	    !info->drmmode.present_flipping &&
644	    pScrn->vtSema &&
645	    DRI2CanFlip(draw) && can_exchange(pScrn, draw, front, back);
646}
647
648static void
649amdgpu_dri2_exchange_buffers(DrawablePtr draw, DRI2BufferPtr front,
650			     DRI2BufferPtr back)
651{
652	struct dri2_buffer_priv *front_priv = front->driverPrivate;
653	struct dri2_buffer_priv *back_priv = back->driverPrivate;
654	struct amdgpu_pixmap *front_pix;
655	struct amdgpu_pixmap *back_pix;
656	ScreenPtr screen;
657	AMDGPUInfoPtr info;
658	RegionRec region;
659	int tmp;
660
661	region.extents.x1 = region.extents.y1 = 0;
662	region.extents.x2 = front_priv->pixmap->drawable.width;
663	region.extents.y2 = front_priv->pixmap->drawable.height;
664	region.data = NULL;
665	DamageRegionAppend(&front_priv->pixmap->drawable, &region);
666
667	/* Swap BO names so DRI works */
668	tmp = front->name;
669	front->name = back->name;
670	back->name = tmp;
671
672	/* Swap pixmap privates */
673	front_pix = amdgpu_get_pixmap_private(front_priv->pixmap);
674	back_pix = amdgpu_get_pixmap_private(back_priv->pixmap);
675	amdgpu_set_pixmap_private(front_priv->pixmap, back_pix);
676	amdgpu_set_pixmap_private(back_priv->pixmap, front_pix);
677
678	/* Do we need to update the Screen? */
679	screen = draw->pScreen;
680	info = AMDGPUPTR(xf86ScreenToScrn(screen));
681	if (front_pix->bo == info->front_buffer) {
682		struct amdgpu_pixmap *screen_priv =
683			amdgpu_get_pixmap_private(screen->GetScreenPixmap(screen));
684
685		amdgpu_bo_ref(back_pix->bo);
686		amdgpu_bo_unref(&info->front_buffer);
687		info->front_buffer = back_pix->bo;
688		*screen_priv = *back_pix;
689	}
690
691	amdgpu_glamor_exchange_buffers(front_priv->pixmap, back_priv->pixmap);
692
693	DamageRegionProcessPending(&front_priv->pixmap->drawable);
694}
695
696static void amdgpu_dri2_frame_event_abort(xf86CrtcPtr crtc, void *event_data)
697{
698	DRI2FrameEventPtr event = event_data;
699
700	TimerCancel(event->timer);
701	TimerFree(event->timer);
702	amdgpu_dri2_unref_buffer(event->front);
703	amdgpu_dri2_unref_buffer(event->back);
704	free(event);
705}
706
707static void amdgpu_dri2_frame_event_handler(xf86CrtcPtr crtc, uint32_t seq,
708					    uint64_t usec, void *event_data)
709{
710	DRI2FrameEventPtr event = event_data;
711	ScrnInfoPtr scrn = crtc->scrn;
712	DrawablePtr drawable;
713	int status;
714	int swap_type;
715	BoxRec box;
716	RegionRec region;
717
718	status = dixLookupDrawable(&drawable, event->drawable_id, serverClient,
719				   M_ANY, DixWriteAccess);
720	if (status != Success)
721		goto cleanup;
722
723	seq += amdgpu_get_msc_delta(drawable, crtc);
724
725	switch (event->type) {
726	case DRI2_FLIP:
727		if (can_flip(scrn, drawable, event->front, event->back) &&
728		    amdgpu_dri2_schedule_flip(crtc,
729					      event->client,
730					      drawable,
731					      event->front,
732					      event->back,
733					      event->event_complete,
734					      event->event_data,
735					      event->frame)) {
736			amdgpu_dri2_exchange_buffers(drawable, event->front,
737						     event->back);
738			break;
739		}
740		/* else fall through to exchange/blit */
741	case DRI2_SWAP:
742		if (DRI2CanExchange(drawable) &&
743		    can_exchange(scrn, drawable, event->front, event->back)) {
744			amdgpu_dri2_exchange_buffers(drawable, event->front,
745						     event->back);
746			swap_type = DRI2_EXCHANGE_COMPLETE;
747		} else {
748			box.x1 = 0;
749			box.y1 = 0;
750			box.x2 = drawable->width;
751			box.y2 = drawable->height;
752			REGION_INIT(pScreen, &region, &box, 0);
753			amdgpu_dri2_copy_region(drawable, &region, event->front,
754						event->back);
755			swap_type = DRI2_BLIT_COMPLETE;
756		}
757
758		DRI2SwapComplete(event->client, drawable, seq, usec / 1000000,
759				 usec % 1000000, swap_type, event->event_complete,
760				 event->event_data);
761
762		break;
763	case DRI2_WAITMSC:
764		DRI2WaitMSCComplete(event->client, drawable, seq, usec / 1000000,
765				    usec % 1000000);
766		break;
767	default:
768		/* Unknown type */
769		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
770			   "%s: unknown vblank event received\n", __func__);
771		break;
772	}
773
774cleanup:
775	amdgpu_dri2_frame_event_abort(crtc, event_data);
776}
777
778drmVBlankSeqType amdgpu_populate_vbl_request_type(xf86CrtcPtr crtc)
779{
780	drmVBlankSeqType type = 0;
781	int crtc_id = drmmode_get_crtc_id(crtc);
782
783	if (crtc_id == 1)
784		type |= DRM_VBLANK_SECONDARY;
785	else if (crtc_id > 1)
786#ifdef DRM_VBLANK_HIGH_CRTC_SHIFT
787		type |= (crtc_id << DRM_VBLANK_HIGH_CRTC_SHIFT) &
788		    DRM_VBLANK_HIGH_CRTC_MASK;
789#else
790		ErrorF("amdgpu driver bug: %s called for CRTC %d > 1, but "
791		       "DRM_VBLANK_HIGH_CRTC_MASK not defined at build time\n",
792		       __func__, crtc_id);
793#endif
794
795	return type;
796}
797
798/*
799 * This function should be called on a disabled CRTC only (i.e., CRTC
800 * in DPMS-off state). It will calculate the delay necessary to reach
801 * target_msc from present time if the CRTC were running.
802 */
803static
804CARD32 amdgpu_dri2_extrapolate_msc_delay(xf86CrtcPtr crtc, CARD64 * target_msc,
805					 CARD64 divisor, CARD64 remainder)
806{
807	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
808	ScrnInfoPtr pScrn = crtc->scrn;
809	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
810	int nominal_frame_rate = drmmode_crtc->dpms_last_fps;
811	CARD64 last_vblank_ust = drmmode_crtc->dpms_last_ust;
812	uint32_t last_vblank_seq = drmmode_crtc->dpms_last_seq;
813	CARD64 now, target_time, delta_t;
814	int64_t d, delta_seq;
815	int ret;
816	CARD32 d_ms;
817
818	if (!last_vblank_ust) {
819		*target_msc = 0;
820		return FALLBACK_SWAP_DELAY;
821	}
822	ret = drmmode_get_current_ust(pAMDGPUEnt->fd, &now);
823	if (ret) {
824		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
825			   "%s cannot get current time\n", __func__);
826		*target_msc = 0;
827		return FALLBACK_SWAP_DELAY;
828	}
829	delta_seq = *target_msc - last_vblank_seq;
830	delta_seq *= 1000000;
831	target_time = last_vblank_ust;
832	target_time += delta_seq / nominal_frame_rate;
833	d = target_time - now;
834	if (d < 0) {
835		/* we missed the event, adjust target_msc, do the divisor magic */
836		CARD64 current_msc = last_vblank_seq;
837
838		delta_t = now - last_vblank_ust;
839		delta_seq = delta_t * nominal_frame_rate;
840		current_msc += delta_seq / 1000000;
841		current_msc &= 0xffffffff;
842		if (divisor == 0) {
843			*target_msc = current_msc;
844			d = 0;
845		} else {
846			*target_msc =
847			    current_msc - (current_msc % divisor) + remainder;
848			if ((current_msc % divisor) >= remainder)
849				*target_msc += divisor;
850			*target_msc &= 0xffffffff;
851			delta_seq = *target_msc - last_vblank_seq;
852			delta_seq *= 1000000;
853			target_time = last_vblank_ust;
854			target_time += delta_seq / nominal_frame_rate;
855			d = target_time - now;
856		}
857	}
858	/*
859	 * convert delay to milliseconds and add margin to prevent the client
860	 * from coming back early (due to timer granularity and rounding
861	 * errors) and getting the same MSC it just got
862	 */
863	d_ms = (CARD32) d / 1000;
864	if ((CARD32) d - d_ms * 1000 > 0)
865		d_ms += 2;
866	else
867		d_ms++;
868	return d_ms;
869}
870
871/*
872 * Get current interpolated frame count and frame count timestamp, based on
873 * drawable's crtc.
874 */
875static int amdgpu_dri2_get_msc(DrawablePtr draw, CARD64 * ust, CARD64 * msc)
876{
877	xf86CrtcPtr crtc = amdgpu_dri2_drawable_crtc(draw, TRUE);
878
879	/* Drawable not displayed, make up a value */
880	if (crtc == NULL) {
881		*ust = 0;
882		*msc = 0;
883		return TRUE;
884	}
885
886	if (!amdgpu_dri2_get_crtc_msc(crtc, ust, msc))
887		return FALSE;
888
889	if (draw && draw->type == DRAWABLE_WINDOW)
890		*msc += get_dri2_window_priv((WindowPtr)draw)->vblank_delta;
891	*msc &= 0xffffffff;
892	return TRUE;
893}
894
895static
896CARD32 amdgpu_dri2_deferred_event(OsTimerPtr timer, CARD32 now, pointer data)
897{
898	DRI2FrameEventPtr event_info = (DRI2FrameEventPtr) data;
899	xf86CrtcPtr crtc = event_info->crtc;
900	ScrnInfoPtr scrn;
901	AMDGPUEntPtr pAMDGPUEnt;
902	CARD64 drm_now;
903	int ret;
904	CARD64 delta_t, delta_seq, frame;
905	drmmode_crtc_private_ptr drmmode_crtc;
906
907	/*
908	 * This is emulated event, so its time is current time, which we
909	 * have to get in DRM-compatible form (which is a bit messy given
910	 * the information that we have at this point). Can't use now argument
911	 * because DRM event time may come from monotonic clock, while
912	 * DIX timer facility uses real-time clock.
913	 */
914	if (!event_info->crtc) {
915		ErrorF("%s no crtc\n", __func__);
916		if (event_info->drm_queue_seq)
917			amdgpu_drm_abort_entry(event_info->drm_queue_seq);
918		else
919			amdgpu_dri2_frame_event_abort(NULL, data);
920		return 0;
921	}
922
923	scrn = crtc->scrn;
924	pAMDGPUEnt = AMDGPUEntPriv(scrn);
925	ret = drmmode_get_current_ust(pAMDGPUEnt->fd, &drm_now);
926	if (ret) {
927		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
928			   "%s cannot get current time\n", __func__);
929		if (event_info->drm_queue_seq)
930			amdgpu_drm_queue_handler(pAMDGPUEnt->fd, 0, 0, 0,
931						 (void*)event_info->drm_queue_seq);
932		else
933			amdgpu_dri2_frame_event_handler(crtc, 0, 0, data);
934		return 0;
935	}
936	/*
937	 * calculate the frame number from current time
938	 * that would come from CRTC if it were running
939	 */
940	drmmode_crtc = event_info->crtc->driver_private;
941	delta_t = drm_now - (CARD64) drmmode_crtc->dpms_last_ust;
942	delta_seq = delta_t * drmmode_crtc->dpms_last_fps;
943	delta_seq /= 1000000;
944	frame = (CARD64) drmmode_crtc->dpms_last_seq + delta_seq;
945	if (event_info->drm_queue_seq)
946		amdgpu_drm_queue_handler(pAMDGPUEnt->fd, frame, drm_now / 1000000,
947					 drm_now % 1000000,
948					 (void*)event_info->drm_queue_seq);
949	else
950		amdgpu_dri2_frame_event_handler(crtc, frame, drm_now, data);
951	return 0;
952}
953
954static
955void amdgpu_dri2_schedule_event(CARD32 delay, DRI2FrameEventPtr event_info)
956{
957	event_info->timer = TimerSet(NULL, 0, delay, amdgpu_dri2_deferred_event,
958				     event_info);
959	if (delay == 0) {
960		CARD32 now = GetTimeInMillis();
961		amdgpu_dri2_deferred_event(event_info->timer, now, event_info);
962	}
963}
964
965/*
966 * Request a DRM event when the requested conditions will be satisfied.
967 *
968 * We need to handle the event and ask the server to wake up the client when
969 * we receive it.
970 */
971static int amdgpu_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
972					 CARD64 target_msc, CARD64 divisor,
973					 CARD64 remainder)
974{
975	ScreenPtr screen = draw->pScreen;
976	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
977	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
978	DRI2FrameEventPtr wait_info = NULL;
979	uintptr_t drm_queue_seq = 0;
980	xf86CrtcPtr crtc = amdgpu_dri2_drawable_crtc(draw, TRUE);
981	uint32_t msc_delta;
982	drmVBlank vbl;
983	int ret;
984	CARD64 current_msc;
985
986	/* Truncate to match kernel interfaces; means occasional overflow
987	 * misses, but that's generally not a big deal */
988	target_msc &= 0xffffffff;
989	divisor &= 0xffffffff;
990	remainder &= 0xffffffff;
991
992	/* Drawable not visible, return immediately */
993	if (crtc == NULL)
994		goto out_complete;
995
996	msc_delta = amdgpu_get_msc_delta(draw, crtc);
997
998	wait_info = calloc(1, sizeof(DRI2FrameEventRec));
999	if (!wait_info)
1000		goto out_complete;
1001
1002	wait_info->drawable_id = draw->id;
1003	wait_info->client = client;
1004	wait_info->type = DRI2_WAITMSC;
1005	wait_info->crtc = crtc;
1006
1007	/*
1008	 * CRTC is in DPMS off state, calculate wait time from current time,
1009	 * target_msc and last vblank time/sequence when CRTC was turned off
1010	 */
1011	if (!amdgpu_crtc_is_enabled(crtc)) {
1012		CARD32 delay;
1013		target_msc -= msc_delta;
1014		delay = amdgpu_dri2_extrapolate_msc_delay(crtc, &target_msc,
1015							  divisor, remainder);
1016		amdgpu_dri2_schedule_event(delay, wait_info);
1017		DRI2BlockClient(client, draw);
1018		return TRUE;
1019	}
1020
1021	/* Get current count */
1022	vbl.request.type = DRM_VBLANK_RELATIVE;
1023	vbl.request.type |= amdgpu_populate_vbl_request_type(crtc);
1024	vbl.request.sequence = 0;
1025	ret = drmWaitVBlank(pAMDGPUEnt->fd, &vbl);
1026	if (ret) {
1027		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1028			   "get vblank counter failed: %s\n", strerror(errno));
1029		goto out_complete;
1030	}
1031
1032	current_msc = vbl.reply.sequence + msc_delta;
1033	current_msc &= 0xffffffff;
1034
1035	drm_queue_seq = amdgpu_drm_queue_alloc(crtc, client, AMDGPU_DRM_QUEUE_ID_DEFAULT,
1036					       wait_info, amdgpu_dri2_frame_event_handler,
1037					       amdgpu_dri2_frame_event_abort);
1038	if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
1039		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1040			   "Allocating DRM queue event entry failed.\n");
1041		goto out_complete;
1042	}
1043	wait_info->drm_queue_seq = drm_queue_seq;
1044
1045	/*
1046	 * If divisor is zero, or current_msc is smaller than target_msc,
1047	 * we just need to make sure target_msc passes  before waking up the
1048	 * client.
1049	 */
1050	if (divisor == 0 || current_msc < target_msc) {
1051		/* If target_msc already reached or passed, set it to
1052		 * current_msc to ensure we return a reasonable value back
1053		 * to the caller. This keeps the client from continually
1054		 * sending us MSC targets from the past by forcibly updating
1055		 * their count on this call.
1056		 */
1057		if (current_msc >= target_msc)
1058			target_msc = current_msc;
1059		vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
1060		vbl.request.type |= amdgpu_populate_vbl_request_type(crtc);
1061		vbl.request.sequence = target_msc - msc_delta;
1062		vbl.request.signal = drm_queue_seq;
1063		ret = drmWaitVBlank(pAMDGPUEnt->fd, &vbl);
1064		if (ret) {
1065			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1066				   "get vblank counter failed: %s\n",
1067				   strerror(errno));
1068			goto out_complete;
1069		}
1070
1071		DRI2BlockClient(client, draw);
1072		return TRUE;
1073	}
1074
1075	/*
1076	 * If we get here, target_msc has already passed or we don't have one,
1077	 * so we queue an event that will satisfy the divisor/remainder equation.
1078	 */
1079	vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
1080	vbl.request.type |= amdgpu_populate_vbl_request_type(crtc);
1081
1082	vbl.request.sequence = current_msc - (current_msc % divisor) +
1083	    remainder - msc_delta;
1084
1085	/*
1086	 * If calculated remainder is larger than requested remainder,
1087	 * it means we've passed the last point where
1088	 * seq % divisor == remainder, so we need to wait for the next time
1089	 * that will happen.
1090	 */
1091	if ((current_msc % divisor) >= remainder)
1092		vbl.request.sequence += divisor;
1093
1094	vbl.request.signal = drm_queue_seq;
1095	ret = drmWaitVBlank(pAMDGPUEnt->fd, &vbl);
1096	if (ret) {
1097		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1098			   "get vblank counter failed: %s\n", strerror(errno));
1099		goto out_complete;
1100	}
1101
1102	DRI2BlockClient(client, draw);
1103
1104	return TRUE;
1105
1106out_complete:
1107	if (wait_info)
1108		amdgpu_dri2_deferred_event(NULL, 0, wait_info);
1109	return TRUE;
1110}
1111
1112/*
1113 * ScheduleSwap is responsible for requesting a DRM vblank event for the
1114 * appropriate frame.
1115 *
1116 * In the case of a blit (e.g. for a windowed swap) or buffer exchange,
1117 * the vblank requested can simply be the last queued swap frame + the swap
1118 * interval for the drawable.
1119 *
1120 * In the case of a page flip, we request an event for the last queued swap
1121 * frame + swap interval - 1, since we'll need to queue the flip for the frame
1122 * immediately following the received event.
1123 *
1124 * The client will be blocked if it tries to perform further GL commands
1125 * after queueing a swap, though in the Intel case after queueing a flip, the
1126 * client is free to queue more commands; they'll block in the kernel if
1127 * they access buffers busy with the flip.
1128 *
1129 * When the swap is complete, the driver should call into the server so it
1130 * can send any swap complete events that have been requested.
1131 */
1132static int amdgpu_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
1133				     DRI2BufferPtr front, DRI2BufferPtr back,
1134				     CARD64 * target_msc, CARD64 divisor,
1135				     CARD64 remainder, DRI2SwapEventPtr func,
1136				     void *data)
1137{
1138	ScreenPtr screen = draw->pScreen;
1139	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
1140	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
1141	xf86CrtcPtr crtc = amdgpu_dri2_drawable_crtc(draw, TRUE);
1142	uint32_t msc_delta;
1143	drmVBlank vbl;
1144	int ret, flip = 0;
1145	DRI2FrameEventPtr swap_info = NULL;
1146	uintptr_t drm_queue_seq;
1147	CARD64 current_msc;
1148	BoxRec box;
1149	RegionRec region;
1150
1151	/* Truncate to match kernel interfaces; means occasional overflow
1152	 * misses, but that's generally not a big deal */
1153	*target_msc &= 0xffffffff;
1154	divisor &= 0xffffffff;
1155	remainder &= 0xffffffff;
1156
1157	/* amdgpu_dri2_frame_event_handler will get called some unknown time in the
1158	 * future with these buffers.  Take a reference to ensure that they won't
1159	 * get destroyed before then.
1160	 */
1161	amdgpu_dri2_ref_buffer(front);
1162	amdgpu_dri2_ref_buffer(back);
1163
1164	/* either off-screen or CRTC not usable... just complete the swap */
1165	if (crtc == NULL)
1166		goto blit_fallback;
1167
1168	msc_delta = amdgpu_get_msc_delta(draw, crtc);
1169
1170	swap_info = calloc(1, sizeof(DRI2FrameEventRec));
1171	if (!swap_info)
1172		goto blit_fallback;
1173
1174	swap_info->type = DRI2_SWAP;
1175	swap_info->drawable_id = draw->id;
1176	swap_info->client = client;
1177	swap_info->event_complete = func;
1178	swap_info->event_data = data;
1179	swap_info->front = front;
1180	swap_info->back = back;
1181	swap_info->crtc = crtc;
1182
1183	drm_queue_seq = amdgpu_drm_queue_alloc(crtc, client, AMDGPU_DRM_QUEUE_ID_DEFAULT,
1184					       swap_info, amdgpu_dri2_frame_event_handler,
1185					       amdgpu_dri2_frame_event_abort);
1186	if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
1187		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1188			   "Allocating DRM queue entry failed.\n");
1189		goto blit_fallback;
1190	}
1191	swap_info->drm_queue_seq = drm_queue_seq;
1192
1193	/*
1194	 * CRTC is in DPMS off state, fallback to blit, but calculate
1195	 * wait time from current time, target_msc and last vblank
1196	 * time/sequence when CRTC was turned off
1197	 */
1198	if (!amdgpu_crtc_is_enabled(crtc)) {
1199		CARD32 delay;
1200		*target_msc -= msc_delta;
1201		delay = amdgpu_dri2_extrapolate_msc_delay(crtc, target_msc,
1202							  divisor, remainder);
1203		*target_msc += msc_delta;
1204		*target_msc &= 0xffffffff;
1205		amdgpu_dri2_schedule_event(delay, swap_info);
1206		return TRUE;
1207	}
1208
1209	/* Get current count */
1210	vbl.request.type = DRM_VBLANK_RELATIVE;
1211	vbl.request.type |= amdgpu_populate_vbl_request_type(crtc);
1212	vbl.request.sequence = 0;
1213	ret = drmWaitVBlank(pAMDGPUEnt->fd, &vbl);
1214	if (ret) {
1215		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1216			   "first get vblank counter failed: %s\n",
1217			   strerror(errno));
1218		goto blit_fallback;
1219	}
1220
1221	current_msc = vbl.reply.sequence + msc_delta;
1222	current_msc &= 0xffffffff;
1223
1224	/* Flips need to be submitted one frame before */
1225	if (can_flip(scrn, draw, front, back)) {
1226		swap_info->type = DRI2_FLIP;
1227		flip = 1;
1228	}
1229
1230	/* Correct target_msc by 'flip' if swap_info->type == DRI2_FLIP.
1231	 * Do it early, so handling of different timing constraints
1232	 * for divisor, remainder and msc vs. target_msc works.
1233	 */
1234	if (*target_msc > 0)
1235		*target_msc -= flip;
1236
1237	/*
1238	 * If divisor is zero, or current_msc is smaller than target_msc
1239	 * we just need to make sure target_msc passes before initiating
1240	 * the swap.
1241	 */
1242	if (divisor == 0 || current_msc < *target_msc) {
1243		vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
1244		/* If non-pageflipping, but blitting/exchanging, we need to use
1245		 * DRM_VBLANK_NEXTONMISS to avoid unreliable timestamping later
1246		 * on.
1247		 */
1248		if (flip == 0)
1249			vbl.request.type |= DRM_VBLANK_NEXTONMISS;
1250		vbl.request.type |= amdgpu_populate_vbl_request_type(crtc);
1251
1252		/* If target_msc already reached or passed, set it to
1253		 * current_msc to ensure we return a reasonable value back
1254		 * to the caller. This makes swap_interval logic more robust.
1255		 */
1256		if (current_msc >= *target_msc)
1257			*target_msc = current_msc;
1258
1259		vbl.request.sequence = *target_msc - msc_delta;
1260		vbl.request.signal = drm_queue_seq;
1261		ret = drmWaitVBlank(pAMDGPUEnt->fd, &vbl);
1262		if (ret) {
1263			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1264				   "divisor 0 get vblank counter failed: %s\n",
1265				   strerror(errno));
1266			goto blit_fallback;
1267		}
1268
1269		*target_msc = vbl.reply.sequence + flip + msc_delta;
1270		*target_msc &= 0xffffffff;
1271		swap_info->frame = *target_msc;
1272
1273		return TRUE;
1274	}
1275
1276	/*
1277	 * If we get here, target_msc has already passed or we don't have one,
1278	 * and we need to queue an event that will satisfy the divisor/remainder
1279	 * equation.
1280	 */
1281	vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
1282	if (flip == 0)
1283		vbl.request.type |= DRM_VBLANK_NEXTONMISS;
1284	vbl.request.type |= amdgpu_populate_vbl_request_type(crtc);
1285
1286	vbl.request.sequence = current_msc - (current_msc % divisor) +
1287	    remainder - msc_delta;
1288
1289	/*
1290	 * If the calculated deadline vbl.request.sequence is smaller than
1291	 * or equal to current_msc, it means we've passed the last point
1292	 * when effective onset frame seq could satisfy
1293	 * seq % divisor == remainder, so we need to wait for the next time
1294	 * this will happen.
1295
1296	 * This comparison takes the 1 frame swap delay in pageflipping mode
1297	 * into account, as well as a potential DRM_VBLANK_NEXTONMISS delay
1298	 * if we are blitting/exchanging instead of flipping.
1299	 */
1300	if (vbl.request.sequence <= current_msc)
1301		vbl.request.sequence += divisor;
1302
1303	/* Account for 1 frame extra pageflip delay if flip > 0 */
1304	vbl.request.sequence -= flip;
1305
1306	vbl.request.signal = drm_queue_seq;
1307	ret = drmWaitVBlank(pAMDGPUEnt->fd, &vbl);
1308	if (ret) {
1309		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1310			   "final get vblank counter failed: %s\n",
1311			   strerror(errno));
1312		goto blit_fallback;
1313	}
1314
1315	/* Adjust returned value for 1 fame pageflip offset of flip > 0 */
1316	*target_msc = vbl.reply.sequence + flip + msc_delta;
1317	*target_msc &= 0xffffffff;
1318	swap_info->frame = *target_msc;
1319
1320	return TRUE;
1321
1322blit_fallback:
1323	if (swap_info) {
1324		swap_info->type = DRI2_SWAP;
1325		amdgpu_dri2_schedule_event(FALLBACK_SWAP_DELAY, swap_info);
1326	} else {
1327		box.x1 = 0;
1328		box.y1 = 0;
1329		box.x2 = draw->width;
1330		box.y2 = draw->height;
1331		REGION_INIT(pScreen, &region, &box, 0);
1332
1333		amdgpu_dri2_copy_region(draw, &region, front, back);
1334
1335		DRI2SwapComplete(client, draw, 0, 0, 0, DRI2_BLIT_COMPLETE, func, data);
1336
1337		amdgpu_dri2_unref_buffer(front);
1338		amdgpu_dri2_unref_buffer(back);
1339	}
1340
1341	*target_msc = 0;	/* offscreen, so zero out target vblank count */
1342	return TRUE;
1343}
1344
1345Bool amdgpu_dri2_screen_init(ScreenPtr pScreen)
1346{
1347	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1348	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
1349	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
1350	DRI2InfoRec dri2_info = { 0 };
1351	const char *driverNames[2];
1352	Bool scheduling_works = TRUE;
1353
1354	if (!info->dri2.available)
1355		return FALSE;
1356
1357	info->dri2.device_name = drmGetDeviceNameFromFd(pAMDGPUEnt->fd);
1358
1359	dri2_info.driverName = SI_DRIVER_NAME;
1360	dri2_info.fd = pAMDGPUEnt->fd;
1361	dri2_info.deviceName = info->dri2.device_name;
1362	dri2_info.version = DRI2INFOREC_VERSION;
1363	dri2_info.CreateBuffer = amdgpu_dri2_create_buffer;
1364	dri2_info.DestroyBuffer = amdgpu_dri2_destroy_buffer;
1365	dri2_info.CopyRegion = amdgpu_dri2_copy_region;
1366
1367	if (info->drmmode.count_crtcs > 2) {
1368#ifdef DRM_CAP_VBLANK_HIGH_CRTC
1369		uint64_t cap_value;
1370
1371		if (drmGetCap
1372		    (pAMDGPUEnt->fd, DRM_CAP_VBLANK_HIGH_CRTC, &cap_value)) {
1373			xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1374				   "You need a newer kernel "
1375				   "for VBLANKs on CRTC > 1\n");
1376			scheduling_works = FALSE;
1377		} else if (!cap_value) {
1378			xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1379				   "Your kernel does not "
1380				   "handle VBLANKs on CRTC > 1\n");
1381			scheduling_works = FALSE;
1382		}
1383#else
1384		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1385			   "You need to rebuild against a "
1386			   "newer libdrm to handle VBLANKs on CRTC > 1\n");
1387		scheduling_works = FALSE;
1388#endif
1389	}
1390
1391	if (scheduling_works) {
1392		dri2_info.version = 4;
1393		dri2_info.ScheduleSwap = amdgpu_dri2_schedule_swap;
1394		dri2_info.GetMSC = amdgpu_dri2_get_msc;
1395		dri2_info.ScheduleWaitMSC = amdgpu_dri2_schedule_wait_msc;
1396		dri2_info.numDrivers = AMDGPU_ARRAY_SIZE(driverNames);
1397		dri2_info.driverNames = driverNames;
1398		driverNames[0] = driverNames[1] = dri2_info.driverName;
1399
1400		if (DRI2InfoCnt == 0) {
1401			if (!dixRegisterPrivateKey(dri2_window_private_key,
1402						   PRIVATE_WINDOW,
1403						   sizeof(struct dri2_window_priv))) {
1404				xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1405					   "Failed to get DRI2 window private\n");
1406				return FALSE;
1407			}
1408
1409			AddCallback(&ClientStateCallback,
1410				    amdgpu_dri2_client_state_changed, 0);
1411		}
1412
1413		DRI2InfoCnt++;
1414	}
1415
1416#if DRI2INFOREC_VERSION >= 9
1417	dri2_info.version = 9;
1418	dri2_info.CreateBuffer2 = amdgpu_dri2_create_buffer2;
1419	dri2_info.DestroyBuffer2 = amdgpu_dri2_destroy_buffer2;
1420	dri2_info.CopyRegion2 = amdgpu_dri2_copy_region2;
1421#endif
1422
1423	info->dri2.enabled = DRI2ScreenInit(pScreen, &dri2_info);
1424	return info->dri2.enabled;
1425}
1426
1427void amdgpu_dri2_close_screen(ScreenPtr pScreen)
1428{
1429	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1430	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
1431
1432	if (--DRI2InfoCnt == 0)
1433		DeleteCallback(&ClientStateCallback,
1434			       amdgpu_dri2_client_state_changed, 0);
1435
1436	DRI2CloseScreen(pScreen);
1437	drmFree(info->dri2.device_name);
1438}
1439
1440#endif /* DRI2 */
1441