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