Merge branch 'master' of git+ssh://joukj@git.freedesktop.org/git/mesa/mesa
[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
18
19 #include <assert.h>
20 #include <stdarg.h>
21 #include <unistd.h>
22 #include <sys/mman.h>
23 #include <stdio.h>
24
25 #ifndef MAP_FAILED
26 #define MAP_FAILED ((void *)-1)
27 #endif
28
29 #include "imports.h"
30 #define None 0
31
32 #include "dri_util.h"
33 #include "drm_sarea.h"
34
35 #ifndef GLX_OML_sync_control
36 typedef GLboolean ( * PFNGLXGETMSCRATEOMLPROC) (__DRIdrawable *drawable, int32_t *numerator, int32_t *denominator);
37 #endif
38
39 /* This pointer *must* be set by the driver's __driCreateNewScreen funciton!
40 */
41 const __DRIinterfaceMethods * dri_interface = NULL;
42
43 /**
44 * This is used in a couple of places that call \c driCreateNewDrawable.
45 */
46 static const int empty_attribute_list[1] = { None };
47
48
49 /**
50 * This is just a token extension used to signal that the driver
51 * supports setting a read drawable.
52 */
53 const __DRIextension driReadDrawableExtension = {
54 __DRI_READ_DRAWABLE, __DRI_READ_DRAWABLE_VERSION
55 };
56
57 /**
58 * Cached copy of the internal API version used by libGL and the client-side
59 * DRI driver.
60 */
61 static int api_ver = 0;
62
63 static void *driCreateNewDrawable(__DRIscreen *screen,
64 const __GLcontextModes *modes,
65 __DRIdrawable *pdraw,
66 drm_drawable_t hwDrawable,
67 int renderType, const int *attrs);
68
69 static void driDestroyDrawable(__DRIdrawable *drawable);
70
71
72 /**
73 * Print message to \c stderr if the \c LIBGL_DEBUG environment variable
74 * is set.
75 *
76 * Is called from the drivers.
77 *
78 * \param f \c printf like format string.
79 */
80 void
81 __driUtilMessage(const char *f, ...)
82 {
83 va_list args;
84
85 if (getenv("LIBGL_DEBUG")) {
86 fprintf(stderr, "libGL error: \n");
87 va_start(args, f);
88 vfprintf(stderr, f, args);
89 va_end(args);
90 fprintf(stderr, "\n");
91 }
92 }
93
94
95 /*****************************************************************/
96 /** \name Context (un)binding functions */
97 /*****************************************************************/
98 /*@{*/
99
100 /**
101 * Unbind context.
102 *
103 * \param scrn the screen.
104 * \param gc context.
105 *
106 * \return \c GL_TRUE on success, or \c GL_FALSE on failure.
107 *
108 * \internal
109 * This function calls __DriverAPIRec::UnbindContext, and then decrements
110 * __DRIdrawablePrivateRec::refcount which must be non-zero for a successful
111 * return.
112 *
113 * While casting the opaque private pointers associated with the parameters
114 * into their respective real types it also assures they are not \c NULL.
115 */
116 static GLboolean driUnbindContext(__DRIcontext *ctx)
117 {
118 __DRIcontextPrivate *pcp;
119 __DRIscreenPrivate *psp;
120 __DRIdrawablePrivate *pdp;
121 __DRIdrawablePrivate *prp;
122
123 /*
124 ** Assume error checking is done properly in glXMakeCurrent before
125 ** calling driUnbindContext.
126 */
127
128 if (ctx == NULL)
129 return GL_FALSE;
130
131 pcp = (__DRIcontextPrivate *)ctx->private;
132 psp = (__DRIscreenPrivate *)pcp->driScreenPriv;
133 pdp = (__DRIdrawablePrivate *)pcp->driDrawablePriv;
134 prp = (__DRIdrawablePrivate *)pcp->driReadablePriv;
135
136 /* Let driver unbind drawable from context */
137 (*psp->DriverAPI.UnbindContext)(pcp);
138
139 if (pdp->refcount == 0) {
140 /* ERROR!!! */
141 return GL_FALSE;
142 }
143
144 pdp->refcount--;
145
146 if (prp != pdp) {
147 if (prp->refcount == 0) {
148 /* ERROR!!! */
149 return GL_FALSE;
150 }
151
152 prp->refcount--;
153 }
154
155
156 /* XXX this is disabled so that if we call SwapBuffers on an unbound
157 * window we can determine the last context bound to the window and
158 * use that context's lock. (BrianP, 2-Dec-2000)
159 */
160 #if 0
161 /* Unbind the drawable */
162 pcp->driDrawablePriv = NULL;
163 pdp->driContextPriv = &psp->dummyContextPriv;
164 #endif
165
166 return GL_TRUE;
167 }
168
169
170 /**
171 * This function takes both a read buffer and a draw buffer. This is needed
172 * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
173 * function.
174 */
175 static GLboolean DoBindContext(__DRIcontext *ctx,
176 __DRIdrawable *pdraw,
177 __DRIdrawable *pread)
178 {
179 __DRIdrawablePrivate *pdp;
180 __DRIdrawablePrivate *prp;
181 __DRIcontextPrivate * const pcp = ctx->private;
182 __DRIscreenPrivate *psp = pcp->driScreenPriv;
183
184 pdp = (__DRIdrawablePrivate *) pdraw->private;
185 prp = (__DRIdrawablePrivate *) pread->private;
186
187 /* Bind the drawable to the context */
188 pcp->driDrawablePriv = pdp;
189 pcp->driReadablePriv = prp;
190 pdp->driContextPriv = pcp;
191 pdp->refcount++;
192 if ( pdp != prp ) {
193 prp->refcount++;
194 }
195
196 /*
197 ** Now that we have a context associated with this drawable, we can
198 ** initialize the drawable information if has not been done before.
199 */
200 if (!pdp->pStamp || *pdp->pStamp != pdp->lastStamp) {
201 DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
202 __driUtilUpdateDrawableInfo(pdp);
203 DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
204 }
205
206 if ((pdp != prp) && (!prp->pStamp || *prp->pStamp != prp->lastStamp)) {
207 DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
208 __driUtilUpdateDrawableInfo(prp);
209 DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
210 }
211
212 /* Call device-specific MakeCurrent */
213 (*psp->DriverAPI.MakeCurrent)(pcp, pdp, prp);
214
215 return GL_TRUE;
216 }
217
218
219 /**
220 * This function takes both a read buffer and a draw buffer. This is needed
221 * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
222 * function.
223 */
224 static GLboolean driBindContext(__DRIcontext * ctx,
225 __DRIdrawable *pdraw,
226 __DRIdrawable *pread)
227 {
228 /*
229 ** Assume error checking is done properly in glXMakeCurrent before
230 ** calling driBindContext.
231 */
232
233 if (ctx == NULL || pdraw == None || pread == None)
234 return GL_FALSE;
235
236 return DoBindContext( ctx, pdraw, pread );
237 }
238 /*@}*/
239
240
241 /*****************************************************************/
242 /** \name Drawable handling functions */
243 /*****************************************************************/
244 /*@{*/
245
246 /**
247 * Update private drawable information.
248 *
249 * \param pdp pointer to the private drawable information to update.
250 *
251 * This function basically updates the __DRIdrawablePrivate struct's
252 * cliprect information by calling \c __DRIinterfaceMethods::getDrawableInfo.
253 * This is usually called by the DRI_VALIDATE_DRAWABLE_INFO macro which
254 * compares the __DRIdrwablePrivate pStamp and lastStamp values. If
255 * the values are different that means we have to update the clipping
256 * info.
257 */
258 void
259 __driUtilUpdateDrawableInfo(__DRIdrawablePrivate *pdp)
260 {
261 __DRIscreenPrivate *psp;
262 __DRIcontextPrivate *pcp = pdp->driContextPriv;
263
264 if (!pcp
265 || ((pdp != pcp->driDrawablePriv) && (pdp != pcp->driReadablePriv))) {
266 /* ERROR!!!
267 * ...but we must ignore it. There can be many contexts bound to a
268 * drawable.
269 */
270 }
271
272 psp = pdp->driScreenPriv;
273 if (!psp) {
274 /* ERROR!!! */
275 _mesa_problem(NULL, "Warning! Possible infinite loop due to bug "
276 "in file %s, line %d\n",
277 __FILE__, __LINE__);
278 return;
279 }
280
281 if (pdp->pClipRects) {
282 _mesa_free(pdp->pClipRects);
283 pdp->pClipRects = NULL;
284 }
285
286 if (pdp->pBackClipRects) {
287 _mesa_free(pdp->pBackClipRects);
288 pdp->pBackClipRects = NULL;
289 }
290
291 DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
292
293 if (! (*dri_interface->getDrawableInfo)(pdp->pdraw,
294 &pdp->index, &pdp->lastStamp,
295 &pdp->x, &pdp->y, &pdp->w, &pdp->h,
296 &pdp->numClipRects, &pdp->pClipRects,
297 &pdp->backX,
298 &pdp->backY,
299 &pdp->numBackClipRects,
300 &pdp->pBackClipRects )) {
301 /* Error -- eg the window may have been destroyed. Keep going
302 * with no cliprects.
303 */
304 pdp->pStamp = &pdp->lastStamp; /* prevent endless loop */
305 pdp->numClipRects = 0;
306 pdp->pClipRects = NULL;
307 pdp->numBackClipRects = 0;
308 pdp->pBackClipRects = NULL;
309 }
310 else
311 pdp->pStamp = &(psp->pSAREA->drawableTable[pdp->index].stamp);
312
313 DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
314
315 }
316
317 /*@}*/
318
319 /*****************************************************************/
320 /** \name GLX callbacks */
321 /*****************************************************************/
322 /*@{*/
323
324 /**
325 * Swap buffers.
326 *
327 * \param drawablePrivate opaque pointer to the per-drawable private info.
328 *
329 * \internal
330 * This function calls __DRIdrawablePrivate::swapBuffers.
331 *
332 * Is called directly from glXSwapBuffers().
333 */
334 static void driSwapBuffers(__DRIdrawable *drawable)
335 {
336 __DRIdrawablePrivate *dPriv = drawable->private;
337 drm_clip_rect_t rect;
338
339 dPriv->swapBuffers(dPriv);
340
341 /* Check that we actually have the new damage report method */
342 if (api_ver < 20070105 || dri_interface->reportDamage == NULL)
343 return;
344
345 /* Assume it's affecting the whole drawable for now */
346 rect.x1 = 0;
347 rect.y1 = 0;
348 rect.x2 = rect.x1 + dPriv->w;
349 rect.y2 = rect.y1 + dPriv->h;
350
351 /* Report the damage. Currently, all our drivers draw directly to the
352 * front buffer, so we report the damage there rather than to the backing
353 * store (if any).
354 */
355 (*dri_interface->reportDamage)(dPriv->pdraw, dPriv->x, dPriv->y,
356 &rect, 1, GL_TRUE);
357 }
358
359 static int driDrawableGetMSC( __DRIscreen *screen, void *drawablePrivate,
360 int64_t *msc )
361 {
362 __DRIscreenPrivate *sPriv = screen->private;
363
364 return sPriv->DriverAPI.GetDrawableMSC( sPriv, drawablePrivate, msc );
365 }
366
367 /**
368 * Called directly from a number of higher-level GLX functions.
369 */
370 static int driGetMSC( __DRIscreen *screen, void *drawablePrivate, int64_t *msc )
371 {
372 __DRIscreenPrivate *sPriv = screen->private;
373
374 return sPriv->DriverAPI.GetMSC( sPriv, msc );
375 }
376
377 static int driWaitForMSC(__DRIdrawable *drawable, int64_t target_msc,
378 int64_t divisor, int64_t remainder,
379 int64_t * msc, int64_t * sbc)
380 {
381 __DRIdrawablePrivate *dPriv = drawable->private;
382 __DRIswapInfo sInfo;
383 int status;
384
385
386 status = dPriv->driScreenPriv->DriverAPI.WaitForMSC( dPriv, target_msc,
387 divisor, remainder,
388 msc );
389
390 /* GetSwapInfo() may not be provided by the driver if GLX_SGI_video_sync
391 * is supported but GLX_OML_sync_control is not. Therefore, don't return
392 * an error value if GetSwapInfo() is not implemented.
393 */
394 if ( status == 0
395 && dPriv->driScreenPriv->DriverAPI.GetSwapInfo ) {
396 status = dPriv->driScreenPriv->DriverAPI.GetSwapInfo( dPriv, & sInfo );
397 *sbc = sInfo.swap_count;
398 }
399
400 return status;
401 }
402
403 const __DRImediaStreamCounterExtension driMediaStreamCounterExtension = {
404 { __DRI_MEDIA_STREAM_COUNTER, __DRI_MEDIA_STREAM_COUNTER_VERSION },
405 driGetMSC,
406 driWaitForMSC,
407 driDrawableGetMSC,
408 };
409
410 static void driCopySubBuffer(__DRIdrawable *drawable,
411 int x, int y, int w, int h)
412 {
413 __DRIdrawablePrivate *dPriv = drawable->private;
414 dPriv->driScreenPriv->DriverAPI.CopySubBuffer(dPriv, x, y, w, h);
415 }
416
417 const __DRIcopySubBufferExtension driCopySubBufferExtension = {
418 { __DRI_COPY_SUB_BUFFER, __DRI_COPY_SUB_BUFFER_VERSION },
419 driCopySubBuffer
420 };
421
422 static void driSetSwapInterval(__DRIdrawable *drawable, unsigned int interval)
423 {
424 __DRIdrawablePrivate *dpriv = drawable->private;
425
426 dpriv->swap_interval = interval;
427 }
428
429 static unsigned int driGetSwapInterval(__DRIdrawable *drawable)
430 {
431 __DRIdrawablePrivate *dpriv = drawable->private;
432
433 return dpriv->swap_interval;
434 }
435
436 const __DRIswapControlExtension driSwapControlExtension = {
437 { __DRI_SWAP_CONTROL, __DRI_SWAP_CONTROL_VERSION },
438 driSetSwapInterval,
439 driGetSwapInterval
440 };
441
442
443 /**
444 * This is called via __DRIscreenRec's createNewDrawable pointer.
445 */
446 static void *driCreateNewDrawable(__DRIscreen *screen,
447 const __GLcontextModes *modes,
448 __DRIdrawable *pdraw,
449 drm_drawable_t hwDrawable,
450 int renderType,
451 const int *attrs)
452 {
453 __DRIscreenPrivate *psp;
454 __DRIdrawablePrivate *pdp;
455
456
457 pdraw->private = NULL;
458
459 /* Since pbuffers are not yet supported, no drawable attributes are
460 * supported either.
461 */
462 (void) attrs;
463
464 pdp = (__DRIdrawablePrivate *)_mesa_malloc(sizeof(__DRIdrawablePrivate));
465 if (!pdp) {
466 return NULL;
467 }
468
469 pdp->hHWDrawable = hwDrawable;
470 pdp->pdraw = pdraw;
471 pdp->refcount = 0;
472 pdp->pStamp = NULL;
473 pdp->lastStamp = 0;
474 pdp->index = 0;
475 pdp->x = 0;
476 pdp->y = 0;
477 pdp->w = 0;
478 pdp->h = 0;
479 pdp->numClipRects = 0;
480 pdp->numBackClipRects = 0;
481 pdp->pClipRects = NULL;
482 pdp->pBackClipRects = NULL;
483 pdp->vblSeq = 0;
484 pdp->vblFlags = 0;
485
486 psp = (__DRIscreenPrivate *)screen->private;
487 pdp->driScreenPriv = psp;
488 pdp->driContextPriv = &psp->dummyContextPriv;
489
490 if (!(*psp->DriverAPI.CreateBuffer)(psp, pdp, modes,
491 renderType == GLX_PIXMAP_BIT)) {
492 _mesa_free(pdp);
493 return NULL;
494 }
495
496 pdraw->private = pdp;
497 pdraw->destroyDrawable = driDestroyDrawable;
498 pdraw->swapBuffers = driSwapBuffers; /* called by glXSwapBuffers() */
499 pdp->msc_base = 0;
500
501 /* This special default value is replaced with the configured
502 * default value when the drawable is first bound to a direct
503 * rendering context.
504 */
505 pdp->swap_interval = (unsigned)-1;
506
507 pdp->swapBuffers = psp->DriverAPI.SwapBuffers;
508
509 return (void *) pdp;
510 }
511
512 static void
513 driDestroyDrawable(__DRIdrawable *drawable)
514 {
515 __DRIdrawablePrivate *pdp = drawable->private;
516 __DRIscreenPrivate *psp;
517
518 if (pdp) {
519 psp = pdp->driScreenPriv;
520 (*psp->DriverAPI.DestroyBuffer)(pdp);
521 if (pdp->pClipRects) {
522 _mesa_free(pdp->pClipRects);
523 pdp->pClipRects = NULL;
524 }
525 if (pdp->pBackClipRects) {
526 _mesa_free(pdp->pBackClipRects);
527 pdp->pBackClipRects = NULL;
528 }
529 _mesa_free(pdp);
530 }
531 }
532
533 /*@}*/
534
535
536 /*****************************************************************/
537 /** \name Context handling functions */
538 /*****************************************************************/
539 /*@{*/
540
541 /**
542 * Destroy the per-context private information.
543 *
544 * \param contextPrivate opaque pointer to the per-drawable private info.
545 *
546 * \internal
547 * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls
548 * drmDestroyContext(), and finally frees \p contextPrivate.
549 */
550 static void
551 driDestroyContext(__DRIcontext *context)
552 {
553 __DRIcontextPrivate *pcp = context->private;
554
555 if (pcp) {
556 (*pcp->driScreenPriv->DriverAPI.DestroyContext)(pcp);
557 _mesa_free(pcp);
558 }
559 }
560
561
562 /**
563 * Create the per-drawable private driver information.
564 *
565 * \param dpy The display handle.
566 * \param modes Mode used to create the new context.
567 * \param render_type Type of rendering target. \c GLX_RGBA is the only
568 * type likely to ever be supported for direct-rendering.
569 * \param shared The shared context dependent methods or \c NULL if
570 * non-existent.
571 * \param pctx DRI context to receive the context dependent methods.
572 *
573 * \returns An opaque pointer to the per-context private information on
574 * success, or \c NULL on failure.
575 *
576 * \internal
577 * This function allocates and fills a __DRIcontextPrivateRec structure. It
578 * performs some device independent initialization and passes all the
579 * relevent information to __DriverAPIRec::CreateContext to create the
580 * context.
581 *
582 */
583 static void *
584 driCreateNewContext(__DRIscreen *screen, const __GLcontextModes *modes,
585 int render_type, __DRIcontext *shared,
586 drm_context_t hwContext, __DRIcontext *pctx)
587 {
588 __DRIcontextPrivate *pcp;
589 __DRIcontextPrivate *pshare = (shared != NULL) ? shared->private : NULL;
590 __DRIscreenPrivate *psp;
591 void * const shareCtx = (pshare != NULL) ? pshare->driverPrivate : NULL;
592
593 psp = (__DRIscreenPrivate *)screen->private;
594
595 pcp = (__DRIcontextPrivate *)_mesa_malloc(sizeof(__DRIcontextPrivate));
596 if (!pcp) {
597 return NULL;
598 }
599
600 pcp->hHWContext = hwContext;
601 pcp->driScreenPriv = psp;
602 pcp->driDrawablePriv = NULL;
603
604 /* When the first context is created for a screen, initialize a "dummy"
605 * context.
606 */
607
608 if (!psp->dummyContextPriv.driScreenPriv) {
609 psp->dummyContextPriv.hHWContext = psp->pSAREA->dummy_context;
610 psp->dummyContextPriv.driScreenPriv = psp;
611 psp->dummyContextPriv.driDrawablePriv = NULL;
612 psp->dummyContextPriv.driverPrivate = NULL;
613 /* No other fields should be used! */
614 }
615
616 pctx->destroyContext = driDestroyContext;
617 pctx->bindContext = driBindContext;
618 pctx->unbindContext = driUnbindContext;
619
620 if ( !(*psp->DriverAPI.CreateContext)(modes, pcp, shareCtx) ) {
621 _mesa_free(pcp);
622 return NULL;
623 }
624
625 return pcp;
626 }
627 /*@}*/
628
629
630 static const __DRIextension **
631 driGetExtensions(__DRIscreen *screen)
632 {
633 __DRIscreenPrivate *psp = screen->private;
634
635 return psp->extensions;
636 }
637
638 /*****************************************************************/
639 /** \name Screen handling functions */
640 /*****************************************************************/
641 /*@{*/
642
643 /**
644 * Destroy the per-screen private information.
645 *
646 * \param dpy the display handle.
647 * \param scrn the screen number.
648 * \param screenPrivate opaque pointer to the per-screen private information.
649 *
650 * \internal
651 * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls
652 * drmClose(), and finally frees \p screenPrivate.
653 */
654 static void driDestroyScreen(__DRIscreen *screen)
655 {
656 __DRIscreenPrivate *psp = screen->private;
657
658 if (psp) {
659 /* No interaction with the X-server is possible at this point. This
660 * routine is called after XCloseDisplay, so there is no protocol
661 * stream open to the X-server anymore.
662 */
663
664 if (psp->DriverAPI.DestroyScreen)
665 (*psp->DriverAPI.DestroyScreen)(psp);
666
667 (void)drmUnmap((drmAddress)psp->pSAREA, SAREA_MAX);
668 (void)drmUnmap((drmAddress)psp->pFB, psp->fbSize);
669 (void)drmCloseOnce(psp->fd);
670
671 _mesa_free(psp);
672 }
673 }
674
675
676 /**
677 * This is the bootstrap function for the driver. libGL supplies all of the
678 * requisite information about the system, and the driver initializes itself.
679 * This routine also fills in the linked list pointed to by \c driver_modes
680 * with the \c __GLcontextModes that the driver can support for windows or
681 * pbuffers.
682 *
683 * \param scrn Index of the screen
684 * \param psc DRI screen data (not driver private)
685 * \param modes Linked list of known display modes. This list is, at a
686 * minimum, a list of modes based on the current display mode.
687 * These roughly match the set of available X11 visuals, but it
688 * need not be limited to X11! The calling libGL should create
689 * a list that will inform the driver of the current display
690 * mode (i.e., color buffer depth, depth buffer depth, etc.).
691 * \param ddx_version Version of the 2D DDX. This may not be meaningful for
692 * all drivers.
693 * \param dri_version Version of the "server-side" DRI.
694 * \param drm_version Version of the kernel DRM.
695 * \param frame_buffer Data describing the location and layout of the
696 * framebuffer.
697 * \param pSAREA Pointer the the SAREA.
698 * \param fd Device handle for the DRM.
699 * \param internal_api_version Version of the internal interface between the
700 * driver and libGL.
701 * \param driverAPI Driver API functions used by other routines in dri_util.c.
702 *
703 * \note There is no need to check the minimum API version in this
704 * function. Since the name of this function is versioned, it is
705 * impossible for a loader that is too old to even load this driver.
706 */
707 PUBLIC
708 void * __DRI_CREATE_NEW_SCREEN( int scrn, __DRIscreen *psc,
709 const __DRIversion * ddx_version,
710 const __DRIversion * dri_version,
711 const __DRIversion * drm_version,
712 const __DRIframebuffer * frame_buffer,
713 drmAddress pSAREA, int fd,
714 int internal_api_version,
715 const __DRIinterfaceMethods * interface,
716 __GLcontextModes ** driver_modes )
717
718 {
719 __DRIscreenPrivate *psp;
720 static const __DRIextension *emptyExtensionList[] = { NULL };
721 dri_interface = interface;
722 api_ver = internal_api_version;
723
724 psp = _mesa_malloc(sizeof(*psp));
725 if (!psp)
726 return NULL;
727
728 psp->psc = psc;
729
730 /*
731 ** NOT_DONE: This is used by the X server to detect when the client
732 ** has died while holding the drawable lock. The client sets the
733 ** drawable lock to this value.
734 */
735 psp->drawLockID = 1;
736
737 psp->drm_version = *drm_version;
738 psp->ddx_version = *ddx_version;
739 psp->dri_version = *dri_version;
740
741 psp->pSAREA = pSAREA;
742
743 psp->pFB = frame_buffer->base;
744 psp->fbSize = frame_buffer->size;
745 psp->fbStride = frame_buffer->stride;
746 psp->fbWidth = frame_buffer->width;
747 psp->fbHeight = frame_buffer->height;
748 psp->devPrivSize = frame_buffer->dev_priv_size;
749 psp->pDevPriv = frame_buffer->dev_priv;
750 psp->fbBPP = psp->fbStride * 8 / frame_buffer->width;
751
752 psp->extensions = emptyExtensionList;
753 psp->fd = fd;
754 psp->myNum = scrn;
755
756 /*
757 ** Do not init dummy context here; actual initialization will be
758 ** done when the first DRI context is created. Init screen priv ptr
759 ** to NULL to let CreateContext routine that it needs to be inited.
760 */
761 psp->dummyContextPriv.driScreenPriv = NULL;
762
763 psc->destroyScreen = driDestroyScreen;
764 psc->getExtensions = driGetExtensions;
765 psc->createNewDrawable = driCreateNewDrawable;
766 psc->createNewContext = driCreateNewContext;
767
768 *driver_modes = __driDriverInitScreen(psp);
769 if (*driver_modes == NULL) {
770 _mesa_free(psp);
771 return NULL;
772 }
773
774 return psp;
775 }
776
777 /**
778 * Compare the current GLX API version with a driver supplied required version.
779 *
780 * The minimum required version is compared with the API version exported by
781 * the \c __glXGetInternalVersion function (in libGL.so).
782 *
783 * \param required_version Minimum required internal GLX API version.
784 * \return A tri-value return, as from strcmp is returned. A value less
785 * than, equal to, or greater than zero will be returned if the
786 * internal GLX API version is less than, equal to, or greater
787 * than \c required_version.
788 *
789 * \sa __glXGetInternalVersion().
790 */
791 int driCompareGLXAPIVersion( GLint required_version )
792 {
793 if ( api_ver > required_version ) {
794 return 1;
795 }
796 else if ( api_ver == required_version ) {
797 return 0;
798 }
799
800 return -1;
801 }
802
803
804 static int
805 driFrameTracking(__DRIdrawable *drawable, GLboolean enable)
806 {
807 return GLX_BAD_CONTEXT;
808 }
809
810 static int
811 driQueryFrameTracking(__DRIdrawable *drawable,
812 int64_t * sbc, int64_t * missedFrames,
813 float * lastMissedUsage, float * usage)
814 {
815 __DRIswapInfo sInfo;
816 int status;
817 int64_t ust;
818 __DRIdrawablePrivate * dpriv = drawable->private;
819
820
821 status = dpriv->driScreenPriv->DriverAPI.GetSwapInfo( dpriv, & sInfo );
822 if ( status == 0 ) {
823 *sbc = sInfo.swap_count;
824 *missedFrames = sInfo.swap_missed_count;
825 *lastMissedUsage = sInfo.swap_missed_usage;
826
827 (*dri_interface->getUST)( & ust );
828 *usage = driCalculateSwapUsage( dpriv, sInfo.swap_ust, ust );
829 }
830
831 return status;
832 }
833
834 const __DRIframeTrackingExtension driFrameTrackingExtension = {
835 { __DRI_FRAME_TRACKING, __DRI_FRAME_TRACKING_VERSION },
836 driFrameTracking,
837 driQueryFrameTracking
838 };
839
840 /**
841 * Calculate amount of swap interval used between GLX buffer swaps.
842 *
843 * The usage value, on the range [0,max], is the fraction of total swap
844 * interval time used between GLX buffer swaps is calculated.
845 *
846 * \f$p = t_d / (i * t_r)\f$
847 *
848 * Where \f$t_d\f$ is the time since the last GLX buffer swap, \f$i\f$ is the
849 * swap interval (as set by \c glXSwapIntervalSGI), and \f$t_r\f$ time
850 * required for a single vertical refresh period (as returned by \c
851 * glXGetMscRateOML).
852 *
853 * See the documentation for the GLX_MESA_swap_frame_usage extension for more
854 * details.
855 *
856 * \param dPriv Pointer to the private drawable structure.
857 * \return If less than a single swap interval time period was required
858 * between GLX buffer swaps, a number greater than 0 and less than
859 * 1.0 is returned. If exactly one swap interval time period is
860 * required, 1.0 is returned, and if more than one is required then
861 * a number greater than 1.0 will be returned.
862 *
863 * \sa glXSwapIntervalSGI glXGetMscRateOML
864 *
865 * \todo Instead of caching the \c glXGetMscRateOML function pointer, would it
866 * be possible to cache the sync rate?
867 */
868 float
869 driCalculateSwapUsage( __DRIdrawablePrivate *dPriv, int64_t last_swap_ust,
870 int64_t current_ust )
871 {
872 int32_t n;
873 int32_t d;
874 int interval;
875 float usage = 1.0;
876
877
878 if ( (*dri_interface->getMSCRate)(dPriv->pdraw, &n, &d) ) {
879 interval = (dPriv->swap_interval != 0) ? dPriv->swap_interval : 1;
880
881
882 /* We want to calculate
883 * (current_UST - last_swap_UST) / (interval * us_per_refresh). We get
884 * current_UST by calling __glXGetUST. last_swap_UST is stored in
885 * dPriv->swap_ust. interval has already been calculated.
886 *
887 * The only tricky part is us_per_refresh. us_per_refresh is
888 * 1000000 / MSC_rate. We know the MSC_rate is n / d. We can flip it
889 * around and say us_per_refresh = 1000000 * d / n. Since this goes in
890 * the denominator of the final calculation, we calculate
891 * (interval * 1000000 * d) and move n into the numerator.
892 */
893
894 usage = (current_ust - last_swap_ust);
895 usage *= n;
896 usage /= (interval * d);
897 usage /= 1000000.0;
898 }
899
900 return usage;
901 }
902
903 /*@}*/