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-2003 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.
34 /* $Id: miniglx.c,v 1.2 2003/10/21 06:05:40 jonsmirl Exp $ */
39 * \section miniglxIntro Introduction
41 * The Mini GLX interface facilitates OpenGL rendering on embedded devices. The
42 * interface is a subset of the GLX interface, plus a minimal set of Xlib-like
45 * Programs written to the Mini GLX specification should run unchanged
46 * on systems with the X Window System and the GLX extension (after
47 * recompilation). The intention is to allow flexibility for
48 * prototyping and testing.
50 * The files in the src/miniglx/ directory are compiled to build the
51 * libGL.so library. This is the library which applications link with.
52 * libGL.so in turn, loads the hardware-specific device driver.
55 * \section miniglxDoxygen About Doxygen
57 * For a list of all files, select <b>File List</b>. Choose a file from
58 * the list for a list of all functions in the file.
60 * For a list of all functions, types, constants, etc.
61 * select <b>File Members</b>.
64 * \section miniglxReferences References
66 * - <A HREF="file:../../docs/MiniGLX.html">Mini GLX Specification</A>,
67 * Tungsten Graphics, Inc.
68 * - OpenGL Graphics with the X Window System, Silicon Graphics, Inc.,
69 * ftp://ftp.sgi.com/opengl/doc/opengl1.2/glx1.3.ps
70 * - Xlib - C Language X Interface, X Consortium Standard, X Version 11,
71 * Release 6.4, ftp://ftp.x.org/pub/R6.4/xc/doc/hardcopy/X11/xlib.PS.gz
72 * - XFree86 Man pages, The XFree86 Project, Inc.,
73 * http://www.xfree86.org/current/manindex3.html
78 * \page datatypes Notes on the XVisualInfo, Visual, and __GLXvisualConfig data types
80 * -# X (unfortunately) has two (or three) data types which
81 * describe visuals. Ideally, there would just be one.
82 * -# We need the #__GLXvisualConfig type to augment #XVisualInfo and #Visual
83 * because we need to describe the GLX-specific attributes of visuals.
84 * -# In this interface there is a one-to-one-to-one correspondence between
85 * the three types and they're all interconnected.
86 * -# The #XVisualInfo type has a pointer to a #Visual. The #Visual structure
87 * (aka MiniGLXVisualRec) has a pointer to the #__GLXvisualConfig. The
88 * #Visual structure also has a pointer pointing back to the #XVisualInfo.
89 * -# The #XVisualInfo structure is the only one who's contents are public.
90 * -# The glXChooseVisual() and XGetVisualInfo() are the only functions that
91 * return #XVisualInfo structures. They can be freed with XFree(), though
92 * there is a small memory leak.
105 #include <sys/ioctl.h>
106 #include <sys/mman.h>
107 #include <sys/types.h>
108 #include <linux/kd.h>
109 #include <linux/vt.h>
111 #include "miniglxP.h"
119 * \brief Current GLX context.
121 * \sa glXGetCurrentContext().
123 static GLXContext CurrentContext
= NULL
;
127 static Display
*SignalDisplay
= 0;
129 static void SwitchVT(int sig
)
131 fprintf(stderr
, "SwitchVT %d dpy %p\n", sig
, SignalDisplay
);
134 SignalDisplay
->vtSignalFlag
= 1;
137 case SIGUSR1
: /* vt has been released */
138 SignalDisplay
->haveVT
= 0;
140 case SIGUSR2
: /* vt has been acquired */
141 SignalDisplay
->haveVT
= 1;
147 /**********************************************************************/
148 /** \name Framebuffer device functions */
149 /**********************************************************************/
153 * \brief Do the first part of setting up the framebuffer device.
155 * \param dpy the display handle.
156 * \param use_vt use a VT for display or not
158 * \return GL_TRUE on success, or GL_FALSE on failure.
160 * \sa This is called during XOpenDisplay().
163 * Gets the VT number, opens the respective console TTY device. Saves its state
164 * to restore when exiting and goes into graphics mode.
166 * Opens the framebuffer device and make a copy of the original variable screen
167 * information and gets the fixed screen information. Maps the framebuffer and
168 * MMIO region into the process address space.
171 OpenFBDev( Display
*dpy
, int use_vt
)
174 int fd
, vtnumber
, ttyfd
;
179 fprintf(stderr
, "error: you need to be root\n");
185 /* open /dev/tty0 and get the VT number */
186 if ((fd
= open("/dev/tty0", O_WRONLY
, 0)) < 0) {
187 fprintf(stderr
, "error opening /dev/tty0\n");
190 if (ioctl(fd
, VT_OPENQRY
, &vtnumber
) < 0 || vtnumber
< 0) {
191 fprintf(stderr
, "error: couldn't get a free vt\n");
195 fprintf(stderr
, "*** got vt nr: %d\n", vtnumber
);
198 /* open the console tty */
199 sprintf(ttystr
, "/dev/tty%d", vtnumber
); /* /dev/tty1-64 */
200 dpy
->ConsoleFD
= open(ttystr
, O_RDWR
| O_NDELAY
, 0);
201 if (dpy
->ConsoleFD
< 0) {
202 fprintf(stderr
, "error couldn't open console fd\n");
206 /* save current vt number */
209 if (ioctl(dpy
->ConsoleFD
, VT_GETSTATE
, &vts
) == 0)
210 dpy
->OriginalVT
= vts
.v_active
;
213 /* disconnect from controlling tty */
214 ttyfd
= open("/dev/tty", O_RDWR
);
216 ioctl(ttyfd
, TIOCNOTTY
, 0);
220 /* some magic to restore the vt when we exit */
223 struct sigaction sig_tty
;
225 /* Set-up tty signal handler to catch the signal we request below */
227 memset( &sig_tty
, 0, sizeof( sig_tty
) );
228 sig_tty
.sa_handler
= SwitchVT
;
229 sigemptyset( &sig_tty
.sa_mask
);
230 if( sigaction( SIGUSR1
, &sig_tty
, &dpy
->OrigSigUsr1
) ||
231 sigaction( SIGUSR2
, &sig_tty
, &dpy
->OrigSigUsr2
) )
233 fprintf(stderr
, "error: can't set up signal handler (%s)",
240 vt
.mode
= VT_PROCESS
;
244 if (ioctl(dpy
->ConsoleFD
, VT_SETMODE
, &vt
) < 0) {
245 fprintf(stderr
, "error: ioctl(VT_SETMODE) failed: %s\n",
251 if (ioctl(dpy
->ConsoleFD
, VT_ACTIVATE
, vtnumber
) != 0)
252 printf("ioctl VT_ACTIVATE: %s\n", strerror(errno
));
253 if (ioctl(dpy
->ConsoleFD
, VT_WAITACTIVE
, vtnumber
) != 0)
254 printf("ioctl VT_WAITACTIVE: %s\n", strerror(errno
));
256 if (ioctl(dpy
->ConsoleFD
, VT_GETMODE
, &vt
) < 0) {
257 fprintf(stderr
, "error: ioctl VT_GETMODE: %s\n", strerror(errno
));
265 /* go into graphics mode */
266 if (ioctl(dpy
->ConsoleFD
, KDSETMODE
, KD_GRAPHICS
) < 0) {
267 fprintf(stderr
, "error: ioctl(KDSETMODE, KD_GRAPHICS) failed: %s\n",
273 /* open the framebuffer device */
274 dpy
->FrameBufferFD
= open(dpy
->fbdevDevice
, O_RDWR
);
275 if (dpy
->FrameBufferFD
< 0) {
276 fprintf(stderr
, "Error opening /dev/fb0: %s\n", strerror(errno
));
280 /* get the original variable screen info */
281 if (ioctl(dpy
->FrameBufferFD
, FBIOGET_VSCREENINFO
, &dpy
->OrigVarInfo
)) {
282 fprintf(stderr
, "error: ioctl(FBIOGET_VSCREENINFO) failed: %s\n",
288 dpy
->VarInfo
= dpy
->OrigVarInfo
; /* structure copy */
290 /* Turn off hw accels (otherwise mmap of mmio region will be
293 dpy
->VarInfo
.accel_flags
= 0;
294 if (ioctl(dpy
->FrameBufferFD
, FBIOPUT_VSCREENINFO
, &dpy
->VarInfo
)) {
295 fprintf(stderr
, "error: ioctl(FBIOPUT_VSCREENINFO) failed: %s\n",
302 /* Get the fixed screen info */
303 if (ioctl(dpy
->FrameBufferFD
, FBIOGET_FSCREENINFO
, &dpy
->FixedInfo
)) {
304 fprintf(stderr
, "error: ioctl(FBIOGET_FSCREENINFO) failed: %s\n",
311 /* mmap the framebuffer into our address space */
312 dpy
->driverContext
.FBStart
= dpy
->FixedInfo
.smem_start
;
313 dpy
->driverContext
.FBSize
= dpy
->FixedInfo
.smem_len
;
314 dpy
->driverContext
.shared
.fbSize
= dpy
->FixedInfo
.smem_len
;
315 dpy
->driverContext
.FBAddress
= (caddr_t
) mmap(0, /* start */
316 dpy
->driverContext
.shared
.fbSize
, /* bytes */
317 PROT_READ
| PROT_WRITE
, /* prot */
318 MAP_SHARED
, /* flags */
319 dpy
->FrameBufferFD
, /* fd */
321 if (dpy
->driverContext
.FBAddress
== (caddr_t
) - 1) {
322 fprintf(stderr
, "error: unable to mmap framebuffer: %s\n",
327 /* mmap the MMIO region into our address space */
328 dpy
->driverContext
.MMIOStart
= dpy
->FixedInfo
.mmio_start
;
329 dpy
->driverContext
.MMIOSize
= dpy
->FixedInfo
.mmio_len
;
330 dpy
->driverContext
.MMIOAddress
= (caddr_t
) mmap(0, /* start */
331 dpy
->driverContext
.MMIOSize
, /* bytes */
332 PROT_READ
| PROT_WRITE
, /* prot */
333 MAP_SHARED
, /* flags */
334 dpy
->FrameBufferFD
, /* fd */
335 dpy
->FixedInfo
.smem_len
/* offset */);
336 if (dpy
->driverContext
.MMIOAddress
== (caddr_t
) - 1) {
337 fprintf(stderr
, "error: unable to mmap mmio region: %s\n",
342 fprintf(stderr
, "got MMIOAddress %p offset %d\n",
343 dpy
->driverContext
.MMIOAddress
,
344 dpy
->FixedInfo
.smem_len
);
353 * \brief Setup up the desired framebuffer device mode.
355 * \param dpy the display handle.
357 * \return GL_TRUE on success, or GL_FALSE on failure.
359 * \sa This is called during __miniglx_StartServer().
363 * Bumps the size of the window the the next supported mode. Sets the
364 * variable screen information according to the desired mode and asks
365 * the driver to validate the mode. Certifies that a DirectColor or
366 * TrueColor visual is used from the updated fixed screen information.
367 * In the case of DirectColor visuals, sets up an 'identity' colormap to
368 * mimic a TrueColor visual.
370 * Calls the driver hooks 'ValidateMode' and 'PostValidateMode' to
371 * allow the driver to make modifications to the chosen mode according
372 * to hardware constraints, or to save and restore videocard registers
373 * that may be clobbered by the fbdev driver.
375 * \todo Timings are hard-coded in the source for a set of supported modes.
378 SetupFBDev( Display
*dpy
)
384 width
= dpy
->driverContext
.shared
.virtualWidth
;
385 height
= dpy
->driverContext
.shared
.virtualHeight
;
387 /* Bump size up to next supported mode.
389 if (width
<= 800 && height
<= 600) {
390 width
= 800; height
= 600;
392 else if (width
<= 1024 && height
<= 768) {
393 width
= 1024; height
= 768;
395 else if (width
<= 768 && height
<= 1024) {
396 width
= 768; height
= 1024;
398 else if (width
<= 1280 && height
<= 1024) {
399 width
= 1280; height
= 1024;
403 dpy
->driverContext
.shared
.virtualHeight
= height
;
404 dpy
->driverContext
.shared
.virtualWidth
= width
;
405 dpy
->driverContext
.shared
.fbStride
= width
* (dpy
->driverContext
.bpp
/ 8);
407 /* set the depth, resolution, etc */
408 dpy
->VarInfo
= dpy
->OrigVarInfo
;
409 dpy
->VarInfo
.bits_per_pixel
= dpy
->driverContext
.bpp
;
410 dpy
->VarInfo
.xres_virtual
= dpy
->driverContext
.shared
.virtualWidth
;
411 dpy
->VarInfo
.yres_virtual
= dpy
->driverContext
.shared
.virtualHeight
;
412 dpy
->VarInfo
.xres
= width
;
413 dpy
->VarInfo
.yres
= height
;
414 dpy
->VarInfo
.xoffset
= 0;
415 dpy
->VarInfo
.yoffset
= 0;
416 dpy
->VarInfo
.nonstd
= 0;
417 dpy
->VarInfo
.vmode
&= ~FB_VMODE_YWRAP
; /* turn off scrolling */
419 if (dpy
->VarInfo
.bits_per_pixel
== 32) {
420 dpy
->VarInfo
.red
.offset
= 16;
421 dpy
->VarInfo
.green
.offset
= 8;
422 dpy
->VarInfo
.blue
.offset
= 0;
423 dpy
->VarInfo
.transp
.offset
= 24;
424 dpy
->VarInfo
.red
.length
= 8;
425 dpy
->VarInfo
.green
.length
= 8;
426 dpy
->VarInfo
.blue
.length
= 8;
427 dpy
->VarInfo
.transp
.length
= 8;
429 else if (dpy
->VarInfo
.bits_per_pixel
== 16) {
430 dpy
->VarInfo
.red
.offset
= 11;
431 dpy
->VarInfo
.green
.offset
= 5;
432 dpy
->VarInfo
.blue
.offset
= 0;
433 dpy
->VarInfo
.red
.length
= 5;
434 dpy
->VarInfo
.green
.length
= 6;
435 dpy
->VarInfo
.blue
.length
= 5;
436 dpy
->VarInfo
.transp
.offset
= 0;
437 dpy
->VarInfo
.transp
.length
= 0;
440 fprintf(stderr
, "Only 32bpp and 16bpp modes supported at the moment\n");
444 if (!dpy
->driver
->validateMode( &dpy
->driverContext
)) {
445 fprintf(stderr
, "Driver validateMode() failed\n");
449 if (dpy
->VarInfo
.xres
== 1280 &&
450 dpy
->VarInfo
.yres
== 1024) {
451 /* timing values taken from /etc/fb.modes (1280x1024 @ 75Hz) */
452 dpy
->VarInfo
.pixclock
= 7408;
453 dpy
->VarInfo
.left_margin
= 248;
454 dpy
->VarInfo
.right_margin
= 16;
455 dpy
->VarInfo
.upper_margin
= 38;
456 dpy
->VarInfo
.lower_margin
= 1;
457 dpy
->VarInfo
.hsync_len
= 144;
458 dpy
->VarInfo
.vsync_len
= 3;
460 else if (dpy
->VarInfo
.xres
== 1024 &&
461 dpy
->VarInfo
.yres
== 768) {
462 /* timing values taken from /etc/fb.modes (1024x768 @ 75Hz) */
463 dpy
->VarInfo
.pixclock
= 12699;
464 dpy
->VarInfo
.left_margin
= 176;
465 dpy
->VarInfo
.right_margin
= 16;
466 dpy
->VarInfo
.upper_margin
= 28;
467 dpy
->VarInfo
.lower_margin
= 1;
468 dpy
->VarInfo
.hsync_len
= 96;
469 dpy
->VarInfo
.vsync_len
= 3;
471 else if (dpy
->VarInfo
.xres
== 800 &&
472 dpy
->VarInfo
.yres
== 600) {
473 /* timing values taken from /etc/fb.modes (800x600 @ 75Hz) */
474 dpy
->VarInfo
.pixclock
= 20203;
475 dpy
->VarInfo
.left_margin
= 160;
476 dpy
->VarInfo
.right_margin
= 16;
477 dpy
->VarInfo
.upper_margin
= 21;
478 dpy
->VarInfo
.lower_margin
= 1;
479 dpy
->VarInfo
.hsync_len
= 80;
480 dpy
->VarInfo
.vsync_len
= 3;
482 else if (dpy
->VarInfo
.xres
== 768 &&
483 dpy
->VarInfo
.yres
== 1024) {
484 /* timing values for 768x1024 @ 75Hz */
485 dpy
->VarInfo
.pixclock
= 11993;
486 dpy
->VarInfo
.left_margin
= 136;
487 dpy
->VarInfo
.right_margin
= 32;
488 dpy
->VarInfo
.upper_margin
= 41;
489 dpy
->VarInfo
.lower_margin
= 1;
490 dpy
->VarInfo
.hsync_len
= 80;
491 dpy
->VarInfo
.vsync_len
= 3;
494 /* XXX need timings for other screen sizes */
495 fprintf(stderr
, "XXXX screen size %d x %d not supported at this time!\n",
496 dpy
->VarInfo
.xres
, dpy
->VarInfo
.yres
);
500 fprintf(stderr
, "[miniglx] Setting mode: visible %dx%d virtual %dx%dx%d\n",
501 dpy
->VarInfo
.xres
, dpy
->VarInfo
.yres
,
502 dpy
->VarInfo
.xres_virtual
, dpy
->VarInfo
.yres_virtual
,
503 dpy
->VarInfo
.bits_per_pixel
);
505 /* set variable screen info */
506 if (ioctl(dpy
->FrameBufferFD
, FBIOPUT_VSCREENINFO
, &dpy
->VarInfo
)) {
507 fprintf(stderr
, "error: ioctl(FBIOPUT_VSCREENINFO) failed: %s\n",
512 /* get the variable screen info, in case it has been modified */
513 if (ioctl(dpy
->FrameBufferFD
, FBIOGET_VSCREENINFO
, &dpy
->VarInfo
)) {
514 fprintf(stderr
, "error: ioctl(FBIOGET_VSCREENINFO) failed: %s\n",
520 fprintf(stderr
, "[miniglx] Readback mode: visible %dx%d virtual %dx%dx%d\n",
521 dpy
->VarInfo
.xres
, dpy
->VarInfo
.yres
,
522 dpy
->VarInfo
.xres_virtual
, dpy
->VarInfo
.yres_virtual
,
523 dpy
->VarInfo
.bits_per_pixel
);
525 /* Get the fixed screen info */
526 if (ioctl(dpy
->FrameBufferFD
, FBIOGET_FSCREENINFO
, &dpy
->FixedInfo
)) {
527 fprintf(stderr
, "error: ioctl(FBIOGET_FSCREENINFO) failed: %s\n",
532 if (dpy
->FixedInfo
.visual
!= FB_VISUAL_TRUECOLOR
&&
533 dpy
->FixedInfo
.visual
!= FB_VISUAL_DIRECTCOLOR
) {
534 fprintf(stderr
, "non-TRUECOLOR visuals not supported.\n");
538 if (dpy
->FixedInfo
.visual
== FB_VISUAL_DIRECTCOLOR
) {
540 unsigned short red
[256], green
[256], blue
[256];
541 int rcols
= 1 << dpy
->VarInfo
.red
.length
;
542 int gcols
= 1 << dpy
->VarInfo
.green
.length
;
543 int bcols
= 1 << dpy
->VarInfo
.blue
.length
;
553 for (i
= 0; i
< rcols
; i
++)
554 red
[i
] = (65536/(rcols
-1)) * i
;
556 for (i
= 0; i
< gcols
; i
++)
557 green
[i
] = (65536/(gcols
-1)) * i
;
559 for (i
= 0; i
< bcols
; i
++)
560 blue
[i
] = (65536/(bcols
-1)) * i
;
562 if (ioctl(dpy
->FrameBufferFD
, FBIOPUTCMAP
, (void *) &cmap
) < 0) {
563 fprintf(stderr
, "ioctl(FBIOPUTCMAP) failed [%d]\n", i
);
568 /* May need to restore regs fbdev has clobbered:
570 if (!dpy
->driver
->postValidateMode( &dpy
->driverContext
)) {
571 fprintf(stderr
, "Driver postValidateMode() failed\n");
580 * \brief Restore the framebuffer device to state it was in before we started
582 * Undoes the work done by SetupFBDev().
584 * \param dpy the display handle.
586 * \return GL_TRUE on success, or GL_FALSE on failure.
588 * \sa Called from XDestroyWindow().
591 * Restores the original variable screen info.
594 RestoreFBDev( Display
*dpy
)
596 /* restore original variable screen info */
597 if (ioctl(dpy
->FrameBufferFD
, FBIOPUT_VSCREENINFO
, &dpy
->OrigVarInfo
)) {
598 fprintf(stderr
, "ioctl(FBIOPUT_VSCREENINFO failed): %s\n",
602 dpy
->VarInfo
= dpy
->OrigVarInfo
;
609 * \brief Close the framebuffer device.
611 * \param dpy the display handle.
613 * \sa Called from XCloseDisplay().
616 * Unmaps the framebuffer and MMIO region. Restores the text mode and the
617 * original virtual terminal. Closes the console and framebuffer devices.
620 CloseFBDev( Display
*dpy
)
624 munmap(dpy
->driverContext
.FBAddress
, dpy
->driverContext
.FBSize
);
625 munmap(dpy
->driverContext
.MMIOAddress
, dpy
->driverContext
.MMIOSize
);
627 if (dpy
->ConsoleFD
) {
628 /* restore text mode */
629 ioctl(dpy
->ConsoleFD
, KDSETMODE
, KD_TEXT
);
632 if (ioctl(dpy
->ConsoleFD
, VT_GETMODE
, &VT
) != -1) {
634 ioctl(dpy
->ConsoleFD
, VT_SETMODE
, &VT
);
637 /* restore original vt */
638 if (dpy
->OriginalVT
>= 0) {
639 ioctl(dpy
->ConsoleFD
, VT_ACTIVATE
, dpy
->OriginalVT
);
640 dpy
->OriginalVT
= -1;
643 close(dpy
->ConsoleFD
);
645 close(dpy
->FrameBufferFD
);
651 /**********************************************************************/
652 /** \name Misc functions needed for DRI drivers */
653 /**********************************************************************/
657 * \brief Find the DRI screen dependent methods associated with the display.
659 * \param dpy a display handle, as returned by XOpenDisplay().
660 * \param scrn the screen number. Not referenced.
662 * \returns a pointer to a __DRIscreenRec structure.
665 * Returns the MiniGLXDisplayRec::driScreen attribute.
668 __glXFindDRIScreen(Display
*dpy
, int scrn
)
671 return dpy
->driScreen
;
675 * \brief Validate a drawable.
677 * \param dpy a display handle, as returned by XOpenDisplay().
678 * \param draw drawable to validate.
681 * Since Mini GLX only supports one window, compares the specified drawable with
682 * the MiniGLXDisplayRec::TheWindow attribute.
685 __glXWindowExists(Display
*dpy
, GLXDrawable draw
)
687 if (dpy
->TheWindow
== draw
)
694 * \brief Get current thread ID.
702 _glthread_GetID(void)
711 * \brief Scan Linux /prog/bus/pci/devices file to determine hardware
712 * chipset based on supplied bus ID.
714 * \return probed chipset (non-zero) on success, zero otherwise.
718 static int get_chipset_from_busid( Display
*dpy
)
722 const char *fname
= "/proc/bus/pci/devices";
725 if (!(file
= fopen(fname
,"r"))) {
726 fprintf(stderr
, "couldn't open %s: %s\n", fname
, strerror(errno
));
730 while (fgets(buf
, sizeof(buf
)-1, file
)) {
731 unsigned int nr
, bus
, dev
, fn
, vendor
, device
, encode
;
732 nr
= sscanf(buf
, "%04x\t%04x%04x", &encode
,
736 dev
= (encode
& 0xFF) >> 3;
742 if (bus
== dpy
->driverContext
.pciBus
&&
743 dev
== dpy
->driverContext
.pciDevice
&&
744 fn
== dpy
->driverContext
.pciFunc
) {
753 fprintf(stderr
, "[miniglx] probed chipset 0x%x\n", retval
);
755 fprintf(stderr
, "[miniglx] failed to probe chipset\n");
762 * \brief Read settings from a configuration file.
764 * The configuration file is usually "/etc/miniglx.conf", but can be overridden
765 * with the MINIGLX_CONF environment variable.
767 * The format consists in \code option = value \endcode lines. The option names
768 * corresponds to the fields in MiniGLXDisplayRec.
770 * \param dpy the display handle as.
772 * \return non-zero on success, zero otherwise.
775 * Sets some defaults. Opens and parses the the Mini GLX configuration file and
776 * fills in the MiniGLXDisplayRec field that corresponds for each option.
778 static int __read_config_file( Display
*dpy
)
785 dpy
->fbdevDevice
= "/dev/fb0";
786 dpy
->clientDriverName
= "fb_dri.so";
787 dpy
->driverContext
.pciBus
= 0;
788 dpy
->driverContext
.pciDevice
= 0;
789 dpy
->driverContext
.pciFunc
= 0;
790 dpy
->driverContext
.chipset
= 0;
791 dpy
->driverContext
.pciBusID
= 0;
792 dpy
->driverContext
.shared
.virtualWidth
= 1280;
793 dpy
->driverContext
.shared
.virtualHeight
= 1024;
794 dpy
->driverContext
.bpp
= 32;
795 dpy
->driverContext
.cpp
= 4;
798 fname
= getenv("MINIGLX_CONF");
799 if (!fname
) fname
= "/etc/miniglx.conf";
801 file
= fopen(fname
, "r");
803 fprintf(stderr
, "couldn't open config file %s: %s\n", fname
, strerror(errno
));
808 while (!feof(file
)) {
809 char buf
[81], *opt
= buf
, *val
, *tmp1
, *tmp2
;
810 fgets(buf
, sizeof(buf
), file
);
812 /* Parse 'opt = val' -- must be easier ways to do this.
814 while (isspace(*opt
)) opt
++;
816 if (*val
== '#') continue; /* comment */
817 while (!isspace(*val
) && *val
!= '=' && *val
) val
++;
819 while (isspace(*val
)) val
++;
820 if (*val
!= '=') continue;
823 while (isspace(*val
)) val
++;
825 while (!isspace(*tmp2
) && *tmp2
!= '\n' && *tmp2
) tmp2
++;
829 if (strcmp(opt
, "fbdevDevice") == 0)
830 dpy
->fbdevDevice
= strdup(val
);
831 else if (strcmp(opt
, "clientDriverName") == 0)
832 dpy
->clientDriverName
= strdup(val
);
833 else if (strcmp(opt
, "rotateMode") == 0)
834 dpy
->rotateMode
= atoi(val
) ? 1 : 0;
835 else if (strcmp(opt
, "pciBusID") == 0) {
836 if (sscanf(val
, "PCI:%d:%d:%d",
837 &dpy
->driverContext
.pciBus
,
838 &dpy
->driverContext
.pciDevice
,
839 &dpy
->driverContext
.pciFunc
) != 3) {
840 fprintf(stderr
, "malformed bus id: %s\n", val
);
843 dpy
->driverContext
.pciBusID
= strdup(val
);
845 else if (strcmp(opt
, "chipset") == 0) {
846 if (sscanf(val
, "0x%x", &dpy
->driverContext
.chipset
) != 1)
847 fprintf(stderr
, "malformed chipset: %s\n", opt
);
849 else if (strcmp(opt
, "virtualWidth") == 0) {
850 if (sscanf(val
, "%d", &dpy
->driverContext
.shared
.virtualWidth
) != 1)
851 fprintf(stderr
, "malformed virtualWidth: %s\n", opt
);
853 else if (strcmp(opt
, "virtualHeight") == 0) {
854 if (sscanf(val
, "%d", &dpy
->driverContext
.shared
.virtualHeight
) != 1)
855 fprintf(stderr
, "malformed virutalHeight: %s\n", opt
);
857 else if (strcmp(opt
, "bpp") == 0) {
858 if (sscanf(val
, "%d", &dpy
->driverContext
.bpp
) != 1)
859 fprintf(stderr
, "malformed bpp: %s\n", opt
);
860 dpy
->driverContext
.cpp
= dpy
->driverContext
.bpp
/ 8;
866 if (dpy
->driverContext
.chipset
== 0 && dpy
->driverContext
.pciBusID
!= 0)
867 dpy
->driverContext
.chipset
= get_chipset_from_busid( dpy
);
872 static int InitDriver( Display
*dpy
)
876 * We're kind of combining the per-display and per-screen information
877 * which was kept separate in XFree86/DRI's libGL.
879 dpy
->dlHandle
= dlopen(dpy
->clientDriverName
, RTLD_NOW
| RTLD_GLOBAL
);
880 if (!dpy
->dlHandle
) {
881 fprintf(stderr
, "Unable to open %s: %s\n", dpy
->clientDriverName
,
886 /* Pull in Mini GLX specific hooks:
888 dpy
->driver
= (struct DRIDriverRec
*) dlsym(dpy
->dlHandle
,
891 fprintf(stderr
, "Couldn't find __driDriver in %s\n",
892 dpy
->clientDriverName
);
893 dlclose(dpy
->dlHandle
);
897 /* Pull in standard DRI client-side driver hooks:
899 dpy
->createScreen
= (driCreateScreenFunc
*) dlsym(dpy
->dlHandle
,
900 "__driCreateScreen");
901 if (!dpy
->createScreen
) {
902 fprintf(stderr
, "Couldn't find __driCreateScreen in %s\n",
903 dpy
->clientDriverName
);
904 dlclose(dpy
->dlHandle
);
912 /**********************************************************************/
913 /** \name Public API functions (Xlib and GLX) */
914 /**********************************************************************/
919 * \brief Initialize the graphics system.
921 * \param display_name currently ignored. It is recommended to pass it as NULL.
922 * \return a pointer to a #Display if the function is able to initialize
923 * the graphics system, NULL otherwise.
925 * Allocates a MiniGLXDisplayRec structure and fills in with information from a
926 * configuration file.
928 * Calls OpenFBDev() to open the framebuffer device and calls
929 * DRIDriverRec::initFBDev to do the client-side initialization on it.
931 * Loads the DRI driver and pulls in Mini GLX specific hooks into a
932 * DRIDriverRec structure, and the standard DRI \e __driCreateScreen hook.
933 * Asks the driver for a list of supported visuals. Performs the per-screen
934 * client-side initialization. Also setups the callbacks in the screen private
937 * Does the framebuffer device setup. Calls __miniglx_open_connections() to
941 __miniglx_StartServer( const char *display_name
)
946 dpy
= (Display
*)calloc(1, sizeof(Display
));
950 dpy
->IsClient
= False
;
952 if (!__read_config_file( dpy
)) {
953 fprintf(stderr
, "Couldn't get configuration details\n");
958 /* Open the fbdev device
960 if (!OpenFBDev(dpy
, use_vt
)) {
961 fprintf(stderr
, "OpenFBDev failed\n");
966 if (!InitDriver(dpy
)) {
967 fprintf(stderr
, "InitDriver failed\n");
972 /* Ask the driver for a list of supported configs:
974 dpy
->driver
->initContextModes( &dpy
->driverContext
, &dpy
->numModes
, &dpy
->modes
);
976 /* Perform the initialization normally done in the X server
978 if (!dpy
->driver
->initFBDev( &dpy
->driverContext
)) {
979 fprintf(stderr
, "%s: __driInitFBDev failed\n", __FUNCTION__
);
980 dlclose(dpy
->dlHandle
);
986 if (!SetupFBDev(dpy
)) {
987 fprintf(stderr
, "SetupFBDev failed\n");
992 /* unlock here if not using VT -- JDS */
994 if (dpy
->driver
->restoreHardware
)
995 dpy
->driver
->restoreHardware( &dpy
->driverContext
);
996 DRM_UNLOCK( dpy
->driverContext
.drmFD
,
997 dpy
->driverContext
.pSAREA
,
998 dpy
->driverContext
.serverContext
);
1002 /* Ready for clients:
1004 if (!__miniglx_open_connections(dpy
)) {
1014 * \brief Initialize the graphics system.
1016 * \param display_name currently ignored. It is recommended to pass it as NULL.
1017 * \return a pointer to a #Display if the function is able to initialize
1018 * the graphics system, NULL otherwise.
1020 * Allocates a MiniGLXDisplayRec structure and fills in with information from a
1021 * configuration file.
1023 * Calls __miniglx_open_connections() to connect to the server.
1025 * Loads the DRI driver and pulls in Mini GLX specific hooks into a
1026 * DRIDriverRec structure, and the standard DRI \e __driCreateScreen hook.
1027 * Asks the driver for a list of supported visuals. Performs the per-screen
1028 * client-side initialization. Also setups the callbacks in the screen private
1032 * - read config file
1033 * - what about virtualWidth, etc?
1034 * - determine dpy->driverClientMsgSize,
1035 * - allocate dpy->driverClientMsg
1038 XOpenDisplay( const char *display_name
)
1042 dpy
= (Display
*)calloc(1, sizeof(Display
));
1046 dpy
->IsClient
= True
;
1050 if (!__read_config_file( dpy
)) {
1051 fprintf(stderr
, "Couldn't get configuration details\n");
1056 /* Connect to the server and receive driverClientMsg
1058 if (!__miniglx_open_connections(dpy
)) {
1063 /* dlopen the driver .so file
1065 if (!InitDriver(dpy
)) {
1066 fprintf(stderr
, "InitDriver failed\n");
1071 /* Ask the driver for a list of supported configs:
1073 dpy
->driver
->initContextModes( &dpy
->driverContext
, &dpy
->numModes
, &dpy
->modes
);
1075 /* Perform the client-side initialization.
1077 * Clearly there is a limit of one on the number of windows in
1078 * existence at any time.
1080 * Need to shut down DRM and free DRI data in XDestroyWindow(), too.
1082 dpy
->driScreen
= (*dpy
->createScreen
)(dpy
->driver
,
1083 &dpy
->driverContext
);
1084 if (!dpy
->driScreen
) {
1085 fprintf(stderr
, "%s: __driCreateScreen failed\n", __FUNCTION__
);
1086 dlclose(dpy
->dlHandle
);
1091 /* Anything more to do?
1098 * \brief Release display resources.
1100 * When the application is about to exit, the resources associated with the
1101 * graphics system can be released by calling this function.
1103 * \param dpy display handle. It becomes invalid at this point.
1105 * Destroys the window if any, and destroys the per-screen
1106 * driver private information.
1107 * Calls __miniglx_close_connections().
1109 * If a server, puts the the framebuffer back into the initial state.
1111 * Finally frees the display structure.
1114 XCloseDisplay( Display
*dpy
)
1116 glXMakeCurrent( dpy
, NULL
, NULL
);
1118 if (dpy
->NumWindows
)
1119 XDestroyWindow( dpy
, dpy
->TheWindow
);
1121 /* As this is done in XOpenDisplay, need to undo it here:
1123 (*dpy
->driScreen
->destroyScreen
)(dpy
->driScreen
);
1125 __miniglx_close_connections( dpy
);
1127 if (!dpy
->IsClient
) {
1128 /* put framebuffer back to initial state
1130 (*dpy
->driver
->haltFBDev
)( &dpy
->driverContext
);
1135 dlclose(dpy
->dlHandle
);
1141 * \brief Window creation.
1143 * \param display a display handle, as returned by XOpenDisplay().
1144 * \param parent the parent window for the new window. For Mini GLX this should
1146 * \code RootWindow(display, 0) \endcode
1147 * \param x the window abscissa. For Mini GLX, it should be zero.
1148 * \param y the window ordinate. For Mini GLX, it should be zero.
1149 * \param width the window width. For Mini GLX, this specifies the desired
1150 * screen width such as 1024 or 1280.
1151 * \param height the window height. For Mini GLX, this specifies the desired
1152 * screen height such as 768 or 1024.
1153 * \param border_width the border width. For Mini GLX, it should be zero.
1154 * \param depth the window pixel depth. For Mini GLX, this should be the depth
1155 * found in the #XVisualInfo object returned by glXChooseVisual()
1156 * \param class the window class. For Mini GLX this value should be
1158 * \param visual the visual type. It should be the visual field of the
1159 * #XVisualInfo object returned by glXChooseVisual().
1160 * \param valuemask which fields of the XSetWindowAttributes() are to be used.
1161 * For Mini GLX this is typically the bitmask
1162 * \code CWBackPixel | CWBorderPixel | CWColormap \endcode
1163 * \param attributes initial window attributes. The
1164 * XSetWindowAttributes::background_pixel, XSetWindowAttributes::border_pixel
1165 * and XSetWindowAttributes::colormap fields should be set.
1167 * \return a window handle if it succeeds or zero if it fails.
1169 * \note For Mini GLX, windows are full-screen; they cover the entire frame
1170 * buffer. Also, Mini GLX imposes a limit of one window. A second window
1171 * cannot be created until the first one is destroyed.
1173 * This function creates and initializes a ::MiniGLXWindowRec structure after
1174 * ensuring that there is no other window created. Performs the per-drawable
1175 * client-side initialization calling the __DRIscreenRec::createDrawable
1180 XCreateWindow( Display
*dpy
, Window parent
, int x
, int y
,
1181 unsigned int width
, unsigned int height
,
1182 unsigned int border_width
, int depth
, unsigned int class,
1183 Visual
*visual
, unsigned long valuemask
,
1184 XSetWindowAttributes
*attributes
)
1191 (void) border_width
;
1197 if (!dpy
->IsClient
) {
1198 fprintf(stderr
, "Server process may not create windows (currently)\n");
1202 if (dpy
->NumWindows
> 0)
1203 return NULL
; /* only allow one window */
1205 assert(dpy
->TheWindow
== NULL
);
1207 win
= malloc(sizeof(struct MiniGLXWindowRec
));
1211 /* In rotated mode, translate incoming x,y,width,height into
1212 * 'normal' coordinates.
1214 if (dpy
->rotateMode
) {
1216 tmp
= width
; width
= height
; height
= tmp
;
1217 tmp
= x
; x
= y
; y
= tmp
;
1220 /* init other per-window fields */
1225 win
->visual
= visual
; /* ptr assignment */
1227 win
->bytesPerPixel
= dpy
->driverContext
.cpp
;
1228 win
->rowStride
= dpy
->driverContext
.shared
.virtualWidth
* win
->bytesPerPixel
;
1229 win
->size
= win
->rowStride
* height
;
1230 win
->frontStart
= dpy
->driverContext
.FBAddress
;
1231 win
->frontBottom
= (GLubyte
*) win
->frontStart
+ (height
-1) * win
->rowStride
;
1233 /* This is incorrect: the hardware driver could put the backbuffer
1234 * just about anywhere. These fields, including the above are
1235 * hardware dependent & don't really belong here.
1237 if (visual
->mode
->doubleBufferMode
) {
1238 win
->backStart
= (GLubyte
*) win
->frontStart
+
1239 win
->rowStride
* dpy
->driverContext
.shared
.virtualHeight
;
1240 win
->backBottom
= (GLubyte
*) win
->backStart
1241 + (height
- 1) * win
->rowStride
;
1242 win
->curBottom
= win
->backBottom
;
1245 /* single buffered */
1246 win
->backStart
= NULL
;
1247 win
->backBottom
= NULL
;
1248 win
->curBottom
= win
->frontBottom
;
1251 win
->driDrawable
= dpy
->driScreen
->createDrawable(dpy
->driScreen
,
1253 dpy
->clientID
, visual
->mode
);
1255 if (!win
->driDrawable
) {
1256 fprintf(stderr
, "%s: dri.createDrawable failed\n", __FUNCTION__
);
1262 dpy
->TheWindow
= win
;
1269 * \brief Destroy window.
1271 * \param display display handle.
1272 * \param w window handle.
1274 * This function calls XUnmapWindow() and frees window \p w.
1276 * In case of destroying the current buffer first unbinds the GLX context
1277 * by calling glXMakeCurrent() with no drawable.
1280 XDestroyWindow( Display
*display
, Window win
)
1282 if (display
&& display
->IsClient
&& win
) {
1283 /* check if destroying the current buffer */
1284 Window curDraw
= glXGetCurrentDrawable();
1285 if (win
== curDraw
) {
1286 glXMakeCurrent( display
, NULL
, NULL
);
1289 XUnmapWindow( display
, win
);
1291 /* Destroy the drawable. */
1292 (*win
->driDrawable
->destroyDrawable
)(win
->driDrawable
);
1295 /* unlink window from display */
1296 display
->NumWindows
--;
1297 assert(display
->NumWindows
== 0);
1298 display
->TheWindow
= NULL
;
1306 * \brief Create color map structure.
1308 * \param dpy the display handle as returned by XOpenDisplay().
1309 * \param w the window on whose screen you want to create a color map. This
1310 * parameter is ignored by Mini GLX but should be the value returned by the
1311 * \code RootWindow(display, 0) \endcode macro.
1312 * \param visual a visual type supported on the screen. This parameter is
1313 * ignored by Mini GLX but should be the XVisualInfo::visual returned by
1314 * glXChooseVisual().
1315 * \param alloc the color map entries to be allocated. This parameter is ignored
1316 * by Mini GLX but should be set to #AllocNone.
1318 * \return the color map.
1320 * This function is only provided to ease porting. Practically a no-op -
1321 * returns a pointer to a dynamically allocated chunk of memory (one byte).
1324 XCreateColormap( Display
*dpy
, Window w
, Visual
*visual
, int alloc
)
1330 return (Colormap
) malloc(1);
1335 * \brief Destroy color map structure.
1337 * \param display The display handle as returned by XOpenDisplay().
1338 * \param colormap the color map to destroy.
1340 * This function is only provided to ease porting. Practically a no-op.
1342 * Frees the memory pointed by \p colormap.
1345 XFreeColormap( Display
*display
, Colormap colormap
)
1354 * \brief Free client data.
1356 * \param data the data that is to be freed.
1358 * Frees the memory pointed by \p data.
1368 * \brief Query available visuals.
1370 * \param dpy the display handle, as returned by XOpenDisplay().
1371 * \param vinfo_mask a bitmask indicating which fields of the \p vinfo_template
1372 * are to be matched. The value must be \c VisualScreenMask.
1373 * \param vinfo_template a template whose fields indicate which visual
1374 * attributes must be matched by the results. The XVisualInfo::screen field of
1375 * this structure must be zero.
1376 * \param nitens_return will hold the number of visuals returned.
1378 * \return the address of an array of all available visuals.
1380 * An example of using XGetVisualInfo() to get all available visuals follows:
1383 * XVisualInfo vinfo_template, *results;
1384 * int nitens_return;
1385 * Display *dpy = XOpenDisplay(NULL);
1386 * vinfo_template.screen = 0;
1387 * results = XGetVisualInfo(dpy, VisualScreenMask, &vinfo_template, &nitens_return);
1390 * Returns the list of all ::XVisualInfo available, one per
1391 * ::__GLcontextMode stored in MiniGLXDisplayRec::modes.
1394 XGetVisualInfo( Display
*dpy
, long vinfo_mask
, XVisualInfo
*vinfo_template
, int *nitens_return
)
1396 XVisualInfo
*results
;
1400 ASSERT(vinfo_mask
== VisualScreenMask
);
1401 ASSERT(vinfo_template
.screen
== 0);
1404 results
= (XVisualInfo
*)calloc(1, n
* sizeof(XVisualInfo
));
1410 visResults
= (Visual
*)calloc(1, n
* sizeof(Visual
));
1417 for (i
= 0; i
< n
; i
++) {
1418 visResults
[i
].mode
= dpy
->modes
+ i
;
1419 visResults
[i
].visInfo
= results
+ i
;
1420 visResults
[i
].dpy
= dpy
;
1422 if (dpy
->driverContext
.bpp
== 32)
1423 visResults
[i
].pixelFormat
= PF_B8G8R8A8
; /* XXX: FIX ME */
1425 visResults
[i
].pixelFormat
= PF_B5G6R5
; /* XXX: FIX ME */
1427 results
[i
].visual
= visResults
+ i
;
1428 results
[i
].visualid
= i
;
1429 results
[i
].class = TrueColor
;
1430 results
[i
].depth
= dpy
->modes
[i
].redBits
+
1431 dpy
->modes
[i
].redBits
+
1432 dpy
->modes
[i
].redBits
+
1433 dpy
->modes
[i
].redBits
;
1434 results
[i
].bits_per_rgb
= dpy
->driverContext
.bpp
;
1442 * \brief Return a visual that matches specified attributes.
1444 * \param dpy the display handle, as returned by XOpenDisplay().
1445 * \param screen the screen number. It is currently ignored by Mini GLX and
1447 * \param attribList a list of GLX attributes which describe the desired pixel
1448 * format. It is terminated by the token \c None.
1450 * The attributes are as follows:
1452 * This attribute should always be present in order to maintain compatibility
1455 * If present, only RGBA pixel formats will be considered. Otherwise, only
1456 * color index formats are considered.
1457 * \arg GLX_DOUBLEBUFFER:
1458 * if present, only double-buffered pixel formats will be chosen.
1459 * \arg GLX_RED_SIZE \e n:
1460 * Must be followed by a non-negative integer indicating the minimum number of
1461 * bits per red pixel component that is acceptable.
1462 * \arg GLX_GREEN_SIZE \e n:
1463 * Must be followed by a non-negative integer indicating the minimum number of
1464 * bits per green pixel component that is acceptable.
1465 * \arg GLX_BLUE_SIZE \e n:
1466 * Must be followed by a non-negative integer indicating the minimum number of
1467 * bits per blue pixel component that is acceptable.
1468 * \arg GLX_ALPHA_SIZE \e n:
1469 * Must be followed by a non-negative integer indicating the minimum number of
1470 * bits per alpha pixel component that is acceptable.
1471 * \arg GLX_STENCIL_SIZE \e n:
1472 * Must be followed by a non-negative integer indicating the minimum number of
1473 * bits per stencil value that is acceptable.
1474 * \arg GLX_DEPTH_SIZE \e n:
1475 * Must be followed by a non-negative integer indicating the minimum number of
1476 * bits per depth component that is acceptable.
1478 * This token is used to terminate the attribute list.
1480 * \return a pointer to an #XVisualInfo object which most closely matches the
1481 * requirements of the attribute list. If there is no visual which matches the
1482 * request, \c NULL will be returned.
1484 * \note Visuals with accumulation buffers are not available.
1486 * This function searches the list of available visual configurations in
1487 * MiniGLXDisplayRec::configs for a configuration which best matches the GLX
1488 * attribute list parameter. A new ::XVisualInfo object is created which
1489 * describes the visual configuration. The match criteria is described in the
1493 glXChooseVisual( Display
*dpy
, int screen
, int *attribList
)
1496 XVisualInfo
*visInfo
;
1498 GLboolean rgbFlag
= GL_FALSE
, dbFlag
= GL_FALSE
, stereoFlag
= GL_FALSE
;
1499 GLint redBits
= 0, greenBits
= 0, blueBits
= 0, alphaBits
= 0;
1500 GLint indexBits
= 0, depthBits
= 0, stencilBits
= 0;
1501 GLint numSamples
= 0;
1505 * XXX in the future, <screen> might be interpreted as a VT
1508 ASSERT(screen
== 0);
1510 vis
= (Visual
*)calloc(1, sizeof(Visual
));
1514 visInfo
= (XVisualInfo
*)malloc(sizeof(XVisualInfo
));
1520 visInfo
->visual
= vis
;
1521 vis
->visInfo
= visInfo
;
1524 /* parse the attribute list */
1525 for (attrib
= attribList
; attrib
&& *attrib
!= None
; attrib
++) {
1526 switch (attrib
[0]) {
1527 case GLX_DOUBLEBUFFER
:
1534 redBits
= attrib
[1];
1537 case GLX_GREEN_SIZE
:
1538 redBits
= attrib
[1];
1542 redBits
= attrib
[1];
1545 case GLX_ALPHA_SIZE
:
1546 redBits
= attrib
[1];
1549 case GLX_STENCIL_SIZE
:
1550 stencilBits
= attrib
[1];
1553 case GLX_DEPTH_SIZE
:
1554 depthBits
= attrib
[1];
1558 case GLX_ACCUM_RED_SIZE
:
1559 accumRedBits
= attrib
[1];
1562 case GLX_ACCUM_GREEN_SIZE
:
1563 accumGreenBits
= attrib
[1];
1566 case GLX_ACCUM_BLUE_SIZE
:
1567 accumBlueBits
= attrib
[1];
1570 case GLX_ACCUM_ALPHA_SIZE
:
1571 accumAlphaBits
= attrib
[1];
1575 /* ignored for now */
1579 /* unexpected token */
1580 fprintf(stderr
, "unexpected token in glXChooseVisual attrib list\n");
1587 /* search screen configs for suitable visual */
1595 for (i
= 0; i
< dpy
->numModes
; i
++) {
1596 const __GLcontextModes
*mode
= dpy
->modes
+ i
;
1597 if (mode
->rgbMode
== rgbFlag
&&
1598 mode
->redBits
>= redBits
&&
1599 mode
->greenBits
>= greenBits
&&
1600 mode
->blueBits
>= blueBits
&&
1601 mode
->alphaBits
>= alphaBits
&&
1602 mode
->depthBits
>= depthBits
&&
1603 mode
->stencilBits
>= stencilBits
) {
1605 visInfo
->visualid
= i
;
1613 /* compute depth and bpp */
1615 /* XXX maybe support depth 16 someday */
1616 visInfo
->class = TrueColor
;
1617 visInfo
->depth
= dpy
->driverContext
.bpp
;
1618 visInfo
->bits_per_rgb
= dpy
->driverContext
.bpp
;
1619 if (dpy
->driverContext
.bpp
== 32)
1620 vis
->pixelFormat
= PF_B8G8R8A8
;
1622 vis
->pixelFormat
= PF_B5G6R5
;
1625 /* color index mode */
1626 visInfo
->class = PseudoColor
;
1628 visInfo
->bits_per_rgb
= 8; /* bits/pixel */
1629 vis
->pixelFormat
= PF_CI8
;
1637 * \brief Return information about GLX visuals.
1639 * \param dpy the display handle, as returned by XOpenDisplay().
1640 * \param vis the visual to be queried, as returned by glXChooseVisual().
1641 * \param attrib the visual attribute to be returned.
1642 * \param value pointer to an integer in which the result of the query will be
1645 * \return zero if no error occurs, \c GLX_INVALID_ATTRIBUTE if the attribute
1646 * parameter is invalid, or \c GLX_BAD_VISUAL if the \p vis parameter is
1649 * Returns the appropriate attribute of ::__GLXvisualConfig pointed by
1650 * MiniGLXVisualRec::glxConfig of XVisualInfo::visual.
1655 glXGetConfig( Display
*dpy
, XVisualInfo
*vis
, int attrib
, int *value
)
1657 const __GLcontextModes
*mode
= vis
->visual
->mode
;
1660 return GLX_BAD_VISUAL
;
1668 *value
= mode
->rgbMode
;
1670 case GLX_DOUBLEBUFFER
:
1671 *value
= mode
->doubleBufferMode
;
1674 *value
= mode
->redBits
;
1676 case GLX_GREEN_SIZE
:
1677 *value
= mode
->greenBits
;
1680 *value
= mode
->blueBits
;
1682 case GLX_ALPHA_SIZE
:
1683 *value
= mode
->alphaBits
;
1685 case GLX_DEPTH_SIZE
:
1686 *value
= mode
->depthBits
;
1688 case GLX_STENCIL_SIZE
:
1689 *value
= mode
->stencilBits
;
1693 return GLX_BAD_ATTRIBUTE
;
1700 * \brief Create a new GLX rendering context.
1702 * \param dpy the display handle, as returned by XOpenDisplay().
1703 * \param vis the visual that defines the frame buffer resources available to
1704 * the rendering context, as returned by glXChooseVisual().
1705 * \param shareList If non-zero, texture objects and display lists are shared
1706 * with the named rendering context. If zero, texture objects and display lists
1707 * will (initially) be private to this context. They may be shared when a
1708 * subsequent context is created.
1709 * \param direct whether direct or indirect rendering is desired. For Mini GLX
1710 * this value is ignored but it should be set to \c True.
1712 * \return a ::GLXContext handle if it succeeds or zero if it fails due to
1713 * invalid parameter or insufficient resources.
1715 * This function creates and initializes a ::MiniGLXContextRec structure and
1716 * calls the __DRIscreenRec::createContext method to initialize the client
1720 glXCreateContext( Display
*dpy
, XVisualInfo
*vis
,
1721 GLXContext shareList
, Bool direct
)
1728 ctx
= (struct MiniGLXContextRec
*)calloc(1, sizeof(struct MiniGLXContextRec
));
1732 ctx
->vid
= vis
->visualid
;
1735 sharePriv
= shareList
->driContext
;
1739 ctx
->driContext
= (*dpy
->driScreen
->createContext
)(dpy
->driScreen
,
1742 if (!ctx
->driContext
) {
1752 * \brief Destroy a GLX context.
1754 * \param dpy the display handle, as returned by XOpenDisplay().
1755 * \param ctx the GLX context to be destroyed.
1757 * This function frees the \p ctx parameter after unbinding the current context
1758 * by calling the __DRIcontextRec::bindContext method with zeros and calling
1759 * the __DRIcontextRec::destroyContext method.
1762 glXDestroyContext( Display
*dpy
, GLXContext ctx
)
1764 GLXContext glxctx
= glXGetCurrentContext();
1767 if (glxctx
== ctx
) {
1768 /* destroying current context */
1769 (*ctx
->driContext
->bindContext
)(dpy
->driScreen
, 0, 0);
1772 (*ctx
->driContext
->destroyContext
)(ctx
->driContext
);
1779 * \brief Bind a GLX context to a window or a pixmap.
1781 * \param dpy the display handle, as returned by XOpenDisplay().
1782 * \param drawable the window or drawable to bind to the rendering context.
1783 * This should be the value returned by XCreateWindow().
1784 * \param ctx the GLX context to be destroyed.
1786 * \return \c True if it succeeds, \c False otherwise to indicate an invalid
1787 * display, window or context parameter.
1789 * The current rendering context may be unbound by calling glXMakeCurrent()
1790 * with the window and context parameters set to zero.
1792 * An application may create any number of rendering contexts and bind them as
1793 * needed. Note that binding a rendering context is generally not a
1794 * light-weight operation. Most simple OpenGL applications create only one
1795 * rendering context.
1797 * This function first unbinds any old context via
1798 * __DRIcontextRec::unbindContext and binds the new one via
1799 * __DRIcontextRec::bindContext.
1801 * If \p drawable is zero it unbinds the GLX context by calling
1802 * __DRIcontextRec::bindContext with zeros.
1805 glXMakeCurrent( Display
*dpy
, GLXDrawable drawable
, GLXContext ctx
)
1807 if (dpy
&& drawable
&& ctx
) {
1808 GLXContext oldContext
= glXGetCurrentContext();
1809 GLXDrawable oldDrawable
= glXGetCurrentDrawable();
1812 (*oldContext
->driContext
->unbindContext
)(oldDrawable
->driDrawable
, oldContext
->driContext
);
1815 CurrentContext
= ctx
;
1816 (*ctx
->driContext
->bindContext
)(dpy
->driScreen
, drawable
->driDrawable
, ctx
->driContext
);
1817 ctx
->drawBuffer
= drawable
;
1818 ctx
->curBuffer
= drawable
;
1820 else if (ctx
&& dpy
) {
1822 (*ctx
->driContext
->bindContext
)(dpy
->driScreen
, 0, 0);
1825 CurrentContext
= 0; /* kw: this seems to be intended??? */
1833 * \brief Exchange front and back buffers.
1835 * \param dpy the display handle, as returned by XOpenDisplay().
1836 * \param drawable the drawable whose buffers are to be swapped.
1838 * Any pending rendering commands will be completed before the buffer swap
1841 * Calling glXSwapBuffers() on a window which is single-buffered has no effect.
1843 * This function just calls the __DRIdrawableRec::swapBuffers method to do the
1847 glXSwapBuffers( Display
*dpy
, GLXDrawable drawable
)
1849 if (!dpy
|| !drawable
)
1852 (*drawable
->driDrawable
->swapBuffers
)(drawable
->driDrawable
);
1857 * \brief Return the current context
1859 * \return the current context, as specified by glXMakeCurrent(), or zero if no
1860 * context is currently bound.
1862 * \sa glXCreateContext(), glXMakeCurrent()
1864 * Returns the value of the ::CurrentContext global variable.
1867 glXGetCurrentContext( void )
1869 return CurrentContext
;
1874 * \brief Return the current drawable.
1876 * \return the current drawable, as specified by glXMakeCurrent(), or zero if
1877 * no drawable is currently bound.
1879 * This function gets the current context via glXGetCurrentContext() and
1880 * returns the MiniGLXContextRec::drawBuffer attribute.
1883 glXGetCurrentDrawable( void )
1885 GLXContext glxctx
= glXGetCurrentContext();
1887 return glxctx
->drawBuffer
;
1894 * \brief Query function address.
1896 * The glXGetProcAddress() function will return the address of any available
1897 * OpenGL or Mini GLX function.
1899 * \param procName name of the function to be returned.
1901 * \return If \p procName is a valid function name, a pointer to that function
1902 * will be returned. Otherwise, \c NULL will be returned.
1904 * The purpose of glXGetProcAddress() is to facilitate using future extensions
1905 * to OpenGL or Mini GLX. If a future version of the library adds new extension
1906 * functions they'll be accessible via glXGetProcAddress(). The alternative is
1907 * to hard-code calls to the new functions in the application but doing so will
1908 * prevent linking the application with older versions of the library.
1910 * Returns the function address by looking up its name in a static (name,
1911 * address) pair list.
1914 glXGetProcAddress( const GLubyte
*procName
)
1916 struct name_address
{
1920 static const struct name_address functions
[] = {
1921 { "glXChooseVisual", (void *) glXChooseVisual
},
1922 { "glXCreateContext", (void *) glXCreateContext
},
1923 { "glXDestroyContext", (void *) glXDestroyContext
},
1924 { "glXMakeCurrent", (void *) glXMakeCurrent
},
1925 { "glXSwapBuffers", (void *) glXSwapBuffers
},
1926 { "glXGetCurrentContext", (void *) glXGetCurrentContext
},
1927 { "glXGetCurrentDrawable", (void *) glXGetCurrentDrawable
},
1928 { "glXGetProcAddress", (void *) glXGetProcAddress
},
1929 { "XOpenDisplay", (void *) XOpenDisplay
},
1930 { "XCloseDisplay", (void *) XCloseDisplay
},
1931 { "XCreateWindow", (void *) XCreateWindow
},
1932 { "XDestroyWindow", (void *) XDestroyWindow
},
1933 { "XMapWindow", (void *) XMapWindow
},
1934 { "XCreateColormap", (void *) XCreateColormap
},
1935 { "XFreeColormap", (void *) XFreeColormap
},
1936 { "XFree", (void *) XFree
},
1937 { "XGetVisualinfo", (void *) XGetVisualInfo
},
1940 const struct name_address
*entry
;
1941 for (entry
= functions
; entry
->name
; entry
++) {
1942 if (strcmp(entry
->name
, (const char *) procName
) == 0) {
1946 return _glapi_get_proc_address((const char *) procName
);
1951 * \brief Query the Mini GLX version.
1953 * \param dpy the display handle. It is currently ignored, but should be the
1954 * value returned by XOpenDisplay().
1955 * \param major receives the major version number of Mini GLX.
1956 * \param minor receives the minor version number of Mini GLX.
1958 * \return \c True if the function succeeds, \c False if the function fails due
1959 * to invalid parameters.
1961 * \sa #MINI_GLX_VERSION_1_0.
1963 * Returns the hard-coded Mini GLX version.
1966 glXQueryVersion( Display
*dpy
, int *major
, int *minor
)