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