radeon_dri2.c revision 0d16fef4
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 "radeon.h"
33#include "radeon_dri2.h"
34#include "radeon_video.h"
35
36#ifdef DRI2
37
38#include <sys/types.h>
39#include <sys/stat.h>
40#include <fcntl.h>
41#include <errno.h>
42
43#include "radeon_bo_helper.h"
44#include "radeon_version.h"
45#include "radeon_list.h"
46
47#include "radeon_bo_gem.h"
48
49#include <xf86Priv.h>
50
51#if DRI2INFOREC_VERSION >= 9
52#define USE_DRI2_PRIME
53#endif
54
55#define FALLBACK_SWAP_DELAY 16
56
57#include "radeon_glamor.h"
58
59typedef DRI2BufferPtr BufferPtr;
60
61struct dri2_buffer_priv {
62    PixmapPtr   pixmap;
63    unsigned int attachment;
64    unsigned int refcnt;
65};
66
67
68struct dri2_window_priv {
69    xf86CrtcPtr crtc;
70    int vblank_delta;
71};
72
73static DevPrivateKeyRec dri2_window_private_key_rec;
74#define dri2_window_private_key (&dri2_window_private_key_rec)
75
76#define get_dri2_window_priv(window) \
77    ((struct dri2_window_priv*) \
78     dixLookupPrivate(&(window)->devPrivates, dri2_window_private_key))
79
80
81static PixmapPtr get_drawable_pixmap(DrawablePtr drawable)
82{
83    if (drawable->type == DRAWABLE_PIXMAP)
84	return (PixmapPtr)drawable;
85    else
86	return (*drawable->pScreen->GetWindowPixmap)((WindowPtr)drawable);
87}
88
89
90static PixmapPtr fixup_glamor(DrawablePtr drawable, PixmapPtr pixmap)
91{
92	PixmapPtr old = get_drawable_pixmap(drawable);
93#ifdef USE_GLAMOR
94	ScreenPtr screen = drawable->pScreen;
95	struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
96	GCPtr gc;
97
98	/* With a glamor pixmap, 2D pixmaps are created in texture
99	 * and without a static BO attached to it. To support DRI,
100	 * we need to create a new textured-drm pixmap and
101	 * need to copy the original content to this new textured-drm
102	 * pixmap, and then convert the old pixmap to a coherent
103	 * textured-drm pixmap which has a valid BO attached to it
104	 * and also has a valid texture, thus both glamor and DRI2
105	 * can access it.
106	 *
107	 */
108
109	/* Copy the current contents of the pixmap to the bo. */
110	gc = GetScratchGC(drawable->depth, screen);
111	if (gc) {
112		ValidateGC(&pixmap->drawable, gc);
113		gc->ops->CopyArea(&old->drawable, &pixmap->drawable,
114				  gc,
115				  0, 0,
116				  old->drawable.width,
117				  old->drawable.height,
118				  0, 0);
119		FreeScratchGC(gc);
120	}
121
122	radeon_set_pixmap_private(pixmap, NULL);
123
124	/* And redirect the pixmap to the new bo (for 3D). */
125	glamor_egl_exchange_buffers(old, pixmap);
126	radeon_set_pixmap_private(old, priv);
127	old->refcnt++;
128
129	screen->ModifyPixmapHeader(old,
130				   old->drawable.width,
131				   old->drawable.height,
132				   0, 0,
133				   pixmap->devKind,
134				   NULL);
135	old->devPrivate.ptr = NULL;
136
137	screen->DestroyPixmap(pixmap);
138
139#endif /* USE_GLAMOR*/
140
141	return old;
142}
143
144/* Get GEM flink name for a pixmap */
145static Bool
146radeon_get_flink_name(RADEONInfoPtr info, PixmapPtr pixmap, uint32_t *name)
147{
148    struct radeon_bo *bo = radeon_get_pixmap_bo(pixmap);
149    struct drm_gem_flink flink;
150
151    if (bo)
152	return radeon_gem_get_kernel_name(bo, name) == 0;
153
154    if (radeon_get_pixmap_handle(pixmap, &flink.handle)) {
155	if (drmIoctl(info->dri2.drm_fd, DRM_IOCTL_GEM_FLINK, &flink) != 0)
156	    return FALSE;
157
158	*name = flink.name;
159	return TRUE;
160    }
161
162    return FALSE;
163}
164
165static BufferPtr
166radeon_dri2_create_buffer2(ScreenPtr pScreen,
167			   DrawablePtr drawable,
168			   unsigned int attachment,
169			   unsigned int format)
170{
171    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
172    RADEONInfoPtr info = RADEONPTR(pScrn);
173    BufferPtr buffers;
174    struct dri2_buffer_priv *privates;
175    PixmapPtr pixmap;
176    int flags;
177    unsigned front_width;
178    uint32_t tiling = 0;
179    unsigned aligned_width = drawable->width;
180    unsigned height = drawable->height;
181    Bool is_glamor_pixmap = FALSE;
182    int depth;
183    int cpp;
184
185    if (format) {
186	depth = format;
187
188	switch (depth) {
189	case 15:
190	    cpp = 2;
191	    break;
192	case 24:
193	    cpp = 4;
194	    break;
195	default:
196	    cpp = depth / 8;
197	}
198    } else {
199	depth = drawable->depth;
200	cpp = drawable->bitsPerPixel / 8;
201    }
202
203    front_width = pScreen->GetScreenPixmap(pScreen)->drawable.width;
204
205    pixmap = NULL;
206
207    if (attachment == DRI2BufferFrontLeft) {
208	uint32_t handle;
209
210        pixmap = get_drawable_pixmap(drawable);
211	if (pScreen != pixmap->drawable.pScreen)
212	    pixmap = NULL;
213	else if (info->use_glamor && !radeon_get_pixmap_handle(pixmap, &handle)) {
214	    is_glamor_pixmap = TRUE;
215	    aligned_width = pixmap->drawable.width;
216	    height = pixmap->drawable.height;
217	    pixmap = NULL;
218	} else
219	    pixmap->refcnt++;
220    }
221
222    if (!pixmap && (is_glamor_pixmap || attachment != DRI2BufferFrontLeft)) {
223	/* tile the back buffer */
224	switch(attachment) {
225	case DRI2BufferDepth:
226	    /* macro is the preferred setting, but the 2D detiling for software
227	     * fallbacks in mesa still has issues on some configurations
228	     */
229	    if (info->ChipFamily >= CHIP_FAMILY_R600) {
230		if (info->allowColorTiling2D) {
231			flags = RADEON_CREATE_PIXMAP_TILING_MACRO;
232		} else {
233			flags = RADEON_CREATE_PIXMAP_TILING_MICRO;
234		}
235		if (info->ChipFamily >= CHIP_FAMILY_CEDAR)
236		    flags |= RADEON_CREATE_PIXMAP_SZBUFFER;
237	    } else if (cpp == 2 && info->ChipFamily >= CHIP_FAMILY_R300)
238		flags = RADEON_CREATE_PIXMAP_TILING_MACRO | RADEON_CREATE_PIXMAP_TILING_MICRO_SQUARE;
239	    else
240		flags = RADEON_CREATE_PIXMAP_TILING_MACRO | RADEON_CREATE_PIXMAP_TILING_MICRO;
241	    if (IS_R200_3D || info->ChipFamily == CHIP_FAMILY_RV200 || info->ChipFamily == CHIP_FAMILY_RADEON)
242		flags |= RADEON_CREATE_PIXMAP_DEPTH;
243	    break;
244	case DRI2BufferDepthStencil:
245	    /* macro is the preferred setting, but the 2D detiling for software
246	     * fallbacks in mesa still has issues on some configurations
247	     */
248	    if (info->ChipFamily >= CHIP_FAMILY_R600) {
249		if (info->allowColorTiling2D) {
250			flags = RADEON_CREATE_PIXMAP_TILING_MACRO;
251		} else {
252			flags = RADEON_CREATE_PIXMAP_TILING_MICRO;
253		}
254		if (info->ChipFamily >= CHIP_FAMILY_CEDAR)
255		    flags |= RADEON_CREATE_PIXMAP_SZBUFFER;
256	    } else if (cpp == 2 && info->ChipFamily >= CHIP_FAMILY_R300)
257		flags = RADEON_CREATE_PIXMAP_TILING_MACRO | RADEON_CREATE_PIXMAP_TILING_MICRO_SQUARE;
258	    else
259		flags = RADEON_CREATE_PIXMAP_TILING_MACRO | RADEON_CREATE_PIXMAP_TILING_MICRO;
260	    if (IS_R200_3D || info->ChipFamily == CHIP_FAMILY_RV200 || info->ChipFamily == CHIP_FAMILY_RADEON)
261		flags |= RADEON_CREATE_PIXMAP_DEPTH;
262
263	    break;
264	case DRI2BufferBackLeft:
265	case DRI2BufferBackRight:
266	case DRI2BufferFrontLeft:
267	case DRI2BufferFrontRight:
268	case DRI2BufferFakeFrontLeft:
269	case DRI2BufferFakeFrontRight:
270	    if (info->ChipFamily >= CHIP_FAMILY_R600) {
271		if (info->allowColorTiling2D) {
272			flags = RADEON_CREATE_PIXMAP_TILING_MACRO;
273		} else {
274			flags = RADEON_CREATE_PIXMAP_TILING_MICRO;
275		}
276	    } else
277		flags = RADEON_CREATE_PIXMAP_TILING_MACRO;
278	    break;
279	default:
280	    flags = 0;
281	}
282
283	if (flags & RADEON_CREATE_PIXMAP_TILING_MICRO)
284	    tiling |= RADEON_TILING_MICRO;
285	if (flags & RADEON_CREATE_PIXMAP_TILING_MICRO_SQUARE)
286	    tiling |= RADEON_TILING_MICRO_SQUARE;
287	if (flags & RADEON_CREATE_PIXMAP_TILING_MACRO)
288	    tiling |= RADEON_TILING_MACRO;
289
290	    if (aligned_width == front_width)
291		aligned_width = pScrn->virtualX;
292
293	    pixmap = (*pScreen->CreatePixmap)(pScreen,
294					      aligned_width,
295					      height,
296					      depth,
297					      flags | RADEON_CREATE_PIXMAP_DRI2);
298    }
299
300    buffers = calloc(1, sizeof *buffers);
301    if (buffers == NULL)
302        goto error;
303
304    if (pixmap) {
305	if (!info->use_glamor) {
306	    info->exa_force_create = TRUE;
307	    exaMoveInPixmap(pixmap);
308	    info->exa_force_create = FALSE;
309	    if (exaGetPixmapDriverPrivate(pixmap) == NULL) {
310		/* this happen if pixmap is non accelerable */
311		goto error;
312	    }
313	}
314
315	if (is_glamor_pixmap)
316	    pixmap = fixup_glamor(drawable, pixmap);
317	if (!radeon_get_flink_name(info, pixmap, &buffers->name))
318	    goto error;
319    }
320
321    privates = calloc(1, sizeof(struct dri2_buffer_priv));
322    if (privates == NULL)
323        goto error;
324
325    buffers->attachment = attachment;
326    if (pixmap) {
327	buffers->pitch = pixmap->devKind;
328	buffers->cpp = cpp;
329    }
330    buffers->driverPrivate = privates;
331    buffers->format = format;
332    buffers->flags = 0; /* not tiled */
333    privates->pixmap = pixmap;
334    privates->attachment = attachment;
335    privates->refcnt = 1;
336
337    return buffers;
338
339error:
340    free(buffers);
341    if (pixmap)
342        (*pScreen->DestroyPixmap)(pixmap);
343    return NULL;
344}
345
346DRI2BufferPtr
347radeon_dri2_create_buffer(DrawablePtr pDraw, unsigned int attachment,
348			   unsigned int format)
349{
350	return radeon_dri2_create_buffer2(pDraw->pScreen, pDraw,
351					  attachment, format);
352}
353
354static void
355radeon_dri2_destroy_buffer2(ScreenPtr pScreen,
356			    DrawablePtr drawable, BufferPtr buffers)
357{
358    if(buffers)
359    {
360        struct dri2_buffer_priv *private = buffers->driverPrivate;
361
362        /* Trying to free an already freed buffer is unlikely to end well */
363        if (private->refcnt == 0) {
364            ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen);
365
366            xf86DrvMsg(scrn->scrnIndex, X_WARNING,
367                       "Attempted to destroy previously destroyed buffer.\
368 This is a programming error\n");
369            return;
370        }
371
372        private->refcnt--;
373        if (private->refcnt == 0)
374        {
375	    if (private->pixmap)
376                (*pScreen->DestroyPixmap)(private->pixmap);
377
378            free(buffers->driverPrivate);
379            free(buffers);
380        }
381    }
382}
383
384void
385radeon_dri2_destroy_buffer(DrawablePtr pDraw, DRI2BufferPtr buf)
386{
387    radeon_dri2_destroy_buffer2(pDraw->pScreen, pDraw, buf);
388}
389
390
391static inline PixmapPtr GetDrawablePixmap(DrawablePtr drawable)
392{
393    if (drawable->type == DRAWABLE_PIXMAP)
394        return (PixmapPtr)drawable;
395    else {
396        struct _Window *pWin = (struct _Window *)drawable;
397        return drawable->pScreen->GetWindowPixmap(pWin);
398    }
399}
400static void
401radeon_dri2_copy_region2(ScreenPtr pScreen,
402			 DrawablePtr drawable,
403			 RegionPtr region,
404			 BufferPtr dest_buffer,
405			 BufferPtr src_buffer)
406{
407    struct dri2_buffer_priv *src_private = src_buffer->driverPrivate;
408    struct dri2_buffer_priv *dst_private = dest_buffer->driverPrivate;
409    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
410    DrawablePtr src_drawable;
411    DrawablePtr dst_drawable;
412    RegionPtr copy_clip;
413    GCPtr gc;
414    RADEONInfoPtr info = RADEONPTR(pScrn);
415    Bool vsync;
416    Bool translate = FALSE;
417    int off_x = 0, off_y = 0;
418    PixmapPtr dst_ppix;
419
420    dst_ppix = dst_private->pixmap;
421    src_drawable = &src_private->pixmap->drawable;
422    dst_drawable = &dst_private->pixmap->drawable;
423
424    if (src_private->attachment == DRI2BufferFrontLeft) {
425#ifdef USE_DRI2_PRIME
426	if (drawable->pScreen != pScreen) {
427	    src_drawable = DRI2UpdatePrime(drawable, src_buffer);
428	    if (!src_drawable)
429		return;
430	} else
431#endif
432	    src_drawable = drawable;
433    }
434    if (dst_private->attachment == DRI2BufferFrontLeft) {
435#ifdef USE_DRI2_PRIME
436	if (drawable->pScreen != pScreen) {
437	    dst_drawable = DRI2UpdatePrime(drawable, dest_buffer);
438	    if (!dst_drawable)
439		return;
440	    dst_ppix = (PixmapPtr)dst_drawable;
441	    if (dst_drawable != drawable)
442		translate = TRUE;
443	} else
444#endif
445	    dst_drawable = drawable;
446    }
447
448    if (translate && drawable->type == DRAWABLE_WINDOW) {
449	PixmapPtr pPix = GetDrawablePixmap(drawable);
450
451	off_x = drawable->x - pPix->screen_x;
452	off_y = drawable->y - pPix->screen_y;
453    }
454    gc = GetScratchGC(dst_drawable->depth, pScreen);
455    copy_clip = REGION_CREATE(pScreen, NULL, 0);
456    REGION_COPY(pScreen, copy_clip, region);
457
458    if (translate) {
459	REGION_TRANSLATE(pScreen, copy_clip, off_x, off_y);
460    }
461
462    (*gc->funcs->ChangeClip) (gc, CT_REGION, copy_clip, 0);
463    ValidateGC(dst_drawable, gc);
464
465    /* If this is a full buffer swap or frontbuffer flush, throttle on the
466     * previous one
467     */
468    if (dst_private->attachment == DRI2BufferFrontLeft) {
469	if (REGION_NUM_RECTS(region) == 1) {
470	    BoxPtr extents = REGION_EXTENTS(pScreen, region);
471
472	    if (extents->x1 == 0 && extents->y1 == 0 &&
473		extents->x2 == drawable->width &&
474		extents->y2 == drawable->height) {
475		struct radeon_bo *bo = radeon_get_pixmap_bo(dst_ppix);
476
477		if (bo)
478		    radeon_bo_wait(bo);
479	    }
480	}
481    }
482
483    vsync = info->accel_state->vsync;
484
485    /* Driver option "SwapbuffersWait" defines if we vsync DRI2 copy-swaps. */
486    info->accel_state->vsync = info->swapBuffersWait;
487    info->accel_state->force = TRUE;
488
489    (*gc->ops->CopyArea)(src_drawable, dst_drawable, gc,
490                         0, 0, drawable->width, drawable->height, off_x, off_y);
491
492    info->accel_state->force = FALSE;
493    info->accel_state->vsync = vsync;
494
495    FreeScratchGC(gc);
496}
497
498void
499radeon_dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion,
500			 DRI2BufferPtr pDstBuffer, DRI2BufferPtr pSrcBuffer)
501{
502    return radeon_dri2_copy_region2(pDraw->pScreen, pDraw, pRegion,
503				     pDstBuffer, pSrcBuffer);
504}
505
506enum DRI2FrameEventType {
507    DRI2_SWAP,
508    DRI2_FLIP,
509    DRI2_WAITMSC,
510};
511
512typedef struct _DRI2FrameEvent {
513    XID drawable_id;
514    ClientPtr client;
515    enum DRI2FrameEventType type;
516    unsigned frame;
517    xf86CrtcPtr crtc;
518    OsTimerPtr timer;
519    uintptr_t drm_queue_seq;
520
521    /* for swaps & flips only */
522    DRI2SwapEventPtr event_complete;
523    void *event_data;
524    DRI2BufferPtr front;
525    DRI2BufferPtr back;
526} DRI2FrameEventRec, *DRI2FrameEventPtr;
527
528static int DRI2InfoCnt;
529
530static void
531radeon_dri2_ref_buffer(BufferPtr buffer)
532{
533    struct dri2_buffer_priv *private = buffer->driverPrivate;
534    private->refcnt++;
535}
536
537static void
538radeon_dri2_unref_buffer(BufferPtr buffer)
539{
540    if (buffer) {
541        struct dri2_buffer_priv *private = buffer->driverPrivate;
542        radeon_dri2_destroy_buffer(&(private->pixmap->drawable), buffer);
543    }
544}
545
546static void
547radeon_dri2_client_state_changed(CallbackListPtr *ClientStateCallback, pointer data, pointer calldata)
548{
549    NewClientInfoRec *clientinfo = calldata;
550    ClientPtr pClient = clientinfo->client;
551
552    switch (pClient->clientState) {
553    case ClientStateRetained:
554    case ClientStateGone:
555        radeon_drm_abort_client(pClient);
556        break;
557    default:
558        break;
559    }
560}
561
562/*
563 * Get current frame count delta for the specified drawable and CRTC
564 */
565static uint32_t radeon_get_msc_delta(DrawablePtr pDraw, xf86CrtcPtr crtc)
566{
567    drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
568
569    if (pDraw && pDraw->type == DRAWABLE_WINDOW)
570	return drmmode_crtc->interpolated_vblanks +
571	    get_dri2_window_priv((WindowPtr)pDraw)->vblank_delta;
572
573    return drmmode_crtc->interpolated_vblanks;
574}
575
576/*
577 * Get current frame count and timestamp of the specified CRTC
578 */
579static Bool radeon_dri2_get_crtc_msc(xf86CrtcPtr crtc, CARD64 *ust, CARD64 *msc)
580{
581    if (!radeon_crtc_is_enabled(crtc) ||
582	 drmmode_crtc_get_ust_msc(crtc, ust, msc) != Success) {
583	/* CRTC is not running, extrapolate MSC and timestamp */
584	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
585	ScrnInfoPtr scrn = crtc->scrn;
586	RADEONInfoPtr info = RADEONPTR(scrn);
587	CARD64 now, delta_t, delta_seq;
588
589	if (!drmmode_crtc->dpms_last_ust)
590	    return FALSE;
591
592	if (drmmode_get_current_ust(info->dri2.drm_fd, &now) != 0) {
593	    xf86DrvMsg(scrn->scrnIndex, X_ERROR,
594		       "%s cannot get current time\n", __func__);
595	    return FALSE;
596	}
597
598	delta_t = now - drmmode_crtc->dpms_last_ust;
599	delta_seq = delta_t * drmmode_crtc->dpms_last_fps;
600	delta_seq /= 1000000;
601	*ust = drmmode_crtc->dpms_last_ust;
602	delta_t = delta_seq * 1000000;
603	delta_t /= drmmode_crtc->dpms_last_fps;
604	*ust += delta_t;
605	*msc = drmmode_crtc->dpms_last_seq;
606	*msc += delta_seq;
607    }
608
609    return TRUE;
610}
611
612static
613xf86CrtcPtr radeon_dri2_drawable_crtc(DrawablePtr pDraw, Bool consider_disabled)
614{
615    ScreenPtr pScreen = pDraw->pScreen;
616    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
617    xf86CrtcPtr crtc = radeon_pick_best_crtc(pScrn, consider_disabled,
618					      pDraw->x, pDraw->x + pDraw->width,
619					      pDraw->y, pDraw->y + pDraw->height);
620
621    if (crtc && pDraw->type == DRAWABLE_WINDOW) {
622	struct dri2_window_priv *priv = get_dri2_window_priv((WindowPtr)pDraw);
623
624	if (priv->crtc && priv->crtc != crtc) {
625	    CARD64 ust, mscold, mscnew;
626
627	    if (radeon_dri2_get_crtc_msc(priv->crtc, &ust, &mscold) &&
628		radeon_dri2_get_crtc_msc(crtc, &ust, &mscnew))
629		priv->vblank_delta += mscold - mscnew;
630	}
631
632	priv->crtc = crtc;
633    }
634
635    return crtc;
636}
637
638static void
639radeon_dri2_flip_event_abort(xf86CrtcPtr crtc, void *event_data)
640{
641    RADEONInfoPtr info = RADEONPTR(crtc->scrn);
642
643    info->drmmode.dri2_flipping = FALSE;
644    free(event_data);
645}
646
647static void
648radeon_dri2_flip_event_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec,
649			       void *event_data)
650{
651    DRI2FrameEventPtr flip = event_data;
652    ScrnInfoPtr scrn = crtc->scrn;
653    unsigned tv_sec, tv_usec;
654    DrawablePtr drawable;
655    ScreenPtr screen;
656    int status;
657    PixmapPtr pixmap;
658
659    status = dixLookupDrawable(&drawable, flip->drawable_id, serverClient,
660			       M_ANY, DixWriteAccess);
661    if (status != Success)
662	goto abort;
663
664    frame += radeon_get_msc_delta(drawable, crtc);
665
666    screen = scrn->pScreen;
667    pixmap = screen->GetScreenPixmap(screen);
668    xf86DrvMsgVerb(scrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
669		   "%s:%d fevent[%p] width %d pitch %d (/4 %d)\n",
670		   __func__, __LINE__, flip, pixmap->drawable.width, pixmap->devKind, pixmap->devKind/4);
671
672    tv_sec = usec / 1000000;
673    tv_usec = usec % 1000000;
674
675    /* We assume our flips arrive in order, so we don't check the frame */
676    switch (flip->type) {
677    case DRI2_SWAP:
678	/* Check for too small vblank count of pageflip completion, taking wraparound
679	 * into account. This usually means some defective kms pageflip completion,
680	 * causing wrong (msc, ust) return values and possible visual corruption.
681	 */
682	if ((frame < flip->frame) && (flip->frame - frame < 5)) {
683	    xf86DrvMsg(scrn->scrnIndex, X_WARNING,
684		       "%s: Pageflip completion event has impossible msc %u < target_msc %u\n",
685		       __func__, frame, flip->frame);
686	    /* All-Zero values signal failure of (msc, ust) timestamping to client. */
687	    frame = tv_sec = tv_usec = 0;
688	}
689
690	DRI2SwapComplete(flip->client, drawable, frame, tv_sec, tv_usec,
691			 DRI2_FLIP_COMPLETE, flip->event_complete,
692			 flip->event_data);
693	break;
694    default:
695	xf86DrvMsg(scrn->scrnIndex, X_WARNING, "%s: unknown vblank event received\n", __func__);
696	/* Unknown type */
697	break;
698    }
699
700abort:
701    radeon_dri2_flip_event_abort(crtc, event_data);
702}
703
704static Bool
705radeon_dri2_schedule_flip(xf86CrtcPtr crtc, ClientPtr client,
706			  DrawablePtr draw, DRI2BufferPtr front,
707			  DRI2BufferPtr back, DRI2SwapEventPtr func,
708			  void *data, unsigned int target_msc)
709{
710    ScrnInfoPtr scrn = crtc->scrn;
711    RADEONInfoPtr info = RADEONPTR(scrn);
712    struct dri2_buffer_priv *back_priv;
713    struct radeon_bo *bo;
714    DRI2FrameEventPtr flip_info;
715    int ref_crtc_hw_id = drmmode_get_crtc_id(crtc);
716
717    flip_info = calloc(1, sizeof(DRI2FrameEventRec));
718    if (!flip_info)
719	return FALSE;
720
721    flip_info->drawable_id = draw->id;
722    flip_info->client = client;
723    flip_info->type = DRI2_SWAP;
724    flip_info->event_complete = func;
725    flip_info->event_data = data;
726    flip_info->frame = target_msc;
727    flip_info->crtc = crtc;
728
729    xf86DrvMsgVerb(scrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
730		   "%s:%d fevent[%p]\n", __func__, __LINE__, flip_info);
731
732    /* Page flip the full screen buffer */
733    back_priv = back->driverPrivate;
734    bo = radeon_get_pixmap_bo(back_priv->pixmap);
735
736    if (radeon_do_pageflip(scrn, client, bo->handle,
737			   RADEON_DRM_QUEUE_ID_DEFAULT, flip_info,
738			   ref_crtc_hw_id,
739			   radeon_dri2_flip_event_handler,
740			   radeon_dri2_flip_event_abort)) {
741	info->drmmode.dri2_flipping = TRUE;
742	return TRUE;
743    }
744
745    return FALSE;
746}
747
748static Bool
749update_front(DrawablePtr draw, DRI2BufferPtr front)
750{
751    PixmapPtr pixmap;
752    RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(draw->pScreen));
753    struct dri2_buffer_priv *priv = front->driverPrivate;
754
755    pixmap = get_drawable_pixmap(draw);
756    pixmap->refcnt++;
757
758    if (!info->use_glamor)
759	exaMoveInPixmap(pixmap);
760    if (!radeon_get_flink_name(info, pixmap, &front->name)) {
761	(*draw->pScreen->DestroyPixmap)(pixmap);
762	return FALSE;
763    }
764    (*draw->pScreen->DestroyPixmap)(priv->pixmap);
765    front->pitch = pixmap->devKind;
766    front->cpp = pixmap->drawable.bitsPerPixel / 8;
767    priv->pixmap = pixmap;
768
769    return TRUE;
770}
771
772static Bool
773can_exchange(ScrnInfoPtr pScrn, DrawablePtr draw,
774	     DRI2BufferPtr front, DRI2BufferPtr back)
775{
776    struct dri2_buffer_priv *front_priv = front->driverPrivate;
777    struct dri2_buffer_priv *back_priv = back->driverPrivate;
778    PixmapPtr front_pixmap;
779    PixmapPtr back_pixmap = back_priv->pixmap;
780    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
781    int i;
782
783    for (i = 0; i < xf86_config->num_crtc; i++) {
784	xf86CrtcPtr crtc = xf86_config->crtc[i];
785	if (crtc->enabled && crtc->rotatedData)
786	    return FALSE;
787    }
788
789    if (!update_front(draw, front))
790	return FALSE;
791
792    front_pixmap = front_priv->pixmap;
793
794    if (front_pixmap->drawable.width != back_pixmap->drawable.width)
795	return FALSE;
796
797    if (front_pixmap->drawable.height != back_pixmap->drawable.height)
798	return FALSE;
799
800    if (front_pixmap->drawable.bitsPerPixel != back_pixmap->drawable.bitsPerPixel)
801	return FALSE;
802
803    if (front_pixmap->devKind != back_pixmap->devKind)
804	return FALSE;
805
806    return TRUE;
807}
808
809static Bool
810can_flip(ScrnInfoPtr pScrn, DrawablePtr draw,
811	 DRI2BufferPtr front, DRI2BufferPtr back)
812{
813    RADEONInfoPtr info = RADEONPTR(pScrn);
814
815    return draw->type == DRAWABLE_WINDOW &&
816	   info->allowPageFlip &&
817	   !info->hwcursor_disabled &&
818	   !info->drmmode.present_flipping &&
819	   pScrn->vtSema &&
820	   DRI2CanFlip(draw) &&
821	   can_exchange(pScrn, draw, front, back);
822}
823
824static void
825radeon_dri2_exchange_buffers(DrawablePtr draw, DRI2BufferPtr front, DRI2BufferPtr back)
826{
827    struct dri2_buffer_priv *front_priv = front->driverPrivate;
828    struct dri2_buffer_priv *back_priv = back->driverPrivate;
829    struct radeon_bo *front_bo, *back_bo;
830    ScreenPtr screen;
831    RADEONInfoPtr info;
832    RegionRec region;
833    int tmp;
834
835    region.extents.x1 = region.extents.y1 = 0;
836    region.extents.x2 = front_priv->pixmap->drawable.width;
837    region.extents.y2 = front_priv->pixmap->drawable.width;
838    region.data = NULL;
839    DamageRegionAppend(&front_priv->pixmap->drawable, &region);
840
841    /* Swap BO names so DRI works */
842    tmp = front->name;
843    front->name = back->name;
844    back->name = tmp;
845
846    /* Swap pixmap bos */
847    front_bo = radeon_get_pixmap_bo(front_priv->pixmap);
848    back_bo = radeon_get_pixmap_bo(back_priv->pixmap);
849    radeon_set_pixmap_bo(front_priv->pixmap, back_bo);
850    radeon_set_pixmap_bo(back_priv->pixmap, front_bo);
851
852    /* Do we need to update the Screen? */
853    screen = draw->pScreen;
854    info = RADEONPTR(xf86ScreenToScrn(screen));
855    if (front_bo == info->front_bo) {
856	radeon_bo_ref(back_bo);
857	radeon_bo_unref(info->front_bo);
858	info->front_bo = back_bo;
859	radeon_set_pixmap_bo(screen->GetScreenPixmap(screen), back_bo);
860    }
861
862    radeon_glamor_exchange_buffers(front_priv->pixmap, back_priv->pixmap);
863
864    DamageRegionProcessPending(&front_priv->pixmap->drawable);
865}
866
867static void radeon_dri2_frame_event_abort(xf86CrtcPtr crtc, void *event_data)
868{
869    DRI2FrameEventPtr event = event_data;
870
871    TimerCancel(event->timer);
872    TimerFree(event->timer);
873    radeon_dri2_unref_buffer(event->front);
874    radeon_dri2_unref_buffer(event->back);
875    free(event);
876}
877
878static void radeon_dri2_frame_event_handler(xf86CrtcPtr crtc, uint32_t seq,
879					    uint64_t usec, void *event_data)
880{
881    DRI2FrameEventPtr event = event_data;
882    ScrnInfoPtr scrn = crtc->scrn;
883    DrawablePtr drawable;
884    int status;
885    int swap_type;
886    BoxRec box;
887    RegionRec region;
888
889    status = dixLookupDrawable(&drawable, event->drawable_id, serverClient,
890                               M_ANY, DixWriteAccess);
891    if (status != Success)
892        goto cleanup;
893
894    seq += radeon_get_msc_delta(drawable, crtc);
895
896    switch (event->type) {
897    case DRI2_FLIP:
898	if (can_flip(scrn, drawable, event->front, event->back) &&
899	    radeon_dri2_schedule_flip(crtc,
900				      event->client,
901				      drawable,
902				      event->front,
903				      event->back,
904				      event->event_complete,
905				      event->event_data,
906				      event->frame)) {
907	    radeon_dri2_exchange_buffers(drawable, event->front, event->back);
908	    break;
909	}
910	/* else fall through to exchange/blit */
911    case DRI2_SWAP:
912	if (DRI2CanExchange(drawable) &&
913	    can_exchange(scrn, drawable, event->front, event->back)) {
914	    radeon_dri2_exchange_buffers(drawable, event->front, event->back);
915	    swap_type = DRI2_EXCHANGE_COMPLETE;
916	} else {
917	    box.x1 = 0;
918	    box.y1 = 0;
919	    box.x2 = drawable->width;
920	    box.y2 = drawable->height;
921	    REGION_INIT(pScreen, &region, &box, 0);
922	    radeon_dri2_copy_region(drawable, &region, event->front, event->back);
923	    swap_type = DRI2_BLIT_COMPLETE;
924	}
925
926        DRI2SwapComplete(event->client, drawable, seq, usec / 1000000,
927			 usec % 1000000, swap_type, event->event_complete,
928			 event->event_data);
929
930        break;
931    case DRI2_WAITMSC:
932        DRI2WaitMSCComplete(event->client, drawable, seq, usec / 1000000,
933			    usec % 1000000);
934        break;
935    default:
936        /* Unknown type */
937        xf86DrvMsg(scrn->scrnIndex, X_WARNING,
938                "%s: unknown vblank event received\n", __func__);
939        break;
940    }
941
942cleanup:
943    radeon_dri2_frame_event_abort(crtc, event_data);
944}
945
946drmVBlankSeqType radeon_populate_vbl_request_type(xf86CrtcPtr crtc)
947{
948    drmVBlankSeqType type = 0;
949    int crtc_id = drmmode_get_crtc_id(crtc);
950
951    if (crtc_id == 1)
952        type |= DRM_VBLANK_SECONDARY;
953    else if (crtc_id > 1)
954#ifdef DRM_VBLANK_HIGH_CRTC_SHIFT
955	type |= (crtc_id << DRM_VBLANK_HIGH_CRTC_SHIFT) &
956		DRM_VBLANK_HIGH_CRTC_MASK;
957#else
958	ErrorF("radeon driver bug: %s called for CRTC %d > 1, but "
959	       "DRM_VBLANK_HIGH_CRTC_MASK not defined at build time\n",
960	       __func__, crtc_id);
961#endif
962
963    return type;
964}
965
966/*
967 * This function should be called on a disabled CRTC only (i.e., CRTC
968 * in DPMS-off state). It will calculate the delay necessary to reach
969 * target_msc from present time if the CRTC were running.
970 */
971static
972CARD32 radeon_dri2_extrapolate_msc_delay(xf86CrtcPtr crtc, CARD64 *target_msc,
973					 CARD64 divisor, CARD64 remainder)
974{
975    drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
976    ScrnInfoPtr pScrn = crtc->scrn;
977    RADEONInfoPtr info = RADEONPTR(pScrn);
978    int nominal_frame_rate = drmmode_crtc->dpms_last_fps;
979    CARD64 last_vblank_ust = drmmode_crtc->dpms_last_ust;
980    uint32_t last_vblank_seq = drmmode_crtc->dpms_last_seq;
981    CARD64 now, target_time, delta_t;
982    int64_t d, delta_seq;
983    int ret;
984    CARD32 d_ms;
985
986    if (!last_vblank_ust) {
987	*target_msc = 0;
988	return FALLBACK_SWAP_DELAY;
989    }
990    ret = drmmode_get_current_ust(info->dri2.drm_fd, &now);
991    if (ret) {
992	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
993		   "%s cannot get current time\n", __func__);
994	*target_msc = 0;
995	return FALLBACK_SWAP_DELAY;
996    }
997    delta_seq = *target_msc - last_vblank_seq;
998    delta_seq *= 1000000;
999    target_time = last_vblank_ust;
1000    target_time += delta_seq / nominal_frame_rate;
1001    d = target_time - now;
1002    if (d < 0) {
1003	/* we missed the event, adjust target_msc, do the divisor magic */
1004	CARD64 current_msc = last_vblank_seq;
1005
1006	delta_t = now - last_vblank_ust;
1007	delta_seq = delta_t * nominal_frame_rate;
1008	current_msc += delta_seq / 1000000;
1009	current_msc &= 0xffffffff;
1010	if (divisor == 0) {
1011	    *target_msc = current_msc;
1012	    d = 0;
1013	} else {
1014	    *target_msc = current_msc - (current_msc % divisor) + remainder;
1015	    if ((current_msc % divisor) >= remainder)
1016		*target_msc += divisor;
1017	    *target_msc &= 0xffffffff;
1018	    delta_seq = *target_msc - last_vblank_seq;
1019	    delta_seq *= 1000000;
1020	    target_time = last_vblank_ust;
1021	    target_time += delta_seq / nominal_frame_rate;
1022	    d = target_time - now;
1023	}
1024    }
1025    /*
1026     * convert delay to milliseconds and add margin to prevent the client
1027     * from coming back early (due to timer granularity and rounding
1028     * errors) and getting the same MSC it just got
1029     */
1030    d_ms = (CARD32)d / 1000;
1031    if ((CARD32)d - d_ms * 1000 > 0)
1032	d_ms += 2;
1033    else
1034	d_ms++;
1035    return d_ms;
1036}
1037
1038/*
1039 * Get current interpolated frame count and frame count timestamp, based on
1040 * drawable's crtc.
1041 */
1042static int radeon_dri2_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc)
1043{
1044    xf86CrtcPtr crtc = radeon_dri2_drawable_crtc(draw, TRUE);
1045
1046    /* Drawable not displayed, make up a value */
1047    if (crtc == NULL) {
1048        *ust = 0;
1049        *msc = 0;
1050        return TRUE;
1051    }
1052
1053    if (!radeon_dri2_get_crtc_msc(crtc, ust, msc))
1054	return FALSE;
1055
1056    *msc += radeon_get_msc_delta(draw, crtc);
1057    *msc &= 0xffffffff;
1058    return TRUE;
1059}
1060
1061static
1062CARD32 radeon_dri2_deferred_event(OsTimerPtr timer, CARD32 now, pointer data)
1063{
1064    DRI2FrameEventPtr event_info = (DRI2FrameEventPtr)data;
1065    xf86CrtcPtr crtc = event_info->crtc;
1066    ScrnInfoPtr scrn;
1067    RADEONInfoPtr info;
1068    CARD64 drm_now;
1069    int ret;
1070    CARD64 delta_t, delta_seq, frame;
1071    drmmode_crtc_private_ptr drmmode_crtc;
1072
1073    /*
1074     * This is emulated event, so its time is current time, which we
1075     * have to get in DRM-compatible form (which is a bit messy given
1076     * the information that we have at this point). Can't use now argument
1077     * because DRM event time may come from monotonic clock, while
1078     * DIX timer facility uses real-time clock.
1079     */
1080    if (!event_info->crtc) {
1081	ErrorF("%s no crtc\n", __func__);
1082	if (event_info->drm_queue_seq)
1083	    radeon_drm_abort_entry(event_info->drm_queue_seq);
1084	else
1085	    radeon_dri2_frame_event_abort(NULL, data);
1086	return 0;
1087    }
1088
1089    scrn = crtc->scrn;
1090    info = RADEONPTR(scrn);
1091    ret = drmmode_get_current_ust(info->dri2.drm_fd, &drm_now);
1092    if (ret) {
1093	xf86DrvMsg(scrn->scrnIndex, X_ERROR,
1094		   "%s cannot get current time\n", __func__);
1095	if (event_info->drm_queue_seq)
1096	    radeon_drm_queue_handler(info->dri2.drm_fd, 0, 0, 0,
1097				     (void*)event_info->drm_queue_seq);
1098	else
1099	    radeon_dri2_frame_event_handler(crtc, 0, 0, data);
1100	return 0;
1101    }
1102    /*
1103     * calculate the frame number from current time
1104     * that would come from CRTC if it were running
1105     */
1106    drmmode_crtc = event_info->crtc->driver_private;
1107    delta_t = drm_now - (CARD64)drmmode_crtc->dpms_last_ust;
1108    delta_seq = delta_t * drmmode_crtc->dpms_last_fps;
1109    delta_seq /= 1000000;
1110    frame = (CARD64)drmmode_crtc->dpms_last_seq + delta_seq;
1111    if (event_info->drm_queue_seq)
1112	radeon_drm_queue_handler(info->dri2.drm_fd, frame, drm_now / 1000000,
1113				 drm_now % 1000000,
1114				 (void*)event_info->drm_queue_seq);
1115    else
1116	radeon_dri2_frame_event_handler(crtc, frame, drm_now, data);
1117    return 0;
1118}
1119
1120static
1121void radeon_dri2_schedule_event(CARD32 delay, DRI2FrameEventPtr event_info)
1122{
1123    event_info->timer = TimerSet(NULL, 0, delay, radeon_dri2_deferred_event,
1124				 event_info);
1125    if (delay == 0) {
1126	CARD32 now = GetTimeInMillis();
1127	radeon_dri2_deferred_event(event_info->timer, now, event_info);
1128    }
1129}
1130
1131/*
1132 * Request a DRM event when the requested conditions will be satisfied.
1133 *
1134 * We need to handle the event and ask the server to wake up the client when
1135 * we receive it.
1136 */
1137static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
1138                                         CARD64 target_msc, CARD64 divisor,
1139                                         CARD64 remainder)
1140{
1141    ScreenPtr screen = draw->pScreen;
1142    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
1143    RADEONInfoPtr info = RADEONPTR(scrn);
1144    DRI2FrameEventPtr wait_info = NULL;
1145    uintptr_t drm_queue_seq = 0;
1146    xf86CrtcPtr crtc = radeon_dri2_drawable_crtc(draw, TRUE);
1147    uint32_t msc_delta;
1148    drmVBlank vbl;
1149    int ret;
1150    CARD64 current_msc;
1151
1152    /* Truncate to match kernel interfaces; means occasional overflow
1153     * misses, but that's generally not a big deal */
1154    target_msc &= 0xffffffff;
1155    divisor &= 0xffffffff;
1156    remainder &= 0xffffffff;
1157
1158    /* Drawable not visible, return immediately */
1159    if (crtc == NULL)
1160        goto out_complete;
1161
1162    msc_delta = radeon_get_msc_delta(draw, crtc);
1163
1164    wait_info = calloc(1, sizeof(DRI2FrameEventRec));
1165    if (!wait_info)
1166        goto out_complete;
1167
1168    wait_info->drawable_id = draw->id;
1169    wait_info->client = client;
1170    wait_info->type = DRI2_WAITMSC;
1171    wait_info->crtc = crtc;
1172
1173    /*
1174     * CRTC is in DPMS off state, calculate wait time from current time,
1175     * target_msc and last vblank time/sequence when CRTC was turned off
1176     */
1177    if (!radeon_crtc_is_enabled(crtc)) {
1178	CARD32 delay;
1179	target_msc -= msc_delta;
1180	delay = radeon_dri2_extrapolate_msc_delay(crtc, &target_msc,
1181						  divisor, remainder);
1182	radeon_dri2_schedule_event(delay, wait_info);
1183	DRI2BlockClient(client, draw);
1184	return TRUE;
1185    }
1186
1187    /* Get current count */
1188    vbl.request.type = DRM_VBLANK_RELATIVE;
1189    vbl.request.type |= radeon_populate_vbl_request_type(crtc);
1190    vbl.request.sequence = 0;
1191    ret = drmWaitVBlank(info->dri2.drm_fd, &vbl);
1192    if (ret) {
1193        xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1194                "get vblank counter failed: %s\n", strerror(errno));
1195        goto out_complete;
1196    }
1197
1198    current_msc = vbl.reply.sequence + msc_delta;
1199    current_msc &= 0xffffffff;
1200
1201    drm_queue_seq = radeon_drm_queue_alloc(crtc, client, RADEON_DRM_QUEUE_ID_DEFAULT,
1202					   wait_info, radeon_dri2_frame_event_handler,
1203					   radeon_dri2_frame_event_abort);
1204    if (!drm_queue_seq) {
1205        xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1206		   "Allocating DRM queue event entry failed.\n");
1207        goto out_complete;
1208    }
1209    wait_info->drm_queue_seq = drm_queue_seq;
1210
1211    /*
1212     * If divisor is zero, or current_msc is smaller than target_msc,
1213     * we just need to make sure target_msc passes  before waking up the
1214     * client.
1215     */
1216    if (divisor == 0 || current_msc < target_msc) {
1217        /* If target_msc already reached or passed, set it to
1218         * current_msc to ensure we return a reasonable value back
1219         * to the caller. This keeps the client from continually
1220         * sending us MSC targets from the past by forcibly updating
1221         * their count on this call.
1222         */
1223        if (current_msc >= target_msc)
1224            target_msc = current_msc;
1225        vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
1226	vbl.request.type |= radeon_populate_vbl_request_type(crtc);
1227        vbl.request.sequence = target_msc - msc_delta;
1228        vbl.request.signal = drm_queue_seq;
1229        ret = drmWaitVBlank(info->dri2.drm_fd, &vbl);
1230        if (ret) {
1231            xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1232                    "get vblank counter failed: %s\n", strerror(errno));
1233            goto out_complete;
1234        }
1235
1236        DRI2BlockClient(client, draw);
1237        return TRUE;
1238    }
1239
1240    /*
1241     * If we get here, target_msc has already passed or we don't have one,
1242     * so we queue an event that will satisfy the divisor/remainder equation.
1243     */
1244    vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
1245    vbl.request.type |= radeon_populate_vbl_request_type(crtc);
1246
1247    vbl.request.sequence = current_msc - (current_msc % divisor) +
1248        remainder - msc_delta;
1249
1250    /*
1251     * If calculated remainder is larger than requested remainder,
1252     * it means we've passed the last point where
1253     * seq % divisor == remainder, so we need to wait for the next time
1254     * that will happen.
1255     */
1256    if ((current_msc % divisor) >= remainder)
1257        vbl.request.sequence += divisor;
1258
1259    vbl.request.signal = drm_queue_seq;
1260    ret = drmWaitVBlank(info->dri2.drm_fd, &vbl);
1261    if (ret) {
1262        xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1263                "get vblank counter failed: %s\n", strerror(errno));
1264        goto out_complete;
1265    }
1266
1267    DRI2BlockClient(client, draw);
1268
1269    return TRUE;
1270
1271out_complete:
1272    if (wait_info)
1273	radeon_dri2_deferred_event(NULL, 0, wait_info);
1274    return TRUE;
1275}
1276
1277/*
1278 * ScheduleSwap is responsible for requesting a DRM vblank event for the
1279 * appropriate frame.
1280 *
1281 * In the case of a blit (e.g. for a windowed swap) or buffer exchange,
1282 * the vblank requested can simply be the last queued swap frame + the swap
1283 * interval for the drawable.
1284 *
1285 * In the case of a page flip, we request an event for the last queued swap
1286 * frame + swap interval - 1, since we'll need to queue the flip for the frame
1287 * immediately following the received event.
1288 *
1289 * The client will be blocked if it tries to perform further GL commands
1290 * after queueing a swap, though in the Intel case after queueing a flip, the
1291 * client is free to queue more commands; they'll block in the kernel if
1292 * they access buffers busy with the flip.
1293 *
1294 * When the swap is complete, the driver should call into the server so it
1295 * can send any swap complete events that have been requested.
1296 */
1297static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
1298                                     DRI2BufferPtr front, DRI2BufferPtr back,
1299                                     CARD64 *target_msc, CARD64 divisor,
1300                                     CARD64 remainder, DRI2SwapEventPtr func,
1301                                     void *data)
1302{
1303    ScreenPtr screen = draw->pScreen;
1304    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
1305    RADEONInfoPtr info = RADEONPTR(scrn);
1306    xf86CrtcPtr crtc = radeon_dri2_drawable_crtc(draw, TRUE);
1307    uint32_t msc_delta;
1308    drmVBlank vbl;
1309    int ret, flip = 0;
1310    DRI2FrameEventPtr swap_info = NULL;
1311    uintptr_t drm_queue_seq;
1312    CARD64 current_msc;
1313    BoxRec box;
1314    RegionRec region;
1315
1316    /* Truncate to match kernel interfaces; means occasional overflow
1317     * misses, but that's generally not a big deal */
1318    *target_msc &= 0xffffffff;
1319    divisor &= 0xffffffff;
1320    remainder &= 0xffffffff;
1321
1322    /* radeon_dri2_frame_event_handler will get called some unknown time in the
1323     * future with these buffers.  Take a reference to ensure that they won't
1324     * get destroyed before then.
1325     */
1326    radeon_dri2_ref_buffer(front);
1327    radeon_dri2_ref_buffer(back);
1328
1329    /* either off-screen or CRTC not usable... just complete the swap */
1330    if (crtc == NULL)
1331        goto blit_fallback;
1332
1333    msc_delta = radeon_get_msc_delta(draw, crtc);
1334
1335    swap_info = calloc(1, sizeof(DRI2FrameEventRec));
1336    if (!swap_info)
1337        goto blit_fallback;
1338
1339    swap_info->type = DRI2_SWAP;
1340    swap_info->drawable_id = draw->id;
1341    swap_info->client = client;
1342    swap_info->event_complete = func;
1343    swap_info->event_data = data;
1344    swap_info->front = front;
1345    swap_info->back = back;
1346    swap_info->crtc = crtc;
1347
1348    drm_queue_seq = radeon_drm_queue_alloc(crtc, client, RADEON_DRM_QUEUE_ID_DEFAULT,
1349					   swap_info, radeon_dri2_frame_event_handler,
1350					   radeon_dri2_frame_event_abort);
1351    if (!drm_queue_seq) {
1352        xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1353		   "Allocating DRM queue entry failed.\n");
1354        goto blit_fallback;
1355    }
1356    swap_info->drm_queue_seq = drm_queue_seq;
1357
1358    /*
1359     * CRTC is in DPMS off state, fallback to blit, but calculate
1360     * wait time from current time, target_msc and last vblank
1361     * time/sequence when CRTC was turned off
1362     */
1363    if (!radeon_crtc_is_enabled(crtc)) {
1364	CARD32 delay;
1365	*target_msc -= msc_delta;
1366	delay = radeon_dri2_extrapolate_msc_delay(crtc, target_msc,
1367						  divisor, remainder);
1368	*target_msc += msc_delta;
1369	*target_msc &= 0xffffffff;
1370	radeon_dri2_schedule_event(delay, swap_info);
1371	return TRUE;
1372    }
1373
1374    /* Get current count */
1375    vbl.request.type = DRM_VBLANK_RELATIVE;
1376    vbl.request.type |= radeon_populate_vbl_request_type(crtc);
1377    vbl.request.sequence = 0;
1378    ret = drmWaitVBlank(info->dri2.drm_fd, &vbl);
1379    if (ret) {
1380        xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1381                "first get vblank counter failed: %s\n",
1382                strerror(errno));
1383	goto blit_fallback;
1384    }
1385
1386    current_msc = vbl.reply.sequence + msc_delta;
1387    current_msc &= 0xffffffff;
1388
1389    /* Flips need to be submitted one frame before */
1390    if (can_flip(scrn, draw, front, back)) {
1391	swap_info->type = DRI2_FLIP;
1392	flip = 1;
1393    }
1394
1395    /* Correct target_msc by 'flip' if swap_info->type == DRI2_FLIP.
1396     * Do it early, so handling of different timing constraints
1397     * for divisor, remainder and msc vs. target_msc works.
1398     */
1399    if (*target_msc > 0)
1400        *target_msc -= flip;
1401
1402    /*
1403     * If divisor is zero, or current_msc is smaller than target_msc
1404     * we just need to make sure target_msc passes before initiating
1405     * the swap.
1406     */
1407    if (divisor == 0 || current_msc < *target_msc) {
1408        vbl.request.type =  DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
1409        /* If non-pageflipping, but blitting/exchanging, we need to use
1410         * DRM_VBLANK_NEXTONMISS to avoid unreliable timestamping later
1411         * on.
1412         */
1413        if (flip == 0)
1414            vbl.request.type |= DRM_VBLANK_NEXTONMISS;
1415	vbl.request.type |= radeon_populate_vbl_request_type(crtc);
1416
1417        /* If target_msc already reached or passed, set it to
1418         * current_msc to ensure we return a reasonable value back
1419         * to the caller. This makes swap_interval logic more robust.
1420         */
1421        if (current_msc >= *target_msc)
1422            *target_msc = current_msc;
1423
1424        vbl.request.sequence = *target_msc - msc_delta;
1425        vbl.request.signal = drm_queue_seq;
1426        ret = drmWaitVBlank(info->dri2.drm_fd, &vbl);
1427        if (ret) {
1428            xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1429                    "divisor 0 get vblank counter failed: %s\n",
1430                    strerror(errno));
1431	    goto blit_fallback;
1432        }
1433
1434        *target_msc = vbl.reply.sequence + flip + msc_delta;
1435        swap_info->frame = *target_msc;
1436
1437        return TRUE;
1438    }
1439
1440    /*
1441     * If we get here, target_msc has already passed or we don't have one,
1442     * and we need to queue an event that will satisfy the divisor/remainder
1443     * equation.
1444     */
1445    vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
1446    if (flip == 0)
1447        vbl.request.type |= DRM_VBLANK_NEXTONMISS;
1448    vbl.request.type |= radeon_populate_vbl_request_type(crtc);
1449
1450    vbl.request.sequence = current_msc - (current_msc % divisor) +
1451        remainder - msc_delta;
1452
1453    /*
1454     * If the calculated deadline vbl.request.sequence is smaller than
1455     * or equal to current_msc, it means we've passed the last point
1456     * when effective onset frame seq could satisfy
1457     * seq % divisor == remainder, so we need to wait for the next time
1458     * this will happen.
1459
1460     * This comparison takes the 1 frame swap delay in pageflipping mode
1461     * into account, as well as a potential DRM_VBLANK_NEXTONMISS delay
1462     * if we are blitting/exchanging instead of flipping.
1463     */
1464    if (vbl.request.sequence <= current_msc)
1465        vbl.request.sequence += divisor;
1466
1467    /* Account for 1 frame extra pageflip delay if flip > 0 */
1468    vbl.request.sequence -= flip;
1469
1470    vbl.request.signal = drm_queue_seq;
1471    ret = drmWaitVBlank(info->dri2.drm_fd, &vbl);
1472    if (ret) {
1473        xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1474                "final get vblank counter failed: %s\n",
1475                strerror(errno));
1476	goto blit_fallback;
1477    }
1478
1479    /* Adjust returned value for 1 fame pageflip offset of flip > 0 */
1480    *target_msc = vbl.reply.sequence + flip + msc_delta;
1481    *target_msc &= 0xffffffff;
1482    swap_info->frame = *target_msc;
1483
1484    return TRUE;
1485
1486blit_fallback:
1487    if (swap_info) {
1488	swap_info->type = DRI2_SWAP;
1489	radeon_dri2_schedule_event(FALLBACK_SWAP_DELAY, swap_info);
1490    } else {
1491	box.x1 = 0;
1492	box.y1 = 0;
1493	box.x2 = draw->width;
1494	box.y2 = draw->height;
1495	REGION_INIT(pScreen, &region, &box, 0);
1496
1497	radeon_dri2_copy_region(draw, &region, front, back);
1498
1499	DRI2SwapComplete(client, draw, 0, 0, 0, DRI2_BLIT_COMPLETE, func, data);
1500
1501	radeon_dri2_unref_buffer(front);
1502	radeon_dri2_unref_buffer(back);
1503    }
1504
1505    *target_msc = 0; /* offscreen, so zero out target vblank count */
1506    return TRUE;
1507}
1508
1509
1510Bool
1511radeon_dri2_screen_init(ScreenPtr pScreen)
1512{
1513    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1514    RADEONInfoPtr info = RADEONPTR(pScrn);
1515    DRI2InfoRec dri2_info = { 0 };
1516    const char *driverNames[2];
1517    Bool scheduling_works = TRUE;
1518
1519    if (!info->dri2.available)
1520        return FALSE;
1521
1522    info->dri2.device_name = drmGetDeviceNameFromFd(info->dri2.drm_fd);
1523
1524    if ( (info->ChipFamily >= CHIP_FAMILY_TAHITI) ) {
1525        dri2_info.driverName = SI_DRIVER_NAME;
1526    } else if ( (info->ChipFamily >= CHIP_FAMILY_R600) ) {
1527        dri2_info.driverName = R600_DRIVER_NAME;
1528    } else if ( (info->ChipFamily >= CHIP_FAMILY_R300) ) {
1529        dri2_info.driverName = R300_DRIVER_NAME;
1530    } else if ( info->ChipFamily >= CHIP_FAMILY_R200 ) {
1531        dri2_info.driverName = R200_DRIVER_NAME;
1532    } else {
1533        dri2_info.driverName = RADEON_DRIVER_NAME;
1534    }
1535    dri2_info.fd = info->dri2.drm_fd;
1536    dri2_info.deviceName = info->dri2.device_name;
1537    dri2_info.version = DRI2INFOREC_VERSION;
1538    dri2_info.CreateBuffer = radeon_dri2_create_buffer;
1539    dri2_info.DestroyBuffer = radeon_dri2_destroy_buffer;
1540    dri2_info.CopyRegion = radeon_dri2_copy_region;
1541
1542    if (info->dri2.pKernelDRMVersion->version_minor < 4) {
1543	xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "You need a newer kernel for "
1544		   "sync extension\n");
1545	scheduling_works = FALSE;
1546    }
1547
1548    if (scheduling_works && info->drmmode.count_crtcs > 2) {
1549#ifdef DRM_CAP_VBLANK_HIGH_CRTC
1550	uint64_t cap_value;
1551
1552	if (drmGetCap(info->dri2.drm_fd, DRM_CAP_VBLANK_HIGH_CRTC, &cap_value)) {
1553	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "You need a newer kernel "
1554		       "for VBLANKs on CRTC > 1\n");
1555	    scheduling_works = FALSE;
1556	} else if (!cap_value) {
1557	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Your kernel does not "
1558		       "handle VBLANKs on CRTC > 1\n");
1559	    scheduling_works = FALSE;
1560	}
1561#else
1562	xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "You need to rebuild against a "
1563		   "newer libdrm to handle VBLANKs on CRTC > 1\n");
1564	scheduling_works = FALSE;
1565#endif
1566    }
1567
1568    if (scheduling_works) {
1569        dri2_info.version = 4;
1570        dri2_info.ScheduleSwap = radeon_dri2_schedule_swap;
1571        dri2_info.GetMSC = radeon_dri2_get_msc;
1572        dri2_info.ScheduleWaitMSC = radeon_dri2_schedule_wait_msc;
1573        dri2_info.numDrivers = RADEON_ARRAY_SIZE(driverNames);
1574        dri2_info.driverNames = driverNames;
1575        driverNames[0] = dri2_info.driverName;
1576
1577        if (info->ChipFamily >= CHIP_FAMILY_R300)
1578            driverNames[1] = driverNames[0];
1579        else
1580            driverNames[1] = NULL; /* no VDPAU support */
1581
1582	if (DRI2InfoCnt == 0) {
1583	    if (!dixRegisterPrivateKey(dri2_window_private_key,
1584				       PRIVATE_WINDOW,
1585				       sizeof(struct dri2_window_priv))) {
1586		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1587			   "Failed to get DRI2 window private\n");
1588		return FALSE;
1589	    }
1590
1591	    AddCallback(&ClientStateCallback, radeon_dri2_client_state_changed, 0);
1592	}
1593
1594	DRI2InfoCnt++;
1595    }
1596
1597#if DRI2INFOREC_VERSION >= 9
1598    dri2_info.version = 9;
1599    dri2_info.CreateBuffer2 = radeon_dri2_create_buffer2;
1600    dri2_info.DestroyBuffer2 = radeon_dri2_destroy_buffer2;
1601    dri2_info.CopyRegion2 = radeon_dri2_copy_region2;
1602#endif
1603
1604    info->dri2.enabled = DRI2ScreenInit(pScreen, &dri2_info);
1605    return info->dri2.enabled;
1606}
1607
1608void radeon_dri2_close_screen(ScreenPtr pScreen)
1609{
1610    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1611    RADEONInfoPtr info = RADEONPTR(pScrn);
1612
1613    if (--DRI2InfoCnt == 0)
1614    	DeleteCallback(&ClientStateCallback, radeon_dri2_client_state_changed, 0);
1615
1616    DRI2CloseScreen(pScreen);
1617    drmFree(info->dri2.device_name);
1618}
1619
1620#endif /* DRI2 */
1621
1622