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