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