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