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