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