rename class to c_class if using C++ (bug 922294)
[mesa.git] / src / glx / mini / dri_util.c
1 /**
2 * \file dri_util.c
3 * \brief DRI utility functions.
4 *
5 * This module acts as glue between GLX and the actual hardware driver. A DRI
6 * driver doesn't really \e have to use any of this - it's optional. But, some
7 * useful stuff is done here that otherwise would have to be duplicated in most
8 * drivers.
9 *
10 * Basically, these utility functions take care of some of the dirty details of
11 * screen initialization, context creation, context binding, DRM setup, etc.
12 *
13 * These functions are compiled into each DRI driver so libGL.so knows nothing
14 * about them.
15 *
16 */
17
18 #include <assert.h>
19 #include <fcntl.h>
20 #include <stdarg.h>
21 #include <unistd.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <linux/fb.h>
26 #include <linux/vt.h>
27 #include <sys/ioctl.h>
28 #include <sys/mman.h>
29 #include <sys/shm.h>
30
31 #include "dri_util.h"
32
33 /**
34 * \brief Print message to \c stderr if the \c LIBGL_DEBUG environment variable
35 * is set.
36 *
37 * Is called from the drivers.
38 *
39 * \param f \e printf like format.
40 *
41 * \internal
42 * This function is a wrapper around vfprintf().
43 */
44 void
45 __driUtilMessage(const char *f, ...)
46 {
47 va_list args;
48
49 if (getenv("LIBGL_DEBUG")) {
50 fprintf(stderr, "libGL error: \n");
51 va_start(args, f);
52 vfprintf(stderr, f, args);
53 va_end(args);
54 fprintf(stderr, "\n");
55 }
56 }
57
58
59 /*****************************************************************/
60 /** \name Visual utility functions */
61 /*****************************************************************/
62 /*@{*/
63
64
65 /*@}*/
66
67
68 /*****************************************************************/
69 /** \name Context (un)binding functions */
70 /*****************************************************************/
71 /*@{*/
72
73
74 /**
75 * \brief Unbind context.
76 *
77 * \param drawable __DRIdrawable
78 * \param context __DRIcontext
79 * \param will_rebind not used.
80 *
81 * \return GL_TRUE on success, or GL_FALSE on failure.
82 *
83 * \internal
84 * This function calls __DriverAPIRec::UnbindContext, and then decrements
85 * __DRIdrawablePrivateRec::refcount which must be non-zero for a successful
86 * return.
87 *
88 * While casting the opaque private pointers associated with the parameters into their
89 * respective real types it also assures they are not null.
90 */
91 static GLboolean driUnbindContext(__DRIdrawable *drawable,
92 __DRIcontext *context)
93 {
94 __DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *)drawable;
95 __DRIcontextPrivate *pcp = (__DRIcontextPrivate *)context;
96 __DRIscreenPrivate *psp;
97
98 if (pdp == NULL || pcp == NULL)
99 return GL_FALSE;
100
101 if (!(psp = (__DRIscreenPrivate *)pdp->driScreenPriv))
102 return GL_FALSE;
103
104 /* Let driver unbind drawable from context */
105 (*psp->DriverAPI.UnbindContext)(pcp);
106
107 if (pdp->refcount == 0)
108 return GL_FALSE;
109
110 --pdp->refcount;
111
112 return GL_TRUE;
113 }
114
115
116 /**
117 * \brief Unbind context.
118 *
119 * \param pDRIScreen __DRIscreen
120 * \param drawable __DRIdrawable
121 * \param context __DRIcontext
122 *
123 * \internal
124 * This function and increments __DRIdrawablePrivateRec::refcount and calls
125 * __DriverAPIRec::MakeCurrent to binds the drawable.
126 *
127 * While casting the opaque private pointers into their
128 * respective real types it also assures they are not null.
129 */
130 static GLboolean driBindContext(__DRIscreen *screen, __DRIdrawable *drawable,
131 __DRIcontext *context)
132 {
133 __DRIscreenPrivate *psp = (__DRIscreenPrivate *)screen;
134 __DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *)drawable;
135 __DRIcontextPrivate *pcp = (__DRIcontextPrivate *)context;
136
137 if (psp == NULL)
138 return GL_FALSE;
139
140 if (pdp == NULL || pcp == NULL) {
141 (*psp->DriverAPI.MakeCurrent)(0, 0, 0);
142 return GL_TRUE;
143 }
144
145 /* Bind the drawable to the context */
146 pcp->driDrawablePriv = pdp;
147 pdp->driContextPriv = pcp;
148 pdp->refcount++;
149
150 /* Call device-specific MakeCurrent */
151 (*psp->DriverAPI.MakeCurrent)(pcp, pdp, pdp);
152
153 return GL_TRUE;
154 }
155
156 /*@}*/
157
158
159 /*****************************************************************/
160 /** \name Drawable handling functions */
161 /*****************************************************************/
162 /*@{*/
163
164
165 /**
166 * \brief Update private drawable information.
167 *
168 * \param pdp pointer to the private drawable information to update.
169 *
170 * \internal
171 * This function is a no-op. Should never be called but is referenced as an
172 * external symbol from client drivers.
173 */
174 void __driUtilUpdateDrawableInfo(__DRIdrawablePrivate *pdp)
175 {
176 __DRIscreenPrivate *psp = pdp->driScreenPriv;
177
178 pdp->numClipRects = psp->pSAREA->drawableTable[pdp->index].flags ? 1 : 0;
179 pdp->lastStamp = *(pdp->pStamp);
180 }
181
182
183 /**
184 * \brief Swap buffers.
185 *
186 * \param pDRIscreen __DRIscreen
187 * \param drawablePrivate opaque pointer to the per-drawable private info.
188 *
189 * \internal
190 * This function calls __DRIdrawablePrivate::swapBuffers.
191 *
192 * Is called directly from glXSwapBuffers().
193 */
194 static void driSwapBuffers(__DRIdrawable *drawable)
195 {
196 __DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *)drawable;
197 if (pdp)
198 pdp->swapBuffers(pdp);
199 }
200
201
202 /**
203 * \brief Destroy per-drawable private information.
204 *
205 * \param pDRIscreen __DRIscreen
206 * \param drawablePrivate opaque pointer to the per-drawable private info.
207 *
208 * \internal
209 * This function calls __DriverAPIRec::DestroyBuffer on \p drawablePrivate,
210 * frees the clip rects if any, and finally frees \p drawablePrivate itself.
211 */
212 static void driDestroyDrawable(__DRIdrawable *drawable)
213 {
214 __DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *)drawable;
215 __DRIscreenPrivate *psp;
216
217 if (pdp) {
218 psp = pdp->driScreenPriv;
219 (*psp->DriverAPI.DestroyBuffer)(pdp);
220 if (pdp->pClipRects)
221 free(pdp->pClipRects);
222 free(pdp);
223 }
224 }
225
226
227 /**
228 * \brief Create the per-drawable private driver information.
229 *
230 * \param dpy the display handle.
231 * \param scrn the screen number.
232 * \param draw the GLX drawable info.
233 * \param vid visual ID.
234 * \param pdraw will receive the drawable dependent methods.
235 *
236 *
237 * \returns a opaque pointer to the per-drawable private info on success, or NULL
238 * on failure.
239 *
240 * \internal
241 * This function allocates and fills a __DRIdrawablePrivateRec structure,
242 * initializing the invariant window dimensions and clip rects. It obtains the
243 * visual config, converts it into a __GLcontextModesRec and passes it to
244 * __DriverAPIRec::CreateBuffer to create a buffer.
245 */
246 static void *driCreateDrawable(__DRIscreen *screen,
247 int width, int height, int index,
248 const __GLcontextModes *glVisual)
249 {
250 __DRIscreenPrivate *psp = (__DRIscreenPrivate *)screen;
251 __DRIdrawablePrivate *pdp;
252
253 if (!psp)
254 return NULL;
255
256 if (!(pdp = (__DRIdrawablePrivate *)malloc(sizeof(__DRIdrawablePrivate))))
257 return NULL;
258
259 pdp->index = index;
260 pdp->refcount = 0;
261 pdp->lastStamp = -1;
262 pdp->numBackClipRects = 0;
263 pdp->pBackClipRects = NULL;
264
265 /* Initialize with the invariant window dimensions and clip rects here.
266 */
267 pdp->x = 0;
268 pdp->y = 0;
269 pdp->w = width;
270 pdp->h = height;
271 pdp->numClipRects = 0;
272 pdp->pClipRects = (drm_clip_rect_t *) malloc(sizeof(drm_clip_rect_t));
273 (pdp->pClipRects)[0].x1 = 0;
274 (pdp->pClipRects)[0].y1 = 0;
275 (pdp->pClipRects)[0].x2 = width;
276 (pdp->pClipRects)[0].y2 = height;
277
278 pdp->driScreenPriv = psp;
279 pdp->driContextPriv = 0;
280
281 pdp->frontBuffer = psp->pFB;
282 pdp->currentBuffer = pdp->frontBuffer;
283 pdp->currentPitch = psp->fbStride;
284 pdp->backBuffer = psp->pFB + psp->fbStride * psp->fbHeight;
285
286 if (!(*psp->DriverAPI.CreateBuffer)(psp, pdp, glVisual, GL_FALSE)) {
287 free(pdp);
288 return NULL;
289 }
290
291 pdp->entry.destroyDrawable = driDestroyDrawable;
292 pdp->entry.swapBuffers = driSwapBuffers; /* called by glXSwapBuffers() */
293 pdp->swapBuffers = psp->DriverAPI.SwapBuffers;
294
295 pdp->pStamp = &(psp->pSAREA->drawableTable[pdp->index].stamp);
296 return (void *) pdp;
297 }
298
299 /*@}*/
300
301
302 /*****************************************************************/
303 /** \name Context handling functions */
304 /*****************************************************************/
305 /*@{*/
306
307
308 /**
309 * \brief Destroy the per-context private information.
310 *
311 * \param contextPrivate opaque pointer to the per-drawable private info.
312 *
313 * \internal
314 * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls
315 * drmDestroyContext(), and finally frees \p contextPrivate.
316 */
317 static void driDestroyContext(__DRIcontext *context)
318 {
319 __DRIcontextPrivate *pcp = (__DRIcontextPrivate *)context;
320 __DRIscreenPrivate *psp = NULL;
321
322 if (pcp) {
323 (*pcp->driScreenPriv->DriverAPI.DestroyContext)(pcp);
324 psp = pcp->driDrawablePriv->driScreenPriv;
325 if (psp->fd) {
326 printf(">>> drmDestroyContext(0x%x)\n", (int) pcp->hHWContext);
327 drmDestroyContext(psp->fd, pcp->hHWContext);
328 }
329 free(pcp);
330 }
331 }
332
333 /**
334 * \brief Create the per-drawable private driver information.
335 *
336 * \param dpy the display handle.
337 * \param vis the visual information.
338 * \param sharedPrivate the shared context dependent methods or NULL if non-existent.
339 * \param pctx will receive the context dependent methods.
340 *
341 * \returns a opaque pointer to the per-context private information on success, or NULL
342 * on failure.
343 *
344 * \internal
345 * This function allocates and fills a __DRIcontextPrivateRec structure. It
346 * gets the visual, converts it into a __GLcontextModesRec and passes it
347 * to __DriverAPIRec::CreateContext to create the context.
348 */
349 static void *driCreateContext(__DRIscreen *screen,
350 const __GLcontextModes *glVisual,
351 void *sharedPrivate)
352 {
353 __DRIscreenPrivate *psp = (__DRIscreenPrivate *)screen;
354 __DRIcontextPrivate *pcp;
355 __DRIcontextPrivate *pshare = (__DRIcontextPrivate *) sharedPrivate;
356 void *shareCtx;
357
358 if (!psp)
359 return NULL;
360
361 if (!(pcp = (__DRIcontextPrivate *)malloc(sizeof(__DRIcontextPrivate))))
362 return NULL;
363
364 pcp->driScreenPriv = psp;
365 pcp->driDrawablePriv = NULL;
366
367 if (psp->fd) {
368 if (drmCreateContext(psp->fd, &pcp->hHWContext)) {
369 fprintf(stderr, ">>> drmCreateContext failed\n");
370 free(pcp);
371 return NULL;
372 }
373 }
374
375 shareCtx = pshare ? pshare->driverPrivate : NULL;
376
377 if (!(*psp->DriverAPI.CreateContext)(glVisual, pcp, shareCtx)) {
378 if (psp->fd)
379 (void) drmDestroyContext(psp->fd, pcp->hHWContext);
380 free(pcp);
381 return NULL;
382 }
383
384 pcp->entry.destroyContext = driDestroyContext;
385 pcp->entry.bindContext = driBindContext;
386 pcp->entry.unbindContext = driUnbindContext;
387
388 return pcp;
389 }
390
391 /*@}*/
392
393
394 /*****************************************************************/
395 /** \name Screen handling functions */
396 /*****************************************************************/
397 /*@{*/
398
399
400 /**
401 * \brief Destroy the per-screen private information.
402 *
403 * \param pDRIscreen __DRIscreen
404 *
405 * \internal
406 * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls
407 * drmClose(), and finally frees \p screenPrivate.
408 */
409 static void driDestroyScreen(__DRIscreen *screen)
410 {
411 __DRIscreenPrivate *psp = (__DRIscreenPrivate *)screen;
412 if (psp) {
413 if (psp->DriverAPI.DestroyScreen)
414 (*psp->DriverAPI.DestroyScreen)(psp);
415
416 if (psp->fd)
417 (void)drmClose(psp->fd);
418
419 free(psp->pDevPriv);
420 free(psp);
421 }
422 }
423
424
425 /**
426 * \brief Create the per-screen private information.
427 *
428 * \param dpy the display handle.
429 * \param scrn the screen number.
430 * \param psc will receive the screen dependent methods.
431 * \param numConfigs number of visuals.
432 * \param config visuals.
433 * \param driverAPI driver callbacks structure.
434 *
435 * \return a pointer to the per-screen private information.
436 *
437 * \internal
438 * This function allocates and fills a __DRIscreenPrivateRec structure. It
439 * opens the DRM device verifying that the exported version matches the
440 * expected. It copies the driver callback functions and calls
441 * __DriverAPIRec::InitDriver.
442 *
443 * If a client maps the framebuffer and SAREA regions.
444 */
445 __DRIscreenPrivate *
446 __driUtilCreateScreen(struct DRIDriverRec *driver,
447 struct DRIDriverContextRec *driverContext,
448 const struct __DriverAPIRec *driverAPI)
449 {
450 __DRIscreenPrivate *psp;
451
452 if(!(psp = (__DRIscreenPrivate *)malloc(sizeof(__DRIscreenPrivate))))
453 return NULL;
454
455 psp->fd = drmOpen(NULL, driverContext->pciBusID);
456 if (psp->fd < 0) {
457 fprintf(stderr, "libGL error: failed to open DRM: %s\n",
458 strerror(-psp->fd));
459 free(psp);
460 return NULL;
461 }
462
463 {
464 drmVersionPtr version = drmGetVersion(psp->fd);
465 if (version) {
466 psp->drmMajor = version->version_major;
467 psp->drmMinor = version->version_minor;
468 psp->drmPatch = version->version_patchlevel;
469 drmFreeVersion(version);
470 }
471 else {
472 fprintf(stderr, "libGL error: failed to get drm version: %s\n",
473 strerror(-psp->fd));
474 free(psp);
475 return NULL;
476 }
477 }
478
479 /* install driver's callback functions */
480 psp->DriverAPI = *driverAPI;
481
482 /*
483 * Get device-specific info. pDevPriv will point to a struct
484 * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h)
485 * that has information about the screen size, depth, pitch,
486 * ancilliary buffers, DRM mmap handles, etc.
487 */
488 psp->fbOrigin = driverContext->shared.fbOrigin;
489 psp->fbSize = driverContext->shared.fbSize;
490 psp->fbStride = driverContext->shared.fbStride;
491 psp->devPrivSize = driverContext->driverClientMsgSize;
492 psp->pDevPriv = driverContext->driverClientMsg;
493 psp->fbWidth = driverContext->shared.virtualWidth;
494 psp->fbHeight = driverContext->shared.virtualHeight;
495 psp->fbBPP = driverContext->bpp;
496
497 if ((driverContext->FBAddress != NULL) && (driverContext->pSAREA != NULL)) {
498 /* Already mapped in server */
499 psp->pFB = driverContext->FBAddress;
500 psp->pSAREA = driverContext->pSAREA;
501 } else {
502 /*
503 * Map the framebuffer region.
504 */
505 if (drmMap(psp->fd, driverContext->shared.hFrameBuffer, psp->fbSize,
506 (drmAddressPtr)&psp->pFB)) {
507 fprintf(stderr, "libGL error: drmMap of framebuffer failed\n");
508 (void)drmClose(psp->fd);
509 free(psp);
510 return NULL;
511 }
512
513 /*
514 * Map the SAREA region. Further mmap regions may be setup in
515 * each DRI driver's "createScreen" function.
516 */
517 if (drmMap(psp->fd, driverContext->shared.hSAREA,
518 driverContext->shared.SAREASize,
519 (drmAddressPtr)&psp->pSAREA)) {
520 fprintf(stderr, "libGL error: drmMap of sarea failed\n");
521 (void)drmUnmap((drmAddress)psp->pFB, psp->fbSize);
522 (void)drmClose(psp->fd);
523 free(psp);
524 return NULL;
525 }
526
527 #ifdef _EMBEDDED
528 mprotect(psp->pSAREA, driverContext->shared.SAREASize, PROT_READ);
529 #endif
530 }
531
532
533 /* Initialize the screen specific GLX driver */
534 if (psp->DriverAPI.InitDriver) {
535 if (!(*psp->DriverAPI.InitDriver)(psp)) {
536 fprintf(stderr, "libGL error: InitDriver failed\n");
537 free(psp->pDevPriv);
538 (void)drmClose(psp->fd);
539 free(psp);
540 return NULL;
541 }
542 }
543
544 psp->entry.destroyScreen = driDestroyScreen;
545 psp->entry.createContext = driCreateContext;
546 psp->entry.createDrawable = driCreateDrawable;
547
548 return psp;
549 }
550
551
552
553 /**
554 * \brief Create the per-screen private information.
555 *
556 * Version for drivers without a DRM module.
557 *
558 * \param dpy the display handle.
559 * \param scrn the screen number.
560 * \param numConfigs number of visuals.
561 * \param config visuals.
562 * \param driverAPI driver callbacks structure.
563 *
564 * \internal
565 * Same as __driUtilCreateScreen() but without opening the DRM device.
566 */
567 __DRIscreenPrivate *
568 __driUtilCreateScreenNoDRM(struct DRIDriverRec *driver,
569 struct DRIDriverContextRec *driverContext,
570 const struct __DriverAPIRec *driverAPI)
571 {
572 __DRIscreenPrivate *psp;
573
574 psp = (__DRIscreenPrivate *)calloc(1, sizeof(__DRIscreenPrivate));
575 if (!psp)
576 return NULL;
577
578 psp->ddxMajor = 4;
579 psp->ddxMinor = 0;
580 psp->ddxPatch = 1;
581 psp->driMajor = 4;
582 psp->driMinor = 1;
583 psp->driPatch = 0;
584 psp->fd = 0;
585
586 psp->fbOrigin = driverContext->shared.fbOrigin;
587 psp->fbSize = driverContext->shared.fbSize;
588 psp->fbStride = driverContext->shared.fbStride;
589 psp->devPrivSize = driverContext->driverClientMsgSize;
590 psp->pDevPriv = driverContext->driverClientMsg;
591 psp->fbWidth = driverContext->shared.virtualWidth;
592 psp->fbHeight = driverContext->shared.virtualHeight;
593 psp->fbBPP = driverContext->bpp;
594
595 psp->pFB = driverContext->FBAddress;
596
597 /* install driver's callback functions */
598 psp->DriverAPI = *driverAPI;
599
600 if ((driverContext->FBAddress != NULL) && (driverContext->pSAREA != NULL)) {
601 /* Already mapped in server */
602 psp->pFB = driverContext->FBAddress;
603 psp->pSAREA = driverContext->pSAREA;
604 } else {
605 psp->fd = open("/dev/mem", O_RDWR, 0);
606 /*
607 * Map the framebuffer region.
608 */
609 if (drmMap(psp->fd, driverContext->shared.hFrameBuffer, psp->fbSize,
610 (drmAddressPtr)&psp->pFB)) {
611 fprintf(stderr, "libGL error: drmMap of framebuffer failed\n");
612 (void)drmClose(psp->fd);
613 free(psp);
614 return NULL;
615 }
616 driverContext->FBAddress = psp->pFB;
617
618 /*
619 * Map the SAREA region. Non-DRM drivers use a shmem SAREA
620 */
621 int id;
622 id = shmget(driverContext->shared.hSAREA, driverContext->shared.SAREASize, 0);
623 driverContext->pSAREA = shmat(id, NULL, 0);
624 if (!driverContext->pSAREA) {
625 fprintf(stderr, "libGL error: shmget of sarea failed\n");
626 (void)drmUnmap((drmAddress)psp->pFB, psp->fbSize);
627 (void)drmClose(psp->fd);
628 free(psp);
629 return NULL;
630 }
631
632 close(psp->fd);
633 psp->fd = 0;
634 }
635
636 /* Initialize the screen specific GLX driver */
637 if (psp->DriverAPI.InitDriver) {
638 if (!(*psp->DriverAPI.InitDriver)(psp)) {
639 fprintf(stderr, "libGL error: InitDriver failed\n");
640 free(psp->pDevPriv);
641 free(psp);
642 return NULL;
643 }
644 }
645
646 psp->entry.destroyScreen = driDestroyScreen;
647 psp->entry.createContext = driCreateContext;
648 psp->entry.createDrawable = driCreateDrawable;
649
650 return psp;
651 }
652
653 /**
654 * Calculate amount of swap interval used between GLX buffer swaps.
655 *
656 * The usage value, on the range [0,max], is the fraction of total swap
657 * interval time used between GLX buffer swaps is calculated.
658 *
659 * \f$p = t_d / (i * t_r)\f$
660 *
661 * Where \f$t_d\$f is the time since the last GLX buffer swap, \f$i\f$ is the
662 * swap interval (as set by \c glXSwapIntervalSGI), and \f$t_r\f$ time
663 * required for a single vertical refresh period (as returned by \c
664 * glXGetMscRateOML).
665 *
666 * See the documentation for the GLX_MESA_swap_frame_usage extension for more
667 * details.
668 *
669 * \param dPriv Pointer to the private drawable structure.
670 * \return If less than a single swap interval time period was required
671 * between GLX buffer swaps, a number greater than 0 and less than
672 * 1.0 is returned. If exactly one swap interval time period is
673 * required, 1.0 is returned, and if more than one is required then
674 * a number greater than 1.0 will be returned.
675 *
676 * \sa glXSwapIntervalSGI(), glXGetMscRateOML().
677 */
678 float
679 driCalculateSwapUsage( __DRIdrawablePrivate *dPriv, int64_t last_swap_ust,
680 int64_t current_ust )
681 {
682 return 0.0f;
683 }
684
685 /**
686 * Compare the current GLX API version with a driver supplied required version.
687 *
688 * The minimum required version is compared with the API version exported by
689 * the \c __glXGetInternalVersion function (in libGL.so).
690 *
691 * \param required_version Minimum required internal GLX API version.
692 * \return A tri-value return, as from strcmp is returned. A value less
693 * than, equal to, or greater than zero will be returned if the
694 * internal GLX API version is less than, equal to, or greater
695 * than \c required_version.
696 *
697 * \sa __glXGetInternalVersion().
698 */
699 int driCompareGLXAPIVersion( GLuint required_version )
700 {
701 return 0;
702 }
703
704 /*@}*/