3 * \brief Mini GLX interface functions.
6 * The Mini GLX interface is a subset of the GLX interface, plus a
7 * minimal set of Xlib functions.
11 * Mesa 3-D graphics library
14 * Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
16 * Permission is hereby granted, free of charge, to any person obtaining a
17 * copy of this software and associated documentation files (the "Software"),
18 * to deal in the Software without restriction, including without limitation
19 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
20 * and/or sell copies of the Software, and to permit persons to whom the
21 * Software is furnished to do so, subject to the following conditions:
23 * The above copyright notice and this permission notice shall be included
24 * in all copies or substantial portions of the Software.
26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
27 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
29 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
30 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38 * \section miniglxIntro Introduction
40 * The Mini GLX interface facilitates OpenGL rendering on embedded devices. The
41 * interface is a subset of the GLX interface, plus a minimal set of Xlib-like
44 * Programs written to the Mini GLX specification should run unchanged
45 * on systems with the X Window System and the GLX extension (after
46 * recompilation). The intention is to allow flexibility for
47 * prototyping and testing.
49 * The files in the src/miniglx/ directory are compiled to build the
50 * libGL.so library. This is the library which applications link with.
51 * libGL.so in turn, loads the hardware-specific device driver.
54 * \section miniglxDoxygen About Doxygen
56 * For a list of all files, select <b>File List</b>. Choose a file from
57 * the list for a list of all functions in the file.
59 * For a list of all functions, types, constants, etc.
60 * select <b>File Members</b>.
63 * \section miniglxReferences References
65 * - <A HREF="file:../../docs/MiniGLX.html">Mini GLX Specification</A>,
66 * Tungsten Graphics, Inc.
67 * - OpenGL Graphics with the X Window System, Silicon Graphics, Inc.,
68 * ftp://ftp.sgi.com/opengl/doc/opengl1.2/glx1.3.ps
69 * - Xlib - C Language X Interface, X Consortium Standard, X Version 11,
70 * Release 6.4, ftp://ftp.x.org/pub/R6.4/xc/doc/hardcopy/X11/xlib.PS.gz
71 * - XFree86 Man pages, The XFree86 Project, Inc.,
72 * http://www.xfree86.org/current/manindex3.html
77 * \page datatypes Notes on the XVisualInfo, Visual, and __GLXvisualConfig data types
79 * -# X (unfortunately) has two (or three) data types which
80 * describe visuals. Ideally, there would just be one.
81 * -# We need the #__GLXvisualConfig type to augment #XVisualInfo and #Visual
82 * because we need to describe the GLX-specific attributes of visuals.
83 * -# In this interface there is a one-to-one-to-one correspondence between
84 * the three types and they're all interconnected.
85 * -# The #XVisualInfo type has a pointer to a #Visual. The #Visual structure
86 * (aka MiniGLXVisualRec) has a pointer to the #__GLXvisualConfig. The
87 * #Visual structure also has a pointer pointing back to the #XVisualInfo.
88 * -# The #XVisualInfo structure is the only one who's contents are public.
89 * -# The glXChooseVisual() and XGetVisualInfo() are the only functions that
90 * return #XVisualInfo structures. They can be freed with XFree(), though
91 * there is a small memory leak.
104 #include <sys/ioctl.h>
105 #include <sys/mman.h>
106 #include <sys/types.h>
107 #include <sys/time.h> /* for gettimeofday */
108 #include <linux/kd.h>
109 #include <linux/vt.h>
111 #include "miniglxP.h"
112 #include "dri_util.h"
115 #include "glcontextmodes.h"
118 #include "pciaccess.h"
120 static GLboolean
__glXCreateContextWithConfig(__DRInativeDisplay
*dpy
,
121 int screen
, int fbconfigID
, void *contextID
,
122 drm_context_t
*hHWContext
);
124 static GLboolean
__glXGetDrawableInfo(__DRInativeDisplay
*dpy
, int scrn
,
125 __DRIid draw
, unsigned int * index
, unsigned int * stamp
,
126 int * x
, int * y
, int * width
, int * height
,
127 int * numClipRects
, drm_clip_rect_t
** pClipRects
,
128 int * backX
, int * backY
,
129 int * numBackClipRects
, drm_clip_rect_t
** pBackClipRects
);
131 static __DRIscreen
* __glXFindDRIScreen(__DRInativeDisplay
*dpy
, int scrn
);
133 static GLboolean
__glXWindowExists(__DRInativeDisplay
*dpy
, __DRIid draw
);
135 static int __glXGetUST( int64_t * ust
);
137 static GLboolean
__glXGetMscRate(__DRInativeDisplay
* dpy
, __DRIid drawable
,
138 int32_t * numerator
, int32_t * denominator
);
140 static GLboolean
xf86DRI_DestroyContext(__DRInativeDisplay
*dpy
, int screen
,
141 __DRIid context_id
);
143 static GLboolean
xf86DRI_CreateDrawable(__DRInativeDisplay
*dpy
, int screen
,
144 __DRIid drawable
, drm_drawable_t
*hHWDrawable
);
146 static GLboolean
xf86DRI_DestroyDrawable(__DRInativeDisplay
*dpy
, int screen
,
150 /** Wrapper around either malloc() */
152 _mesa_malloc(size_t bytes
)
154 return malloc(bytes
);
157 /** Wrapper around either calloc() */
159 _mesa_calloc(size_t bytes
)
161 return calloc(1, bytes
);
164 /** Wrapper around either free() */
166 _mesa_free(void *ptr
)
173 * \brief Current GLX context.
175 * \sa glXGetCurrentContext().
177 static GLXContext CurrentContext
= NULL
;
181 static Display
*SignalDisplay
= 0;
183 static void SwitchVT(int sig
)
185 fprintf(stderr
, "SwitchVT %d dpy %p\n", sig
, SignalDisplay
);
188 SignalDisplay
->vtSignalFlag
= 1;
191 case SIGUSR1
: /* vt has been released */
192 SignalDisplay
->haveVT
= 0;
194 case SIGUSR2
: /* vt has been acquired */
195 SignalDisplay
->haveVT
= 1;
201 /**********************************************************************/
202 /** \name Framebuffer device functions */
203 /**********************************************************************/
207 * \brief Do the first part of setting up the framebuffer device.
209 * \param dpy the display handle.
210 * \param use_vt use a VT for display or not
212 * \return GL_TRUE on success, or GL_FALSE on failure.
214 * \sa This is called during XOpenDisplay().
217 * Gets the VT number, opens the respective console TTY device. Saves its state
218 * to restore when exiting and goes into graphics mode.
220 * Opens the framebuffer device and make a copy of the original variable screen
221 * information and gets the fixed screen information. Maps the framebuffer and
222 * MMIO region into the process address space.
225 OpenFBDev( Display
*dpy
, int use_vt
)
228 int fd
, vtnumber
, ttyfd
;
233 fprintf(stderr
, "error: you need to be root\n");
239 /* open /dev/tty0 and get the VT number */
240 if ((fd
= open("/dev/tty0", O_WRONLY
, 0)) < 0) {
241 fprintf(stderr
, "error opening /dev/tty0\n");
244 if (ioctl(fd
, VT_OPENQRY
, &vtnumber
) < 0 || vtnumber
< 0) {
245 fprintf(stderr
, "error: couldn't get a free vt\n");
249 fprintf(stderr
, "*** got vt nr: %d\n", vtnumber
);
252 /* open the console tty */
253 sprintf(ttystr
, "/dev/tty%d", vtnumber
); /* /dev/tty1-64 */
254 dpy
->ConsoleFD
= open(ttystr
, O_RDWR
| O_NDELAY
, 0);
255 if (dpy
->ConsoleFD
< 0) {
256 fprintf(stderr
, "error couldn't open console fd\n");
260 /* save current vt number */
263 if (ioctl(dpy
->ConsoleFD
, VT_GETSTATE
, &vts
) == 0)
264 dpy
->OriginalVT
= vts
.v_active
;
267 /* disconnect from controlling tty */
268 ttyfd
= open("/dev/tty", O_RDWR
);
270 ioctl(ttyfd
, TIOCNOTTY
, 0);
274 /* some magic to restore the vt when we exit */
277 struct sigaction sig_tty
;
279 /* Set-up tty signal handler to catch the signal we request below */
281 memset( &sig_tty
, 0, sizeof( sig_tty
) );
282 sig_tty
.sa_handler
= SwitchVT
;
283 sigemptyset( &sig_tty
.sa_mask
);
284 if( sigaction( SIGUSR1
, &sig_tty
, &dpy
->OrigSigUsr1
) ||
285 sigaction( SIGUSR2
, &sig_tty
, &dpy
->OrigSigUsr2
) )
287 fprintf(stderr
, "error: can't set up signal handler (%s)",
294 vt
.mode
= VT_PROCESS
;
298 if (ioctl(dpy
->ConsoleFD
, VT_SETMODE
, &vt
) < 0) {
299 fprintf(stderr
, "error: ioctl(VT_SETMODE) failed: %s\n",
305 if (ioctl(dpy
->ConsoleFD
, VT_ACTIVATE
, vtnumber
) != 0)
306 printf("ioctl VT_ACTIVATE: %s\n", strerror(errno
));
307 if (ioctl(dpy
->ConsoleFD
, VT_WAITACTIVE
, vtnumber
) != 0)
308 printf("ioctl VT_WAITACTIVE: %s\n", strerror(errno
));
310 if (ioctl(dpy
->ConsoleFD
, VT_GETMODE
, &vt
) < 0) {
311 fprintf(stderr
, "error: ioctl VT_GETMODE: %s\n", strerror(errno
));
319 /* go into graphics mode */
320 if (ioctl(dpy
->ConsoleFD
, KDSETMODE
, KD_GRAPHICS
) < 0) {
321 fprintf(stderr
, "error: ioctl(KDSETMODE, KD_GRAPHICS) failed: %s\n",
327 /* open the framebuffer device */
328 dpy
->FrameBufferFD
= open(dpy
->fbdevDevice
, O_RDWR
);
329 if (dpy
->FrameBufferFD
< 0) {
330 fprintf(stderr
, "Error opening /dev/fb0: %s\n", strerror(errno
));
334 /* get the original variable screen info */
335 if (ioctl(dpy
->FrameBufferFD
, FBIOGET_VSCREENINFO
, &dpy
->OrigVarInfo
)) {
336 fprintf(stderr
, "error: ioctl(FBIOGET_VSCREENINFO) failed: %s\n",
342 dpy
->VarInfo
= dpy
->OrigVarInfo
; /* structure copy */
344 /* Turn off hw accels (otherwise mmap of mmio region will be
347 dpy
->VarInfo
.accel_flags
= 0;
348 if (ioctl(dpy
->FrameBufferFD
, FBIOPUT_VSCREENINFO
, &dpy
->VarInfo
)) {
349 fprintf(stderr
, "error: ioctl(FBIOPUT_VSCREENINFO) failed: %s\n",
356 /* Get the fixed screen info */
357 if (ioctl(dpy
->FrameBufferFD
, FBIOGET_FSCREENINFO
, &dpy
->FixedInfo
)) {
358 fprintf(stderr
, "error: ioctl(FBIOGET_FSCREENINFO) failed: %s\n",
365 /* mmap the framebuffer into our address space */
366 dpy
->driverContext
.FBStart
= dpy
->FixedInfo
.smem_start
;
367 dpy
->driverContext
.FBSize
= dpy
->FixedInfo
.smem_len
;
368 dpy
->driverContext
.shared
.fbSize
= dpy
->FixedInfo
.smem_len
;
369 dpy
->driverContext
.FBAddress
= (caddr_t
) mmap(0, /* start */
370 dpy
->driverContext
.shared
.fbSize
, /* bytes */
371 PROT_READ
| PROT_WRITE
, /* prot */
372 MAP_SHARED
, /* flags */
373 dpy
->FrameBufferFD
, /* fd */
375 if (dpy
->driverContext
.FBAddress
== (caddr_t
) - 1) {
376 fprintf(stderr
, "error: unable to mmap framebuffer: %s\n",
381 /* mmap the MMIO region into our address space */
382 dpy
->driverContext
.MMIOStart
= dpy
->FixedInfo
.mmio_start
;
383 dpy
->driverContext
.MMIOSize
= dpy
->FixedInfo
.mmio_len
;
384 dpy
->driverContext
.MMIOAddress
= (caddr_t
) mmap(0, /* start */
385 dpy
->driverContext
.MMIOSize
, /* bytes */
386 PROT_READ
| PROT_WRITE
, /* prot */
387 MAP_SHARED
, /* flags */
388 dpy
->FrameBufferFD
, /* fd */
389 dpy
->FixedInfo
.smem_len
/* offset */);
390 if (dpy
->driverContext
.MMIOAddress
== (caddr_t
) - 1) {
391 fprintf(stderr
, "error: unable to mmap mmio region: %s\n",
396 fprintf(stderr
, "got MMIOAddress %p offset %d\n",
397 dpy
->driverContext
.MMIOAddress
,
398 dpy
->FixedInfo
.smem_len
);
407 * \brief Setup up the desired framebuffer device mode.
409 * \param dpy the display handle.
411 * \return GL_TRUE on success, or GL_FALSE on failure.
413 * \sa This is called during __miniglx_StartServer().
417 * Bumps the size of the window the the next supported mode. Sets the
418 * variable screen information according to the desired mode and asks
419 * the driver to validate the mode. Certifies that a DirectColor or
420 * TrueColor visual is used from the updated fixed screen information.
421 * In the case of DirectColor visuals, sets up an 'identity' colormap to
422 * mimic a TrueColor visual.
424 * Calls the driver hooks 'ValidateMode' and 'PostValidateMode' to
425 * allow the driver to make modifications to the chosen mode according
426 * to hardware constraints, or to save and restore videocard registers
427 * that may be clobbered by the fbdev driver.
429 * \todo Timings are hard-coded in the source for a set of supported modes.
432 SetupFBDev( Display
*dpy
)
438 width
= dpy
->driverContext
.shared
.virtualWidth
;
439 height
= dpy
->driverContext
.shared
.virtualHeight
;
444 /* Bump size up to next supported mode.
446 if (width
<= 720 && height
<= 480) {
447 width
= 720; height
= 480;
449 else if (width
<= 960 && height
<= 540) {
450 width
= 960; height
= 540;
452 else if (width
<= 800 && height
<= 600) {
453 width
= 800; height
= 600;
455 else if (width
<= 1024 && height
<= 768) {
456 width
= 1024; height
= 768;
458 else if (width
<= 768 && height
<= 1024) {
459 width
= 768; height
= 1024;
461 else if (width
<= 1280 && height
<= 1024) {
462 width
= 1280; height
= 1024;
466 dpy
->driverContext
.shared
.fbStride
= width
* (dpy
->driverContext
.bpp
/ 8);
468 /* set the depth, resolution, etc */
469 dpy
->VarInfo
= dpy
->OrigVarInfo
;
470 dpy
->VarInfo
.bits_per_pixel
= dpy
->driverContext
.bpp
;
471 dpy
->VarInfo
.xres_virtual
= dpy
->driverContext
.shared
.virtualWidth
;
472 dpy
->VarInfo
.yres_virtual
= dpy
->driverContext
.shared
.virtualHeight
;
473 dpy
->VarInfo
.xres
= dpy
->driverContext
.shared
.Width
;
474 dpy
->VarInfo
.yres
= height
;
475 dpy
->VarInfo
.xoffset
= 0;
476 dpy
->VarInfo
.yoffset
= 0;
477 dpy
->VarInfo
.nonstd
= 0;
478 dpy
->VarInfo
.vmode
&= ~FB_VMODE_YWRAP
; /* turn off scrolling */
480 if (dpy
->VarInfo
.bits_per_pixel
== 32) {
481 dpy
->VarInfo
.red
.offset
= 16;
482 dpy
->VarInfo
.green
.offset
= 8;
483 dpy
->VarInfo
.blue
.offset
= 0;
484 dpy
->VarInfo
.transp
.offset
= 24;
485 dpy
->VarInfo
.red
.length
= 8;
486 dpy
->VarInfo
.green
.length
= 8;
487 dpy
->VarInfo
.blue
.length
= 8;
488 dpy
->VarInfo
.transp
.length
= 8;
490 else if (dpy
->VarInfo
.bits_per_pixel
== 16) {
491 dpy
->VarInfo
.red
.offset
= 11;
492 dpy
->VarInfo
.green
.offset
= 5;
493 dpy
->VarInfo
.blue
.offset
= 0;
494 dpy
->VarInfo
.red
.length
= 5;
495 dpy
->VarInfo
.green
.length
= 6;
496 dpy
->VarInfo
.blue
.length
= 5;
497 dpy
->VarInfo
.transp
.offset
= 0;
498 dpy
->VarInfo
.transp
.length
= 0;
501 fprintf(stderr
, "Only 32bpp and 16bpp modes supported at the moment\n");
505 if (!dpy
->driver
->validateMode( &dpy
->driverContext
)) {
506 fprintf(stderr
, "Driver validateMode() failed\n");
510 /* These should be calculated with the gtf.c program, and then we could
511 remove all this... AlanH. */
512 if (dpy
->VarInfo
.xres
== 1280 &&
513 dpy
->VarInfo
.yres
== 1024) {
514 /* timing values taken from /etc/fb.modes (1280x1024 @ 75Hz) */
515 dpy
->VarInfo
.pixclock
= 7408;
516 dpy
->VarInfo
.left_margin
= 248;
517 dpy
->VarInfo
.right_margin
= 16;
518 dpy
->VarInfo
.upper_margin
= 38;
519 dpy
->VarInfo
.lower_margin
= 1;
520 dpy
->VarInfo
.hsync_len
= 144;
521 dpy
->VarInfo
.vsync_len
= 3;
523 else if (dpy
->VarInfo
.xres
== 1024 &&
524 dpy
->VarInfo
.yres
== 768) {
525 /* timing values taken from /etc/fb.modes (1024x768 @ 75Hz) */
526 dpy
->VarInfo
.pixclock
= 12699;
527 dpy
->VarInfo
.left_margin
= 176;
528 dpy
->VarInfo
.right_margin
= 16;
529 dpy
->VarInfo
.upper_margin
= 28;
530 dpy
->VarInfo
.lower_margin
= 1;
531 dpy
->VarInfo
.hsync_len
= 96;
532 dpy
->VarInfo
.vsync_len
= 3;
534 else if (dpy
->VarInfo
.xres
== 800 &&
535 dpy
->VarInfo
.yres
== 600) {
536 /* timing values taken from /etc/fb.modes (800x600 @ 75Hz) */
537 dpy
->VarInfo
.pixclock
= 27778;
538 dpy
->VarInfo
.left_margin
= 128;
539 dpy
->VarInfo
.right_margin
= 24;
540 dpy
->VarInfo
.upper_margin
= 22;
541 dpy
->VarInfo
.lower_margin
= 1;
542 dpy
->VarInfo
.hsync_len
= 72;
543 dpy
->VarInfo
.vsync_len
= 2;
545 else if (dpy
->VarInfo
.xres
== 720 &&
546 dpy
->VarInfo
.yres
== 480) {
547 dpy
->VarInfo
.pixclock
= 37202;
548 dpy
->VarInfo
.left_margin
= 88;
549 dpy
->VarInfo
.right_margin
= 16;
550 dpy
->VarInfo
.upper_margin
= 14;
551 dpy
->VarInfo
.lower_margin
= 1;
552 dpy
->VarInfo
.hsync_len
= 72;
553 dpy
->VarInfo
.vsync_len
= 3;
555 else if (dpy
->VarInfo
.xres
== 960 &&
556 dpy
->VarInfo
.yres
== 540) {
557 dpy
->VarInfo
.pixclock
= 24273;
558 dpy
->VarInfo
.left_margin
= 128;
559 dpy
->VarInfo
.right_margin
= 32;
560 dpy
->VarInfo
.upper_margin
= 16;
561 dpy
->VarInfo
.lower_margin
= 1;
562 dpy
->VarInfo
.hsync_len
= 96;
563 dpy
->VarInfo
.vsync_len
= 3;
565 else if (dpy
->VarInfo
.xres
== 768 &&
566 dpy
->VarInfo
.yres
== 1024) {
567 /* timing values for 768x1024 @ 75Hz */
568 dpy
->VarInfo
.pixclock
= 11993;
569 dpy
->VarInfo
.left_margin
= 136;
570 dpy
->VarInfo
.right_margin
= 32;
571 dpy
->VarInfo
.upper_margin
= 41;
572 dpy
->VarInfo
.lower_margin
= 1;
573 dpy
->VarInfo
.hsync_len
= 80;
574 dpy
->VarInfo
.vsync_len
= 3;
577 /* XXX need timings for other screen sizes */
578 fprintf(stderr
, "XXXX screen size %d x %d not supported at this time!\n",
579 dpy
->VarInfo
.xres
, dpy
->VarInfo
.yres
);
583 fprintf(stderr
, "[miniglx] Setting mode: visible %dx%d virtual %dx%dx%d\n",
584 dpy
->VarInfo
.xres
, dpy
->VarInfo
.yres
,
585 dpy
->VarInfo
.xres_virtual
, dpy
->VarInfo
.yres_virtual
,
586 dpy
->VarInfo
.bits_per_pixel
);
588 /* set variable screen info */
589 if (ioctl(dpy
->FrameBufferFD
, FBIOPUT_VSCREENINFO
, &dpy
->VarInfo
)) {
590 fprintf(stderr
, "error: ioctl(FBIOPUT_VSCREENINFO) failed: %s\n",
595 /* get the variable screen info, in case it has been modified */
596 if (ioctl(dpy
->FrameBufferFD
, FBIOGET_VSCREENINFO
, &dpy
->VarInfo
)) {
597 fprintf(stderr
, "error: ioctl(FBIOGET_VSCREENINFO) failed: %s\n",
603 fprintf(stderr
, "[miniglx] Readback mode: visible %dx%d virtual %dx%dx%d\n",
604 dpy
->VarInfo
.xres
, dpy
->VarInfo
.yres
,
605 dpy
->VarInfo
.xres_virtual
, dpy
->VarInfo
.yres_virtual
,
606 dpy
->VarInfo
.bits_per_pixel
);
608 /* Get the fixed screen info */
609 if (ioctl(dpy
->FrameBufferFD
, FBIOGET_FSCREENINFO
, &dpy
->FixedInfo
)) {
610 fprintf(stderr
, "error: ioctl(FBIOGET_FSCREENINFO) failed: %s\n",
615 if (dpy
->FixedInfo
.visual
!= FB_VISUAL_TRUECOLOR
&&
616 dpy
->FixedInfo
.visual
!= FB_VISUAL_DIRECTCOLOR
) {
617 fprintf(stderr
, "non-TRUECOLOR visuals not supported.\n");
621 if (dpy
->FixedInfo
.visual
== FB_VISUAL_DIRECTCOLOR
) {
623 unsigned short red
[256], green
[256], blue
[256];
624 int rcols
= 1 << dpy
->VarInfo
.red
.length
;
625 int gcols
= 1 << dpy
->VarInfo
.green
.length
;
626 int bcols
= 1 << dpy
->VarInfo
.blue
.length
;
636 for (i
= 0; i
< rcols
; i
++)
637 red
[i
] = (65536/(rcols
-1)) * i
;
639 for (i
= 0; i
< gcols
; i
++)
640 green
[i
] = (65536/(gcols
-1)) * i
;
642 for (i
= 0; i
< bcols
; i
++)
643 blue
[i
] = (65536/(bcols
-1)) * i
;
645 if (ioctl(dpy
->FrameBufferFD
, FBIOPUTCMAP
, (void *) &cmap
) < 0) {
646 fprintf(stderr
, "ioctl(FBIOPUTCMAP) failed [%d]\n", i
);
651 /* May need to restore regs fbdev has clobbered:
653 if (!dpy
->driver
->postValidateMode( &dpy
->driverContext
)) {
654 fprintf(stderr
, "Driver postValidateMode() failed\n");
663 * \brief Restore the framebuffer device to state it was in before we started
665 * Undoes the work done by SetupFBDev().
667 * \param dpy the display handle.
669 * \return GL_TRUE on success, or GL_FALSE on failure.
671 * \sa Called from XDestroyWindow().
674 * Restores the original variable screen info.
677 RestoreFBDev( Display
*dpy
)
679 /* restore original variable screen info */
680 if (ioctl(dpy
->FrameBufferFD
, FBIOPUT_VSCREENINFO
, &dpy
->OrigVarInfo
)) {
681 fprintf(stderr
, "ioctl(FBIOPUT_VSCREENINFO failed): %s\n",
685 dpy
->VarInfo
= dpy
->OrigVarInfo
;
692 * \brief Close the framebuffer device.
694 * \param dpy the display handle.
696 * \sa Called from XCloseDisplay().
699 * Unmaps the framebuffer and MMIO region. Restores the text mode and the
700 * original virtual terminal. Closes the console and framebuffer devices.
703 CloseFBDev( Display
*dpy
)
707 munmap(dpy
->driverContext
.FBAddress
, dpy
->driverContext
.FBSize
);
708 munmap(dpy
->driverContext
.MMIOAddress
, dpy
->driverContext
.MMIOSize
);
710 if (dpy
->ConsoleFD
) {
711 /* restore text mode */
712 ioctl(dpy
->ConsoleFD
, KDSETMODE
, KD_TEXT
);
715 if (ioctl(dpy
->ConsoleFD
, VT_GETMODE
, &VT
) != -1) {
717 ioctl(dpy
->ConsoleFD
, VT_SETMODE
, &VT
);
720 /* restore original vt */
721 if (dpy
->OriginalVT
>= 0) {
722 ioctl(dpy
->ConsoleFD
, VT_ACTIVATE
, dpy
->OriginalVT
);
723 dpy
->OriginalVT
= -1;
726 close(dpy
->ConsoleFD
);
728 close(dpy
->FrameBufferFD
);
734 /**********************************************************************/
735 /** \name Misc functions needed for DRI drivers */
736 /**********************************************************************/
740 * \brief Find the DRI screen dependent methods associated with the display.
742 * \param dpy a display handle, as returned by XOpenDisplay().
743 * \param scrn the screen number. Not referenced.
745 * \returns a pointer to a __DRIscreenRec structure.
748 * Returns the MiniGLXDisplayRec::driScreen attribute.
751 __glXFindDRIScreen(__DRInativeDisplay
*dpy
, int scrn
)
754 return &((Display
*)dpy
)->driScreen
;
758 * \brief Validate a drawable.
760 * \param dpy a display handle, as returned by XOpenDisplay().
761 * \param draw drawable to validate.
764 * Since Mini GLX only supports one window, compares the specified drawable with
765 * the MiniGLXDisplayRec::TheWindow attribute.
768 __glXWindowExists(__DRInativeDisplay
*dpy
, __DRIid draw
)
770 const Display
* const display
= (Display
*)dpy
;
771 if (display
->TheWindow
== (Window
) draw
)
778 * \brief Get current thread ID.
786 _glthread_GetID(void)
795 * \brief Scan Linux /prog/bus/pci/devices file to determine hardware
796 * chipset based on supplied bus ID.
798 * \return probed chipset (non-zero) on success, zero otherwise.
802 static int get_chipset_from_busid( Display
*dpy
)
806 const char *fname
= "/proc/bus/pci/devices";
809 if (!(file
= fopen(fname
,"r"))) {
810 fprintf(stderr
, "couldn't open %s: %s\n", fname
, strerror(errno
));
814 while (fgets(buf
, sizeof(buf
)-1, file
)) {
815 unsigned int nr
, bus
, dev
, fn
, vendor
, device
, encode
;
816 nr
= sscanf(buf
, "%04x\t%04x%04x", &encode
,
820 dev
= (encode
& 0xFF) >> 3;
826 if (bus
== dpy
->driverContext
.pciBus
&&
827 dev
== dpy
->driverContext
.pciDevice
&&
828 fn
== dpy
->driverContext
.pciFunc
) {
837 fprintf(stderr
, "[miniglx] probed chipset 0x%x\n", retval
);
839 fprintf(stderr
, "[miniglx] failed to probe chipset\n");
846 * \brief Read settings from a configuration file.
848 * The configuration file is usually "/etc/miniglx.conf", but can be overridden
849 * with the MINIGLX_CONF environment variable.
851 * The format consists in \code option = value \endcode lines. The option names
852 * corresponds to the fields in MiniGLXDisplayRec.
854 * \param dpy the display handle as.
856 * \return non-zero on success, zero otherwise.
859 * Sets some defaults. Opens and parses the the Mini GLX configuration file and
860 * fills in the MiniGLXDisplayRec field that corresponds for each option.
862 static int __read_config_file( Display
*dpy
)
869 dpy
->fbdevDevice
= "/dev/fb0";
870 dpy
->clientDriverName
= "fb_dri.so";
871 dpy
->driverContext
.pciBus
= 0;
872 dpy
->driverContext
.pciDevice
= 0;
873 dpy
->driverContext
.pciFunc
= 0;
874 dpy
->driverContext
.chipset
= 0;
875 dpy
->driverContext
.pciBusID
= 0;
876 dpy
->driverContext
.shared
.virtualWidth
= 1280;
877 dpy
->driverContext
.shared
.virtualHeight
= 1024;
878 dpy
->driverContext
.bpp
= 32;
879 dpy
->driverContext
.cpp
= 4;
881 dpy
->driverContext
.agpmode
= 1;
882 dpy
->driverContext
.isPCI
= 0;
883 dpy
->driverContext
.colorTiling
= 0;
885 fname
= getenv("MINIGLX_CONF");
886 if (!fname
) fname
= "/etc/miniglx.conf";
888 file
= fopen(fname
, "r");
890 fprintf(stderr
, "couldn't open config file %s: %s\n", fname
, strerror(errno
));
895 while (!feof(file
)) {
896 char buf
[81], *opt
= buf
, *val
, *tmp1
, *tmp2
;
897 fgets(buf
, sizeof(buf
), file
);
899 /* Parse 'opt = val' -- must be easier ways to do this.
901 while (isspace(*opt
)) opt
++;
903 if (*val
== '#') continue; /* comment */
904 while (!isspace(*val
) && *val
!= '=' && *val
) val
++;
906 while (isspace(*val
)) val
++;
907 if (*val
!= '=') continue;
910 while (isspace(*val
)) val
++;
912 while (!isspace(*tmp2
) && *tmp2
!= '\n' && *tmp2
) tmp2
++;
916 if (strcmp(opt
, "fbdevDevice") == 0)
917 dpy
->fbdevDevice
= strdup(val
);
918 else if (strcmp(opt
, "clientDriverName") == 0)
919 dpy
->clientDriverName
= strdup(val
);
920 else if (strcmp(opt
, "rotateMode") == 0)
921 dpy
->rotateMode
= atoi(val
) ? 1 : 0;
922 else if (strcmp(opt
, "pciBusID") == 0) {
923 if (sscanf(val
, "PCI:%d:%d:%d",
924 &dpy
->driverContext
.pciBus
,
925 &dpy
->driverContext
.pciDevice
,
926 &dpy
->driverContext
.pciFunc
) != 3) {
927 fprintf(stderr
, "malformed bus id: %s\n", val
);
930 dpy
->driverContext
.pciBusID
= strdup(val
);
932 else if (strcmp(opt
, "chipset") == 0) {
933 if (sscanf(val
, "0x%x", &dpy
->driverContext
.chipset
) != 1)
934 fprintf(stderr
, "malformed chipset: %s\n", opt
);
936 else if (strcmp(opt
, "virtualWidth") == 0) {
937 if (sscanf(val
, "%d", &dpy
->driverContext
.shared
.virtualWidth
) != 1)
938 fprintf(stderr
, "malformed virtualWidth: %s\n", opt
);
940 else if (strcmp(opt
, "virtualHeight") == 0) {
941 if (sscanf(val
, "%d", &dpy
->driverContext
.shared
.virtualHeight
) != 1)
942 fprintf(stderr
, "malformed virutalHeight: %s\n", opt
);
944 else if (strcmp(opt
, "bpp") == 0) {
945 if (sscanf(val
, "%d", &dpy
->driverContext
.bpp
) != 1)
946 fprintf(stderr
, "malformed bpp: %s\n", opt
);
947 dpy
->driverContext
.cpp
= dpy
->driverContext
.bpp
/ 8;
949 else if (strcmp(opt
, "agpmode") == 0) {
950 if (sscanf(val
, "%d", &dpy
->driverContext
.agpmode
) != 1)
951 fprintf(stderr
, "malformed agpmode: %s\n", opt
);
953 else if (strcmp(opt
, "isPCI") == 0) {
954 dpy
->driverContext
.isPCI
= atoi(val
) ? 1 : 0;
956 else if (strcmp(opt
, "colorTiling") == 0) {
957 dpy
->driverContext
.colorTiling
= atoi(val
) ? 1 : 0;
963 if (dpy
->driverContext
.chipset
== 0 && dpy
->driverContext
.pciBusID
!= 0)
964 dpy
->driverContext
.chipset
= get_chipset_from_busid( dpy
);
970 * Versioned name of the expected \c __driCreateNewScreen function.
972 * The version of the last incompatible loader/driver inteface change is
973 * appended to the name of the \c __driCreateNewScreen function. This
974 * prevents loaders from trying to load drivers that are too old.
977 * Create a macro or something so that this is automatically updated.
979 static const char createNewScreenName
[] = "__driCreateNewScreen_20050727";
982 static int InitDriver( Display
*dpy
)
986 * We're kind of combining the per-display and per-screen information
987 * which was kept separate in XFree86/DRI's libGL.
989 dpy
->dlHandle
= dlopen(dpy
->clientDriverName
, RTLD_NOW
| RTLD_GLOBAL
);
990 if (!dpy
->dlHandle
) {
991 fprintf(stderr
, "Unable to open %s: %s\n", dpy
->clientDriverName
,
996 /* Pull in Mini GLX specific hooks:
998 dpy
->driver
= (struct DRIDriverRec
*) dlsym(dpy
->dlHandle
,
1001 fprintf(stderr
, "Couldn't find __driDriver in %s\n",
1002 dpy
->clientDriverName
);
1006 /* Pull in standard DRI client-side driver hooks:
1008 dpy
->createNewScreen
= (PFNCREATENEWSCREENFUNC
)
1009 dlsym(dpy
->dlHandle
, createNewScreenName
);
1010 if (!dpy
->createNewScreen
) {
1011 fprintf(stderr
, "Couldn't find %s in %s\n", createNewScreenName
,
1012 dpy
->clientDriverName
);
1019 if (dpy
->dlHandle
) {
1020 dlclose(dpy
->dlHandle
);
1027 /**********************************************************************/
1028 /** \name Public API functions (Xlib and GLX) */
1029 /**********************************************************************/
1034 * \brief Initialize the graphics system.
1036 * \param display_name currently ignored. It is recommended to pass it as NULL.
1037 * \return a pointer to a #Display if the function is able to initialize
1038 * the graphics system, NULL otherwise.
1040 * Allocates a MiniGLXDisplayRec structure and fills in with information from a
1041 * configuration file.
1043 * Calls OpenFBDev() to open the framebuffer device and calls
1044 * DRIDriverRec::initFBDev to do the client-side initialization on it.
1046 * Loads the DRI driver and pulls in Mini GLX specific hooks into a
1047 * DRIDriverRec structure, and the standard DRI \e __driCreateScreen hook.
1048 * Asks the driver for a list of supported visuals. Performs the per-screen
1049 * client-side initialization. Also setups the callbacks in the screen private
1052 * Does the framebuffer device setup. Calls __miniglx_open_connections() to
1056 __miniglx_StartServer( const char *display_name
)
1063 dpy
= (Display
*)calloc(1, sizeof(Display
));
1067 dpy
->IsClient
= False
;
1069 if (!__read_config_file( dpy
)) {
1070 fprintf(stderr
, "Couldn't get configuration details\n");
1075 /* Open the fbdev device
1077 if (!OpenFBDev(dpy
, use_vt
)) {
1078 fprintf(stderr
, "OpenFBDev failed\n");
1083 if (!InitDriver(dpy
)) {
1084 fprintf(stderr
, "InitDriver failed\n");
1089 /* Perform the initialization normally done in the X server
1091 if (!dpy
->driver
->initFBDev( &dpy
->driverContext
)) {
1092 fprintf(stderr
, "%s: __driInitFBDev failed\n", __FUNCTION__
);
1093 dlclose(dpy
->dlHandle
);
1099 if (!SetupFBDev(dpy
)) {
1100 fprintf(stderr
, "SetupFBDev failed\n");
1105 /* unlock here if not using VT -- JDS */
1107 if (dpy
->driver
->restoreHardware
)
1108 dpy
->driver
->restoreHardware( &dpy
->driverContext
);
1109 DRM_UNLOCK( dpy
->driverContext
.drmFD
,
1110 dpy
->driverContext
.pSAREA
,
1111 dpy
->driverContext
.serverContext
);
1115 /* Ready for clients:
1117 if (!__miniglx_open_connections(dpy
)) {
1127 * Implement \c __DRIinterfaceMethods::getProcAddress.
1129 static __DRIfuncPtr
get_proc_address( const char * proc_name
)
1137 * Table of functions exported by the loader to the driver.
1139 static const __DRIinterfaceMethods interface_methods
= {
1142 _gl_context_modes_create
,
1143 _gl_context_modes_destroy
,
1148 __glXCreateContextWithConfig
,
1149 xf86DRI_DestroyContext
,
1151 xf86DRI_CreateDrawable
,
1152 xf86DRI_DestroyDrawable
,
1153 __glXGetDrawableInfo
,
1161 CallCreateNewScreen(Display
*dpy
, int scrn
, __DRIscreen
*psc
)
1164 drm_handle_t hSAREA
;
1168 __DRIversion ddx_version
;
1169 __DRIversion dri_version
;
1170 __DRIversion drm_version
;
1171 __DRIframebuffer framebuffer
;
1174 const char * err_msg
;
1175 const char * err_extra
;
1176 drmVersionPtr version
;
1181 hSAREA
= dpy
->driverContext
.shared
.hSAREA
;
1182 BusID
= dpy
->driverContext
.pciBusID
;
1184 fd
= drmOpen(NULL
, BusID
);
1186 err_msg
= "open DRM";
1187 err_extra
= strerror( -fd
);
1189 if (fd
< 0) goto done
;
1191 err_msg
= "drmGetMagic";
1194 if (drmGetMagic(fd
, &magic
)) goto done
;
1196 dpy
->authorized
= False
;
1197 send_char_msg( dpy
, 0, _Authorize
);
1198 send_msg( dpy
, 0, &magic
, sizeof(magic
));
1200 /* force net buffer flush */
1201 while (!dpy
->authorized
)
1202 handle_fd_events( dpy
, 0 );
1204 version
= drmGetVersion(fd
);
1206 drm_version
.major
= version
->version_major
;
1207 drm_version
.minor
= version
->version_minor
;
1208 drm_version
.patch
= version
->version_patchlevel
;
1209 drmFreeVersion(version
);
1212 drm_version
.major
= -1;
1213 drm_version
.minor
= -1;
1214 drm_version
.patch
= -1;
1218 * Get device name (like "tdfx") and the ddx version numbers.
1219 * We'll check the version in each DRI driver's "createScreen"
1222 ddx_version
.major
= -1;
1223 ddx_version
.minor
= 0;
1224 ddx_version
.patch
= 0;
1227 * Get the DRI X extension version.
1229 dri_version
.major
= 4;
1230 dri_version
.minor
= 0;
1231 dri_version
.patch
= 0;
1234 * Get device-specific info. pDevPriv will point to a struct
1235 * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h)
1236 * that has information about the screen size, depth, pitch,
1237 * ancilliary buffers, DRM mmap handles, etc.
1239 hFB
= dpy
->driverContext
.shared
.hFrameBuffer
;
1240 framebuffer
.size
= dpy
->driverContext
.shared
.fbSize
;
1241 framebuffer
.stride
= dpy
->driverContext
.shared
.fbStride
;
1242 framebuffer
.dev_priv_size
= dpy
->driverContext
.driverClientMsgSize
;
1243 framebuffer
.dev_priv
= dpy
->driverContext
.driverClientMsg
;
1244 framebuffer
.width
= dpy
->driverContext
.shared
.virtualWidth
;
1245 framebuffer
.height
= dpy
->driverContext
.shared
.virtualHeight
;
1248 * Map the framebuffer region.
1250 status
= drmMap(fd
, hFB
, framebuffer
.size
,
1251 (drmAddressPtr
)&framebuffer
.base
);
1253 err_msg
= "drmMap of framebuffer";
1254 err_extra
= strerror( -status
);
1256 if ( status
!= 0 ) goto done
;
1259 * Map the SAREA region. Further mmap regions may be setup in
1260 * each DRI driver's "createScreen" function.
1262 status
= drmMap(fd
, hSAREA
, SAREA_MAX
, &pSAREA
);
1264 err_msg
= "drmMap of sarea";
1265 err_extra
= strerror( -status
);
1267 if ( status
== 0 ) {
1268 err_msg
= "InitDriver";
1270 psp
= dpy
->createNewScreen(dpy
, scrn
, psc
, NULL
,
1278 & interface_methods
,
1279 (__GLcontextModes
**) &dpy
->driver_modes
);
1281 /* fill in dummy visual ids */
1283 __GLcontextModes
*temp
;
1284 temp
= (__GLcontextModes
*)dpy
->driver_modes
;
1288 temp
->visualID
= i
++;
1295 if ( psp
== NULL
) {
1296 if ( pSAREA
!= MAP_FAILED
) {
1297 (void)drmUnmap(pSAREA
, SAREA_MAX
);
1300 if ( framebuffer
.base
!= MAP_FAILED
) {
1301 (void)drmUnmap((drmAddress
)framebuffer
.base
, framebuffer
.size
);
1304 if ( framebuffer
.dev_priv
!= NULL
) {
1305 free(framebuffer
.dev_priv
);
1312 if ( err_extra
!= NULL
) {
1313 fprintf(stderr
, "libGL error: %s failed (%s)\n", err_msg
,
1317 fprintf(stderr
, "libGL error: %s failed\n", err_msg
);
1320 fprintf(stderr
, "libGL error: reverting to (slow) indirect rendering\n");
1327 * \brief Initialize the graphics system.
1329 * \param display_name currently ignored. It is recommended to pass it as NULL.
1330 * \return a pointer to a #Display if the function is able to initialize
1331 * the graphics system, NULL otherwise.
1333 * Allocates a MiniGLXDisplayRec structure and fills in with information from a
1334 * configuration file.
1336 * Calls __miniglx_open_connections() to connect to the server.
1338 * Loads the DRI driver and pulls in Mini GLX specific hooks into a
1339 * DRIDriverRec structure, and the standard DRI \e __driCreateScreen hook.
1340 * Asks the driver for a list of supported visuals. Performs the per-screen
1341 * client-side initialization. Also setups the callbacks in the screen private
1345 * - read config file
1346 * - what about virtualWidth, etc?
1347 * - determine dpy->driverClientMsgSize,
1348 * - allocate dpy->driverClientMsg
1351 XOpenDisplay( const char *display_name
)
1355 dpy
= (Display
*)calloc(1, sizeof(Display
));
1359 dpy
->IsClient
= True
;
1363 if (!__read_config_file( dpy
)) {
1364 fprintf(stderr
, "Couldn't get configuration details\n");
1369 /* Connect to the server and receive driverClientMsg
1371 if (!__miniglx_open_connections(dpy
)) {
1376 /* dlopen the driver .so file
1378 if (!InitDriver(dpy
)) {
1379 fprintf(stderr
, "InitDriver failed\n");
1384 /* Perform the client-side initialization.
1386 * Clearly there is a limit of one on the number of windows in
1387 * existence at any time.
1389 * Need to shut down DRM and free DRI data in XDestroyWindow(), too.
1391 dpy
->driScreen
.private = CallCreateNewScreen(dpy
, 0, &dpy
->driScreen
);
1392 if (!dpy
->driScreen
.private) {
1393 fprintf(stderr
, "%s: __driCreateScreen failed\n", __FUNCTION__
);
1394 dlclose(dpy
->dlHandle
);
1399 /* Anything more to do?
1406 * \brief Release display resources.
1408 * When the application is about to exit, the resources associated with the
1409 * graphics system can be released by calling this function.
1411 * \param dpy display handle. It becomes invalid at this point.
1413 * Destroys the window if any, and destroys the per-screen
1414 * driver private information.
1415 * Calls __miniglx_close_connections().
1417 * If a server, puts the the framebuffer back into the initial state.
1419 * Finally frees the display structure.
1422 XCloseDisplay( Display
*dpy
)
1424 glXMakeCurrent( dpy
, NULL
, NULL
);
1426 if (dpy
->NumWindows
)
1427 XDestroyWindow( dpy
, dpy
->TheWindow
);
1429 /* As this is done in XOpenDisplay, need to undo it here:
1431 dpy
->driScreen
.destroyScreen(dpy
, 0, dpy
->driScreen
.private);
1433 __miniglx_close_connections( dpy
);
1435 if (!dpy
->IsClient
) {
1436 /* put framebuffer back to initial state
1438 (*dpy
->driver
->haltFBDev
)( &dpy
->driverContext
);
1443 dlclose(dpy
->dlHandle
);
1449 * \brief Window creation.
1451 * \param display a display handle, as returned by XOpenDisplay().
1452 * \param parent the parent window for the new window. For Mini GLX this should
1454 * \code RootWindow(display, 0) \endcode
1455 * \param x the window abscissa. For Mini GLX, it should be zero.
1456 * \param y the window ordinate. For Mini GLX, it should be zero.
1457 * \param width the window width. For Mini GLX, this specifies the desired
1458 * screen width such as 1024 or 1280.
1459 * \param height the window height. For Mini GLX, this specifies the desired
1460 * screen height such as 768 or 1024.
1461 * \param border_width the border width. For Mini GLX, it should be zero.
1462 * \param depth the window pixel depth. For Mini GLX, this should be the depth
1463 * found in the #XVisualInfo object returned by glXChooseVisual()
1464 * \param winclass the window class. For Mini GLX this value should be
1466 * \param visual the visual type. It should be the visual field of the
1467 * #XVisualInfo object returned by glXChooseVisual().
1468 * \param valuemask which fields of the XSetWindowAttributes() are to be used.
1469 * For Mini GLX this is typically the bitmask
1470 * \code CWBackPixel | CWBorderPixel | CWColormap \endcode
1471 * \param attributes initial window attributes. The
1472 * XSetWindowAttributes::background_pixel, XSetWindowAttributes::border_pixel
1473 * and XSetWindowAttributes::colormap fields should be set.
1475 * \return a window handle if it succeeds or zero if it fails.
1477 * \note For Mini GLX, windows are full-screen; they cover the entire frame
1478 * buffer. Also, Mini GLX imposes a limit of one window. A second window
1479 * cannot be created until the first one is destroyed.
1481 * This function creates and initializes a ::MiniGLXWindowRec structure after
1482 * ensuring that there is no other window created. Performs the per-drawable
1483 * client-side initialization calling the __DRIscreenRec::createDrawable
1488 XCreateWindow( Display
*dpy
, Window parent
, int x
, int y
,
1489 unsigned int width
, unsigned int height
,
1490 unsigned int border_width
, int depth
, unsigned int winclass
,
1491 Visual
*visual
, unsigned long valuemask
,
1492 XSetWindowAttributes
*attributes
)
1494 const int empty_attribute_list
[1] = { None
};
1501 (void) border_width
;
1507 if (!dpy
->IsClient
) {
1508 fprintf(stderr
, "Server process may not create windows (currently)\n");
1512 if (dpy
->NumWindows
> 0)
1513 return NULL
; /* only allow one window */
1515 assert(dpy
->TheWindow
== NULL
);
1517 win
= malloc(sizeof(struct MiniGLXWindowRec
));
1521 /* In rotated mode, translate incoming x,y,width,height into
1522 * 'normal' coordinates.
1524 if (dpy
->rotateMode
) {
1526 tmp
= width
; width
= height
; height
= tmp
;
1527 tmp
= x
; x
= y
; y
= tmp
;
1530 /* init other per-window fields */
1535 win
->visual
= visual
; /* ptr assignment */
1537 win
->bytesPerPixel
= dpy
->driverContext
.cpp
;
1538 win
->rowStride
= dpy
->driverContext
.shared
.virtualWidth
* win
->bytesPerPixel
;
1539 win
->size
= win
->rowStride
* height
;
1540 win
->frontStart
= dpy
->driverContext
.FBAddress
+ (win
->rowStride
* win
->x
) + (win
->y
* win
->bytesPerPixel
);
1541 win
->frontBottom
= (GLubyte
*) win
->frontStart
+ (height
-1) * win
->rowStride
;
1543 /* This is incorrect: the hardware driver could put the backbuffer
1544 * just about anywhere. These fields, including the above are
1545 * hardware dependent & don't really belong here.
1547 if (visual
->mode
->doubleBufferMode
) {
1548 win
->backStart
= (GLubyte
*) win
->frontStart
+
1549 win
->rowStride
* dpy
->driverContext
.shared
.virtualHeight
;
1550 win
->backBottom
= (GLubyte
*) win
->backStart
1551 + (height
- 1) * win
->rowStride
;
1552 win
->curBottom
= win
->backBottom
;
1555 /* single buffered */
1556 win
->backStart
= NULL
;
1557 win
->backBottom
= NULL
;
1558 win
->curBottom
= win
->frontBottom
;
1561 dpy
->driScreen
.createNewDrawable(dpy
, visual
->mode
, (int) win
,
1562 &win
->driDrawable
, GLX_WINDOW_BIT
, empty_attribute_list
);
1564 if (!win
->driDrawable
.private) {
1565 fprintf(stderr
, "%s: dri.createDrawable failed\n", __FUNCTION__
);
1571 dpy
->TheWindow
= win
;
1578 * \brief Destroy window.
1580 * \param display display handle.
1581 * \param w window handle.
1583 * This function calls XUnmapWindow() and frees window \p w.
1585 * In case of destroying the current buffer first unbinds the GLX context
1586 * by calling glXMakeCurrent() with no drawable.
1589 XDestroyWindow( Display
*display
, Window win
)
1591 if (display
&& display
->IsClient
&& win
) {
1592 /* check if destroying the current buffer */
1593 Window curDraw
= glXGetCurrentDrawable();
1594 if (win
== curDraw
) {
1595 glXMakeCurrent( display
, NULL
, NULL
);
1598 XUnmapWindow( display
, win
);
1600 /* Destroy the drawable. */
1601 win
->driDrawable
.destroyDrawable(display
, win
->driDrawable
.private);
1604 /* unlink window from display */
1605 display
->NumWindows
--;
1606 assert(display
->NumWindows
== 0);
1607 display
->TheWindow
= NULL
;
1615 * \brief Create color map structure.
1617 * \param dpy the display handle as returned by XOpenDisplay().
1618 * \param w the window on whose screen you want to create a color map. This
1619 * parameter is ignored by Mini GLX but should be the value returned by the
1620 * \code RootWindow(display, 0) \endcode macro.
1621 * \param visual a visual type supported on the screen. This parameter is
1622 * ignored by Mini GLX but should be the XVisualInfo::visual returned by
1623 * glXChooseVisual().
1624 * \param alloc the color map entries to be allocated. This parameter is ignored
1625 * by Mini GLX but should be set to #AllocNone.
1627 * \return the color map.
1629 * This function is only provided to ease porting. Practically a no-op -
1630 * returns a pointer to a dynamically allocated chunk of memory (one byte).
1633 XCreateColormap( Display
*dpy
, Window w
, Visual
*visual
, int alloc
)
1639 return (Colormap
) malloc(1);
1644 * \brief Destroy color map structure.
1646 * \param display The display handle as returned by XOpenDisplay().
1647 * \param colormap the color map to destroy.
1649 * This function is only provided to ease porting. Practically a no-op.
1651 * Frees the memory pointed by \p colormap.
1654 XFreeColormap( Display
*display
, Colormap colormap
)
1663 * \brief Free client data.
1665 * \param data the data that is to be freed.
1667 * Frees the memory pointed by \p data.
1677 * \brief Query available visuals.
1679 * \param dpy the display handle, as returned by XOpenDisplay().
1680 * \param vinfo_mask a bitmask indicating which fields of the \p vinfo_template
1681 * are to be matched. The value must be \c VisualScreenMask.
1682 * \param vinfo_template a template whose fields indicate which visual
1683 * attributes must be matched by the results. The XVisualInfo::screen field of
1684 * this structure must be zero.
1685 * \param nitens_return will hold the number of visuals returned.
1687 * \return the address of an array of all available visuals.
1689 * An example of using XGetVisualInfo() to get all available visuals follows:
1692 * XVisualInfo vinfo_template, *results;
1693 * int nitens_return;
1694 * Display *dpy = XOpenDisplay(NULL);
1695 * vinfo_template.screen = 0;
1696 * results = XGetVisualInfo(dpy, VisualScreenMask, &vinfo_template, &nitens_return);
1699 * Returns the list of all ::XVisualInfo available, one per
1700 * ::__GLcontextMode stored in MiniGLXDisplayRec::modes.
1703 XGetVisualInfo( Display
*dpy
, long vinfo_mask
, XVisualInfo
*vinfo_template
, int *nitens_return
)
1705 const __GLcontextModes
*mode
;
1706 XVisualInfo
*results
;
1710 // ASSERT(vinfo_mask == VisualScreenMask);
1711 ASSERT(vinfo_template
.screen
== 0);
1713 if (vinfo_mask
== VisualIDMask
)
1715 for ( mode
= dpy
->driver_modes
; mode
!= NULL
; mode
= mode
->next
)
1716 if (mode
->visualID
== vinfo_template
->visualid
)
1722 results
= (XVisualInfo
*)calloc(1, n
* sizeof(XVisualInfo
));
1728 visResults
= (Visual
*)calloc(1, n
* sizeof(Visual
));
1735 for ( mode
= dpy
->driver_modes
; mode
!= NULL
; mode
= mode
->next
)
1736 if (mode
->visualID
== vinfo_template
->visualid
)
1738 visResults
[0].mode
=mode
;
1739 visResults
[0].visInfo
= results
;
1740 visResults
[0].dpy
= dpy
;
1741 if (dpy
->driverContext
.bpp
== 32)
1742 visResults
[0].pixelFormat
= PF_B8G8R8A8
; /* XXX: FIX ME */
1744 visResults
[0].pixelFormat
= PF_B5G6R5
; /* XXX: FIX ME */
1746 results
[0].visual
= visResults
;
1747 results
[0].visualid
= mode
->visualID
;
1748 #if defined(__cplusplus) || defined(c_plusplus)
1749 results
[0].c_class
= TrueColor
;
1751 results
[0].class = TrueColor
;
1753 results
[0].depth
= mode
->redBits
+
1757 results
[0].bits_per_rgb
= dpy
->driverContext
.bpp
;
1762 else // if (vinfo_mask == VisualScreenMask)
1765 for ( mode
= dpy
->driver_modes
; mode
!= NULL
; mode
= mode
->next
)
1768 results
= (XVisualInfo
*)calloc(1, n
* sizeof(XVisualInfo
));
1774 visResults
= (Visual
*)calloc(1, n
* sizeof(Visual
));
1781 for ( mode
= dpy
->driver_modes
, i
= 0 ; mode
!= NULL
; mode
= mode
->next
, i
++ ) {
1782 visResults
[i
].mode
= mode
;
1783 visResults
[i
].visInfo
= results
+ i
;
1784 visResults
[i
].dpy
= dpy
;
1786 if (dpy
->driverContext
.bpp
== 32)
1787 visResults
[i
].pixelFormat
= PF_B8G8R8A8
; /* XXX: FIX ME */
1789 visResults
[i
].pixelFormat
= PF_B5G6R5
; /* XXX: FIX ME */
1791 results
[i
].visual
= visResults
+ i
;
1792 results
[i
].visualid
= mode
->visualID
;
1793 #if defined(__cplusplus) || defined(c_plusplus)
1794 results
[i
].c_class
= TrueColor
;
1796 results
[i
].class = TrueColor
;
1798 results
[i
].depth
= mode
->redBits
+
1802 results
[i
].bits_per_rgb
= dpy
->driverContext
.bpp
;
1811 * \brief Return a visual that matches specified attributes.
1813 * \param dpy the display handle, as returned by XOpenDisplay().
1814 * \param screen the screen number. It is currently ignored by Mini GLX and
1816 * \param attribList a list of GLX attributes which describe the desired pixel
1817 * format. It is terminated by the token \c None.
1819 * The attributes are as follows:
1821 * This attribute should always be present in order to maintain compatibility
1824 * If present, only RGBA pixel formats will be considered. Otherwise, only
1825 * color index formats are considered.
1826 * \arg GLX_DOUBLEBUFFER:
1827 * if present, only double-buffered pixel formats will be chosen.
1828 * \arg GLX_RED_SIZE \e n:
1829 * Must be followed by a non-negative integer indicating the minimum number of
1830 * bits per red pixel component that is acceptable.
1831 * \arg GLX_GREEN_SIZE \e n:
1832 * Must be followed by a non-negative integer indicating the minimum number of
1833 * bits per green pixel component that is acceptable.
1834 * \arg GLX_BLUE_SIZE \e n:
1835 * Must be followed by a non-negative integer indicating the minimum number of
1836 * bits per blue pixel component that is acceptable.
1837 * \arg GLX_ALPHA_SIZE \e n:
1838 * Must be followed by a non-negative integer indicating the minimum number of
1839 * bits per alpha pixel component that is acceptable.
1840 * \arg GLX_STENCIL_SIZE \e n:
1841 * Must be followed by a non-negative integer indicating the minimum number of
1842 * bits per stencil value that is acceptable.
1843 * \arg GLX_DEPTH_SIZE \e n:
1844 * Must be followed by a non-negative integer indicating the minimum number of
1845 * bits per depth component that is acceptable.
1847 * This token is used to terminate the attribute list.
1849 * \return a pointer to an #XVisualInfo object which most closely matches the
1850 * requirements of the attribute list. If there is no visual which matches the
1851 * request, \c NULL will be returned.
1853 * \note Visuals with accumulation buffers are not available.
1855 * This function searches the list of available visual configurations in
1856 * MiniGLXDisplayRec::configs for a configuration which best matches the GLX
1857 * attribute list parameter. A new ::XVisualInfo object is created which
1858 * describes the visual configuration. The match criteria is described in the
1862 glXChooseVisual( Display
*dpy
, int screen
, int *attribList
)
1864 const __GLcontextModes
*mode
;
1866 XVisualInfo
*visInfo
;
1868 GLboolean rgbFlag
= GL_FALSE
, dbFlag
= GL_FALSE
, stereoFlag
= GL_FALSE
;
1869 GLint redBits
= 0, greenBits
= 0, blueBits
= 0, alphaBits
= 0;
1870 GLint indexBits
= 0, depthBits
= 0, stencilBits
= 0;
1871 GLint numSamples
= 0;
1875 * XXX in the future, <screen> might be interpreted as a VT
1878 ASSERT(screen
== 0);
1880 vis
= (Visual
*)calloc(1, sizeof(Visual
));
1884 visInfo
= (XVisualInfo
*)malloc(sizeof(XVisualInfo
));
1890 visInfo
->visual
= vis
;
1891 vis
->visInfo
= visInfo
;
1894 /* parse the attribute list */
1895 for (attrib
= attribList
; attrib
&& *attrib
!= None
; attrib
++) {
1896 switch (attrib
[0]) {
1897 case GLX_DOUBLEBUFFER
:
1904 redBits
= attrib
[1];
1907 case GLX_GREEN_SIZE
:
1908 greenBits
= attrib
[1];
1912 blueBits
= attrib
[1];
1915 case GLX_ALPHA_SIZE
:
1916 alphaBits
= attrib
[1];
1919 case GLX_STENCIL_SIZE
:
1920 stencilBits
= attrib
[1];
1923 case GLX_DEPTH_SIZE
:
1924 depthBits
= attrib
[1];
1928 case GLX_ACCUM_RED_SIZE
:
1929 accumRedBits
= attrib
[1];
1932 case GLX_ACCUM_GREEN_SIZE
:
1933 accumGreenBits
= attrib
[1];
1936 case GLX_ACCUM_BLUE_SIZE
:
1937 accumBlueBits
= attrib
[1];
1940 case GLX_ACCUM_ALPHA_SIZE
:
1941 accumAlphaBits
= attrib
[1];
1945 /* ignored for now */
1949 /* unexpected token */
1950 fprintf(stderr
, "unexpected token in glXChooseVisual attrib list\n");
1957 /* search screen configs for suitable visual */
1965 for ( mode
= dpy
->driver_modes
; mode
!= NULL
; mode
= mode
->next
) {
1967 if (mode
->rgbMode
== rgbFlag
&&
1968 mode
->doubleBufferMode
== dbFlag
&&
1969 mode
->redBits
>= redBits
&&
1970 mode
->greenBits
>= greenBits
&&
1971 mode
->blueBits
>= blueBits
&&
1972 mode
->alphaBits
>= alphaBits
&&
1973 mode
->depthBits
>= depthBits
&&
1974 mode
->stencilBits
>= stencilBits
) {
1976 visInfo
->visualid
= i
;
1984 /* compute depth and bpp */
1986 /* XXX maybe support depth 16 someday */
1987 #if defined(__cplusplus) || defined(c_plusplus)
1988 visInfo
->c_class
= TrueColor
;
1990 visInfo
->class = TrueColor
;
1992 visInfo
->depth
= dpy
->driverContext
.bpp
;
1993 visInfo
->bits_per_rgb
= dpy
->driverContext
.bpp
;
1994 if (dpy
->driverContext
.bpp
== 32)
1995 vis
->pixelFormat
= PF_B8G8R8A8
;
1997 vis
->pixelFormat
= PF_B5G6R5
;
2000 /* color index mode */
2001 #if defined(__cplusplus) || defined(c_plusplus)
2002 visInfo
->c_class
= PseudoColor
;
2004 visInfo
->class = PseudoColor
;
2007 visInfo
->bits_per_rgb
= 8; /* bits/pixel */
2008 vis
->pixelFormat
= PF_CI8
;
2016 * \brief Return information about GLX visuals.
2018 * \param dpy the display handle, as returned by XOpenDisplay().
2019 * \param vis the visual to be queried, as returned by glXChooseVisual().
2020 * \param attrib the visual attribute to be returned.
2021 * \param value pointer to an integer in which the result of the query will be
2024 * \return zero if no error occurs, \c GLX_INVALID_ATTRIBUTE if the attribute
2025 * parameter is invalid, or \c GLX_BAD_VISUAL if the \p vis parameter is
2028 * Returns the appropriate attribute of ::__GLXvisualConfig pointed by
2029 * MiniGLXVisualRec::glxConfig of XVisualInfo::visual.
2034 glXGetConfig( Display
*dpy
, XVisualInfo
*vis
, int attrib
, int *value
)
2036 const __GLcontextModes
*mode
= vis
->visual
->mode
;
2039 return GLX_BAD_VISUAL
;
2047 *value
= mode
->rgbMode
;
2049 case GLX_DOUBLEBUFFER
:
2050 *value
= mode
->doubleBufferMode
;
2053 *value
= mode
->redBits
;
2055 case GLX_GREEN_SIZE
:
2056 *value
= mode
->greenBits
;
2059 *value
= mode
->blueBits
;
2061 case GLX_ALPHA_SIZE
:
2062 *value
= mode
->alphaBits
;
2064 case GLX_DEPTH_SIZE
:
2065 *value
= mode
->depthBits
;
2067 case GLX_STENCIL_SIZE
:
2068 *value
= mode
->stencilBits
;
2072 return GLX_BAD_ATTRIBUTE
;
2079 * \brief Create a new GLX rendering context.
2081 * \param dpy the display handle, as returned by XOpenDisplay().
2082 * \param vis the visual that defines the frame buffer resources available to
2083 * the rendering context, as returned by glXChooseVisual().
2084 * \param shareList If non-zero, texture objects and display lists are shared
2085 * with the named rendering context. If zero, texture objects and display lists
2086 * will (initially) be private to this context. They may be shared when a
2087 * subsequent context is created.
2088 * \param direct whether direct or indirect rendering is desired. For Mini GLX
2089 * this value is ignored but it should be set to \c True.
2091 * \return a ::GLXContext handle if it succeeds or zero if it fails due to
2092 * invalid parameter or insufficient resources.
2094 * This function creates and initializes a ::MiniGLXContextRec structure and
2095 * calls the __DRIscreenRec::createContext method to initialize the client
2099 glXCreateContext( Display
*dpy
, XVisualInfo
*vis
,
2100 GLXContext shareList
, Bool direct
)
2107 ctx
= (struct MiniGLXContextRec
*)calloc(1, sizeof(struct MiniGLXContextRec
));
2111 ctx
->vid
= vis
->visualid
;
2114 sharePriv
= shareList
->driContext
.private;
2118 ctx
->driContext
.mode
= vis
->visual
->mode
;
2119 ctx
->driContext
.private = dpy
->driScreen
.createNewContext(dpy
, vis
->visual
->mode
,
2120 GLX_WINDOW_BIT
, sharePriv
, &ctx
->driContext
);
2122 if (!ctx
->driContext
.private) {
2132 * \brief Destroy a GLX context.
2134 * \param dpy the display handle, as returned by XOpenDisplay().
2135 * \param ctx the GLX context to be destroyed.
2137 * This function frees the \p ctx parameter after unbinding the current context
2138 * by calling the __DRIcontextRec::bindContext method with zeros and calling
2139 * the __DRIcontextRec::destroyContext method.
2142 glXDestroyContext( Display
*dpy
, GLXContext ctx
)
2144 GLXContext glxctx
= glXGetCurrentContext();
2147 if (glxctx
== ctx
) {
2148 /* destroying current context */
2149 ctx
->driContext
.bindContext(dpy
, 0, 0, 0, 0);
2152 ctx
->driContext
.destroyContext(dpy
, 0, ctx
->driContext
.private);
2159 * \brief Bind a GLX context to a window or a pixmap.
2161 * \param dpy the display handle, as returned by XOpenDisplay().
2162 * \param drawable the window or drawable to bind to the rendering context.
2163 * This should be the value returned by XCreateWindow().
2164 * \param ctx the GLX context to be destroyed.
2166 * \return \c True if it succeeds, \c False otherwise to indicate an invalid
2167 * display, window or context parameter.
2169 * The current rendering context may be unbound by calling glXMakeCurrent()
2170 * with the window and context parameters set to zero.
2172 * An application may create any number of rendering contexts and bind them as
2173 * needed. Note that binding a rendering context is generally not a
2174 * light-weight operation. Most simple OpenGL applications create only one
2175 * rendering context.
2177 * This function first unbinds any old context via
2178 * __DRIcontextRec::unbindContext and binds the new one via
2179 * __DRIcontextRec::bindContext.
2181 * If \p drawable is zero it unbinds the GLX context by calling
2182 * __DRIcontextRec::bindContext with zeros.
2185 glXMakeCurrent( Display
*dpy
, GLXDrawable drawable
, GLXContext ctx
)
2187 if (dpy
&& drawable
&& ctx
) {
2188 GLXContext oldContext
= glXGetCurrentContext();
2189 GLXDrawable oldDrawable
= glXGetCurrentDrawable();
2192 oldContext
->driContext
.unbindContext(dpy
, 0,
2193 (__DRIid
) oldDrawable
, (__DRIid
) oldDrawable
,
2194 &oldContext
->driContext
);
2197 CurrentContext
= ctx
;
2198 ctx
->driContext
.bindContext(dpy
, 0, (__DRIid
) drawable
,
2199 (__DRIid
) drawable
, &ctx
->driContext
);
2200 ctx
->drawBuffer
= drawable
;
2201 ctx
->curBuffer
= drawable
;
2203 else if (ctx
&& dpy
) {
2205 ctx
->driContext
.bindContext(dpy
, 0, 0, 0, 0);
2208 CurrentContext
= 0; /* kw: this seems to be intended??? */
2216 * \brief Exchange front and back buffers.
2218 * \param dpy the display handle, as returned by XOpenDisplay().
2219 * \param drawable the drawable whose buffers are to be swapped.
2221 * Any pending rendering commands will be completed before the buffer swap
2224 * Calling glXSwapBuffers() on a window which is single-buffered has no effect.
2226 * This function just calls the __DRIdrawableRec::swapBuffers method to do the
2230 glXSwapBuffers( Display
*dpy
, GLXDrawable drawable
)
2232 if (!dpy
|| !drawable
)
2235 drawable
->driDrawable
.swapBuffers(dpy
, drawable
->driDrawable
.private);
2240 * \brief Return the current context
2242 * \return the current context, as specified by glXMakeCurrent(), or zero if no
2243 * context is currently bound.
2245 * \sa glXCreateContext(), glXMakeCurrent()
2247 * Returns the value of the ::CurrentContext global variable.
2250 glXGetCurrentContext( void )
2252 return CurrentContext
;
2257 * \brief Return the current drawable.
2259 * \return the current drawable, as specified by glXMakeCurrent(), or zero if
2260 * no drawable is currently bound.
2262 * This function gets the current context via glXGetCurrentContext() and
2263 * returns the MiniGLXContextRec::drawBuffer attribute.
2266 glXGetCurrentDrawable( void )
2268 GLXContext glxctx
= glXGetCurrentContext();
2270 return glxctx
->drawBuffer
;
2277 __glXCreateContextWithConfig(__DRInativeDisplay
*dpy
, int screen
,
2278 int fbconfigID
, void *contextID
, drm_context_t
*hHWContext
)
2280 __DRIscreen
*pDRIScreen
;
2283 pDRIScreen
= __glXFindDRIScreen(dpy
, screen
);
2284 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
2288 psp
= (__DRIscreen
*) pDRIScreen
->private;
2291 if (drmCreateContext(psp
->fd
, hHWContext
)) {
2292 fprintf(stderr
, ">>> drmCreateContext failed\n");
2295 *(void**)contextID
= (void*) *hHWContext
;
2303 __glXGetDrawableInfo(__DRInativeDisplay
*dpy
, int scrn
,
2304 __DRIid draw
, unsigned int * index
, unsigned int * stamp
,
2305 int * x
, int * y
, int * width
, int * height
,
2306 int * numClipRects
, drm_clip_rect_t
** pClipRects
,
2307 int * backX
, int * backY
,
2308 int * numBackClipRects
, drm_clip_rect_t
** pBackClipRects
)
2310 GLXDrawable drawable
= (GLXDrawable
) draw
;
2311 drm_clip_rect_t
* cliprect
;
2312 Display
* display
= (Display
*)dpy
;
2313 __DRIscreen
*psp
= display
->driScreen
.private;
2314 __DRIcontext
*pcp
= (__DRIcontext
*)CurrentContext
->driContext
.private;
2315 __DRIdrawable
*pdp
= pcp
->driDrawablePriv
;
2316 if (drawable
== 0) {
2320 cliprect
= (drm_clip_rect_t
*) _mesa_malloc(sizeof(drm_clip_rect_t
));
2321 cliprect
->x1
= drawable
->x
;
2322 cliprect
->y1
= drawable
->y
;
2323 cliprect
->x2
= drawable
->x
+ drawable
->w
;
2324 cliprect
->y2
= drawable
->y
+ drawable
->h
;
2326 /* the drawable index is by client id */
2327 *index
= display
->clientID
;
2329 *stamp
= pcp
->driScreenPriv
->pSAREA
->drawableTable
[display
->clientID
].stamp
;
2330 drmUpdateDrawableInfo(psp
->fd
, pdp
->hHWDrawable
, DRM_DRAWABLE_CLIPRECTS
, 1, cliprect
);
2333 *width
= drawable
->w
;
2334 *height
= drawable
->h
;
2336 *pClipRects
= cliprect
;
2338 *backX
= drawable
->x
;
2339 *backY
= drawable
->y
;
2340 *numBackClipRects
= 0;
2341 *pBackClipRects
= 0;
2348 xf86DRI_DestroyContext(__DRInativeDisplay
*dpy
, int screen
, __DRIid context_id
)
2355 xf86DRI_CreateDrawable(__DRInativeDisplay
*dpy
, int screen
, __DRIid drawable
,
2356 drm_drawable_t
*hHWDrawable
)
2359 Display
*display
= (Display
*)dpy
;
2360 __DRIscreen
*psp
= display
->driScreen
.private;
2362 ret
= drmCreateDrawable(psp
->fd
, hHWDrawable
);
2364 fprintf(stderr
, "drawable is %d %08X ret is %d\n", *hHWDrawable
, drawable
, -ret
);
2372 xf86DRI_DestroyDrawable(__DRInativeDisplay
*dpy
, int screen
, __DRIid drawable
)
2379 * \brief Query function address.
2381 * The glXGetProcAddress() function will return the address of any available
2382 * OpenGL or Mini GLX function.
2384 * \param procName name of the function to be returned.
2386 * \return If \p procName is a valid function name, a pointer to that function
2387 * will be returned. Otherwise, \c NULL will be returned.
2389 * The purpose of glXGetProcAddress() is to facilitate using future extensions
2390 * to OpenGL or Mini GLX. If a future version of the library adds new extension
2391 * functions they'll be accessible via glXGetProcAddress(). The alternative is
2392 * to hard-code calls to the new functions in the application but doing so will
2393 * prevent linking the application with older versions of the library.
2395 * Returns the function address by looking up its name in a static (name,
2396 * address) pair list.
2398 void (*glXGetProcAddress(const GLubyte
*procname
))( void )
2400 struct name_address
{
2404 static const struct name_address functions
[] = {
2405 { "glXChooseVisual", (void *) glXChooseVisual
},
2406 { "glXCreateContext", (void *) glXCreateContext
},
2407 { "glXDestroyContext", (void *) glXDestroyContext
},
2408 { "glXMakeCurrent", (void *) glXMakeCurrent
},
2409 { "glXSwapBuffers", (void *) glXSwapBuffers
},
2410 { "glXGetCurrentContext", (void *) glXGetCurrentContext
},
2411 { "glXGetCurrentDrawable", (void *) glXGetCurrentDrawable
},
2412 { "glXGetProcAddress", (void *) glXGetProcAddress
},
2413 { "XOpenDisplay", (void *) XOpenDisplay
},
2414 { "XCloseDisplay", (void *) XCloseDisplay
},
2415 { "XCreateWindow", (void *) XCreateWindow
},
2416 { "XDestroyWindow", (void *) XDestroyWindow
},
2417 { "XMapWindow", (void *) XMapWindow
},
2418 { "XCreateColormap", (void *) XCreateColormap
},
2419 { "XFreeColormap", (void *) XFreeColormap
},
2420 { "XFree", (void *) XFree
},
2421 { "XGetVisualinfo", (void *) XGetVisualInfo
},
2422 { "glXCreatePbuffer", (void *) glXCreatePbuffer
},
2423 { "glXDestroyPbuffer", (void *) glXDestroyPbuffer
},
2424 { "glXChooseFBConfig", (void *) glXChooseFBConfig
},
2425 { "glXGetVisualFromFBConfig", (void *) glXGetVisualFromFBConfig
},
2428 const struct name_address
*entry
;
2429 for (entry
= functions
; entry
->name
; entry
++) {
2430 if (strcmp(entry
->name
, (const char *) procname
) == 0) {
2434 return _glapi_get_proc_address((const char *) procname
);
2437 void (*glXGetProcAddressARB(const GLubyte
*procName
))( void ) __attribute__ ((alias ("glXGetProcAddress")));
2440 * \brief Query the Mini GLX version.
2442 * \param dpy the display handle. It is currently ignored, but should be the
2443 * value returned by XOpenDisplay().
2444 * \param major receives the major version number of Mini GLX.
2445 * \param minor receives the minor version number of Mini GLX.
2447 * \return \c True if the function succeeds, \c False if the function fails due
2448 * to invalid parameters.
2450 * \sa #MINI_GLX_VERSION_1_0.
2452 * Returns the hard-coded Mini GLX version.
2455 glXQueryVersion( Display
*dpy
, int *major
, int *minor
)
2465 * \brief Create a new pbuffer.
2468 glXCreatePbuffer( Display
*dpy
, GLXFBConfig config
, const int *attribList
)
2475 glXDestroyPbuffer( Display
*dpy
, GLXPbuffer pbuf
)
2482 glXChooseFBConfig( Display
*dpy
, int screen
, const int *attribList
,
2485 GLXFBConfig
*f
= (GLXFBConfig
*) malloc(sizeof(GLXFBConfig
));
2486 f
->visInfo
= glXChooseVisual( dpy
, screen
, (int *) attribList
);
2500 glXGetVisualFromFBConfig( Display
*dpy
, GLXFBConfig config
)
2502 /* XVisualInfo and GLXFBConfig are the same structure */
2504 return config
.visInfo
;
2507 void *glXAllocateMemoryMESA(Display
*dpy
, int scrn
,
2508 size_t size
, float readFreq
,
2509 float writeFreq
, float priority
)
2511 if (dpy
->driScreen
.private && dpy
->driScreen
.allocateMemory
) {
2512 return (*dpy
->driScreen
.allocateMemory
)( dpy
, scrn
, size
,
2513 readFreq
, writeFreq
,
2520 void glXFreeMemoryMESA(Display
*dpy
, int scrn
, void *pointer
)
2522 if (dpy
->driScreen
.private && dpy
->driScreen
.freeMemory
) {
2523 (*dpy
->driScreen
.freeMemory
)( dpy
, scrn
, pointer
);
2527 GLuint
glXGetMemoryOffsetMESA( Display
*dpy
, int scrn
,
2528 const void *pointer
)
2530 if (dpy
->driScreen
.private && dpy
->driScreen
.memoryOffset
) {
2531 return (*dpy
->driScreen
.memoryOffset
)( dpy
, scrn
, pointer
);
2539 * Get the unadjusted system time (UST). Currently, the UST is measured in
2540 * microseconds since Epoc. The actual resolution of the UST may vary from
2541 * system to system, and the units may vary from release to release.
2542 * Drivers should not call this function directly. They should instead use
2543 * \c glXGetProcAddress to obtain a pointer to the function.
2545 * \param ust Location to store the 64-bit UST
2546 * \returns Zero on success or a negative errno value on failure.
2549 * This function was copied directly from src/glx/x11/glxcmds.c.
2551 static int __glXGetUST( int64_t * ust
)
2555 if ( ust
== NULL
) {
2559 if ( gettimeofday( & tv
, NULL
) == 0 ) {
2560 ust
[0] = (tv
.tv_sec
* 1000000) + tv
.tv_usec
;
2571 * This needs to be implemented for miniGlx.
2573 static GLboolean
__glXGetMscRate(__DRInativeDisplay
* dpy
, __DRIid drawable
,
2574 int32_t * numerator
, int32_t * denominator
)