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