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