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