428472873e442e688a4a2d7bf144b83f5ccb7672
[mesa.git] / src / mesa / drivers / dri / dri_client / dri_util.c
1 /* $XFree86: xc/lib/GL/dri/dri_util.c,v 1.7 2003/04/28 17:01:25 dawes Exp $ */
2 /**
3 * \file dri_util.c
4 * DRI utility functions.
5 *
6 * This module acts as glue between GLX and the actual hardware driver. A DRI
7 * driver doesn't really \e have to use any of this - it's optional. But, some
8 * useful stuff is done here that otherwise would have to be duplicated in most
9 * drivers.
10 *
11 * Basically, these utility functions take care of some of the dirty details of
12 * screen initialization, context creation, context binding, DRM setup, etc.
13 *
14 * These functions are compiled into each DRI driver so libGL.so knows nothing
15 * about them.
16 *
17 * \note
18 * When \c DRI_NEW_INTERFACE_ONLY is defined, code is built / not built so
19 * that only the "new" libGL-to-driver interfaces are supported. This breaks
20 * backwards compatability. However, this may be necessary when DRI drivers
21 * are built to be used in non-XFree86 environments.
22 *
23 * \todo There are still some places in the code that need to be wrapped with
24 * \c DRI_NEW_INTERFACE_ONLY.
25 */
26
27
28 #ifdef GLX_DIRECT_RENDERING
29
30 #include <inttypes.h>
31 #include <assert.h>
32 #include <stdarg.h>
33 #include <unistd.h>
34 #include <sys/mman.h>
35 #include <X11/Xlibint.h>
36 #include <Xext.h>
37 #include <extutil.h>
38 #include <stdio.h>
39 #include "xf86dri.h"
40 #include "sarea.h"
41 #include "dri_util.h"
42 #include "glcontextmodes.h"
43
44 /*#define DRI_NEW_INTERFACE_ONLY*/
45
46 /**
47 * This is used in a couple of places that call \c driCreateNewDrawable.
48 */
49 static const int empty_attribute_list[1] = { None };
50
51 /**
52 * Function used to determine if a drawable (window) still exists. Ideally
53 * this function comes from libGL. With older versions of libGL from XFree86
54 * we can fall-back to an internal version.
55 *
56 * \sa __driWindowExists __glXWindowExists
57 */
58 static PFNGLXWINDOWEXISTSPROC window_exists;
59
60 typedef Bool (*PFNGLXCREATECONTEXTWITHCONFIGPROC)( Display*, int, int, void *,
61 drmContextPtr );
62
63 static PFNGLXCREATECONTEXTWITHCONFIGPROC create_context_with_config;
64
65 /**
66 * Cached copy of the internal API version used by libGL and the client-side
67 * DRI driver.
68 */
69 static int api_ver = 0;
70
71 /* forward declarations */
72 static int driQueryFrameTracking( Display * dpy, void * priv,
73 int64_t * sbc, int64_t * missedFrames, float * lastMissedUsage,
74 float * usage );
75
76 static void *driCreateNewDrawable(Display *dpy, const __GLcontextModes *modes,
77 GLXDrawable draw, __DRIdrawable *pdraw, int renderType, const int *attrs);
78
79 static void driDestroyDrawable(Display *dpy, void *drawablePrivate);
80
81
82
83
84 #ifdef not_defined
85 static Bool driFeatureOn(const char *name)
86 {
87 char *env = getenv(name);
88
89 if (!env) return GL_FALSE;
90 if (!strcasecmp(env, "enable")) return GL_TRUE;
91 if (!strcasecmp(env, "1")) return GL_TRUE;
92 if (!strcasecmp(env, "on")) return GL_TRUE;
93 if (!strcasecmp(env, "true")) return GL_TRUE;
94 if (!strcasecmp(env, "t")) return GL_TRUE;
95 if (!strcasecmp(env, "yes")) return GL_TRUE;
96 if (!strcasecmp(env, "y")) return GL_TRUE;
97
98 return GL_FALSE;
99 }
100 #endif /* not_defined */
101
102
103 /**
104 * Print message to \c stderr if the \c LIBGL_DEBUG environment variable
105 * is set.
106 *
107 * Is called from the drivers.
108 *
109 * \param f \c printf like format string.
110 */
111 void
112 __driUtilMessage(const char *f, ...)
113 {
114 va_list args;
115
116 if (getenv("LIBGL_DEBUG")) {
117 fprintf(stderr, "libGL error: \n");
118 va_start(args, f);
119 vfprintf(stderr, f, args);
120 va_end(args);
121 fprintf(stderr, "\n");
122 }
123 }
124
125
126 /*****************************************************************/
127 /** \name Visual utility functions */
128 /*****************************************************************/
129 /*@{*/
130
131 #ifndef DRI_NEW_INTERFACE_ONLY
132 /**
133 * Find a \c __GLcontextModes structure matching the given visual ID.
134 *
135 * \param dpy Display to search for a matching configuration.
136 * \param scrn Screen number on \c dpy to be searched.
137 * \param vid Desired \c VisualID to find.
138 *
139 * \returns A pointer to a \c __GLcontextModes structure that matches \c vid,
140 * if found, or \c NULL if no match is found.
141 */
142 static const __GLcontextModes *
143 findConfigMode(Display *dpy, int scrn, VisualID vid,
144 const __DRIscreen * pDRIScreen)
145 {
146 if ( (pDRIScreen != NULL) && (pDRIScreen->private != NULL) ) {
147 const __DRIscreenPrivate * const psp =
148 (const __DRIscreenPrivate *) pDRIScreen->private;
149
150 return _gl_context_modes_find_visual( psp->modes, vid );
151 }
152
153 return NULL;
154 }
155
156
157 /**
158 * This function is a hack to work-around old versions of libGL.so that
159 * do not export \c XF86DRICreateContextWithConfig. I would modify the
160 * code to just use this function, but the stand-alone driver (i.e., DRI
161 * drivers that are built to work without XFree86) shouldn't have to know
162 * about X structures like a \c Visual.
163 */
164 static Bool
165 fake_XF86DRICreateContextWithConfig( Display* dpy, int screen, int configID,
166 XID* context, drmContextPtr hHWContext )
167 {
168 Visual vis;
169
170 vis.visualid = configID;
171 return XF86DRICreateContext( dpy, screen, & vis, context, hHWContext );
172 }
173 #endif /* DRI_NEW_INTERFACE_ONLY */
174
175 /*@}*/
176
177
178 /*****************************************************************/
179 /** \name Drawable list management */
180 /*****************************************************************/
181 /*@{*/
182
183 static Bool __driAddDrawable(void *drawHash, __DRIdrawable *pdraw)
184 {
185 __DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *)pdraw->private;
186
187 if (drmHashInsert(drawHash, pdp->draw, pdraw))
188 return GL_FALSE;
189
190 return GL_TRUE;
191 }
192
193 static __DRIdrawable *__driFindDrawable(void *drawHash, GLXDrawable draw)
194 {
195 int retcode;
196 __DRIdrawable *pdraw;
197
198 retcode = drmHashLookup(drawHash, draw, (void **)&pdraw);
199 if (retcode)
200 return NULL;
201
202 return pdraw;
203 }
204
205 static void __driRemoveDrawable(void *drawHash, __DRIdrawable *pdraw)
206 {
207 int retcode;
208 __DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *)pdraw->private;
209
210 retcode = drmHashLookup(drawHash, pdp->draw, (void **)&pdraw);
211 if (!retcode) { /* Found */
212 drmHashDelete(drawHash, pdp->draw);
213 }
214 }
215
216 #ifndef DRI_NEW_INTERFACE_ONLY
217 static Bool __driWindowExistsFlag;
218
219 static int __driWindowExistsErrorHandler(Display *dpy, XErrorEvent *xerr)
220 {
221 if (xerr->error_code == BadWindow) {
222 __driWindowExistsFlag = GL_FALSE;
223 }
224 return 0;
225 }
226
227 /**
228 * Determine if a window associated with a \c GLXDrawable exists on the
229 * X-server.
230 *
231 * \param dpy Display associated with the drawable to be queried.
232 * \param draw \c GLXDrawable to test.
233 *
234 * \returns \c GL_TRUE if a window exists that is associated with \c draw,
235 * otherwise \c GL_FALSE is returned.
236 *
237 * \warning This function is not currently thread-safe.
238 *
239 * \deprecated
240 * \c __glXWindowExists (from libGL) is prefered over this function. Starting
241 * with the next major release of XFree86, this function will be removed.
242 * Even now this function is no longer directly called. Instead it is called
243 * via a function pointer if and only if \c __glXWindowExists does not exist.
244 *
245 * \sa __glXWindowExists glXGetProcAddress window_exists
246 */
247 static Bool __driWindowExists(Display *dpy, GLXDrawable draw)
248 {
249 XWindowAttributes xwa;
250 int (*oldXErrorHandler)(Display *, XErrorEvent *);
251
252 XSync(dpy, GL_FALSE);
253 __driWindowExistsFlag = GL_TRUE;
254 oldXErrorHandler = XSetErrorHandler(__driWindowExistsErrorHandler);
255 XGetWindowAttributes(dpy, draw, &xwa); /* dummy request */
256 XSetErrorHandler(oldXErrorHandler);
257 return __driWindowExistsFlag;
258 }
259 #endif /* DRI_NEW_INTERFACE_ONLY */
260
261 /**
262 * Find drawables in the local hash that have been destroyed on the
263 * server.
264 *
265 * \param drawHash Hash-table containing all know drawables.
266 */
267 static void __driGarbageCollectDrawables(void *drawHash)
268 {
269 GLXDrawable draw;
270 __DRIdrawable *pdraw;
271 Display *dpy;
272
273 if (drmHashFirst(drawHash, &draw, (void **)&pdraw)) {
274 do {
275 __DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *)pdraw->private;
276 dpy = pdp->driScreenPriv->display;
277 if (! (*window_exists)(dpy, draw)) {
278 /* Destroy the local drawable data in the hash table, if the
279 drawable no longer exists in the Xserver */
280 __driRemoveDrawable(drawHash, pdraw);
281 (*pdraw->destroyDrawable)(dpy, pdraw->private);
282 Xfree(pdraw);
283 }
284 } while (drmHashNext(drawHash, &draw, (void **)&pdraw));
285 }
286 }
287
288 /*@}*/
289
290
291 /*****************************************************************/
292 /** \name Context (un)binding functions */
293 /*****************************************************************/
294 /*@{*/
295
296 /**
297 * Unbind context.
298 *
299 * \param dpy the display handle.
300 * \param scrn the screen number.
301 * \param draw drawable.
302 * \param read Current reading drawable.
303 * \param gc context.
304 *
305 * \return \c GL_TRUE on success, or \c GL_FALSE on failure.
306 *
307 * \internal
308 * This function calls __DriverAPIRec::UnbindContext, and then decrements
309 * __DRIdrawablePrivateRec::refcount which must be non-zero for a successful
310 * return.
311 *
312 * While casting the opaque private pointers associated with the parameters
313 * into their respective real types it also assures they are not \c NULL.
314 */
315 static Bool driUnbindContext2(Display *dpy, int scrn,
316 GLXDrawable draw, GLXDrawable read,
317 GLXContext gc)
318 {
319 __DRIscreen *pDRIScreen;
320 __DRIdrawable *pdraw;
321 __DRIdrawable *pread;
322 __DRIcontextPrivate *pcp;
323 __DRIscreenPrivate *psp;
324 __DRIdrawablePrivate *pdp;
325 __DRIdrawablePrivate *prp;
326
327 /*
328 ** Assume error checking is done properly in glXMakeCurrent before
329 ** calling driUnbindContext2.
330 */
331
332 if (gc == NULL || draw == None || read == None) {
333 /* ERROR!!! */
334 return GL_FALSE;
335 }
336
337 pDRIScreen = __glXFindDRIScreen(dpy, scrn);
338 if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) {
339 /* ERROR!!! */
340 return GL_FALSE;
341 }
342
343 psp = (__DRIscreenPrivate *)pDRIScreen->private;
344 pcp = (__DRIcontextPrivate *)gc->driContext.private;
345
346 pdraw = __driFindDrawable(psp->drawHash, draw);
347 if (!pdraw) {
348 /* ERROR!!! */
349 return GL_FALSE;
350 }
351 pdp = (__DRIdrawablePrivate *)pdraw->private;
352
353 pread = __driFindDrawable(psp->drawHash, read);
354 if (!pread) {
355 /* ERROR!!! */
356 return GL_FALSE;
357 }
358 prp = (__DRIdrawablePrivate *)pread->private;
359
360
361 /* Let driver unbind drawable from context */
362 (*psp->DriverAPI.UnbindContext)(pcp);
363
364
365 if (pdp->refcount == 0) {
366 /* ERROR!!! */
367 return GL_FALSE;
368 }
369
370 pdp->refcount--;
371
372 if (prp != pdp) {
373 if (prp->refcount == 0) {
374 /* ERROR!!! */
375 return GL_FALSE;
376 }
377
378 prp->refcount--;
379 }
380
381
382 /* XXX this is disabled so that if we call SwapBuffers on an unbound
383 * window we can determine the last context bound to the window and
384 * use that context's lock. (BrianP, 2-Dec-2000)
385 */
386 #if 0
387 /* Unbind the drawable */
388 pcp->driDrawablePriv = NULL;
389 pdp->driContextPriv = &psp->dummyContextPriv;
390 #endif
391
392 return GL_TRUE;
393 }
394
395
396 /**
397 * This function takes both a read buffer and a draw buffer. This is needed
398 * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
399 * function.
400 *
401 * \bug This function calls \c driCreateNewDrawable in two places with the
402 * \c renderType hard-coded to \c GLX_WINDOW_BIT. Some checking might
403 * be needed in those places when support for pbuffers and / or pixmaps
404 * is added. Is it safe to assume that the drawable is a window?
405 */
406 static Bool driBindContext2(Display *dpy, int scrn,
407 GLXDrawable draw, GLXDrawable read,
408 GLXContext gc)
409 {
410 __DRIscreen *pDRIScreen;
411 __DRIdrawable *pdraw;
412 __DRIdrawablePrivate *pdp;
413 __DRIdrawable *pread;
414 __DRIdrawablePrivate *prp;
415 __DRIscreenPrivate *psp;
416 __DRIcontextPrivate *pcp;
417 const __GLcontextModes *modes;
418
419 /*
420 ** Assume error checking is done properly in glXMakeCurrent before
421 ** calling driBindContext.
422 */
423
424 if (gc == NULL || draw == None || read == None) {
425 /* ERROR!!! */
426 return GL_FALSE;
427 }
428
429 pDRIScreen = __glXFindDRIScreen(dpy, scrn);
430 #ifdef DRI_NEW_INTERFACE_ONLY
431 if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) {
432 /* ERROR!!! */
433 return GL_FALSE;
434 }
435 #else
436 if ( driCompareGLXAPIVersion( 20031201 ) >= 0 ) {
437 #endif /* DRI_NEW_INTERFACE_ONLY */
438 modes = gc->mode;
439 #ifndef DRI_NEW_INTERFACE_ONLY
440 }
441 else {
442 modes = findConfigMode( dpy, scrn, gc->vid, pDRIScreen );
443 if ( modes == NULL ) {
444 /* ERROR!!! */
445 return GL_FALSE;
446 }
447 }
448
449
450 /* findConfigMode will return NULL if the DRI screen or screen private
451 * are NULL.
452 */
453 assert( (pDRIScreen != NULL) && (pDRIScreen->private != NULL) );
454 #endif /* DRI_NEW_INTERFACE_ONLY */
455
456
457 /* Find the _DRIdrawable which corresponds to the writing GLXDrawable */
458 psp = (__DRIscreenPrivate *)pDRIScreen->private;
459 pdraw = __driFindDrawable(psp->drawHash, draw);
460 if (!pdraw) {
461 /* Allocate a new drawable */
462 pdraw = (__DRIdrawable *)Xmalloc(sizeof(__DRIdrawable));
463 if (!pdraw) {
464 /* ERROR!!! */
465 return GL_FALSE;
466 }
467
468 /* Create a new drawable */
469 driCreateNewDrawable(dpy, modes, draw, pdraw, GLX_WINDOW_BIT,
470 empty_attribute_list);
471 if (!pdraw->private) {
472 /* ERROR!!! */
473 Xfree(pdraw);
474 return GL_FALSE;
475 }
476
477 }
478 pdp = (__DRIdrawablePrivate *) pdraw->private;
479
480 /* Find the _DRIdrawable which corresponds to the reading GLXDrawable */
481 if (read == draw) {
482 /* read buffer == draw buffer */
483 prp = pdp;
484 }
485 else {
486 pread = __driFindDrawable(psp->drawHash, read);
487 if (!pread) {
488 /* Allocate a new drawable */
489 pread = (__DRIdrawable *)Xmalloc(sizeof(__DRIdrawable));
490 if (!pread) {
491 /* ERROR!!! */
492 return GL_FALSE;
493 }
494
495 /* Create a new drawable */
496 driCreateNewDrawable(dpy, modes, read, pread, GLX_WINDOW_BIT,
497 empty_attribute_list);
498 if (!pread->private) {
499 /* ERROR!!! */
500 Xfree(pread);
501 return GL_FALSE;
502 }
503 }
504 prp = (__DRIdrawablePrivate *) pread->private;
505 }
506
507 /* Bind the drawable to the context */
508 pcp = (__DRIcontextPrivate *)gc->driContext.private;
509 pcp->driDrawablePriv = pdp;
510 pdp->driContextPriv = pcp;
511 pdp->refcount++;
512 if ( pdp != prp ) {
513 prp->refcount++;
514 }
515
516 /*
517 ** Now that we have a context associated with this drawable, we can
518 ** initialize the drawable information if has not been done before.
519 */
520 if (!pdp->pStamp || *pdp->pStamp != pdp->lastStamp) {
521 DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
522 __driUtilUpdateDrawableInfo(pdp);
523 DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
524 }
525
526 /* Call device-specific MakeCurrent */
527 (*psp->DriverAPI.MakeCurrent)(pcp, pdp, prp);
528
529 return GL_TRUE;
530 }
531
532
533 /*
534 * Simply call bind with the same GLXDrawable for the read and draw buffers.
535 */
536 static Bool driBindContext(Display *dpy, int scrn,
537 GLXDrawable draw, GLXContext gc)
538 {
539 return driBindContext2(dpy, scrn, draw, draw, gc);
540 }
541
542
543 /*
544 * Simply call bind with the same GLXDrawable for the read and draw buffers.
545 */
546 static Bool driUnbindContext(Display *dpy, int scrn,
547 GLXDrawable draw, GLXContext gc,
548 int will_rebind)
549 {
550 (void) will_rebind;
551 return driUnbindContext2( dpy, scrn, draw, draw, gc );
552 }
553
554 /*@}*/
555
556
557 /*****************************************************************/
558 /** \name Drawable handling functions */
559 /*****************************************************************/
560 /*@{*/
561
562 /**
563 * Update private drawable information.
564 *
565 * \param pdp pointer to the private drawable information to update.
566 *
567 * This function basically updates the __DRIdrawablePrivate struct's
568 * cliprect information by calling \c __DRIDrawablePrivate::getInfo. This is
569 * usually called by the DRI_VALIDATE_DRAWABLE_INFO macro which
570 * compares the __DRIdrwablePrivate pStamp and lastStamp values. If
571 * the values are different that means we have to update the clipping
572 * info.
573 */
574 void
575 __driUtilUpdateDrawableInfo(__DRIdrawablePrivate *pdp)
576 {
577 __DRIscreenPrivate *psp;
578 __DRIcontextPrivate *pcp = pdp->driContextPriv;
579
580 if (!pcp || (pdp != pcp->driDrawablePriv)) {
581 /* ERROR!!! */
582 return;
583 }
584
585 psp = pdp->driScreenPriv;
586 if (!psp) {
587 /* ERROR!!! */
588 return;
589 }
590
591 if (pdp->pClipRects) {
592 Xfree(pdp->pClipRects);
593 }
594
595 if (pdp->pBackClipRects) {
596 Xfree(pdp->pBackClipRects);
597 }
598
599 DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
600
601 if (!__driFindDrawable(psp->drawHash, pdp->draw) ||
602 ! (*pdp->getInfo)(pdp->display, pdp->screen, pdp->draw,
603 &pdp->index, &pdp->lastStamp,
604 &pdp->x, &pdp->y, &pdp->w, &pdp->h,
605 &pdp->numClipRects, &pdp->pClipRects,
606 &pdp->backX,
607 &pdp->backY,
608 &pdp->numBackClipRects,
609 &pdp->pBackClipRects )) {
610 /* Error -- eg the window may have been destroyed. Keep going
611 * with no cliprects.
612 */
613 pdp->pStamp = &pdp->lastStamp; /* prevent endless loop */
614 pdp->numClipRects = 0;
615 pdp->pClipRects = NULL;
616 pdp->numBackClipRects = 0;
617 pdp->pBackClipRects = NULL;
618 }
619 else
620 pdp->pStamp = &(psp->pSAREA->drawableTable[pdp->index].stamp);
621
622 DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
623
624 }
625
626 /*@}*/
627
628 /*****************************************************************/
629 /** \name GLX callbacks */
630 /*****************************************************************/
631 /*@{*/
632
633 /**
634 * Swap buffers.
635 *
636 * \param dpy the display handle.
637 * \param drawablePrivate opaque pointer to the per-drawable private info.
638 *
639 * \internal
640 * This function calls __DRIdrawablePrivate::swapBuffers.
641 *
642 * Is called directly from glXSwapBuffers().
643 */
644 static void driSwapBuffers( Display *dpy, void *drawablePrivate )
645 {
646 __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePrivate;
647 dPriv->swapBuffers(dPriv);
648 (void) dpy;
649 }
650
651 /**
652 * Called directly from a number of higher-level GLX functions.
653 */
654 static int driGetMSC( void *screenPrivate, int64_t *msc )
655 {
656 __DRIscreenPrivate *sPriv = (__DRIscreenPrivate *) screenPrivate;
657
658 return sPriv->DriverAPI.GetMSC( sPriv, msc );
659 }
660
661 /**
662 * Called directly from a number of higher-level GLX functions.
663 */
664 static int driGetSBC( Display *dpy, void *drawablePrivate, int64_t *sbc )
665 {
666 __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePrivate;
667 __DRIswapInfo sInfo;
668 int status;
669
670
671 status = dPriv->driScreenPriv->DriverAPI.GetSwapInfo( dPriv, & sInfo );
672 *sbc = sInfo.swap_count;
673
674 return status;
675 }
676
677 static int driWaitForSBC( Display * dpy, void *drawablePriv,
678 int64_t target_sbc,
679 int64_t * msc, int64_t * sbc )
680 {
681 __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePriv;
682
683 return dPriv->driScreenPriv->DriverAPI.WaitForSBC( dPriv, target_sbc,
684 msc, sbc );
685 }
686
687 static int driWaitForMSC( Display * dpy, void *drawablePriv,
688 int64_t target_msc,
689 int64_t divisor, int64_t remainder,
690 int64_t * msc, int64_t * sbc )
691 {
692 __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePriv;
693 __DRIswapInfo sInfo;
694 int status;
695
696
697 status = dPriv->driScreenPriv->DriverAPI.WaitForMSC( dPriv, target_msc,
698 divisor, remainder,
699 msc );
700
701 /* GetSwapInfo() may not be provided by the driver if GLX_SGI_video_sync
702 * is supported but GLX_OML_sync_control is not. Therefore, don't return
703 * an error value if GetSwapInfo() is not implemented.
704 */
705 if ( status == 0
706 && dPriv->driScreenPriv->DriverAPI.GetSwapInfo ) {
707 status = dPriv->driScreenPriv->DriverAPI.GetSwapInfo( dPriv, & sInfo );
708 *sbc = sInfo.swap_count;
709 }
710
711 return status;
712 }
713
714 static int64_t driSwapBuffersMSC( Display * dpy, void *drawablePriv,
715 int64_t target_msc,
716 int64_t divisor, int64_t remainder )
717 {
718 __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePriv;
719
720 return dPriv->driScreenPriv->DriverAPI.SwapBuffersMSC( dPriv, target_msc,
721 divisor,
722 remainder );
723 }
724
725
726 /**
727 * This is called via __DRIscreenRec's createNewDrawable pointer.
728 */
729 static void *driCreateNewDrawable(Display *dpy,
730 const __GLcontextModes *modes,
731 GLXDrawable draw,
732 __DRIdrawable *pdraw,
733 int renderType,
734 const int *attrs)
735 {
736 __DRIscreen * const pDRIScreen = __glXFindDRIScreen(dpy, modes->screen);
737 __DRIscreenPrivate *psp;
738 __DRIdrawablePrivate *pdp;
739
740
741 /* Since pbuffers are not yet supported, no drawable attributes are
742 * supported either.
743 */
744 (void) attrs;
745
746 if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) {
747 return NULL;
748 }
749
750 pdp = (__DRIdrawablePrivate *)Xmalloc(sizeof(__DRIdrawablePrivate));
751 if (!pdp) {
752 return NULL;
753 }
754
755 if (!XF86DRICreateDrawable(dpy, modes->screen, draw, &pdp->hHWDrawable)) {
756 Xfree(pdp);
757 return NULL;
758 }
759
760 pdp->draw = draw;
761 pdp->pdraw = pdraw;
762 pdp->refcount = 0;
763 pdp->pStamp = NULL;
764 pdp->lastStamp = 0;
765 pdp->index = 0;
766 pdp->x = 0;
767 pdp->y = 0;
768 pdp->w = 0;
769 pdp->h = 0;
770 pdp->numClipRects = 0;
771 pdp->numBackClipRects = 0;
772 pdp->pClipRects = NULL;
773 pdp->pBackClipRects = NULL;
774 pdp->display = dpy;
775 pdp->screen = modes->screen;
776
777 psp = (__DRIscreenPrivate *)pDRIScreen->private;
778 pdp->driScreenPriv = psp;
779 pdp->driContextPriv = &psp->dummyContextPriv;
780
781 pdp->getInfo = (GetDrawableInfo *)
782 glXGetProcAddress( (const GLubyte *) "__glXGetDrawableInfo" );
783 if ( pdp->getInfo == NULL ) {
784 pdp->getInfo = XF86DRIGetDrawableInfo;
785 }
786
787 if (!(*psp->DriverAPI.CreateBuffer)(psp, pdp, modes,
788 renderType == GLX_PIXMAP_BIT)) {
789 (void)XF86DRIDestroyDrawable(dpy, modes->screen, pdp->draw);
790 Xfree(pdp);
791 return NULL;
792 }
793
794 pdraw->private = pdp;
795 pdraw->destroyDrawable = driDestroyDrawable;
796 pdraw->swapBuffers = driSwapBuffers; /* called by glXSwapBuffers() */
797
798 if ( driCompareGLXAPIVersion( 20030317 ) >= 0 ) {
799 pdraw->getSBC = driGetSBC;
800 pdraw->waitForSBC = driWaitForSBC;
801 pdraw->waitForMSC = driWaitForMSC;
802 pdraw->swapBuffersMSC = driSwapBuffersMSC;
803 pdraw->frameTracking = NULL;
804 pdraw->queryFrameTracking = driQueryFrameTracking;
805
806 /* This special default value is replaced with the configured
807 * default value when the drawable is first bound to a direct
808 * rendering context. */
809 pdraw->swap_interval = (unsigned)-1;
810 }
811
812 pdp->swapBuffers = psp->DriverAPI.SwapBuffers;
813
814 /* Add pdraw to drawable list */
815 if (!__driAddDrawable(psp->drawHash, pdraw)) {
816 /* ERROR!!! */
817 (*pdraw->destroyDrawable)(dpy, pdp);
818 Xfree(pdp);
819 pdp = NULL;
820 pdraw->private = NULL;
821 }
822
823 return (void *) pdp;
824 }
825
826 static __DRIdrawable *driGetDrawable(Display *dpy, GLXDrawable draw,
827 void *screenPrivate)
828 {
829 __DRIscreenPrivate *psp = (__DRIscreenPrivate *) screenPrivate;
830
831 /*
832 ** Make sure this routine returns NULL if the drawable is not bound
833 ** to a direct rendering context!
834 */
835 return __driFindDrawable(psp->drawHash, draw);
836 }
837
838 static void driDestroyDrawable(Display *dpy, void *drawablePrivate)
839 {
840 __DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *) drawablePrivate;
841 __DRIscreenPrivate *psp = pdp->driScreenPriv;
842 int scrn = psp->myNum;
843
844 if (pdp) {
845 (*psp->DriverAPI.DestroyBuffer)(pdp);
846 if ((*window_exists)(dpy, pdp->draw))
847 (void)XF86DRIDestroyDrawable(dpy, scrn, pdp->draw);
848 if (pdp->pClipRects) {
849 Xfree(pdp->pClipRects);
850 pdp->pClipRects = NULL;
851 }
852 if (pdp->pBackClipRects) {
853 Xfree(pdp->pBackClipRects);
854 pdp->pBackClipRects = NULL;
855 }
856 Xfree(pdp);
857 }
858 }
859
860 /*@}*/
861
862
863 /*****************************************************************/
864 /** \name Context handling functions */
865 /*****************************************************************/
866 /*@{*/
867
868 /**
869 * Destroy the per-context private information.
870 *
871 * \param dpy the display handle.
872 * \param scrn the screen number.
873 * \param contextPrivate opaque pointer to the per-drawable private info.
874 *
875 * \internal
876 * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls
877 * drmDestroyContext(), and finally frees \p contextPrivate.
878 */
879 static void driDestroyContext(Display *dpy, int scrn, void *contextPrivate)
880 {
881 __DRIcontextPrivate *pcp = (__DRIcontextPrivate *) contextPrivate;
882
883 if (pcp) {
884 (*pcp->driScreenPriv->DriverAPI.DestroyContext)(pcp);
885 __driGarbageCollectDrawables(pcp->driScreenPriv->drawHash);
886 (void)XF86DRIDestroyContext(dpy, scrn, pcp->contextID);
887 Xfree(pcp);
888 }
889 }
890
891
892 /**
893 * Create the per-drawable private driver information.
894 *
895 * \param dpy The display handle.
896 * \param modes Mode used to create the new context.
897 * \param render_type Type of rendering target. \c GLX_RGBA is the only
898 * type likely to ever be supported for direct-rendering.
899 * \param sharedPrivate The shared context dependent methods or \c NULL if
900 * non-existent.
901 * \param pctx DRI context to receive the context dependent methods.
902 *
903 * \returns An opaque pointer to the per-context private information on
904 * success, or \c NULL on failure.
905 *
906 * \internal
907 * This function allocates and fills a __DRIcontextPrivateRec structure. It
908 * performs some device independent initialization and passes all the
909 * relevent information to __DriverAPIRec::CreateContext to create the
910 * context.
911 *
912 */
913 static void *
914 driCreateNewContext(Display *dpy, const __GLcontextModes *modes,
915 int render_type, void *sharedPrivate, __DRIcontext *pctx)
916 {
917 __DRIscreen *pDRIScreen;
918 __DRIcontextPrivate *pcp;
919 __DRIcontextPrivate *pshare = (__DRIcontextPrivate *) sharedPrivate;
920 __DRIscreenPrivate *psp;
921 void * const shareCtx = (pshare != NULL) ? pshare->driverPrivate : NULL;
922
923 pDRIScreen = __glXFindDRIScreen(dpy, modes->screen);
924 if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) {
925 /* ERROR!!! */
926 return NULL;
927 }
928
929 psp = (__DRIscreenPrivate *)pDRIScreen->private;
930
931 pcp = (__DRIcontextPrivate *)Xmalloc(sizeof(__DRIcontextPrivate));
932 if (!pcp) {
933 return NULL;
934 }
935
936 if (! (*create_context_with_config)(dpy, modes->screen, modes->fbconfigID,
937 &pcp->contextID, &pcp->hHWContext)) {
938 Xfree(pcp);
939 return NULL;
940 }
941
942 pcp->display = dpy;
943 pcp->driScreenPriv = psp;
944 pcp->driDrawablePriv = NULL;
945
946 /* When the first context is created for a screen, initialize a "dummy"
947 * context.
948 */
949
950 if (!psp->dummyContextPriv.driScreenPriv) {
951 psp->dummyContextPriv.contextID = 0;
952 psp->dummyContextPriv.hHWContext = psp->pSAREA->dummy_context;
953 psp->dummyContextPriv.driScreenPriv = psp;
954 psp->dummyContextPriv.driDrawablePriv = NULL;
955 psp->dummyContextPriv.driverPrivate = NULL;
956 /* No other fields should be used! */
957 }
958
959 pctx->destroyContext = driDestroyContext;
960 pctx->bindContext = driBindContext;
961 pctx->unbindContext = driUnbindContext;
962 if ( driCompareGLXAPIVersion( 20030606 ) >= 0 ) {
963 pctx->bindContext2 = driBindContext2;
964 pctx->unbindContext2 = driUnbindContext2;
965 }
966
967 if ( !(*psp->DriverAPI.CreateContext)(modes, pcp, shareCtx) ) {
968 (void)XF86DRIDestroyContext(dpy, modes->screen, pcp->contextID);
969 Xfree(pcp);
970 return NULL;
971 }
972
973 __driGarbageCollectDrawables(pcp->driScreenPriv->drawHash);
974
975 return pcp;
976 }
977
978
979 #ifndef DRI_NEW_INTERFACE_ONLY
980 /**
981 * Create the per-drawable private driver information.
982 *
983 * \param dpy the display handle.
984 * \param vis the visual information.
985 * \param sharedPrivate the shared context dependent methods or \c NULL if
986 * non-existent.
987 * \param pctx will receive the context dependent methods.
988 *
989 * \returns a opaque pointer to the per-context private information on success, or \c NULL
990 * on failure.
991 *
992 * \deprecated
993 * This function has been replaced by \c driCreateNewContext. In drivers
994 * built to work with XFree86, this function will continue to exist to support
995 * older versions of libGL. Starting with the next major relelase of XFree86,
996 * this function will be removed.
997 *
998 * \internal
999 * This function allocates and fills a __DRIcontextPrivateRec structure. It
1000 * gets the visual, converts it into a __GLcontextModesRec and passes it
1001 * to __DriverAPIRec::CreateContext to create the context.
1002 */
1003 static void *driCreateContext(Display *dpy, XVisualInfo *vis,
1004 void *sharedPrivate, __DRIcontext *pctx)
1005 {
1006 __DRIscreen *pDRIScreen;
1007 const __GLcontextModes *modes;
1008
1009 pDRIScreen = __glXFindDRIScreen(dpy, vis->screen);
1010 if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) {
1011 /* ERROR!!! */
1012 return NULL;
1013 }
1014
1015
1016 /* Setup a __GLcontextModes struct corresponding to vis->visualid
1017 * and create the rendering context.
1018 */
1019
1020 modes = findConfigMode(dpy, vis->screen, vis->visualid, pDRIScreen);
1021 return (modes == NULL)
1022 ? NULL
1023 : driCreateNewContext( dpy, modes, GLX_RGBA_TYPE,
1024 sharedPrivate, pctx );
1025 }
1026 #endif /* DRI_NEW_INTERFACE_ONLY */
1027
1028 /*@}*/
1029
1030
1031 /*****************************************************************/
1032 /** \name Screen handling functions */
1033 /*****************************************************************/
1034 /*@{*/
1035
1036 /**
1037 * Destroy the per-screen private information.
1038 *
1039 * \param dpy the display handle.
1040 * \param scrn the screen number.
1041 * \param screenPrivate opaque pointer to the per-screen private information.
1042 *
1043 * \internal
1044 * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls
1045 * drmClose(), and finally frees \p screenPrivate.
1046 */
1047 static void driDestroyScreen(Display *dpy, int scrn, void *screenPrivate)
1048 {
1049 __DRIscreenPrivate *psp = (__DRIscreenPrivate *) screenPrivate;
1050
1051 if (psp) {
1052 /* No interaction with the X-server is possible at this point. This
1053 * routine is called after XCloseDisplay, so there is no protocol
1054 * stream open to the X-server anymore.
1055 */
1056
1057 if (psp->DriverAPI.DestroyScreen)
1058 (*psp->DriverAPI.DestroyScreen)(psp);
1059
1060 (void)drmUnmap((drmAddress)psp->pSAREA, SAREA_MAX);
1061 (void)drmUnmap((drmAddress)psp->pFB, psp->fbSize);
1062 Xfree(psp->pDevPriv);
1063 (void)drmClose(psp->fd);
1064 if ( psp->modes != NULL ) {
1065 _gl_context_modes_destroy( psp->modes );
1066 }
1067 Xfree(psp);
1068 }
1069 }
1070
1071
1072 /**
1073 * Utility function used to create a new driver-private screen structure.
1074 *
1075 * \param dpy Display pointer
1076 * \param scrn Index of the screen
1077 * \param psc DRI screen data (not driver private)
1078 * \param modes Linked list of known display modes. This list is, at a
1079 * minimum, a list of modes based on the current display mode.
1080 * These roughly match the set of available X11 visuals, but it
1081 * need not be limited to X11! The calling libGL should create
1082 * a list that will inform the driver of the current display
1083 * mode (i.e., color buffer depth, depth buffer depth, etc.).
1084 * \param ddx_version Version of the 2D DDX. This may not be meaningful for
1085 * all drivers.
1086 * \param dri_version Version of the "server-side" DRI.
1087 * \param drm_version Version of the kernel DRM.
1088 * \param frame_buffer Data describing the location and layout of the
1089 * framebuffer.
1090 * \param pSAREA Pointer the the SAREA.
1091 * \param fd Device handle for the DRM.
1092 * \param internal_api_version Version of the internal interface between the
1093 * driver and libGL.
1094 * \param driverAPI Driver API functions used by other routines in dri_util.c.
1095 */
1096 __DRIscreenPrivate *
1097 __driUtilCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc,
1098 __GLcontextModes * modes,
1099 const __DRIversion * ddx_version,
1100 const __DRIversion * dri_version,
1101 const __DRIversion * drm_version,
1102 const __DRIframebuffer * frame_buffer,
1103 drmAddress pSAREA,
1104 int fd,
1105 int internal_api_version,
1106 const struct __DriverAPIRec *driverAPI)
1107 {
1108 __DRIscreenPrivate *psp;
1109
1110
1111 window_exists = (PFNGLXWINDOWEXISTSPROC)
1112 glXGetProcAddress( (const GLubyte *) "__glXWindowExists" );
1113
1114 if ( window_exists == NULL ) {
1115 #ifdef DRI_NEW_INTERFACE_ONLY
1116 fprintf( stderr, "libGL error: libGL.so version (%08u) is too old. "
1117 "20021128 or later is required.\n", internal_api_version );
1118 return NULL;
1119 #else
1120 window_exists = (PFNGLXWINDOWEXISTSPROC) __driWindowExists;
1121 #endif /* DRI_NEW_INTERFACE_ONLY */
1122 }
1123
1124 create_context_with_config = (PFNGLXCREATECONTEXTWITHCONFIGPROC)
1125 glXGetProcAddress( (const GLubyte *) "__glXCreateContextWithConfig" );
1126 if ( create_context_with_config == NULL ) {
1127 #ifdef DRI_NEW_INTERFACE_ONLY
1128 fprintf( stderr, "libGL error: libGL.so version (%08u) is too old. "
1129 "20031201 or later is required.\n", internal_api_version );
1130 return NULL;
1131 #else
1132 create_context_with_config = (PFNGLXCREATECONTEXTWITHCONFIGPROC)
1133 fake_XF86DRICreateContextWithConfig;
1134 #endif /* DRI_NEW_INTERFACE_ONLY */
1135 }
1136
1137 api_ver = internal_api_version;
1138
1139 psp = (__DRIscreenPrivate *)Xmalloc(sizeof(__DRIscreenPrivate));
1140 if (!psp) {
1141 return NULL;
1142 }
1143
1144 /* Create the hash table */
1145 psp->drawHash = drmHashCreate();
1146 if ( psp->drawHash == NULL ) {
1147 Xfree( psp );
1148 return NULL;
1149 }
1150
1151 psp->display = dpy;
1152 psp->myNum = scrn;
1153 psp->psc = psc;
1154 psp->modes = modes;
1155
1156 /*
1157 ** NOT_DONE: This is used by the X server to detect when the client
1158 ** has died while holding the drawable lock. The client sets the
1159 ** drawable lock to this value.
1160 */
1161 psp->drawLockID = 1;
1162
1163 psp->drmMajor = drm_version->major;
1164 psp->drmMinor = drm_version->minor;
1165 psp->drmPatch = drm_version->patch;
1166 psp->ddxMajor = ddx_version->major;
1167 psp->ddxMinor = ddx_version->minor;
1168 psp->ddxPatch = ddx_version->patch;
1169 psp->driMajor = dri_version->major;
1170 psp->driMinor = dri_version->minor;
1171 psp->driPatch = dri_version->patch;
1172
1173 /* install driver's callback functions */
1174 memcpy( &psp->DriverAPI, driverAPI, sizeof(struct __DriverAPIRec) );
1175
1176 psp->pSAREA = pSAREA;
1177
1178 psp->pFB = frame_buffer->base;
1179 psp->fbSize = frame_buffer->size;
1180 psp->fbStride = frame_buffer->stride;
1181 psp->fbWidth = frame_buffer->width;
1182 psp->fbHeight = frame_buffer->height;
1183 psp->devPrivSize = frame_buffer->dev_priv_size;
1184 psp->pDevPriv = frame_buffer->dev_priv;
1185
1186 psp->fd = fd;
1187
1188 /*
1189 ** Do not init dummy context here; actual initialization will be
1190 ** done when the first DRI context is created. Init screen priv ptr
1191 ** to NULL to let CreateContext routine that it needs to be inited.
1192 */
1193 psp->dummyContextPriv.driScreenPriv = NULL;
1194
1195 psc->destroyScreen = driDestroyScreen;
1196 #ifndef DRI_NEW_INTERFACE_ONLY
1197 psc->createContext = driCreateContext;
1198 #else
1199 psc->createConteext = NULL;
1200 #endif
1201 psc->createNewDrawable = driCreateNewDrawable;
1202 psc->getDrawable = driGetDrawable;
1203 if ( driCompareGLXAPIVersion( 20030317 ) >= 0 ) {
1204 psc->getMSC = driGetMSC;
1205
1206 if ( driCompareGLXAPIVersion( 20030824 ) >= 0 ) {
1207 psc->createNewContext = driCreateNewContext;
1208 }
1209 }
1210
1211 if ( (psp->DriverAPI.InitDriver != NULL)
1212 && !(*psp->DriverAPI.InitDriver)(psp) ) {
1213 Xfree( psp );
1214 return NULL;
1215 }
1216
1217
1218 return psp;
1219 }
1220
1221
1222 #ifndef DRI_NEW_INTERFACE_ONLY
1223 /**
1224 * Utility function used to create a new driver-private screen structure.
1225 *
1226 * \param dpy Display pointer.
1227 * \param scrn Index of the screen.
1228 * \param psc DRI screen data (not driver private)
1229 * \param numConfigs Number of visual configs pointed to by \c configs.
1230 * \param configs Array of GLXvisualConfigs exported by the 2D driver.
1231 * \param driverAPI Driver API functions used by other routines in dri_util.c.
1232 *
1233 * \deprecated
1234 * This function has been replaced by \c __driUtilCreateNewScreen. In drivers
1235 * built to work with XFree86, this function will continue to exist to support
1236 * older versions of libGL. Starting with the next major relelase of XFree86,
1237 * this function will be removed.
1238 */
1239 __DRIscreenPrivate *
1240 __driUtilCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
1241 int numConfigs, __GLXvisualConfig *configs,
1242 const struct __DriverAPIRec *driverAPI)
1243 {
1244 int directCapable;
1245 __DRIscreenPrivate *psp = NULL;
1246 drmHandle hSAREA;
1247 drmAddress pSAREA;
1248 char *BusID;
1249 __GLcontextModes *modes;
1250 __GLcontextModes *temp;
1251 int i;
1252 __DRIversion ddx_version;
1253 __DRIversion dri_version;
1254 __DRIversion drm_version;
1255 __DRIframebuffer framebuffer;
1256 int fd = -1;
1257 int status;
1258 const char * err_msg;
1259 const char * err_extra;
1260
1261
1262 if (!XF86DRIQueryDirectRenderingCapable(dpy, scrn, &directCapable)
1263 || !directCapable) {
1264 return NULL;
1265 }
1266
1267
1268 /* Create the linked list of context modes, and populate it with the
1269 * GLX visual information passed in by libGL.
1270 */
1271
1272 modes = _gl_context_modes_create( numConfigs, sizeof(__GLcontextModes) );
1273 if ( modes == NULL ) {
1274 return NULL;
1275 }
1276
1277 temp = modes;
1278 for ( i = 0 ; i < numConfigs ; i++ ) {
1279 assert( temp != NULL );
1280 _gl_copy_visual_to_context_mode( temp, & configs[i] );
1281 temp->screen = scrn;
1282
1283 temp = temp->next;
1284 }
1285
1286 err_msg = "XF86DRIOpenConnection";
1287 err_extra = NULL;
1288
1289 if (XF86DRIOpenConnection(dpy, scrn, &hSAREA, &BusID)) {
1290 fd = drmOpen(NULL,BusID);
1291 Xfree(BusID); /* No longer needed */
1292
1293 err_msg = "open DRM";
1294 err_extra = strerror( -fd );
1295
1296 if (fd >= 0) {
1297 drmMagic magic;
1298
1299 err_msg = "drmGetMagic";
1300 err_extra = NULL;
1301
1302 if (!drmGetMagic(fd, &magic)) {
1303 drmVersionPtr version = drmGetVersion(fd);
1304 if (version) {
1305 drm_version.major = version->version_major;
1306 drm_version.minor = version->version_minor;
1307 drm_version.patch = version->version_patchlevel;
1308 drmFreeVersion(version);
1309 }
1310 else {
1311 drm_version.major = -1;
1312 drm_version.minor = -1;
1313 drm_version.patch = -1;
1314 }
1315
1316 err_msg = "XF86DRIAuthConnection";
1317 if (XF86DRIAuthConnection(dpy, scrn, magic)) {
1318 char *driverName;
1319
1320 /*
1321 * Get device name (like "tdfx") and the ddx version numbers.
1322 * We'll check the version in each DRI driver's "createScreen"
1323 * function.
1324 */
1325 err_msg = "XF86DRIGetClientDriverName";
1326 if (XF86DRIGetClientDriverName(dpy, scrn,
1327 &ddx_version.major,
1328 &ddx_version.minor,
1329 &ddx_version.patch,
1330 &driverName)) {
1331
1332 /* No longer needed. */
1333 Xfree( driverName );
1334
1335 /*
1336 * Get the DRI X extension version.
1337 */
1338 err_msg = "XF86DRIQueryVersion";
1339 if (XF86DRIQueryVersion(dpy,
1340 &dri_version.major,
1341 &dri_version.minor,
1342 &dri_version.patch)) {
1343 drmHandle hFB;
1344 int junk;
1345
1346 /*
1347 * Get device-specific info. pDevPriv will point to a struct
1348 * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h)
1349 * that has information about the screen size, depth, pitch,
1350 * ancilliary buffers, DRM mmap handles, etc.
1351 */
1352 err_msg = "XF86DRIGetDeviceInfo";
1353 if (XF86DRIGetDeviceInfo(dpy, scrn,
1354 &hFB,
1355 &junk,
1356 &framebuffer.size,
1357 &framebuffer.stride,
1358 &framebuffer.dev_priv_size,
1359 &framebuffer.dev_priv)) {
1360 framebuffer.width = DisplayWidth(dpy, scrn);
1361 framebuffer.height = DisplayHeight(dpy, scrn);
1362
1363 /*
1364 * Map the framebuffer region.
1365 */
1366 status = drmMap(fd, hFB, framebuffer.size,
1367 (drmAddressPtr)&framebuffer.base);
1368
1369 err_msg = "drmMap of framebuffer";
1370 err_extra = strerror( -status );
1371
1372 if ( status == 0 ) {
1373 /*
1374 * Map the SAREA region. Further mmap regions may be setup in
1375 * each DRI driver's "createScreen" function.
1376 */
1377 status = drmMap(fd, hSAREA, SAREA_MAX,
1378 &pSAREA);
1379
1380 err_msg = "drmMap of sarea";
1381 err_extra = strerror( -status );
1382
1383 if ( status == 0 ) {
1384 PFNGLXGETINTERNALVERSIONPROC get_ver;
1385
1386 get_ver = (PFNGLXGETINTERNALVERSIONPROC)
1387 glXGetProcAddress( (const GLubyte *) "__glXGetInternalVersion" );
1388
1389 err_msg = "InitDriver";
1390 err_extra = NULL;
1391 psp = __driUtilCreateNewScreen( dpy, scrn, psc, modes,
1392 & ddx_version,
1393 & dri_version,
1394 & drm_version,
1395 & framebuffer,
1396 pSAREA,
1397 fd,
1398 (get_ver != NULL) ? (*get_ver)() : 1,
1399 driverAPI );
1400 }
1401 }
1402 }
1403 }
1404 }
1405 }
1406 }
1407 }
1408 }
1409
1410 if ( psp == NULL ) {
1411 if ( pSAREA != MAP_FAILED ) {
1412 (void)drmUnmap(pSAREA, SAREA_MAX);
1413 }
1414
1415 if ( framebuffer.base != MAP_FAILED ) {
1416 (void)drmUnmap((drmAddress)framebuffer.base, framebuffer.size);
1417 }
1418
1419 if ( framebuffer.dev_priv != NULL ) {
1420 Xfree(framebuffer.dev_priv);
1421 }
1422
1423 if ( fd >= 0 ) {
1424 (void)drmClose(fd);
1425 }
1426
1427 if ( modes != NULL ) {
1428 _gl_context_modes_destroy( modes );
1429 }
1430
1431 (void)XF86DRICloseConnection(dpy, scrn);
1432
1433 if ( err_extra != NULL ) {
1434 fprintf(stderr, "libGL error: %s failed (%s)\n", err_msg,
1435 err_extra);
1436 }
1437 else {
1438 fprintf(stderr, "libGL error: %s failed\n", err_msg );
1439 }
1440
1441 fprintf(stderr, "libGL error: reverting to (slow) indirect rendering\n");
1442 }
1443
1444 return psp;
1445 }
1446 #endif /* DRI_NEW_INTERFACE_ONLY */
1447
1448
1449 /**
1450 * Compare the current GLX API version with a driver supplied required version.
1451 *
1452 * The minimum required version is compared with the API version exported by
1453 * the \c __glXGetInternalVersion function (in libGL.so).
1454 *
1455 * \param required_version Minimum required internal GLX API version.
1456 * \return A tri-value return, as from strcmp is returned. A value less
1457 * than, equal to, or greater than zero will be returned if the
1458 * internal GLX API version is less than, equal to, or greater
1459 * than \c required_version.
1460 *
1461 * \sa __glXGetInternalVersion().
1462 */
1463 int driCompareGLXAPIVersion( GLuint required_version )
1464 {
1465 if ( api_ver > required_version ) {
1466 return 1;
1467 }
1468 else if ( api_ver == required_version ) {
1469 return 0;
1470 }
1471
1472 return -1;
1473 }
1474
1475
1476 static int
1477 driQueryFrameTracking( Display * dpy, void * priv,
1478 int64_t * sbc, int64_t * missedFrames,
1479 float * lastMissedUsage, float * usage )
1480 {
1481 static PFNGLXGETUSTPROC get_ust;
1482 __DRIswapInfo sInfo;
1483 int status;
1484 int64_t ust;
1485 __DRIdrawablePrivate * dpriv = (__DRIdrawablePrivate *) priv;
1486
1487 if ( get_ust == NULL ) {
1488 get_ust = (PFNGLXGETUSTPROC) glXGetProcAddress( (const GLubyte *) "__glXGetUST" );
1489 }
1490
1491 status = dpriv->driScreenPriv->DriverAPI.GetSwapInfo( dpriv, & sInfo );
1492 if ( status == 0 ) {
1493 *sbc = sInfo.swap_count;
1494 *missedFrames = sInfo.swap_missed_count;
1495 *lastMissedUsage = sInfo.swap_missed_usage;
1496
1497 (*get_ust)( & ust );
1498 *usage = driCalculateSwapUsage( dpriv, sInfo.swap_ust, ust );
1499 }
1500
1501 return status;
1502 }
1503
1504
1505 /**
1506 * Calculate amount of swap interval used between GLX buffer swaps.
1507 *
1508 * The usage value, on the range [0,max], is the fraction of total swap
1509 * interval time used between GLX buffer swaps is calculated.
1510 *
1511 * \f$p = t_d / (i * t_r)\f$
1512 *
1513 * Where \f$t_d\f$ is the time since the last GLX buffer swap, \f$i\f$ is the
1514 * swap interval (as set by \c glXSwapIntervalSGI), and \f$t_r\f$ time
1515 * required for a single vertical refresh period (as returned by \c
1516 * glXGetMscRateOML).
1517 *
1518 * See the documentation for the GLX_MESA_swap_frame_usage extension for more
1519 * details.
1520 *
1521 * \param dPriv Pointer to the private drawable structure.
1522 * \return If less than a single swap interval time period was required
1523 * between GLX buffer swaps, a number greater than 0 and less than
1524 * 1.0 is returned. If exactly one swap interval time period is
1525 * required, 1.0 is returned, and if more than one is required then
1526 * a number greater than 1.0 will be returned.
1527 *
1528 * \sa glXSwapIntervalSGI glXGetMscRateOML
1529 *
1530 * \todo Instead of caching the \c glXGetMscRateOML function pointer, would it
1531 * be possible to cache the sync rate?
1532 */
1533 float
1534 driCalculateSwapUsage( __DRIdrawablePrivate *dPriv, int64_t last_swap_ust,
1535 int64_t current_ust )
1536 {
1537 static PFNGLXGETMSCRATEOMLPROC get_msc_rate = NULL;
1538 int32_t n;
1539 int32_t d;
1540 int interval;
1541 float usage = 1.0;
1542
1543
1544 if ( get_msc_rate == NULL ) {
1545 get_msc_rate = (PFNGLXGETMSCRATEOMLPROC)
1546 glXGetProcAddress( (const GLubyte *) "glXGetMscRateOML" );
1547 }
1548
1549 if ( (get_msc_rate != NULL)
1550 && get_msc_rate( dPriv->display, dPriv->draw, &n, &d ) ) {
1551 interval = (dPriv->pdraw->swap_interval != 0)
1552 ? dPriv->pdraw->swap_interval : 1;
1553
1554
1555 /* We want to calculate
1556 * (current_UST - last_swap_UST) / (interval * us_per_refresh). We get
1557 * current_UST by calling __glXGetUST. last_swap_UST is stored in
1558 * dPriv->swap_ust. interval has already been calculated.
1559 *
1560 * The only tricky part is us_per_refresh. us_per_refresh is
1561 * 1000000 / MSC_rate. We know the MSC_rate is n / d. We can flip it
1562 * around and say us_per_refresh = 1000000 * d / n. Since this goes in
1563 * the denominator of the final calculation, we calculate
1564 * (interval * 1000000 * d) and move n into the numerator.
1565 */
1566
1567 usage = (current_ust - last_swap_ust);
1568 usage *= n;
1569 usage /= (interval * d);
1570 usage /= 1000000.0;
1571 }
1572
1573 return usage;
1574 }
1575
1576 /*@}*/
1577
1578 #endif /* GLX_DIRECT_RENDERING */