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