amdgpu_dri2.c revision 35d5b7c7
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	if (!pixmap)
165		return NULL;
166
167	buffers = calloc(1, sizeof *buffers);
168	if (!buffers)
169		goto error;
170
171	if (is_glamor_pixmap) {
172		pixmap = amdgpu_glamor_set_pixmap_bo(drawable, pixmap);
173		pixmap->refcnt++;
174	}
175
176	if (!amdgpu_get_flink_name(pAMDGPUEnt, pixmap, &buffers->name))
177		goto error;
178
179	privates = calloc(1, sizeof(struct dri2_buffer_priv));
180	if (!privates)
181		goto error;
182
183	buffers->attachment = attachment;
184	buffers->pitch = pixmap->devKind;
185	buffers->cpp = cpp;
186	buffers->driverPrivate = privates;
187	buffers->format = format;
188	buffers->flags = 0;	/* not tiled */
189	privates->pixmap = pixmap;
190	privates->attachment = attachment;
191	privates->refcnt = 1;
192
193	return buffers;
194
195error:
196	free(buffers);
197	(*pScreen->DestroyPixmap) (pixmap);
198	return NULL;
199}
200
201static void
202amdgpu_dri2_destroy_buffer2(ScreenPtr pScreen,
203			    DrawablePtr drawable, BufferPtr buffers)
204{
205	if (buffers) {
206		struct dri2_buffer_priv *private = buffers->driverPrivate;
207
208		/* Trying to free an already freed buffer is unlikely to end well */
209		if (private->refcnt == 0) {
210			ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen);
211
212			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
213				   "Attempted to destroy previously destroyed buffer.\
214 This is a programming error\n");
215			return;
216		}
217
218		private->refcnt--;
219		if (private->refcnt == 0) {
220			if (private->pixmap)
221				(*pScreen->DestroyPixmap) (private->pixmap);
222
223			free(buffers->driverPrivate);
224			free(buffers);
225		}
226	}
227}
228
229static inline PixmapPtr GetDrawablePixmap(DrawablePtr drawable)
230{
231	if (drawable->type == DRAWABLE_PIXMAP)
232		return (PixmapPtr) drawable;
233	else {
234		struct _Window *pWin = (struct _Window *)drawable;
235		return drawable->pScreen->GetWindowPixmap(pWin);
236	}
237}
238
239static void
240amdgpu_dri2_copy_region2(ScreenPtr pScreen,
241			 DrawablePtr drawable,
242			 RegionPtr region,
243			 BufferPtr dest_buffer, BufferPtr src_buffer)
244{
245	struct dri2_buffer_priv *src_private = src_buffer->driverPrivate;
246	struct dri2_buffer_priv *dst_private = dest_buffer->driverPrivate;
247	DrawablePtr src_drawable;
248	DrawablePtr dst_drawable;
249	RegionPtr copy_clip;
250	GCPtr gc;
251	Bool translate = FALSE;
252	int off_x = 0, off_y = 0;
253
254	src_drawable = &src_private->pixmap->drawable;
255	dst_drawable = &dst_private->pixmap->drawable;
256
257	if (src_private->attachment == DRI2BufferFrontLeft) {
258		if (drawable->pScreen != pScreen) {
259			src_drawable = DRI2UpdatePrime(drawable, src_buffer);
260			if (!src_drawable)
261				return;
262		} else
263			src_drawable = drawable;
264	}
265	if (dst_private->attachment == DRI2BufferFrontLeft) {
266		if (drawable->pScreen != pScreen) {
267			dst_drawable = DRI2UpdatePrime(drawable, dest_buffer);
268			if (!dst_drawable)
269				return;
270			if (dst_drawable != drawable)
271				translate = TRUE;
272		} else
273			dst_drawable = drawable;
274	}
275
276	if (translate && drawable->type == DRAWABLE_WINDOW) {
277		PixmapPtr pPix = GetDrawablePixmap(drawable);
278
279		off_x = drawable->x - pPix->screen_x;
280		off_y = drawable->y - pPix->screen_y;
281	}
282	gc = GetScratchGC(dst_drawable->depth, pScreen);
283	copy_clip = REGION_CREATE(pScreen, NULL, 0);
284	REGION_COPY(pScreen, copy_clip, region);
285
286	if (translate) {
287		REGION_TRANSLATE(pScreen, copy_clip, off_x, off_y);
288	}
289
290	(*gc->funcs->ChangeClip) (gc, CT_REGION, copy_clip, 0);
291	ValidateGC(dst_drawable, gc);
292
293	(*gc->ops->CopyArea) (src_drawable, dst_drawable, gc,
294			      0, 0, drawable->width, drawable->height, off_x,
295			      off_y);
296
297	FreeScratchGC(gc);
298}
299
300enum DRI2FrameEventType {
301	DRI2_SWAP,
302	DRI2_FLIP,
303	DRI2_WAITMSC,
304};
305
306typedef struct _DRI2FrameEvent {
307	XID drawable_id;
308	ClientPtr client;
309	enum DRI2FrameEventType type;
310	unsigned frame;
311	xf86CrtcPtr crtc;
312	OsTimerPtr timer;
313	uintptr_t drm_queue_seq;
314
315	/* for swaps & flips only */
316	DRI2SwapEventPtr event_complete;
317	void *event_data;
318	DRI2BufferPtr front;
319	DRI2BufferPtr back;
320} DRI2FrameEventRec, *DRI2FrameEventPtr;
321
322static int DRI2InfoCnt;
323
324static void amdgpu_dri2_ref_buffer(BufferPtr buffer)
325{
326	struct dri2_buffer_priv *private = buffer->driverPrivate;
327	private->refcnt++;
328}
329
330static void amdgpu_dri2_unref_buffer(BufferPtr buffer)
331{
332	if (buffer) {
333		struct dri2_buffer_priv *private = buffer->driverPrivate;
334		DrawablePtr draw = &private->pixmap->drawable;
335
336		amdgpu_dri2_destroy_buffer2(draw->pScreen, draw, buffer);
337	}
338}
339
340static void
341amdgpu_dri2_client_state_changed(CallbackListPtr * ClientStateCallback,
342				 pointer data, pointer calldata)
343{
344	NewClientInfoRec *clientinfo = calldata;
345	ClientPtr pClient = clientinfo->client;
346
347	switch (pClient->clientState) {
348	case ClientStateRetained:
349	case ClientStateGone:
350		amdgpu_drm_abort_client(pClient);
351		break;
352	default:
353		break;
354	}
355}
356
357/*
358 * Get current frame count delta for the specified drawable and CRTC
359 */
360static uint32_t amdgpu_get_msc_delta(DrawablePtr pDraw, xf86CrtcPtr crtc)
361{
362	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
363
364	if (pDraw && pDraw->type == DRAWABLE_WINDOW)
365		return drmmode_crtc->interpolated_vblanks +
366			get_dri2_window_priv((WindowPtr)pDraw)->vblank_delta;
367
368	return drmmode_crtc->interpolated_vblanks;
369}
370
371/*
372 * Get current frame count and timestamp of the specified CRTC
373 */
374static Bool amdgpu_dri2_get_crtc_msc(xf86CrtcPtr crtc, CARD64 *ust, CARD64 *msc)
375{
376	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
377
378	if (!amdgpu_crtc_is_enabled(crtc) ||
379	    drmmode_crtc_get_ust_msc(crtc, ust, msc) != Success) {
380		/* CRTC is not running, extrapolate MSC and timestamp */
381		ScrnInfoPtr scrn = crtc->scrn;
382		AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
383		CARD64 now, delta_t, delta_seq;
384
385		if (!drmmode_crtc->dpms_last_ust)
386			return FALSE;
387
388		if (drmmode_get_current_ust(pAMDGPUEnt->fd, &now) != 0) {
389			xf86DrvMsg(scrn->scrnIndex, X_ERROR,
390				   "%s cannot get current time\n", __func__);
391			return FALSE;
392		}
393
394		delta_t = now - drmmode_crtc->dpms_last_ust;
395		delta_seq = delta_t * drmmode_crtc->dpms_last_fps;
396		delta_seq /= 1000000;
397		*ust = drmmode_crtc->dpms_last_ust;
398		delta_t = delta_seq * 1000000;
399		delta_t /= drmmode_crtc->dpms_last_fps;
400		*ust += delta_t;
401		*msc = drmmode_crtc->dpms_last_seq;
402		*msc += delta_seq;
403	}
404
405	*msc += drmmode_crtc->interpolated_vblanks;
406
407	return TRUE;
408}
409
410static
411xf86CrtcPtr amdgpu_dri2_drawable_crtc(DrawablePtr pDraw, Bool consider_disabled)
412{
413	ScreenPtr pScreen = pDraw->pScreen;
414	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
415	xf86CrtcPtr crtc = amdgpu_pick_best_crtc(pScrn, consider_disabled,
416						 pDraw->x, pDraw->x + pDraw->width,
417						 pDraw->y, pDraw->y + pDraw->height);
418
419	if (crtc && pDraw->type == DRAWABLE_WINDOW) {
420		struct dri2_window_priv *priv = get_dri2_window_priv((WindowPtr)pDraw);
421
422		if (priv->crtc && priv->crtc != crtc) {
423			CARD64 ust, mscold, mscnew;
424
425			if (amdgpu_dri2_get_crtc_msc(priv->crtc, &ust, &mscold) &&
426			    amdgpu_dri2_get_crtc_msc(crtc, &ust, &mscnew))
427				priv->vblank_delta += mscold - mscnew;
428		}
429
430		priv->crtc = crtc;
431	}
432
433	return crtc;
434}
435
436static void
437amdgpu_dri2_flip_event_abort(xf86CrtcPtr crtc, void *event_data)
438{
439	if (crtc)
440		AMDGPUPTR(crtc->scrn)->drmmode.dri2_flipping = FALSE;
441
442	free(event_data);
443}
444
445static void
446amdgpu_dri2_flip_event_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec,
447			       void *event_data)
448{
449	DRI2FrameEventPtr flip = event_data;
450	ScrnInfoPtr scrn = crtc->scrn;
451	unsigned tv_sec, tv_usec;
452	DrawablePtr drawable;
453	ScreenPtr screen;
454	int status;
455	PixmapPtr pixmap;
456
457	status = dixLookupDrawable(&drawable, flip->drawable_id, serverClient,
458				   M_ANY, DixWriteAccess);
459	if (status != Success)
460		goto abort;
461
462	frame += amdgpu_get_msc_delta(drawable, crtc);
463
464	screen = scrn->pScreen;
465	pixmap = screen->GetScreenPixmap(screen);
466	xf86DrvMsgVerb(scrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
467		       "%s:%d fevent[%p] width %d pitch %d (/4 %d)\n",
468		       __func__, __LINE__, flip, pixmap->drawable.width,
469		       pixmap->devKind, pixmap->devKind / 4);
470
471	tv_sec = usec / 1000000;
472	tv_usec = usec % 1000000;
473
474	/* We assume our flips arrive in order, so we don't check the frame */
475	switch (flip->type) {
476	case DRI2_SWAP:
477		/* Check for too small vblank count of pageflip completion, taking wraparound
478		 * into account. This usually means some defective kms pageflip completion,
479		 * causing wrong (msc, ust) return values and possible visual corruption.
480		 */
481		if ((frame < flip->frame) && (flip->frame - frame < 5)) {
482			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
483				   "%s: Pageflip completion event has impossible msc %u < target_msc %u\n",
484				   __func__, frame, flip->frame);
485			/* All-Zero values signal failure of (msc, ust) timestamping to client. */
486			frame = tv_sec = tv_usec = 0;
487		}
488
489		DRI2SwapComplete(flip->client, drawable, frame, tv_sec, tv_usec,
490				 DRI2_FLIP_COMPLETE, flip->event_complete,
491				 flip->event_data);
492		break;
493	default:
494		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
495			   "%s: unknown vblank event received\n", __func__);
496		/* Unknown type */
497		break;
498	}
499
500abort:
501	amdgpu_dri2_flip_event_abort(crtc, event_data);
502}
503
504static Bool
505amdgpu_dri2_schedule_flip(xf86CrtcPtr crtc, ClientPtr client,
506			  DrawablePtr draw, DRI2BufferPtr front,
507			  DRI2BufferPtr back, DRI2SwapEventPtr func,
508			  void *data, unsigned int target_msc)
509{
510	ScrnInfoPtr scrn = crtc->scrn;
511	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
512	struct dri2_buffer_priv *back_priv;
513	DRI2FrameEventPtr flip_info;
514
515	flip_info = calloc(1, sizeof(DRI2FrameEventRec));
516	if (!flip_info)
517		return FALSE;
518
519	flip_info->drawable_id = draw->id;
520	flip_info->client = client;
521	flip_info->type = DRI2_SWAP;
522	flip_info->event_complete = func;
523	flip_info->event_data = data;
524	flip_info->frame = target_msc;
525	flip_info->crtc = crtc;
526
527	xf86DrvMsgVerb(scrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
528		       "%s:%d fevent[%p]\n", __func__, __LINE__, flip_info);
529
530	/* Page flip the full screen buffer */
531	back_priv = back->driverPrivate;
532	if (amdgpu_do_pageflip(scrn, client, back_priv->pixmap,
533			       AMDGPU_DRM_QUEUE_ID_DEFAULT, flip_info, crtc,
534			       amdgpu_dri2_flip_event_handler,
535			       amdgpu_dri2_flip_event_abort, FLIP_VSYNC,
536			       target_msc - amdgpu_get_msc_delta(draw, crtc))) {
537		info->drmmode.dri2_flipping = TRUE;
538		return TRUE;
539	}
540	return FALSE;
541}
542
543static Bool update_front(DrawablePtr draw, DRI2BufferPtr front)
544{
545	ScreenPtr screen = draw->pScreen;
546	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
547	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
548	PixmapPtr pixmap = get_drawable_pixmap(draw);
549	struct dri2_buffer_priv *priv = front->driverPrivate;
550
551	if (!amdgpu_get_flink_name(pAMDGPUEnt, pixmap, &front->name))
552		return FALSE;
553
554	(*draw->pScreen->DestroyPixmap) (priv->pixmap);
555	front->pitch = pixmap->devKind;
556	front->cpp = pixmap->drawable.bitsPerPixel / 8;
557	priv->pixmap = pixmap;
558	pixmap->refcnt++;
559
560	return TRUE;
561}
562
563static Bool
564can_exchange(ScrnInfoPtr pScrn, DrawablePtr draw,
565	     DRI2BufferPtr front, DRI2BufferPtr back)
566{
567	struct dri2_buffer_priv *front_priv = front->driverPrivate;
568	struct dri2_buffer_priv *back_priv = back->driverPrivate;
569	PixmapPtr front_pixmap;
570	PixmapPtr back_pixmap = back_priv->pixmap;
571
572	if (!update_front(draw, front))
573		return FALSE;
574
575	front_pixmap = front_priv->pixmap;
576
577	if (front_pixmap->drawable.width != back_pixmap->drawable.width)
578		return FALSE;
579
580	if (front_pixmap->drawable.height != back_pixmap->drawable.height)
581		return FALSE;
582
583	if (front_pixmap->drawable.bitsPerPixel !=
584	    back_pixmap->drawable.bitsPerPixel)
585		return FALSE;
586
587	if (front_pixmap->devKind != back_pixmap->devKind)
588		return FALSE;
589
590	return TRUE;
591}
592
593static Bool
594can_flip(xf86CrtcPtr crtc, DrawablePtr draw,
595	 DRI2BufferPtr front, DRI2BufferPtr back)
596{
597	ScrnInfoPtr pScrn = crtc->scrn;
598	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
599	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
600	int num_crtcs_on;
601	int i;
602
603	if (draw->type != DRAWABLE_WINDOW ||
604	    !info->allowPageFlip ||
605	    info->sprites_visible > 0 ||
606	    info->drmmode.present_flipping ||
607	    !pScrn->vtSema ||
608	    !DRI2CanFlip(draw))
609		return FALSE;
610
611	for (i = 0, num_crtcs_on = 0; i < config->num_crtc; i++) {
612		if (drmmode_crtc_can_flip(config->crtc[i]))
613			num_crtcs_on++;
614	}
615
616	return num_crtcs_on > 0 && can_exchange(pScrn, draw, front, back);
617}
618
619static void
620amdgpu_dri2_exchange_buffers(DrawablePtr draw, DRI2BufferPtr front,
621			     DRI2BufferPtr back)
622{
623	struct dri2_buffer_priv *front_priv = front->driverPrivate;
624	struct dri2_buffer_priv *back_priv = back->driverPrivate;
625	struct amdgpu_pixmap *front_pix;
626	struct amdgpu_pixmap *back_pix;
627	ScreenPtr screen;
628	AMDGPUInfoPtr info;
629	RegionRec region;
630	int tmp;
631
632	region.extents.x1 = region.extents.y1 = 0;
633	region.extents.x2 = front_priv->pixmap->drawable.width;
634	region.extents.y2 = front_priv->pixmap->drawable.height;
635	region.data = NULL;
636	DamageRegionAppend(&front_priv->pixmap->drawable, &region);
637
638	/* Swap BO names so DRI works */
639	tmp = front->name;
640	front->name = back->name;
641	back->name = tmp;
642
643	/* Swap pixmap privates */
644	front_pix = amdgpu_get_pixmap_private(front_priv->pixmap);
645	back_pix = amdgpu_get_pixmap_private(back_priv->pixmap);
646	amdgpu_set_pixmap_private(front_priv->pixmap, back_pix);
647	amdgpu_set_pixmap_private(back_priv->pixmap, front_pix);
648
649	/* Do we need to update the Screen? */
650	screen = draw->pScreen;
651	info = AMDGPUPTR(xf86ScreenToScrn(screen));
652	if (front_pix->bo == info->front_buffer) {
653		struct amdgpu_pixmap *screen_priv =
654			amdgpu_get_pixmap_private(screen->GetScreenPixmap(screen));
655
656		amdgpu_bo_ref(back_pix->bo);
657		amdgpu_bo_unref(&info->front_buffer);
658		info->front_buffer = back_pix->bo;
659		*screen_priv = *back_pix;
660	}
661
662	amdgpu_glamor_exchange_buffers(front_priv->pixmap, back_priv->pixmap);
663
664	DamageRegionProcessPending(&front_priv->pixmap->drawable);
665}
666
667static void amdgpu_dri2_frame_event_abort(xf86CrtcPtr crtc, void *event_data)
668{
669	DRI2FrameEventPtr event = event_data;
670
671	TimerCancel(event->timer);
672	TimerFree(event->timer);
673	amdgpu_dri2_unref_buffer(event->front);
674	amdgpu_dri2_unref_buffer(event->back);
675	free(event);
676}
677
678static void amdgpu_dri2_frame_event_handler(xf86CrtcPtr crtc, uint32_t seq,
679					    uint64_t usec, void *event_data)
680{
681	DRI2FrameEventPtr event = event_data;
682	ScrnInfoPtr scrn = crtc->scrn;
683	DrawablePtr drawable;
684	int status;
685	int swap_type;
686	BoxRec box;
687	RegionRec region;
688
689	status = dixLookupDrawable(&drawable, event->drawable_id, serverClient,
690				   M_ANY, DixWriteAccess);
691	if (status != Success)
692		goto cleanup;
693
694	seq += amdgpu_get_msc_delta(drawable, crtc);
695
696	switch (event->type) {
697	case DRI2_FLIP:
698		if (can_flip(crtc, drawable, event->front, event->back) &&
699		    amdgpu_dri2_schedule_flip(crtc,
700					      event->client,
701					      drawable,
702					      event->front,
703					      event->back,
704					      event->event_complete,
705					      event->event_data,
706					      event->frame)) {
707			amdgpu_dri2_exchange_buffers(drawable, event->front,
708						     event->back);
709			break;
710		}
711		/* else fall through to exchange/blit */
712	case DRI2_SWAP:
713		if (DRI2CanExchange(drawable) &&
714		    can_exchange(scrn, drawable, event->front, event->back)) {
715			amdgpu_dri2_exchange_buffers(drawable, event->front,
716						     event->back);
717			swap_type = DRI2_EXCHANGE_COMPLETE;
718		} else {
719			box.x1 = 0;
720			box.y1 = 0;
721			box.x2 = drawable->width;
722			box.y2 = drawable->height;
723			REGION_INIT(pScreen, &region, &box, 0);
724			amdgpu_dri2_copy_region2(drawable->pScreen, drawable, &region,
725						 event->front, event->back);
726			swap_type = DRI2_BLIT_COMPLETE;
727		}
728
729		DRI2SwapComplete(event->client, drawable, seq, usec / 1000000,
730				 usec % 1000000, swap_type, event->event_complete,
731				 event->event_data);
732
733		break;
734	case DRI2_WAITMSC:
735		DRI2WaitMSCComplete(event->client, drawable, seq, usec / 1000000,
736				    usec % 1000000);
737		break;
738	default:
739		/* Unknown type */
740		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
741			   "%s: unknown vblank event received\n", __func__);
742		break;
743	}
744
745cleanup:
746	amdgpu_dri2_frame_event_abort(crtc, event_data);
747}
748
749/*
750 * This function should be called on a disabled CRTC only (i.e., CRTC
751 * in DPMS-off state). It will calculate the delay necessary to reach
752 * target_msc from present time if the CRTC were running.
753 */
754static
755CARD32 amdgpu_dri2_extrapolate_msc_delay(xf86CrtcPtr crtc, CARD64 * target_msc,
756					 CARD64 divisor, CARD64 remainder)
757{
758	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
759	ScrnInfoPtr pScrn = crtc->scrn;
760	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
761	int nominal_frame_rate = drmmode_crtc->dpms_last_fps;
762	CARD64 last_vblank_ust = drmmode_crtc->dpms_last_ust;
763	uint32_t last_vblank_seq = drmmode_crtc->dpms_last_seq;
764	CARD64 now, target_time, delta_t;
765	int64_t d, delta_seq;
766	int ret;
767	CARD32 d_ms;
768
769	if (!last_vblank_ust) {
770		*target_msc = 0;
771		return FALLBACK_SWAP_DELAY;
772	}
773	ret = drmmode_get_current_ust(pAMDGPUEnt->fd, &now);
774	if (ret) {
775		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
776			   "%s cannot get current time\n", __func__);
777		*target_msc = 0;
778		return FALLBACK_SWAP_DELAY;
779	}
780	delta_seq = *target_msc - last_vblank_seq;
781	delta_seq *= 1000000;
782	target_time = last_vblank_ust;
783	target_time += delta_seq / nominal_frame_rate;
784	d = target_time - now;
785	if (d < 0) {
786		/* we missed the event, adjust target_msc, do the divisor magic */
787		CARD64 current_msc = last_vblank_seq;
788
789		delta_t = now - last_vblank_ust;
790		delta_seq = delta_t * nominal_frame_rate;
791		current_msc += delta_seq / 1000000;
792		current_msc &= 0xffffffff;
793		if (divisor == 0) {
794			*target_msc = current_msc;
795			d = 0;
796		} else {
797			*target_msc =
798			    current_msc - (current_msc % divisor) + remainder;
799			if ((current_msc % divisor) >= remainder)
800				*target_msc += divisor;
801			*target_msc &= 0xffffffff;
802			delta_seq = *target_msc - last_vblank_seq;
803			delta_seq *= 1000000;
804			target_time = last_vblank_ust;
805			target_time += delta_seq / nominal_frame_rate;
806			d = target_time - now;
807		}
808	}
809	/*
810	 * convert delay to milliseconds and add margin to prevent the client
811	 * from coming back early (due to timer granularity and rounding
812	 * errors) and getting the same MSC it just got
813	 */
814	d_ms = (CARD32) d / 1000;
815	if ((CARD32) d - d_ms * 1000 > 0)
816		d_ms += 2;
817	else
818		d_ms++;
819	return d_ms;
820}
821
822/*
823 * Get current interpolated frame count and frame count timestamp, based on
824 * drawable's crtc.
825 */
826static int amdgpu_dri2_get_msc(DrawablePtr draw, CARD64 * ust, CARD64 * msc)
827{
828	xf86CrtcPtr crtc = amdgpu_dri2_drawable_crtc(draw, TRUE);
829
830	/* Drawable not displayed, make up a value */
831	if (!crtc) {
832		*ust = 0;
833		*msc = 0;
834		return TRUE;
835	}
836
837	if (!amdgpu_dri2_get_crtc_msc(crtc, ust, msc))
838		return FALSE;
839
840	if (draw && draw->type == DRAWABLE_WINDOW)
841		*msc += get_dri2_window_priv((WindowPtr)draw)->vblank_delta;
842	*msc &= 0xffffffff;
843	return TRUE;
844}
845
846static
847CARD32 amdgpu_dri2_deferred_event(OsTimerPtr timer, CARD32 now, pointer data)
848{
849	DRI2FrameEventPtr event_info = (DRI2FrameEventPtr) data;
850	xf86CrtcPtr crtc = event_info->crtc;
851	ScrnInfoPtr scrn;
852	AMDGPUEntPtr pAMDGPUEnt;
853	CARD64 drm_now;
854	int ret;
855	CARD64 delta_t, delta_seq, frame;
856	drmmode_crtc_private_ptr drmmode_crtc;
857
858	/*
859	 * This is emulated event, so its time is current time, which we
860	 * have to get in DRM-compatible form (which is a bit messy given
861	 * the information that we have at this point). Can't use now argument
862	 * because DRM event time may come from monotonic clock, while
863	 * DIX timer facility uses real-time clock.
864	 */
865	if (!event_info->crtc) {
866		ErrorF("%s no crtc\n", __func__);
867		if (event_info->drm_queue_seq)
868			amdgpu_drm_abort_entry(event_info->drm_queue_seq);
869		else
870			amdgpu_dri2_frame_event_abort(NULL, data);
871		return 0;
872	}
873
874	scrn = crtc->scrn;
875	pAMDGPUEnt = AMDGPUEntPriv(scrn);
876	drmmode_crtc = event_info->crtc->driver_private;
877	ret = drmmode_get_current_ust(pAMDGPUEnt->fd, &drm_now);
878	if (ret) {
879		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
880			   "%s cannot get current time\n", __func__);
881		if (event_info->drm_queue_seq)
882			drmmode_crtc->drmmode->event_context.
883				vblank_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	delta_t = drm_now - (CARD64) drmmode_crtc->dpms_last_ust;
894	delta_seq = delta_t * drmmode_crtc->dpms_last_fps;
895	delta_seq /= 1000000;
896	frame = (CARD64) drmmode_crtc->dpms_last_seq + delta_seq;
897	if (event_info->drm_queue_seq)
898		drmmode_crtc->drmmode->event_context.
899			vblank_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)
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)
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