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