intel_dri.c revision 13496ba1
1/**************************************************************************
2
3Copyright 2001 VA Linux Systems Inc., Fremont, California.
4Copyright © 2002 by David Dawes
5
6All Rights Reserved.
7
8Permission is hereby granted, free of charge, to any person obtaining a
9copy of this software and associated documentation files (the "Software"),
10to deal in the Software without restriction, including without limitation
11on the rights to use, copy, modify, merge, publish, distribute, sub
12license, and/or sell copies of the Software, and to permit persons to whom
13the Software is furnished to do so, subject to the following conditions:
14
15The above copyright notice and this permission notice (including the next
16paragraph) shall be included in all copies or substantial portions of the
17Software.
18
19THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
22ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
23DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
25USE OR OTHER DEALINGS IN THE SOFTWARE.
26
27**************************************************************************/
28
29/*
30 * Authors: Jeff Hartmann <jhartmann@valinux.com>
31 *          David Dawes <dawes@xfree86.org>
32 *          Keith Whitwell <keith@tungstengraphics.com>
33 */
34
35#ifdef HAVE_CONFIG_H
36#include "config.h"
37#endif
38
39#include <stdio.h>
40#include <string.h>
41#include <assert.h>
42#include <sys/types.h>
43#include <sys/stat.h>
44#include <sys/ioctl.h>
45#include <unistd.h>
46#include <fcntl.h>
47#include <sys/time.h>
48#include <time.h>
49#include <errno.h>
50
51#include "xorg-server.h"
52#include "xf86.h"
53#include "xf86_OSproc.h"
54
55#include "xf86Pci.h"
56#include "xf86drm.h"
57
58#include "windowstr.h"
59#include "shadow.h"
60#include "fb.h"
61
62#include "intel.h"
63#include "i830_reg.h"
64
65#include "i915_drm.h"
66
67#include "dri2.h"
68
69#if USE_UXA
70#include "intel_uxa.h"
71#endif
72
73typedef struct {
74	int refcnt;
75	PixmapPtr pixmap;
76} I830DRI2BufferPrivateRec, *I830DRI2BufferPrivatePtr;
77
78#if HAS_DEVPRIVATEKEYREC
79static DevPrivateKeyRec i830_client_key;
80#else
81static int i830_client_key;
82#endif
83
84static uint32_t pixmap_flink(PixmapPtr pixmap)
85{
86	struct intel_uxa_pixmap *priv = intel_uxa_get_pixmap_private(pixmap);
87	uint32_t name;
88
89	if (priv == NULL || priv->bo == NULL)
90		return 0;
91
92	if (dri_bo_flink(priv->bo, &name) != 0)
93		return 0;
94
95	priv->pinned |= PIN_DRI2;
96	return name;
97}
98
99static PixmapPtr get_front_buffer(DrawablePtr drawable)
100{
101	PixmapPtr pixmap;
102
103	pixmap = get_drawable_pixmap(drawable);
104	if (!intel_get_pixmap_bo(pixmap))
105		return NULL;
106
107	pixmap->refcnt++;
108	return pixmap;
109}
110
111#if DRI2INFOREC_VERSION < 2
112static DRI2BufferPtr
113I830DRI2CreateBuffers(DrawablePtr drawable, unsigned int *attachments,
114		      int count)
115{
116	ScreenPtr screen = drawable->pScreen;
117	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
118	intel_screen_private *intel = intel_get_screen_private(scrn);
119	DRI2BufferPtr buffers;
120	I830DRI2BufferPrivatePtr privates;
121	PixmapPtr pixmap, pDepthPixmap;
122	int i;
123
124	buffers = calloc(count, sizeof *buffers);
125	if (buffers == NULL)
126		return NULL;
127	privates = calloc(count, sizeof *privates);
128	if (privates == NULL) {
129		free(buffers);
130		return NULL;
131	}
132
133	pDepthPixmap = NULL;
134	for (i = 0; i < count; i++) {
135		pixmap = NULL;
136		if (attachments[i] == DRI2BufferFrontLeft) {
137			pixmap = get_front_buffer(drawable);
138
139			if (pixmap == NULL)
140				drawable = &(get_drawable_pixmap(drawable)->drawable);
141		} else if (attachments[i] == DRI2BufferStencil && pDepthPixmap) {
142			pixmap = pDepthPixmap;
143			pixmap->refcnt++;
144		}
145
146		if (pixmap == NULL) {
147			unsigned int hint = INTEL_CREATE_PIXMAP_DRI2;
148
149			if (intel->tiling & INTEL_TILING_3D) {
150				switch (attachments[i]) {
151				case DRI2BufferDepth:
152					if (SUPPORTS_YTILING(intel))
153						hint |= INTEL_CREATE_PIXMAP_TILING_Y;
154					else
155						hint |= INTEL_CREATE_PIXMAP_TILING_X;
156					break;
157				case DRI2BufferFakeFrontLeft:
158				case DRI2BufferFakeFrontRight:
159				case DRI2BufferBackLeft:
160				case DRI2BufferBackRight:
161					hint |= INTEL_CREATE_PIXMAP_TILING_X;
162					break;
163				}
164			}
165
166			pixmap = screen->CreatePixmap(screen,
167						      drawable->width,
168						      drawable->height,
169						      drawable->depth,
170						      hint);
171			if (pixmap == NULL ||
172			    intel_get_pixmap_bo(pixmap) == NULL)
173			{
174				if (pixmap)
175					screen->DestroyPixmap(pixmap);
176				goto unwind;
177			}
178		}
179
180		if (attachments[i] == DRI2BufferDepth)
181			pDepthPixmap = pixmap;
182
183		buffers[i].attachment = attachments[i];
184		buffers[i].pitch = pixmap->devKind;
185		buffers[i].cpp = pixmap->drawable.bitsPerPixel / 8;
186		buffers[i].driverPrivate = &privates[i];
187		buffers[i].flags = 0;	/* not tiled */
188		privates[i].refcnt = 1;
189		privates[i].pixmap = pixmap;
190
191		if ((buffers[i].name = pixmap_flink(pixmap)) == 0) {
192			/* failed to name buffer */
193			screen->DestroyPixmap(pixmap);
194			goto unwind;
195		}
196	}
197
198	return buffers;
199
200unwind:
201	while (i--)
202		screen->DestroyPixmap(privates[i].pixmap);
203	free(privates);
204	free(buffers);
205	return NULL;
206}
207
208static void
209I830DRI2DestroyBuffers(DrawablePtr drawable, DRI2BufferPtr buffers, int count)
210{
211	ScreenPtr screen = drawable->pScreen;
212	I830DRI2BufferPrivatePtr private;
213	int i;
214
215	for (i = 0; i < count; i++) {
216		private = buffers[i].driverPrivate;
217		screen->DestroyPixmap(private->pixmap);
218	}
219
220	if (buffers) {
221		free(buffers[0].driverPrivate);
222		free(buffers);
223	}
224}
225
226#else
227
228static DRI2Buffer2Ptr
229I830DRI2CreateBuffer(DrawablePtr drawable, unsigned int attachment,
230		     unsigned int format)
231{
232	ScreenPtr screen = drawable->pScreen;
233	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
234	intel_screen_private *intel = intel_get_screen_private(scrn);
235	DRI2Buffer2Ptr buffer;
236	I830DRI2BufferPrivatePtr privates;
237	PixmapPtr pixmap;
238
239	buffer = calloc(1, sizeof *buffer);
240	if (buffer == NULL)
241		return NULL;
242	privates = calloc(1, sizeof *privates);
243	if (privates == NULL) {
244		free(buffer);
245		return NULL;
246	}
247
248	pixmap = NULL;
249	if (attachment == DRI2BufferFrontLeft) {
250		pixmap = get_front_buffer(drawable);
251		if (pixmap == NULL)
252			drawable = &(get_drawable_pixmap(drawable)->drawable);
253	}
254
255	if (pixmap == NULL) {
256		unsigned int hint = INTEL_CREATE_PIXMAP_DRI2;
257		int pixmap_width = drawable->width;
258		int pixmap_height = drawable->height;
259		int pixmap_cpp = (format != 0) ? format : drawable->depth;
260
261		if (intel->tiling & INTEL_TILING_3D) {
262			switch (attachment) {
263			case DRI2BufferDepth:
264			case DRI2BufferDepthStencil:
265			case DRI2BufferHiz:
266				if (SUPPORTS_YTILING(intel)) {
267					hint |= INTEL_CREATE_PIXMAP_TILING_Y;
268					break;
269				}
270			case DRI2BufferAccum:
271			case DRI2BufferBackLeft:
272			case DRI2BufferBackRight:
273			case DRI2BufferFakeFrontLeft:
274			case DRI2BufferFakeFrontRight:
275			case DRI2BufferFrontLeft:
276			case DRI2BufferFrontRight:
277				hint |= INTEL_CREATE_PIXMAP_TILING_X;
278				break;
279			case DRI2BufferStencil:
280				/*
281				 * The stencil buffer is W tiled. However, we
282				 * request from the kernel a non-tiled buffer
283				 * because the GTT is incapable of W fencing.
284				 */
285				hint |= INTEL_CREATE_PIXMAP_TILING_NONE;
286				break;
287			default:
288				free(privates);
289				free(buffer);
290				return NULL;
291                        }
292		}
293
294		/*
295		 * The stencil buffer has quirky pitch requirements.  From Vol
296		 * 2a, 11.5.6.2.1 3DSTATE_STENCIL_BUFFER, field "Surface
297		 * Pitch":
298		 *    The pitch must be set to 2x the value computed based on
299		 *    width, as the stencil buffer is stored with two rows
300		 *    interleaved.
301		 * To accomplish this, we resort to the nasty hack of doubling
302		 * the drm region's cpp and halving its height.
303		 *
304		 * If we neglect to double the pitch, then render corruption
305		 * occurs.
306		 */
307		if (attachment == DRI2BufferStencil) {
308			pixmap_width = ALIGN(pixmap_width, 64);
309			pixmap_height = ALIGN((pixmap_height + 1) / 2, 64);
310			pixmap_cpp *= 2;
311		}
312
313		pixmap = screen->CreatePixmap(screen,
314					      pixmap_width,
315					      pixmap_height,
316					      pixmap_cpp,
317					      hint);
318		if (pixmap == NULL || intel_get_pixmap_bo(pixmap) == NULL) {
319			if (pixmap)
320				screen->DestroyPixmap(pixmap);
321			free(privates);
322			free(buffer);
323			return NULL;
324		}
325	}
326
327	buffer->attachment = attachment;
328	buffer->pitch = pixmap->devKind;
329	buffer->cpp = pixmap->drawable.bitsPerPixel / 8;
330	buffer->driverPrivate = privates;
331	buffer->format = format;
332	buffer->flags = 0;	/* not tiled */
333	privates->refcnt = 1;
334	privates->pixmap = pixmap;
335
336	if ((buffer->name = pixmap_flink(pixmap)) == 0) {
337		/* failed to name buffer */
338		screen->DestroyPixmap(pixmap);
339		free(privates);
340		free(buffer);
341		return NULL;
342	}
343
344	return buffer;
345}
346
347static void I830DRI2DestroyBuffer(DrawablePtr drawable, DRI2Buffer2Ptr buffer)
348{
349	if (buffer && buffer->driverPrivate) {
350		I830DRI2BufferPrivatePtr private = buffer->driverPrivate;
351		if (--private->refcnt == 0) {
352			ScreenPtr screen = private->pixmap->drawable.pScreen;
353			screen->DestroyPixmap(private->pixmap);
354
355			free(private);
356			free(buffer);
357		}
358	} else
359		free(buffer);
360}
361
362#endif
363
364static void
365I830DRI2CopyRegion(DrawablePtr drawable, RegionPtr pRegion,
366		   DRI2BufferPtr destBuffer, DRI2BufferPtr sourceBuffer)
367{
368	I830DRI2BufferPrivatePtr srcPrivate = sourceBuffer->driverPrivate;
369	I830DRI2BufferPrivatePtr dstPrivate = destBuffer->driverPrivate;
370	ScreenPtr screen = drawable->pScreen;
371	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
372	intel_screen_private *intel = intel_get_screen_private(scrn);
373	DrawablePtr src = (sourceBuffer->attachment == DRI2BufferFrontLeft)
374		? drawable : &srcPrivate->pixmap->drawable;
375	DrawablePtr dst = (destBuffer->attachment == DRI2BufferFrontLeft)
376		? drawable : &dstPrivate->pixmap->drawable;
377	RegionPtr pCopyClip;
378	GCPtr gc;
379
380	gc = GetScratchGC(dst->depth, screen);
381	if (!gc)
382		return;
383
384	pCopyClip = REGION_CREATE(screen, NULL, 0);
385	REGION_COPY(screen, pCopyClip, pRegion);
386	(*gc->funcs->ChangeClip) (gc, CT_REGION, pCopyClip, 0);
387	ValidateGC(dst, gc);
388
389	/* Wait for the scanline to be outside the region to be copied */
390	if (scrn->vtSema &&
391	    pixmap_is_scanout(get_drawable_pixmap(dst)) &&
392	    intel->swapbuffers_wait && INTEL_INFO(intel)->gen < 060) {
393		BoxPtr box;
394		BoxRec crtcbox;
395		int y1, y2;
396		int event, load_scan_lines_pipe;
397		xf86CrtcPtr crtc;
398		Bool full_height = FALSE;
399
400		box = REGION_EXTENTS(unused, gc->pCompositeClip);
401		crtc = intel_covering_crtc(scrn, box, NULL, &crtcbox);
402
403		/*
404		 * Make sure the CRTC is valid and this is the real front
405		 * buffer
406		 */
407		if (crtc != NULL && !crtc->rotatedData) {
408			int pipe = intel_crtc_to_pipe(crtc);
409
410			/*
411			 * Make sure we don't wait for a scanline that will
412			 * never occur
413			 */
414			y1 = (crtcbox.y1 <= box->y1) ? box->y1 - crtcbox.y1 : 0;
415			y2 = (box->y2 <= crtcbox.y2) ?
416			    box->y2 - crtcbox.y1 : crtcbox.y2 - crtcbox.y1;
417
418			if (y1 == 0 && y2 == (crtcbox.y2 - crtcbox.y1))
419			    full_height = TRUE;
420
421			/*
422			 * Pre-965 doesn't have SVBLANK, so we need a bit
423			 * of extra time for the blitter to start up and
424			 * do its job for a full height blit
425			 */
426			if (full_height && INTEL_INFO(intel)->gen < 040)
427			    y2 -= 2;
428
429			if (pipe == 0) {
430				event = MI_WAIT_FOR_PIPEA_SCAN_LINE_WINDOW;
431				load_scan_lines_pipe =
432				    MI_LOAD_SCAN_LINES_DISPLAY_PIPEA;
433				if (full_height && INTEL_INFO(intel)->gen >= 040)
434				    event = MI_WAIT_FOR_PIPEA_SVBLANK;
435			} else {
436				event = MI_WAIT_FOR_PIPEB_SCAN_LINE_WINDOW;
437				load_scan_lines_pipe =
438				    MI_LOAD_SCAN_LINES_DISPLAY_PIPEB;
439				if (full_height && INTEL_INFO(intel)->gen >= 040)
440				    event = MI_WAIT_FOR_PIPEB_SVBLANK;
441			}
442
443			if (crtc->mode.Flags & V_INTERLACE) {
444				/* DSL count field lines */
445				y1 /= 2;
446				y2 /= 2;
447			}
448
449			BEGIN_BATCH(5);
450			/*
451			 * The documentation says that the LOAD_SCAN_LINES
452			 * command always comes in pairs. Don't ask me why.
453			 */
454			OUT_BATCH(MI_LOAD_SCAN_LINES_INCL |
455				  load_scan_lines_pipe);
456			OUT_BATCH((y1 << 16) | (y2-1));
457			OUT_BATCH(MI_LOAD_SCAN_LINES_INCL |
458				  load_scan_lines_pipe);
459			OUT_BATCH((y1 << 16) | (y2-1));
460			OUT_BATCH(MI_WAIT_FOR_EVENT | event);
461			ADVANCE_BATCH();
462		}
463	}
464
465	/* It's important that this copy gets submitted before the
466	 * direct rendering client submits rendering for the next
467	 * frame, but we don't actually need to submit right now.  The
468	 * client will wait for the DRI2CopyRegion reply or the swap
469	 * buffer event before rendering, and we'll hit the flush
470	 * callback chain before those messages are sent.  We submit
471	 * our batch buffers from the flush callback chain so we know
472	 * that will happen before the client tries to render
473	 * again. */
474
475	gc->ops->CopyArea(src, dst, gc,
476			  0, 0,
477			  drawable->width, drawable->height,
478			  0, 0);
479
480	FreeScratchGC(gc);
481
482	/* And make sure the WAIT_FOR_EVENT is queued before any
483	 * modesetting/dpms operations on the pipe.
484	 */
485	intel_batch_submit(scrn);
486}
487
488static void
489I830DRI2FallbackBlitSwap(DrawablePtr drawable,
490			 DRI2BufferPtr dst,
491			 DRI2BufferPtr src)
492{
493	BoxRec box;
494	RegionRec region;
495
496	box.x1 = 0;
497	box.y1 = 0;
498	box.x2 = drawable->width;
499	box.y2 = drawable->height;
500	REGION_INIT(pScreen, &region, &box, 0);
501
502	I830DRI2CopyRegion(drawable, &region, dst, src);
503}
504
505#if DRI2INFOREC_VERSION >= 4
506
507static void I830DRI2ReferenceBuffer(DRI2Buffer2Ptr buffer)
508{
509	if (buffer) {
510		I830DRI2BufferPrivatePtr private = buffer->driverPrivate;
511		private->refcnt++;
512	}
513}
514
515static xf86CrtcPtr
516I830DRI2DrawableCrtc(DrawablePtr pDraw)
517{
518	ScreenPtr pScreen = pDraw->pScreen;
519	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
520	BoxRec box, crtcbox;
521	xf86CrtcPtr crtc = NULL;
522
523	box.x1 = pDraw->x;
524	box.y1 = pDraw->y;
525	box.x2 = box.x1 + pDraw->width;
526	box.y2 = box.y1 + pDraw->height;
527
528	if (pDraw->type != DRAWABLE_PIXMAP)
529		crtc = intel_covering_crtc(pScrn, &box, NULL, &crtcbox);
530
531	/* Make sure the CRTC is valid and this is the real front buffer */
532	if (crtc != NULL && !crtc->rotatedData)
533                return crtc;
534
535	return NULL;
536}
537
538static RESTYPE	frame_event_client_type, frame_event_drawable_type;
539
540struct i830_dri2_resource {
541	XID id;
542	RESTYPE type;
543	struct list list;
544};
545
546static struct i830_dri2_resource *
547get_resource(XID id, RESTYPE type)
548{
549	struct i830_dri2_resource *resource;
550	void *ptr;
551
552	ptr = NULL;
553	dixLookupResourceByType(&ptr, id, type, NULL, DixWriteAccess);
554	if (ptr)
555		return ptr;
556
557	resource = malloc(sizeof(*resource));
558	if (resource == NULL)
559		return NULL;
560
561	if (!AddResource(id, type, resource)) {
562		free(resource);
563		return NULL;
564	}
565
566	resource->id = id;
567	resource->type = type;
568	list_init(&resource->list);
569	return resource;
570}
571
572static int
573i830_dri2_frame_event_client_gone(void *data, XID id)
574{
575	struct i830_dri2_resource *resource = data;
576
577	while (!list_is_empty(&resource->list)) {
578		DRI2FrameEventPtr info =
579			list_first_entry(&resource->list,
580					 DRI2FrameEventRec,
581					 client_resource);
582
583		list_del(&info->client_resource);
584		info->client = NULL;
585	}
586	free(resource);
587
588	return Success;
589}
590
591static int
592i830_dri2_frame_event_drawable_gone(void *data, XID id)
593{
594	struct i830_dri2_resource *resource = data;
595
596	while (!list_is_empty(&resource->list)) {
597		DRI2FrameEventPtr info =
598			list_first_entry(&resource->list,
599					 DRI2FrameEventRec,
600					 drawable_resource);
601
602		list_del(&info->drawable_resource);
603		info->drawable_id = None;
604	}
605	free(resource);
606
607	return Success;
608}
609
610static Bool
611i830_dri2_register_frame_event_resource_types(void)
612{
613	frame_event_client_type = CreateNewResourceType(i830_dri2_frame_event_client_gone, "Frame Event Client");
614	if (!frame_event_client_type)
615		return FALSE;
616
617	frame_event_drawable_type = CreateNewResourceType(i830_dri2_frame_event_drawable_gone, "Frame Event Drawable");
618	if (!frame_event_drawable_type)
619		return FALSE;
620
621	return TRUE;
622}
623
624static XID
625get_client_id(ClientPtr client)
626{
627#if HAS_DIXREGISTERPRIVATEKEY
628	XID *ptr = dixGetPrivateAddr(&client->devPrivates, &i830_client_key);
629#else
630	XID *ptr = dixLookupPrivate(&client->devPrivates, &i830_client_key);
631#endif
632	if (*ptr == 0)
633		*ptr = FakeClientID(client->index);
634	return *ptr;
635}
636
637/*
638 * Hook this frame event into the server resource
639 * database so we can clean it up if the drawable or
640 * client exits while the swap is pending
641 */
642static Bool
643i830_dri2_add_frame_event(DRI2FrameEventPtr info)
644{
645	struct i830_dri2_resource *resource;
646
647	resource = get_resource(get_client_id(info->client),
648				frame_event_client_type);
649	if (resource == NULL)
650		return FALSE;
651
652	list_add(&info->client_resource, &resource->list);
653
654	resource = get_resource(info->drawable_id, frame_event_drawable_type);
655	if (resource == NULL) {
656		list_del(&info->client_resource);
657		return FALSE;
658	}
659
660	list_add(&info->drawable_resource, &resource->list);
661
662	return TRUE;
663}
664
665static void
666i830_dri2_del_frame_event(DRI2FrameEventPtr info)
667{
668	list_del(&info->client_resource);
669	list_del(&info->drawable_resource);
670
671	if (info->front)
672		I830DRI2DestroyBuffer(NULL, info->front);
673	if (info->back)
674		I830DRI2DestroyBuffer(NULL, info->back);
675
676	free(info);
677}
678
679static struct intel_uxa_pixmap *
680intel_exchange_pixmap_buffers(struct intel_screen_private *intel, PixmapPtr front, PixmapPtr back)
681{
682	struct intel_uxa_pixmap *new_front = NULL, *new_back;
683	RegionRec region;
684
685	/* Post damage on the front buffer so that listeners, such
686	 * as DisplayLink know take a copy and shove it over the USB.
687	 * also for sw cursors.
688	 */
689	region.extents.x1 = region.extents.y1 = 0;
690	region.extents.x2 = front->drawable.width;
691	region.extents.y2 = front->drawable.height;
692	region.data = NULL;
693	DamageRegionAppend(&front->drawable, &region);
694
695	new_front = intel_uxa_get_pixmap_private(back);
696	new_back = intel_uxa_get_pixmap_private(front);
697	intel_uxa_set_pixmap_private(front, new_front);
698	intel_uxa_set_pixmap_private(back, new_back);
699	new_front->busy = 1;
700	new_back->busy = -1;
701
702	DamageRegionProcessPending(&front->drawable);
703
704	return new_front;
705}
706
707static void
708I830DRI2ExchangeBuffers(struct intel_screen_private *intel, DRI2BufferPtr front, DRI2BufferPtr back)
709{
710	I830DRI2BufferPrivatePtr front_priv, back_priv;
711	int tmp;
712	struct intel_uxa_pixmap *new_front;
713
714	front_priv = front->driverPrivate;
715	back_priv = back->driverPrivate;
716
717	/* Swap BO names so DRI works */
718	tmp = front->name;
719	front->name = back->name;
720	back->name = tmp;
721
722	/* Swap pixmap bos */
723	new_front = intel_exchange_pixmap_buffers(intel,
724						  front_priv->pixmap,
725						  back_priv->pixmap);
726	dri_bo_unreference (intel->front_buffer);
727	intel->front_buffer = new_front->bo;
728	dri_bo_reference (intel->front_buffer);
729}
730
731static drm_intel_bo *get_pixmap_bo(I830DRI2BufferPrivatePtr priv)
732{
733	drm_intel_bo *bo = intel_get_pixmap_bo(priv->pixmap);
734	assert(bo != NULL); /* guaranteed by construction of the DRI2 buffer */
735	return bo;
736}
737
738static void
739I830DRI2FlipComplete(uint64_t frame, uint64_t usec, void *pageflip_data)
740{
741        DRI2FrameEventPtr info = pageflip_data;
742
743        I830DRI2FlipEventHandler((uint32_t) frame, usec / 1000000,
744                                 usec % 1000000,
745                                 info);
746}
747
748static void
749I830DRI2FlipAbort(void *pageflip_data)
750{
751        DRI2FrameEventPtr info = pageflip_data;
752
753        i830_dri2_del_frame_event(info);
754}
755
756/*
757 * Our internal swap routine takes care of actually exchanging, blitting, or
758 * flipping buffers as necessary.
759 */
760static Bool
761I830DRI2ScheduleFlip(struct intel_screen_private *intel,
762		     DrawablePtr draw,
763		     DRI2FrameEventPtr info)
764{
765	I830DRI2BufferPrivatePtr priv = info->back->driverPrivate;
766	drm_intel_bo *new_back, *old_back;
767	int tmp_name;
768
769	if (!intel->use_triple_buffer) {
770		info->type = DRI2_SWAP;
771		if (!intel_do_pageflip(intel,
772				       get_pixmap_bo(priv),
773				       info->pipe, FALSE, info,
774                                       I830DRI2FlipComplete,
775                                       I830DRI2FlipAbort))
776			return FALSE;
777
778		I830DRI2ExchangeBuffers(intel, info->front, info->back);
779		return TRUE;
780	}
781
782	if (intel->pending_flip[info->pipe]) {
783		assert(intel->pending_flip[info->pipe]->chain == NULL);
784		intel->pending_flip[info->pipe]->chain = info;
785		return TRUE;
786	}
787
788	if (intel->back_buffer == NULL) {
789		new_back = drm_intel_bo_alloc(intel->bufmgr, "front buffer",
790					      intel->front_buffer->size, 0);
791		if (new_back == NULL)
792			return FALSE;
793
794		if (intel->front_tiling != I915_TILING_NONE) {
795			uint32_t tiling = intel->front_tiling;
796			drm_intel_bo_set_tiling(new_back, &tiling, intel->front_pitch);
797			if (tiling != intel->front_tiling) {
798				drm_intel_bo_unreference(new_back);
799				return FALSE;
800			}
801		}
802
803		drm_intel_bo_disable_reuse(new_back);
804		dri_bo_flink(new_back, &intel->back_name);
805	} else {
806		new_back = intel->back_buffer;
807		intel->back_buffer = NULL;
808	}
809
810	old_back = get_pixmap_bo(priv);
811	if (!intel_do_pageflip(intel, old_back, info->pipe, FALSE, info, I830DRI2FlipComplete, I830DRI2FlipAbort)) {
812		intel->back_buffer = new_back;
813		return FALSE;
814	}
815	info->type = DRI2_SWAP_CHAIN;
816	intel->pending_flip[info->pipe] = info;
817
818	priv = info->front->driverPrivate;
819
820	/* Exchange the current front-buffer with the fresh bo */
821
822	intel->back_buffer = intel->front_buffer;
823	drm_intel_bo_reference(intel->back_buffer);
824	intel_set_pixmap_bo(priv->pixmap, new_back);
825	drm_intel_bo_unreference(new_back);
826
827	tmp_name = info->front->name;
828	info->front->name = intel->back_name;
829	intel->back_name = tmp_name;
830
831	/* Then flip DRI2 pointers and update the screen pixmap */
832	I830DRI2ExchangeBuffers(intel, info->front, info->back);
833	DRI2SwapComplete(info->client, draw, 0, 0, 0,
834			 DRI2_EXCHANGE_COMPLETE,
835			 info->event_complete,
836			 info->event_data);
837	return TRUE;
838}
839
840static Bool
841can_exchange(DrawablePtr drawable, DRI2BufferPtr front, DRI2BufferPtr back)
842{
843	ScrnInfoPtr pScrn = xf86ScreenToScrn(drawable->pScreen);
844	struct intel_screen_private *intel = intel_get_screen_private(pScrn);
845	I830DRI2BufferPrivatePtr front_priv = front->driverPrivate;
846	I830DRI2BufferPrivatePtr back_priv = back->driverPrivate;
847	PixmapPtr front_pixmap = front_priv->pixmap;
848	PixmapPtr back_pixmap = back_priv->pixmap;
849	struct intel_uxa_pixmap *front_intel = intel_uxa_get_pixmap_private(front_pixmap);
850	struct intel_uxa_pixmap *back_intel = intel_uxa_get_pixmap_private(back_pixmap);
851
852	if (!pScrn->vtSema)
853		return FALSE;
854
855	if (I830DRI2DrawableCrtc(drawable) == NULL)
856		return FALSE;
857
858	if (!DRI2CanFlip(drawable))
859		return FALSE;
860
861	if (intel->shadow_present)
862		return FALSE;
863
864	if (!intel->use_pageflipping)
865		return FALSE;
866
867	if (front_pixmap->drawable.width != back_pixmap->drawable.width)
868		return FALSE;
869
870	if (front_pixmap->drawable.height != back_pixmap->drawable.height)
871		return FALSE;
872
873	/* XXX should we be checking depth instead of bpp? */
874#if 0
875	if (front_pixmap->drawable.depth != back_pixmap->drawable.depth)
876		return FALSE;
877#else
878	if (front_pixmap->drawable.bitsPerPixel != back_pixmap->drawable.bitsPerPixel)
879		return FALSE;
880#endif
881
882	/* prevent an implicit tiling mode change */
883	if (front_intel->tiling != back_intel->tiling)
884		return FALSE;
885
886	if (front_intel->pinned & ~(PIN_SCANOUT | PIN_DRI2))
887		return FALSE;
888
889	return TRUE;
890}
891
892void I830DRI2FrameEventHandler(unsigned int frame, unsigned int tv_sec,
893			       unsigned int tv_usec, DRI2FrameEventPtr swap_info)
894{
895	intel_screen_private *intel = swap_info->intel;
896	DrawablePtr drawable;
897	int status;
898
899	if (!swap_info->drawable_id)
900		status = BadDrawable;
901	else
902		status = dixLookupDrawable(&drawable, swap_info->drawable_id, serverClient,
903					   M_ANY, DixWriteAccess);
904	if (status != Success) {
905		i830_dri2_del_frame_event(swap_info);
906		return;
907	}
908
909
910	switch (swap_info->type) {
911	case DRI2_FLIP:
912		/* If we can still flip... */
913		if (can_exchange(drawable, swap_info->front, swap_info->back) &&
914		    I830DRI2ScheduleFlip(intel, drawable, swap_info))
915			return;
916
917		/* else fall through to exchange/blit */
918	case DRI2_SWAP: {
919		I830DRI2FallbackBlitSwap(drawable,
920					 swap_info->front, swap_info->back);
921		DRI2SwapComplete(swap_info->client, drawable, frame, tv_sec, tv_usec,
922				 DRI2_BLIT_COMPLETE,
923				 swap_info->client ? swap_info->event_complete : NULL,
924				 swap_info->event_data);
925		break;
926	}
927	case DRI2_WAITMSC:
928		if (swap_info->client)
929			DRI2WaitMSCComplete(swap_info->client, drawable,
930					    frame, tv_sec, tv_usec);
931		break;
932	default:
933		xf86DrvMsg(intel->scrn->scrnIndex, X_WARNING,
934			   "%s: unknown vblank event received\n", __func__);
935		/* Unknown type */
936		break;
937	}
938
939	i830_dri2_del_frame_event(swap_info);
940}
941
942void I830DRI2FlipEventHandler(unsigned int frame, unsigned int tv_sec,
943			      unsigned int tv_usec, DRI2FrameEventPtr flip_info)
944{
945	struct intel_screen_private *intel = flip_info->intel;
946	DrawablePtr drawable;
947	DRI2FrameEventPtr chain;
948
949	drawable = NULL;
950	if (flip_info->drawable_id)
951		dixLookupDrawable(&drawable, flip_info->drawable_id, serverClient,
952				  M_ANY, DixWriteAccess);
953
954
955	/* We assume our flips arrive in order, so we don't check the frame */
956	switch (flip_info->type) {
957	case DRI2_SWAP:
958		if (!drawable)
959			break;
960
961		/* Check for too small vblank count of pageflip completion, taking wraparound
962		 * into account. This usually means some defective kms pageflip completion,
963		 * causing wrong (msc, ust) return values and possible visual corruption.
964		 */
965		if ((frame < flip_info->frame) && (flip_info->frame - frame < 5)) {
966			static int limit = 5;
967
968			/* XXX we are currently hitting this path with older
969			 * kernels, so make it quieter.
970			 */
971			if (limit) {
972				xf86DrvMsg(intel->scrn->scrnIndex, X_WARNING,
973					   "%s: Pageflip completion has impossible msc %d < target_msc %d\n",
974					   __func__, frame, flip_info->frame);
975				limit--;
976			}
977
978			/* All-0 values signal timestamping failure. */
979			frame = tv_sec = tv_usec = 0;
980		}
981
982		DRI2SwapComplete(flip_info->client, drawable, frame, tv_sec, tv_usec,
983				 DRI2_FLIP_COMPLETE, flip_info->client ? flip_info->event_complete : NULL,
984				 flip_info->event_data);
985		break;
986
987	case DRI2_SWAP_CHAIN:
988		assert(intel->pending_flip[flip_info->pipe] == flip_info);
989		intel->pending_flip[flip_info->pipe] = NULL;
990
991		chain = flip_info->chain;
992		if (chain) {
993			DrawablePtr chain_drawable = NULL;
994			if (chain->drawable_id)
995				 dixLookupDrawable(&chain_drawable,
996						   chain->drawable_id,
997						   serverClient,
998						   M_ANY, DixWriteAccess);
999			if (chain_drawable == NULL) {
1000				i830_dri2_del_frame_event(chain);
1001			} else if (!can_exchange(chain_drawable, chain->front, chain->back) ||
1002				   !I830DRI2ScheduleFlip(intel, chain_drawable, chain)) {
1003				I830DRI2FallbackBlitSwap(chain_drawable,
1004							 chain->front,
1005							 chain->back);
1006
1007				DRI2SwapComplete(chain->client, chain_drawable, frame, tv_sec, tv_usec,
1008						 DRI2_BLIT_COMPLETE,
1009						 chain->client ? chain->event_complete : NULL,
1010						 chain->event_data);
1011				i830_dri2_del_frame_event(chain);
1012			}
1013		}
1014		break;
1015
1016	default:
1017		xf86DrvMsg(intel->scrn->scrnIndex, X_WARNING,
1018			   "%s: unknown vblank event received\n", __func__);
1019		/* Unknown type */
1020		break;
1021	}
1022
1023	i830_dri2_del_frame_event(flip_info);
1024}
1025
1026static uint32_t pipe_select(int pipe)
1027{
1028	if (pipe > 1)
1029		return pipe << DRM_VBLANK_HIGH_CRTC_SHIFT;
1030	else if (pipe > 0)
1031		return DRM_VBLANK_SECONDARY;
1032	else
1033		return 0;
1034}
1035
1036static void
1037intel_dri2_vblank_handler(ScrnInfoPtr scrn,
1038                          xf86CrtcPtr crtc,
1039                          uint64_t msc,
1040                          uint64_t usec,
1041                          void *data)
1042{
1043        DRI2FrameEventPtr swap_info = data;
1044
1045        I830DRI2FrameEventHandler((uint32_t) msc, usec / 1000000, usec % 1000000, swap_info);
1046}
1047
1048static void
1049intel_dri2_vblank_abort(ScrnInfoPtr scrn,
1050                        xf86CrtcPtr crtc,
1051                        void *data)
1052{
1053        DRI2FrameEventPtr swap_info = data;
1054
1055        i830_dri2_del_frame_event(swap_info);
1056}
1057
1058/*
1059 * ScheduleSwap is responsible for requesting a DRM vblank event for the
1060 * appropriate frame.
1061 *
1062 * In the case of a blit (e.g. for a windowed swap) or buffer exchange,
1063 * the vblank requested can simply be the last queued swap frame + the swap
1064 * interval for the drawable.
1065 *
1066 * In the case of a page flip, we request an event for the last queued swap
1067 * frame + swap interval - 1, since we'll need to queue the flip for the frame
1068 * immediately following the received event.
1069 *
1070 * The client will be blocked if it tries to perform further GL commands
1071 * after queueing a swap, though in the Intel case after queueing a flip, the
1072 * client is free to queue more commands; they'll block in the kernel if
1073 * they access buffers busy with the flip.
1074 *
1075 * When the swap is complete, the driver should call into the server so it
1076 * can send any swap complete events that have been requested.
1077 */
1078static int
1079I830DRI2ScheduleSwap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
1080		     DRI2BufferPtr back, CARD64 *target_msc, CARD64 divisor,
1081		     CARD64 remainder, DRI2SwapEventPtr func, void *data)
1082{
1083	ScreenPtr screen = draw->pScreen;
1084	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
1085	intel_screen_private *intel = intel_get_screen_private(scrn);
1086	drmVBlank vbl;
1087	int ret;
1088        xf86CrtcPtr crtc = I830DRI2DrawableCrtc(draw);
1089        int pipe = crtc ? intel_crtc_to_pipe(crtc) : -1;
1090        int flip = 0;
1091	DRI2FrameEventPtr swap_info = NULL;
1092	enum DRI2FrameEventType swap_type = DRI2_SWAP;
1093	uint64_t current_msc, current_ust;
1094        uint64_t request_msc;
1095        uint32_t seq;
1096
1097	/* Drawable not displayed... just complete the swap */
1098	if (pipe == -1)
1099	    goto blit_fallback;
1100
1101	swap_info = calloc(1, sizeof(DRI2FrameEventRec));
1102	if (!swap_info)
1103	    goto blit_fallback;
1104
1105	swap_info->intel = intel;
1106	swap_info->drawable_id = draw->id;
1107	swap_info->client = client;
1108	swap_info->event_complete = func;
1109	swap_info->event_data = data;
1110	swap_info->front = front;
1111	swap_info->back = back;
1112	swap_info->pipe = pipe;
1113
1114	if (!i830_dri2_add_frame_event(swap_info)) {
1115	    free(swap_info);
1116	    swap_info = NULL;
1117	    goto blit_fallback;
1118	}
1119
1120	I830DRI2ReferenceBuffer(front);
1121	I830DRI2ReferenceBuffer(back);
1122
1123        ret = intel_get_crtc_msc_ust(scrn, crtc, &current_msc, &current_ust);
1124	if (ret)
1125	    goto blit_fallback;
1126
1127	/* Flips need to be submitted one frame before */
1128	if (can_exchange(draw, front, back)) {
1129	    swap_type = DRI2_FLIP;
1130	    flip = 1;
1131	}
1132
1133	swap_info->type = swap_type;
1134
1135	/* Correct target_msc by 'flip' if swap_type == DRI2_FLIP.
1136	 * Do it early, so handling of different timing constraints
1137	 * for divisor, remainder and msc vs. target_msc works.
1138	 */
1139	if (*target_msc > 0)
1140		*target_msc -= flip;
1141
1142	/*
1143	 * If divisor is zero, or current_msc is smaller than target_msc
1144	 * we just need to make sure target_msc passes before initiating
1145	 * the swap.
1146	 */
1147	if (divisor == 0 || current_msc < *target_msc) {
1148		/*
1149		 * If we can, schedule the flip directly from here rather
1150		 * than waiting for an event from the kernel for the current
1151		 * (or a past) MSC.
1152		 */
1153		if (flip && divisor == 0 && current_msc >= *target_msc &&
1154		    I830DRI2ScheduleFlip(intel, draw, swap_info))
1155			return TRUE;
1156
1157		vbl.request.type =
1158			DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT | pipe_select(pipe);
1159
1160		/* If non-pageflipping, but blitting/exchanging, we need to use
1161		 * DRM_VBLANK_NEXTONMISS to avoid unreliable timestamping later
1162		 * on.
1163		 */
1164		if (flip == 0)
1165			vbl.request.type |= DRM_VBLANK_NEXTONMISS;
1166
1167		/* If target_msc already reached or passed, set it to
1168		 * current_msc to ensure we return a reasonable value back
1169		 * to the caller. This makes swap_interval logic more robust.
1170		 */
1171		if (current_msc >= *target_msc)
1172			*target_msc = current_msc;
1173
1174                seq = intel_drm_queue_alloc(scrn, crtc, swap_info, intel_dri2_vblank_handler, intel_dri2_vblank_abort);
1175                if (!seq)
1176                        goto blit_fallback;
1177
1178		vbl.request.sequence = intel_crtc_msc_to_sequence(scrn, crtc, *target_msc);
1179		vbl.request.signal = seq;
1180
1181		ret = drmWaitVBlank(intel->drmSubFD, &vbl);
1182		if (ret) {
1183			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1184				   "divisor 0 get vblank counter failed: %s\n",
1185				   strerror(errno));
1186			goto blit_fallback;
1187		}
1188
1189                *target_msc = intel_sequence_to_crtc_msc(crtc, vbl.reply.sequence + flip);
1190		swap_info->frame = *target_msc;
1191
1192		return TRUE;
1193	}
1194
1195	/*
1196	 * If we get here, target_msc has already passed or we don't have one,
1197	 * and we need to queue an event that will satisfy the divisor/remainder
1198	 * equation.
1199	 */
1200	vbl.request.type =
1201		DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT | pipe_select(pipe);
1202	if (flip == 0)
1203		vbl.request.type |= DRM_VBLANK_NEXTONMISS;
1204
1205        request_msc = current_msc - (current_msc % divisor) +
1206                remainder;
1207
1208	/*
1209	 * If the calculated deadline vbl.request.sequence is smaller than
1210	 * or equal to current_msc, it means we've passed the last point
1211	 * when effective onset frame seq could satisfy
1212	 * seq % divisor == remainder, so we need to wait for the next time
1213	 * this will happen.
1214
1215	 * This comparison takes the 1 frame swap delay in pageflipping mode
1216	 * into account, as well as a potential DRM_VBLANK_NEXTONMISS delay
1217	 * if we are blitting/exchanging instead of flipping.
1218	 */
1219	if (request_msc <= current_msc)
1220		request_msc += divisor;
1221
1222        seq = intel_drm_queue_alloc(scrn, crtc, swap_info, intel_dri2_vblank_handler, intel_dri2_vblank_abort);
1223        if (!seq)
1224                goto blit_fallback;
1225
1226	/* Account for 1 frame extra pageflip delay if flip > 0 */
1227        vbl.request.sequence = intel_crtc_msc_to_sequence(scrn, crtc, request_msc) - flip;
1228	vbl.request.signal = seq;
1229
1230	ret = drmWaitVBlank(intel->drmSubFD, &vbl);
1231	if (ret) {
1232		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1233			   "final get vblank counter failed: %s\n",
1234			   strerror(errno));
1235		goto blit_fallback;
1236	}
1237
1238	/* Adjust returned value for 1 fame pageflip offset of flip > 0 */
1239	*target_msc = intel_sequence_to_crtc_msc(crtc, vbl.reply.sequence + flip);
1240	swap_info->frame = *target_msc;
1241
1242	return TRUE;
1243
1244blit_fallback:
1245	I830DRI2FallbackBlitSwap(draw, front, back);
1246	DRI2SwapComplete(client, draw, 0, 0, 0, DRI2_BLIT_COMPLETE, func, data);
1247	if (swap_info)
1248	    i830_dri2_del_frame_event(swap_info);
1249	*target_msc = 0; /* offscreen, so zero out target vblank count */
1250	return TRUE;
1251}
1252
1253static uint64_t gettime_us(void)
1254{
1255	struct timespec tv;
1256
1257	if (clock_gettime(CLOCK_MONOTONIC, &tv))
1258		return 0;
1259
1260	return (uint64_t)tv.tv_sec * 1000000 + tv.tv_nsec / 1000;
1261}
1262
1263/*
1264 * Get current frame count and frame count timestamp, based on drawable's
1265 * crtc.
1266 */
1267static int
1268I830DRI2GetMSC(DrawablePtr draw, CARD64 *ust, CARD64 *msc)
1269{
1270	ScreenPtr screen = draw->pScreen;
1271	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
1272	int ret;
1273        xf86CrtcPtr crtc = I830DRI2DrawableCrtc(draw);
1274
1275	/* Drawable not displayed, make up a *monotonic* value */
1276	if (crtc == NULL) {
1277fail:
1278		*ust = gettime_us();
1279		*msc = 0;
1280		return TRUE;
1281	}
1282
1283        ret = intel_get_crtc_msc_ust(scrn, crtc, msc, ust);
1284	if (ret) {
1285		static int limit = 5;
1286		if (limit) {
1287			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1288				   "%s:%d get vblank counter failed: %s\n",
1289				   __FUNCTION__, __LINE__,
1290				   strerror(errno));
1291			limit--;
1292		}
1293		goto fail;
1294	}
1295
1296	return TRUE;
1297}
1298
1299/*
1300 * Request a DRM event when the requested conditions will be satisfied.
1301 *
1302 * We need to handle the event and ask the server to wake up the client when
1303 * we receive it.
1304 */
1305static int
1306I830DRI2ScheduleWaitMSC(ClientPtr client, DrawablePtr draw, CARD64 target_msc,
1307			CARD64 divisor, CARD64 remainder)
1308{
1309	ScreenPtr screen = draw->pScreen;
1310	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
1311	intel_screen_private *intel = intel_get_screen_private(scrn);
1312	DRI2FrameEventPtr wait_info;
1313	drmVBlank vbl;
1314	int ret;
1315        xf86CrtcPtr crtc = I830DRI2DrawableCrtc(draw);
1316        int pipe = crtc ? intel_crtc_to_pipe(crtc) : -1;
1317	CARD64 current_msc, current_ust, request_msc;
1318        uint32_t seq;
1319
1320	/* Drawable not visible, return immediately */
1321	if (pipe == -1)
1322		goto out_complete;
1323
1324	wait_info = calloc(1, sizeof(DRI2FrameEventRec));
1325	if (!wait_info)
1326		goto out_complete;
1327
1328	wait_info->intel = intel;
1329	wait_info->drawable_id = draw->id;
1330	wait_info->client = client;
1331	wait_info->type = DRI2_WAITMSC;
1332
1333	if (!i830_dri2_add_frame_event(wait_info)) {
1334	    free(wait_info);
1335	    wait_info = NULL;
1336	    goto out_complete;
1337	}
1338
1339	/* Get current count */
1340        ret = intel_get_crtc_msc_ust(scrn, crtc, &current_msc, &current_ust);
1341	if (ret)
1342	    goto out_free;
1343
1344	/*
1345	 * If divisor is zero, or current_msc is smaller than target_msc,
1346	 * we just need to make sure target_msc passes  before waking up the
1347	 * client.
1348	 */
1349	if (divisor == 0 || current_msc < target_msc) {
1350		/* If target_msc already reached or passed, set it to
1351		 * current_msc to ensure we return a reasonable value back
1352		 * to the caller. This keeps the client from continually
1353		 * sending us MSC targets from the past by forcibly updating
1354		 * their count on this call.
1355		 */
1356                seq = intel_drm_queue_alloc(scrn, crtc, wait_info, intel_dri2_vblank_handler, intel_dri2_vblank_abort);
1357                if (!seq)
1358                        goto out_free;
1359
1360		if (current_msc >= target_msc)
1361			target_msc = current_msc;
1362		vbl.request.type =
1363			DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT | pipe_select(pipe);
1364		vbl.request.sequence = intel_crtc_msc_to_sequence(scrn, crtc, target_msc);
1365		vbl.request.signal = seq;
1366
1367		ret = drmWaitVBlank(intel->drmSubFD, &vbl);
1368		if (ret) {
1369			static int limit = 5;
1370			if (limit) {
1371				xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1372					   "%s:%d get vblank counter failed: %s\n",
1373					   __FUNCTION__, __LINE__,
1374					   strerror(errno));
1375				limit--;
1376			}
1377			goto out_free;
1378		}
1379
1380		wait_info->frame = intel_sequence_to_crtc_msc(crtc, vbl.reply.sequence);
1381		DRI2BlockClient(client, draw);
1382		return TRUE;
1383	}
1384
1385	/*
1386	 * If we get here, target_msc has already passed or we don't have one,
1387	 * so we queue an event that will satisfy the divisor/remainder equation.
1388	 */
1389	vbl.request.type =
1390		DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT | pipe_select(pipe);
1391
1392        request_msc = current_msc - (current_msc % divisor) +
1393                remainder;
1394	/*
1395	 * If calculated remainder is larger than requested remainder,
1396	 * it means we've passed the last point where
1397	 * seq % divisor == remainder, so we need to wait for the next time
1398	 * that will happen.
1399	 */
1400	if ((current_msc % divisor) >= remainder)
1401                request_msc += divisor;
1402
1403        seq = intel_drm_queue_alloc(scrn, crtc, wait_info, intel_dri2_vblank_handler, intel_dri2_vblank_abort);
1404        if (!seq)
1405                goto out_free;
1406
1407	vbl.request.sequence = intel_crtc_msc_to_sequence(scrn, crtc, request_msc);
1408	vbl.request.signal = seq;
1409
1410	ret = drmWaitVBlank(intel->drmSubFD, &vbl);
1411	if (ret) {
1412		static int limit = 5;
1413		if (limit) {
1414			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1415				   "%s:%d get vblank counter failed: %s\n",
1416				   __FUNCTION__, __LINE__,
1417				   strerror(errno));
1418			limit--;
1419		}
1420		goto out_free;
1421	}
1422
1423	wait_info->frame = intel_sequence_to_crtc_msc(crtc, vbl.reply.sequence);
1424	DRI2BlockClient(client, draw);
1425
1426	return TRUE;
1427
1428out_free:
1429	i830_dri2_del_frame_event(wait_info);
1430out_complete:
1431	DRI2WaitMSCComplete(client, draw, target_msc, 0, 0);
1432	return TRUE;
1433}
1434
1435static int dri2_server_generation;
1436#endif
1437
1438static int has_i830_dri(void)
1439{
1440	return access(DRI_DRIVER_PATH "/i830_dri.so", R_OK) == 0;
1441}
1442
1443static const char *dri_driver_name(intel_screen_private *intel)
1444{
1445#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,7,99,901,0)
1446	const char *s = xf86GetOptValString(intel->Options, OPTION_DRI);
1447	Bool dummy;
1448
1449	if (s == NULL || xf86getBoolValue(&dummy, s)) {
1450		if (INTEL_INFO(intel)->gen < 030)
1451			return has_i830_dri() ? "i830" : "i915";
1452		else if (INTEL_INFO(intel)->gen < 040)
1453			return "i915";
1454		else
1455			return "i965";
1456	}
1457
1458	return s;
1459#else
1460	if (INTEL_INFO(intel)->gen < 030)
1461		return has_i830_dri() ? "i830" : "i915";
1462	else if (INTEL_INFO(intel)->gen < 040)
1463		return "i915";
1464	else
1465		return "i965";
1466#endif
1467}
1468
1469Bool I830DRI2ScreenInit(ScreenPtr screen)
1470{
1471	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
1472	intel_screen_private *intel = intel_get_screen_private(scrn);
1473	DRI2InfoRec info;
1474	int dri2scr_major = 1;
1475	int dri2scr_minor = 0;
1476#if DRI2INFOREC_VERSION >= 4
1477	const char *driverNames[2];
1478#endif
1479
1480	if (intel->force_fallback) {
1481		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1482			   "cannot enable DRI2 whilst forcing software fallbacks\n");
1483		return FALSE;
1484	}
1485
1486	if (xf86LoaderCheckSymbol("DRI2Version"))
1487		DRI2Version(&dri2scr_major, &dri2scr_minor);
1488
1489	if (dri2scr_minor < 1) {
1490		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1491			   "DRI2 requires DRI2 module version 1.1.0 or later\n");
1492		return FALSE;
1493	}
1494
1495#if HAS_DIXREGISTERPRIVATEKEY
1496	if (!dixRegisterPrivateKey(&i830_client_key, PRIVATE_CLIENT, sizeof(XID)))
1497		return FALSE;
1498#else
1499	if (!dixRequestPrivate(&i830_client_key, sizeof(XID)))
1500		return FALSE;
1501#endif
1502
1503
1504#if DRI2INFOREC_VERSION >= 4
1505	if (serverGeneration != dri2_server_generation) {
1506	    dri2_server_generation = serverGeneration;
1507	    if (!i830_dri2_register_frame_event_resource_types()) {
1508		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1509			   "Cannot register DRI2 frame event resources\n");
1510		return FALSE;
1511	    }
1512	}
1513#endif
1514
1515	intel->deviceName = drmGetDeviceNameFromFd(intel->drmSubFD);
1516	memset(&info, '\0', sizeof(info));
1517	info.fd = intel->drmSubFD;
1518	info.driverName = dri_driver_name(intel);
1519	info.deviceName = intel->deviceName;
1520
1521#if DRI2INFOREC_VERSION == 1
1522	info.version = 1;
1523	info.CreateBuffers = I830DRI2CreateBuffers;
1524	info.DestroyBuffers = I830DRI2DestroyBuffers;
1525#elif DRI2INFOREC_VERSION == 2
1526	/* The ABI between 2 and 3 was broken so we could get rid of
1527	 * the multi-buffer alloc functions.  Make sure we indicate the
1528	 * right version so DRI2 can reject us if it's version 3 or above. */
1529	info.version = 2;
1530	info.CreateBuffer = I830DRI2CreateBuffer;
1531	info.DestroyBuffer = I830DRI2DestroyBuffer;
1532#else
1533	info.version = 3;
1534	info.CreateBuffer = I830DRI2CreateBuffer;
1535	info.DestroyBuffer = I830DRI2DestroyBuffer;
1536#endif
1537
1538	info.CopyRegion = I830DRI2CopyRegion;
1539#if DRI2INFOREC_VERSION >= 4
1540	info.version = 4;
1541	info.ScheduleSwap = I830DRI2ScheduleSwap;
1542	info.GetMSC = I830DRI2GetMSC;
1543	info.ScheduleWaitMSC = I830DRI2ScheduleWaitMSC;
1544	info.numDrivers = 2;
1545	info.driverNames = driverNames;
1546	driverNames[0] = info.driverName;
1547	driverNames[1] = info.driverName;
1548#endif
1549
1550	return DRI2ScreenInit(screen, &info);
1551}
1552
1553void I830DRI2CloseScreen(ScreenPtr screen)
1554{
1555	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
1556	intel_screen_private *intel = intel_get_screen_private(scrn);
1557
1558	DRI2CloseScreen(screen);
1559	drmFree(intel->deviceName);
1560}
1561