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