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 <linux/kd.h>
108 #include <linux/vt.h>
110 #include "miniglxP.h"
111 #include "dri_util.h"
114 #include "glcontextmodes.h"
118 extern GLboolean
__glXCreateContextWithConfig(__DRInativeDisplay
*dpy
,
119 int screen
, int fbconfigID
, void *contextID
,
120 drm_context_t
*hHWContext
);
122 extern GLboolean
__glXGetDrawableInfo(__DRInativeDisplay
*dpy
, int scrn
,
123 __DRIid draw
, unsigned int * index
, unsigned int * stamp
,
124 int * x
, int * y
, int * width
, int * height
,
125 int * numClipRects
, drm_clip_rect_t
** pClipRects
,
126 int * backX
, int * backY
,
127 int * numBackClipRects
, drm_clip_rect_t
** pBackClipRects
);
130 /** Wrapper around either malloc() */
132 _mesa_malloc(size_t bytes
)
134 return malloc(bytes
);
137 /** Wrapper around either calloc() */
139 _mesa_calloc(size_t bytes
)
141 return calloc(1, bytes
);
144 /** Wrapper around either free() */
146 _mesa_free(void *ptr
)
153 * \brief Current GLX context.
155 * \sa glXGetCurrentContext().
157 static GLXContext CurrentContext
= NULL
;
161 static Display
*SignalDisplay
= 0;
163 static void SwitchVT(int sig
)
165 fprintf(stderr
, "SwitchVT %d dpy %p\n", sig
, SignalDisplay
);
168 SignalDisplay
->vtSignalFlag
= 1;
171 case SIGUSR1
: /* vt has been released */
172 SignalDisplay
->haveVT
= 0;
174 case SIGUSR2
: /* vt has been acquired */
175 SignalDisplay
->haveVT
= 1;
181 /**********************************************************************/
182 /** \name Framebuffer device functions */
183 /**********************************************************************/
187 * \brief Do the first part of setting up the framebuffer device.
189 * \param dpy the display handle.
190 * \param use_vt use a VT for display or not
192 * \return GL_TRUE on success, or GL_FALSE on failure.
194 * \sa This is called during XOpenDisplay().
197 * Gets the VT number, opens the respective console TTY device. Saves its state
198 * to restore when exiting and goes into graphics mode.
200 * Opens the framebuffer device and make a copy of the original variable screen
201 * information and gets the fixed screen information. Maps the framebuffer and
202 * MMIO region into the process address space.
205 OpenFBDev( Display
*dpy
, int use_vt
)
208 int fd
, vtnumber
, ttyfd
;
213 fprintf(stderr
, "error: you need to be root\n");
219 /* open /dev/tty0 and get the VT number */
220 if ((fd
= open("/dev/tty0", O_WRONLY
, 0)) < 0) {
221 fprintf(stderr
, "error opening /dev/tty0\n");
224 if (ioctl(fd
, VT_OPENQRY
, &vtnumber
) < 0 || vtnumber
< 0) {
225 fprintf(stderr
, "error: couldn't get a free vt\n");
229 fprintf(stderr
, "*** got vt nr: %d\n", vtnumber
);
232 /* open the console tty */
233 sprintf(ttystr
, "/dev/tty%d", vtnumber
); /* /dev/tty1-64 */
234 dpy
->ConsoleFD
= open(ttystr
, O_RDWR
| O_NDELAY
, 0);
235 if (dpy
->ConsoleFD
< 0) {
236 fprintf(stderr
, "error couldn't open console fd\n");
240 /* save current vt number */
243 if (ioctl(dpy
->ConsoleFD
, VT_GETSTATE
, &vts
) == 0)
244 dpy
->OriginalVT
= vts
.v_active
;
247 /* disconnect from controlling tty */
248 ttyfd
= open("/dev/tty", O_RDWR
);
250 ioctl(ttyfd
, TIOCNOTTY
, 0);
254 /* some magic to restore the vt when we exit */
257 struct sigaction sig_tty
;
259 /* Set-up tty signal handler to catch the signal we request below */
261 memset( &sig_tty
, 0, sizeof( sig_tty
) );
262 sig_tty
.sa_handler
= SwitchVT
;
263 sigemptyset( &sig_tty
.sa_mask
);
264 if( sigaction( SIGUSR1
, &sig_tty
, &dpy
->OrigSigUsr1
) ||
265 sigaction( SIGUSR2
, &sig_tty
, &dpy
->OrigSigUsr2
) )
267 fprintf(stderr
, "error: can't set up signal handler (%s)",
274 vt
.mode
= VT_PROCESS
;
278 if (ioctl(dpy
->ConsoleFD
, VT_SETMODE
, &vt
) < 0) {
279 fprintf(stderr
, "error: ioctl(VT_SETMODE) failed: %s\n",
285 if (ioctl(dpy
->ConsoleFD
, VT_ACTIVATE
, vtnumber
) != 0)
286 printf("ioctl VT_ACTIVATE: %s\n", strerror(errno
));
287 if (ioctl(dpy
->ConsoleFD
, VT_WAITACTIVE
, vtnumber
) != 0)
288 printf("ioctl VT_WAITACTIVE: %s\n", strerror(errno
));
290 if (ioctl(dpy
->ConsoleFD
, VT_GETMODE
, &vt
) < 0) {
291 fprintf(stderr
, "error: ioctl VT_GETMODE: %s\n", strerror(errno
));
299 /* go into graphics mode */
300 if (ioctl(dpy
->ConsoleFD
, KDSETMODE
, KD_GRAPHICS
) < 0) {
301 fprintf(stderr
, "error: ioctl(KDSETMODE, KD_GRAPHICS) failed: %s\n",
307 /* open the framebuffer device */
308 dpy
->FrameBufferFD
= open(dpy
->fbdevDevice
, O_RDWR
);
309 if (dpy
->FrameBufferFD
< 0) {
310 fprintf(stderr
, "Error opening /dev/fb0: %s\n", strerror(errno
));
314 /* get the original variable screen info */
315 if (ioctl(dpy
->FrameBufferFD
, FBIOGET_VSCREENINFO
, &dpy
->OrigVarInfo
)) {
316 fprintf(stderr
, "error: ioctl(FBIOGET_VSCREENINFO) failed: %s\n",
322 dpy
->VarInfo
= dpy
->OrigVarInfo
; /* structure copy */
324 /* Turn off hw accels (otherwise mmap of mmio region will be
327 dpy
->VarInfo
.accel_flags
= 0;
328 if (ioctl(dpy
->FrameBufferFD
, FBIOPUT_VSCREENINFO
, &dpy
->VarInfo
)) {
329 fprintf(stderr
, "error: ioctl(FBIOPUT_VSCREENINFO) failed: %s\n",
336 /* Get the fixed screen info */
337 if (ioctl(dpy
->FrameBufferFD
, FBIOGET_FSCREENINFO
, &dpy
->FixedInfo
)) {
338 fprintf(stderr
, "error: ioctl(FBIOGET_FSCREENINFO) failed: %s\n",
345 /* mmap the framebuffer into our address space */
346 dpy
->driverContext
.FBStart
= dpy
->FixedInfo
.smem_start
;
347 dpy
->driverContext
.FBSize
= dpy
->FixedInfo
.smem_len
;
348 dpy
->driverContext
.shared
.fbSize
= dpy
->FixedInfo
.smem_len
;
349 dpy
->driverContext
.FBAddress
= (caddr_t
) mmap(0, /* start */
350 dpy
->driverContext
.shared
.fbSize
, /* bytes */
351 PROT_READ
| PROT_WRITE
, /* prot */
352 MAP_SHARED
, /* flags */
353 dpy
->FrameBufferFD
, /* fd */
355 if (dpy
->driverContext
.FBAddress
== (caddr_t
) - 1) {
356 fprintf(stderr
, "error: unable to mmap framebuffer: %s\n",
361 /* mmap the MMIO region into our address space */
362 dpy
->driverContext
.MMIOStart
= dpy
->FixedInfo
.mmio_start
;
363 dpy
->driverContext
.MMIOSize
= dpy
->FixedInfo
.mmio_len
;
364 dpy
->driverContext
.MMIOAddress
= (caddr_t
) mmap(0, /* start */
365 dpy
->driverContext
.MMIOSize
, /* bytes */
366 PROT_READ
| PROT_WRITE
, /* prot */
367 MAP_SHARED
, /* flags */
368 dpy
->FrameBufferFD
, /* fd */
369 dpy
->FixedInfo
.smem_len
/* offset */);
370 if (dpy
->driverContext
.MMIOAddress
== (caddr_t
) - 1) {
371 fprintf(stderr
, "error: unable to mmap mmio region: %s\n",
376 fprintf(stderr
, "got MMIOAddress %p offset %d\n",
377 dpy
->driverContext
.MMIOAddress
,
378 dpy
->FixedInfo
.smem_len
);
387 * \brief Setup up the desired framebuffer device mode.
389 * \param dpy the display handle.
391 * \return GL_TRUE on success, or GL_FALSE on failure.
393 * \sa This is called during __miniglx_StartServer().
397 * Bumps the size of the window the the next supported mode. Sets the
398 * variable screen information according to the desired mode and asks
399 * the driver to validate the mode. Certifies that a DirectColor or
400 * TrueColor visual is used from the updated fixed screen information.
401 * In the case of DirectColor visuals, sets up an 'identity' colormap to
402 * mimic a TrueColor visual.
404 * Calls the driver hooks 'ValidateMode' and 'PostValidateMode' to
405 * allow the driver to make modifications to the chosen mode according
406 * to hardware constraints, or to save and restore videocard registers
407 * that may be clobbered by the fbdev driver.
409 * \todo Timings are hard-coded in the source for a set of supported modes.
412 SetupFBDev( Display
*dpy
)
418 width
= dpy
->driverContext
.shared
.virtualWidth
;
419 height
= dpy
->driverContext
.shared
.virtualHeight
;
421 /* Bump size up to next supported mode.
423 if (width
<= 720 && height
<= 480) {
424 width
= 720; height
= 480;
426 else if (width
<= 960 && height
<= 540) {
427 width
= 960; height
= 540;
429 else if (width
<= 800 && height
<= 600) {
430 width
= 800; height
= 600;
432 else if (width
<= 1024 && height
<= 768) {
433 width
= 1024; height
= 768;
435 else if (width
<= 768 && height
<= 1024) {
436 width
= 768; height
= 1024;
438 else if (width
<= 1280 && height
<= 1024) {
439 width
= 1280; height
= 1024;
443 dpy
->driverContext
.shared
.virtualHeight
= height
;
444 dpy
->driverContext
.shared
.virtualWidth
= width
;
445 dpy
->driverContext
.shared
.fbStride
= width
* (dpy
->driverContext
.bpp
/ 8);
447 /* set the depth, resolution, etc */
448 dpy
->VarInfo
= dpy
->OrigVarInfo
;
449 dpy
->VarInfo
.bits_per_pixel
= dpy
->driverContext
.bpp
;
450 dpy
->VarInfo
.xres_virtual
= dpy
->driverContext
.shared
.virtualWidth
;
451 dpy
->VarInfo
.yres_virtual
= dpy
->driverContext
.shared
.virtualHeight
;
452 dpy
->VarInfo
.xres
= width
;
453 dpy
->VarInfo
.yres
= height
;
454 dpy
->VarInfo
.xoffset
= 0;
455 dpy
->VarInfo
.yoffset
= 0;
456 dpy
->VarInfo
.nonstd
= 0;
457 dpy
->VarInfo
.vmode
&= ~FB_VMODE_YWRAP
; /* turn off scrolling */
459 if (dpy
->VarInfo
.bits_per_pixel
== 32) {
460 dpy
->VarInfo
.red
.offset
= 16;
461 dpy
->VarInfo
.green
.offset
= 8;
462 dpy
->VarInfo
.blue
.offset
= 0;
463 dpy
->VarInfo
.transp
.offset
= 24;
464 dpy
->VarInfo
.red
.length
= 8;
465 dpy
->VarInfo
.green
.length
= 8;
466 dpy
->VarInfo
.blue
.length
= 8;
467 dpy
->VarInfo
.transp
.length
= 8;
469 else if (dpy
->VarInfo
.bits_per_pixel
== 16) {
470 dpy
->VarInfo
.red
.offset
= 11;
471 dpy
->VarInfo
.green
.offset
= 5;
472 dpy
->VarInfo
.blue
.offset
= 0;
473 dpy
->VarInfo
.red
.length
= 5;
474 dpy
->VarInfo
.green
.length
= 6;
475 dpy
->VarInfo
.blue
.length
= 5;
476 dpy
->VarInfo
.transp
.offset
= 0;
477 dpy
->VarInfo
.transp
.length
= 0;
480 fprintf(stderr
, "Only 32bpp and 16bpp modes supported at the moment\n");
484 if (!dpy
->driver
->validateMode( &dpy
->driverContext
)) {
485 fprintf(stderr
, "Driver validateMode() failed\n");
489 /* These should be calculated with the gtf.c program, and then we could
490 remove all this... AlanH. */
491 if (dpy
->VarInfo
.xres
== 1280 &&
492 dpy
->VarInfo
.yres
== 1024) {
493 /* timing values taken from /etc/fb.modes (1280x1024 @ 75Hz) */
494 dpy
->VarInfo
.pixclock
= 7408;
495 dpy
->VarInfo
.left_margin
= 248;
496 dpy
->VarInfo
.right_margin
= 16;
497 dpy
->VarInfo
.upper_margin
= 38;
498 dpy
->VarInfo
.lower_margin
= 1;
499 dpy
->VarInfo
.hsync_len
= 144;
500 dpy
->VarInfo
.vsync_len
= 3;
502 else if (dpy
->VarInfo
.xres
== 1024 &&
503 dpy
->VarInfo
.yres
== 768) {
504 /* timing values taken from /etc/fb.modes (1024x768 @ 75Hz) */
505 dpy
->VarInfo
.pixclock
= 12699;
506 dpy
->VarInfo
.left_margin
= 176;
507 dpy
->VarInfo
.right_margin
= 16;
508 dpy
->VarInfo
.upper_margin
= 28;
509 dpy
->VarInfo
.lower_margin
= 1;
510 dpy
->VarInfo
.hsync_len
= 96;
511 dpy
->VarInfo
.vsync_len
= 3;
513 else if (dpy
->VarInfo
.xres
== 800 &&
514 dpy
->VarInfo
.yres
== 600) {
515 /* timing values taken from /etc/fb.modes (800x600 @ 75Hz) */
516 dpy
->VarInfo
.pixclock
= 27778;
517 dpy
->VarInfo
.left_margin
= 128;
518 dpy
->VarInfo
.right_margin
= 24;
519 dpy
->VarInfo
.upper_margin
= 22;
520 dpy
->VarInfo
.lower_margin
= 1;
521 dpy
->VarInfo
.hsync_len
= 72;
522 dpy
->VarInfo
.vsync_len
= 2;
524 else if (dpy
->VarInfo
.xres
== 720 &&
525 dpy
->VarInfo
.yres
== 480) {
526 dpy
->VarInfo
.pixclock
= 37202;
527 dpy
->VarInfo
.left_margin
= 88;
528 dpy
->VarInfo
.right_margin
= 16;
529 dpy
->VarInfo
.upper_margin
= 14;
530 dpy
->VarInfo
.lower_margin
= 1;
531 dpy
->VarInfo
.hsync_len
= 72;
532 dpy
->VarInfo
.vsync_len
= 3;
534 else if (dpy
->VarInfo
.xres
== 960 &&
535 dpy
->VarInfo
.yres
== 540) {
536 dpy
->VarInfo
.pixclock
= 24273;
537 dpy
->VarInfo
.left_margin
= 128;
538 dpy
->VarInfo
.right_margin
= 32;
539 dpy
->VarInfo
.upper_margin
= 16;
540 dpy
->VarInfo
.lower_margin
= 1;
541 dpy
->VarInfo
.hsync_len
= 96;
542 dpy
->VarInfo
.vsync_len
= 3;
544 else if (dpy
->VarInfo
.xres
== 768 &&
545 dpy
->VarInfo
.yres
== 1024) {
546 /* timing values for 768x1024 @ 75Hz */
547 dpy
->VarInfo
.pixclock
= 11993;
548 dpy
->VarInfo
.left_margin
= 136;
549 dpy
->VarInfo
.right_margin
= 32;
550 dpy
->VarInfo
.upper_margin
= 41;
551 dpy
->VarInfo
.lower_margin
= 1;
552 dpy
->VarInfo
.hsync_len
= 80;
553 dpy
->VarInfo
.vsync_len
= 3;
556 /* XXX need timings for other screen sizes */
557 fprintf(stderr
, "XXXX screen size %d x %d not supported at this time!\n",
558 dpy
->VarInfo
.xres
, dpy
->VarInfo
.yres
);
562 fprintf(stderr
, "[miniglx] Setting mode: visible %dx%d virtual %dx%dx%d\n",
563 dpy
->VarInfo
.xres
, dpy
->VarInfo
.yres
,
564 dpy
->VarInfo
.xres_virtual
, dpy
->VarInfo
.yres_virtual
,
565 dpy
->VarInfo
.bits_per_pixel
);
567 /* set variable screen info */
568 if (ioctl(dpy
->FrameBufferFD
, FBIOPUT_VSCREENINFO
, &dpy
->VarInfo
)) {
569 fprintf(stderr
, "error: ioctl(FBIOPUT_VSCREENINFO) failed: %s\n",
574 /* get the variable screen info, in case it has been modified */
575 if (ioctl(dpy
->FrameBufferFD
, FBIOGET_VSCREENINFO
, &dpy
->VarInfo
)) {
576 fprintf(stderr
, "error: ioctl(FBIOGET_VSCREENINFO) failed: %s\n",
582 fprintf(stderr
, "[miniglx] Readback mode: visible %dx%d virtual %dx%dx%d\n",
583 dpy
->VarInfo
.xres
, dpy
->VarInfo
.yres
,
584 dpy
->VarInfo
.xres_virtual
, dpy
->VarInfo
.yres_virtual
,
585 dpy
->VarInfo
.bits_per_pixel
);
587 /* Get the fixed screen info */
588 if (ioctl(dpy
->FrameBufferFD
, FBIOGET_FSCREENINFO
, &dpy
->FixedInfo
)) {
589 fprintf(stderr
, "error: ioctl(FBIOGET_FSCREENINFO) failed: %s\n",
594 if (dpy
->FixedInfo
.visual
!= FB_VISUAL_TRUECOLOR
&&
595 dpy
->FixedInfo
.visual
!= FB_VISUAL_DIRECTCOLOR
) {
596 fprintf(stderr
, "non-TRUECOLOR visuals not supported.\n");
600 if (dpy
->FixedInfo
.visual
== FB_VISUAL_DIRECTCOLOR
) {
602 unsigned short red
[256], green
[256], blue
[256];
603 int rcols
= 1 << dpy
->VarInfo
.red
.length
;
604 int gcols
= 1 << dpy
->VarInfo
.green
.length
;
605 int bcols
= 1 << dpy
->VarInfo
.blue
.length
;
615 for (i
= 0; i
< rcols
; i
++)
616 red
[i
] = (65536/(rcols
-1)) * i
;
618 for (i
= 0; i
< gcols
; i
++)
619 green
[i
] = (65536/(gcols
-1)) * i
;
621 for (i
= 0; i
< bcols
; i
++)
622 blue
[i
] = (65536/(bcols
-1)) * i
;
624 if (ioctl(dpy
->FrameBufferFD
, FBIOPUTCMAP
, (void *) &cmap
) < 0) {
625 fprintf(stderr
, "ioctl(FBIOPUTCMAP) failed [%d]\n", i
);
630 /* May need to restore regs fbdev has clobbered:
632 if (!dpy
->driver
->postValidateMode( &dpy
->driverContext
)) {
633 fprintf(stderr
, "Driver postValidateMode() failed\n");
642 * \brief Restore the framebuffer device to state it was in before we started
644 * Undoes the work done by SetupFBDev().
646 * \param dpy the display handle.
648 * \return GL_TRUE on success, or GL_FALSE on failure.
650 * \sa Called from XDestroyWindow().
653 * Restores the original variable screen info.
656 RestoreFBDev( Display
*dpy
)
658 /* restore original variable screen info */
659 if (ioctl(dpy
->FrameBufferFD
, FBIOPUT_VSCREENINFO
, &dpy
->OrigVarInfo
)) {
660 fprintf(stderr
, "ioctl(FBIOPUT_VSCREENINFO failed): %s\n",
664 dpy
->VarInfo
= dpy
->OrigVarInfo
;
671 * \brief Close the framebuffer device.
673 * \param dpy the display handle.
675 * \sa Called from XCloseDisplay().
678 * Unmaps the framebuffer and MMIO region. Restores the text mode and the
679 * original virtual terminal. Closes the console and framebuffer devices.
682 CloseFBDev( Display
*dpy
)
686 munmap(dpy
->driverContext
.FBAddress
, dpy
->driverContext
.FBSize
);
687 munmap(dpy
->driverContext
.MMIOAddress
, dpy
->driverContext
.MMIOSize
);
689 if (dpy
->ConsoleFD
) {
690 /* restore text mode */
691 ioctl(dpy
->ConsoleFD
, KDSETMODE
, KD_TEXT
);
694 if (ioctl(dpy
->ConsoleFD
, VT_GETMODE
, &VT
) != -1) {
696 ioctl(dpy
->ConsoleFD
, VT_SETMODE
, &VT
);
699 /* restore original vt */
700 if (dpy
->OriginalVT
>= 0) {
701 ioctl(dpy
->ConsoleFD
, VT_ACTIVATE
, dpy
->OriginalVT
);
702 dpy
->OriginalVT
= -1;
705 close(dpy
->ConsoleFD
);
707 close(dpy
->FrameBufferFD
);
713 /**********************************************************************/
714 /** \name Misc functions needed for DRI drivers */
715 /**********************************************************************/
719 * \brief Find the DRI screen dependent methods associated with the display.
721 * \param dpy a display handle, as returned by XOpenDisplay().
722 * \param scrn the screen number. Not referenced.
724 * \returns a pointer to a __DRIscreenRec structure.
727 * Returns the MiniGLXDisplayRec::driScreen attribute.
730 __glXFindDRIScreen(__DRInativeDisplay
*dpy
, int scrn
)
733 return &((Display
*)dpy
)->driScreen
;
737 * \brief Validate a drawable.
739 * \param dpy a display handle, as returned by XOpenDisplay().
740 * \param draw drawable to validate.
743 * Since Mini GLX only supports one window, compares the specified drawable with
744 * the MiniGLXDisplayRec::TheWindow attribute.
747 __glXWindowExists(__DRInativeDisplay
*dpy
, GLXDrawable draw
)
749 Display
* display
= (Display
*)dpy
;
750 if (display
->TheWindow
== draw
)
757 * \brief Get current thread ID.
765 _glthread_GetID(void)
774 * \brief Scan Linux /prog/bus/pci/devices file to determine hardware
775 * chipset based on supplied bus ID.
777 * \return probed chipset (non-zero) on success, zero otherwise.
781 static int get_chipset_from_busid( Display
*dpy
)
785 const char *fname
= "/proc/bus/pci/devices";
788 if (!(file
= fopen(fname
,"r"))) {
789 fprintf(stderr
, "couldn't open %s: %s\n", fname
, strerror(errno
));
793 while (fgets(buf
, sizeof(buf
)-1, file
)) {
794 unsigned int nr
, bus
, dev
, fn
, vendor
, device
, encode
;
795 nr
= sscanf(buf
, "%04x\t%04x%04x", &encode
,
799 dev
= (encode
& 0xFF) >> 3;
805 if (bus
== dpy
->driverContext
.pciBus
&&
806 dev
== dpy
->driverContext
.pciDevice
&&
807 fn
== dpy
->driverContext
.pciFunc
) {
816 fprintf(stderr
, "[miniglx] probed chipset 0x%x\n", retval
);
818 fprintf(stderr
, "[miniglx] failed to probe chipset\n");
825 * \brief Read settings from a configuration file.
827 * The configuration file is usually "/etc/miniglx.conf", but can be overridden
828 * with the MINIGLX_CONF environment variable.
830 * The format consists in \code option = value \endcode lines. The option names
831 * corresponds to the fields in MiniGLXDisplayRec.
833 * \param dpy the display handle as.
835 * \return non-zero on success, zero otherwise.
838 * Sets some defaults. Opens and parses the the Mini GLX configuration file and
839 * fills in the MiniGLXDisplayRec field that corresponds for each option.
841 static int __read_config_file( Display
*dpy
)
848 dpy
->fbdevDevice
= "/dev/fb0";
849 dpy
->clientDriverName
= "fb_dri.so";
850 dpy
->driverContext
.pciBus
= 0;
851 dpy
->driverContext
.pciDevice
= 0;
852 dpy
->driverContext
.pciFunc
= 0;
853 dpy
->driverContext
.chipset
= 0;
854 dpy
->driverContext
.pciBusID
= 0;
855 dpy
->driverContext
.shared
.virtualWidth
= 1280;
856 dpy
->driverContext
.shared
.virtualHeight
= 1024;
857 dpy
->driverContext
.bpp
= 32;
858 dpy
->driverContext
.cpp
= 4;
860 dpy
->driverContext
.agpmode
= 1;
861 dpy
->driverContext
.isPCI
= 0;
863 fname
= getenv("MINIGLX_CONF");
864 if (!fname
) fname
= "/etc/miniglx.conf";
866 file
= fopen(fname
, "r");
868 fprintf(stderr
, "couldn't open config file %s: %s\n", fname
, strerror(errno
));
873 while (!feof(file
)) {
874 char buf
[81], *opt
= buf
, *val
, *tmp1
, *tmp2
;
875 fgets(buf
, sizeof(buf
), file
);
877 /* Parse 'opt = val' -- must be easier ways to do this.
879 while (isspace(*opt
)) opt
++;
881 if (*val
== '#') continue; /* comment */
882 while (!isspace(*val
) && *val
!= '=' && *val
) val
++;
884 while (isspace(*val
)) val
++;
885 if (*val
!= '=') continue;
888 while (isspace(*val
)) val
++;
890 while (!isspace(*tmp2
) && *tmp2
!= '\n' && *tmp2
) tmp2
++;
894 if (strcmp(opt
, "fbdevDevice") == 0)
895 dpy
->fbdevDevice
= strdup(val
);
896 else if (strcmp(opt
, "clientDriverName") == 0)
897 dpy
->clientDriverName
= strdup(val
);
898 else if (strcmp(opt
, "rotateMode") == 0)
899 dpy
->rotateMode
= atoi(val
) ? 1 : 0;
900 else if (strcmp(opt
, "pciBusID") == 0) {
901 if (sscanf(val
, "PCI:%d:%d:%d",
902 &dpy
->driverContext
.pciBus
,
903 &dpy
->driverContext
.pciDevice
,
904 &dpy
->driverContext
.pciFunc
) != 3) {
905 fprintf(stderr
, "malformed bus id: %s\n", val
);
908 dpy
->driverContext
.pciBusID
= strdup(val
);
910 else if (strcmp(opt
, "chipset") == 0) {
911 if (sscanf(val
, "0x%x", &dpy
->driverContext
.chipset
) != 1)
912 fprintf(stderr
, "malformed chipset: %s\n", opt
);
914 else if (strcmp(opt
, "virtualWidth") == 0) {
915 if (sscanf(val
, "%d", &dpy
->driverContext
.shared
.virtualWidth
) != 1)
916 fprintf(stderr
, "malformed virtualWidth: %s\n", opt
);
918 else if (strcmp(opt
, "virtualHeight") == 0) {
919 if (sscanf(val
, "%d", &dpy
->driverContext
.shared
.virtualHeight
) != 1)
920 fprintf(stderr
, "malformed virutalHeight: %s\n", opt
);
922 else if (strcmp(opt
, "bpp") == 0) {
923 if (sscanf(val
, "%d", &dpy
->driverContext
.bpp
) != 1)
924 fprintf(stderr
, "malformed bpp: %s\n", opt
);
925 dpy
->driverContext
.cpp
= dpy
->driverContext
.bpp
/ 8;
927 else if (strcmp(opt
, "agpmode") == 0) {
928 if (sscanf(val
, "%d", &dpy
->driverContext
.agpmode
) != 1)
929 fprintf(stderr
, "malformed agpmode: %s\n", opt
);
931 else if (strcmp(opt
, "isPCI") == 0) {
932 dpy
->driverContext
.isPCI
= atoi(val
) ? 1 : 0;
938 if (dpy
->driverContext
.chipset
== 0 && dpy
->driverContext
.pciBusID
!= 0)
939 dpy
->driverContext
.chipset
= get_chipset_from_busid( dpy
);
944 static int InitDriver( Display
*dpy
)
948 * We're kind of combining the per-display and per-screen information
949 * which was kept separate in XFree86/DRI's libGL.
951 dpy
->dlHandle
= dlopen(dpy
->clientDriverName
, RTLD_NOW
| RTLD_GLOBAL
);
952 if (!dpy
->dlHandle
) {
953 fprintf(stderr
, "Unable to open %s: %s\n", dpy
->clientDriverName
,
958 /* Pull in Mini GLX specific hooks:
960 dpy
->driver
= (struct DRIDriverRec
*) dlsym(dpy
->dlHandle
,
963 fprintf(stderr
, "Couldn't find __driDriver in %s\n",
964 dpy
->clientDriverName
);
968 /* Pull in standard DRI client-side driver hooks:
970 dpy
->createNewScreen
= (PFNCREATENEWSCREENFUNC
)
971 dlsym(dpy
->dlHandle
, "__driCreateNewScreen");
972 if (!dpy
->createNewScreen
) {
973 fprintf(stderr
, "Couldn't find __driCreateScreen in %s\n",
974 dpy
->clientDriverName
);
982 dlclose(dpy
->dlHandle
);
989 /**********************************************************************/
990 /** \name Public API functions (Xlib and GLX) */
991 /**********************************************************************/
996 * \brief Initialize the graphics system.
998 * \param display_name currently ignored. It is recommended to pass it as NULL.
999 * \return a pointer to a #Display if the function is able to initialize
1000 * the graphics system, NULL otherwise.
1002 * Allocates a MiniGLXDisplayRec structure and fills in with information from a
1003 * configuration file.
1005 * Calls OpenFBDev() to open the framebuffer device and calls
1006 * DRIDriverRec::initFBDev to do the client-side initialization on it.
1008 * Loads the DRI driver and pulls in Mini GLX specific hooks into a
1009 * DRIDriverRec structure, and the standard DRI \e __driCreateScreen hook.
1010 * Asks the driver for a list of supported visuals. Performs the per-screen
1011 * client-side initialization. Also setups the callbacks in the screen private
1014 * Does the framebuffer device setup. Calls __miniglx_open_connections() to
1018 __miniglx_StartServer( const char *display_name
)
1023 dpy
= (Display
*)calloc(1, sizeof(Display
));
1027 dpy
->IsClient
= False
;
1029 if (!__read_config_file( dpy
)) {
1030 fprintf(stderr
, "Couldn't get configuration details\n");
1035 /* Open the fbdev device
1037 if (!OpenFBDev(dpy
, use_vt
)) {
1038 fprintf(stderr
, "OpenFBDev failed\n");
1043 if (!InitDriver(dpy
)) {
1044 fprintf(stderr
, "InitDriver failed\n");
1049 /* Perform the initialization normally done in the X server
1051 if (!dpy
->driver
->initFBDev( &dpy
->driverContext
)) {
1052 fprintf(stderr
, "%s: __driInitFBDev failed\n", __FUNCTION__
);
1053 dlclose(dpy
->dlHandle
);
1059 if (!SetupFBDev(dpy
)) {
1060 fprintf(stderr
, "SetupFBDev failed\n");
1065 /* unlock here if not using VT -- JDS */
1067 if (dpy
->driver
->restoreHardware
)
1068 dpy
->driver
->restoreHardware( &dpy
->driverContext
);
1069 DRM_UNLOCK( dpy
->driverContext
.drmFD
,
1070 dpy
->driverContext
.pSAREA
,
1071 dpy
->driverContext
.serverContext
);
1075 /* Ready for clients:
1077 if (!__miniglx_open_connections(dpy
)) {
1087 CallCreateNewScreen(Display
*dpy
, int scrn
, __DRIscreen
*psc
)
1091 drm_handle_t hSAREA
;
1095 __DRIversion ddx_version
;
1096 __DRIversion dri_version
;
1097 __DRIversion drm_version
;
1098 __DRIframebuffer framebuffer
;
1101 const char * err_msg
;
1102 const char * err_extra
;
1103 drmVersionPtr version
;
1107 err_msg
= "XF86DRIOpenConnection";
1110 hSAREA
= dpy
->driverContext
.shared
.hSAREA
;
1111 BusID
= dpy
->driverContext
.pciBusID
;
1113 fd
= drmOpen(NULL
, BusID
);
1115 err_msg
= "open DRM";
1116 err_extra
= strerror( -fd
);
1118 if (fd
< 0) goto done
;
1122 err_msg
= "drmGetMagic";
1125 if (drmGetMagic(fd
, &magic
)) goto done
;
1127 dpy
->authorized
= False
;
1128 send_char_msg( dpy
, 0, _Authorize
);
1129 send_msg( dpy
, 0, &magic
, sizeof(magic
));
1131 /* force net buffer flush */
1132 while (!dpy
->authorized
)
1133 handle_fd_events( dpy
, 0 );
1135 version
= drmGetVersion(fd
);
1137 drm_version
.major
= version
->version_major
;
1138 drm_version
.minor
= version
->version_minor
;
1139 drm_version
.patch
= version
->version_patchlevel
;
1140 drmFreeVersion(version
);
1143 drm_version
.major
= -1;
1144 drm_version
.minor
= -1;
1145 drm_version
.patch
= -1;
1149 * Get device name (like "tdfx") and the ddx version numbers.
1150 * We'll check the version in each DRI driver's "createScreen"
1153 err_msg
= "XF86DRIGetClientDriverName";
1154 ddx_version
.major
= 4;
1155 ddx_version
.minor
= 0;
1156 ddx_version
.patch
= 0;
1159 * Get the DRI X extension version.
1161 err_msg
= "XF86DRIQueryVersion";
1162 dri_version
.major
= 4;
1163 dri_version
.minor
= 0;
1164 dri_version
.patch
= 0;
1167 * Get device-specific info. pDevPriv will point to a struct
1168 * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h)
1169 * that has information about the screen size, depth, pitch,
1170 * ancilliary buffers, DRM mmap handles, etc.
1172 err_msg
= "XF86DRIGetDeviceInfo";
1173 hFB
= dpy
->driverContext
.shared
.hFrameBuffer
;
1174 framebuffer
.size
= dpy
->driverContext
.shared
.fbSize
;
1175 framebuffer
.stride
= dpy
->driverContext
.shared
.fbStride
;
1176 framebuffer
.dev_priv_size
= dpy
->driverContext
.driverClientMsgSize
;
1177 framebuffer
.dev_priv
= dpy
->driverContext
.driverClientMsg
;
1178 framebuffer
.width
= dpy
->driverContext
.shared
.virtualWidth
;
1179 framebuffer
.height
= dpy
->driverContext
.shared
.virtualHeight
;
1182 * Map the framebuffer region.
1184 status
= drmMap(fd
, hFB
, framebuffer
.size
,
1185 (drmAddressPtr
)&framebuffer
.base
);
1187 err_msg
= "drmMap of framebuffer";
1188 err_extra
= strerror( -status
);
1190 if ( status
!= 0 ) goto done
;
1193 * Map the SAREA region. Further mmap regions may be setup in
1194 * each DRI driver's "createScreen" function.
1196 status
= drmMap(fd
, hSAREA
, SAREA_MAX
, &pSAREA
);
1198 err_msg
= "drmMap of sarea";
1199 err_extra
= strerror( -status
);
1201 if ( status
== 0 ) {
1202 PFNGLXGETINTERNALVERSIONPROC get_ver
;
1204 get_ver
= (PFNGLXGETINTERNALVERSIONPROC
)
1205 glXGetProcAddress( (const GLubyte
*) "__glXGetInternalVersion" );
1207 err_msg
= "InitDriver";
1209 psp
= dpy
->createNewScreen(dpy
, scrn
, psc
, NULL
,
1216 (get_ver
!= NULL
) ? (*get_ver
)() : 20040602,
1217 (__GLcontextModes
**) &dpy
->driver_modes
);
1219 /* fill in dummy visual ids */
1221 __GLcontextModes
*temp
;
1222 temp
= (__GLcontextModes
*)dpy
->driver_modes
;
1226 temp
->visualID
= i
++;
1233 if ( psp
== NULL
) {
1234 if ( pSAREA
!= MAP_FAILED
) {
1235 (void)drmUnmap(pSAREA
, SAREA_MAX
);
1238 if ( framebuffer
.base
!= MAP_FAILED
) {
1239 (void)drmUnmap((drmAddress
)framebuffer
.base
, framebuffer
.size
);
1242 if ( framebuffer
.dev_priv
!= NULL
) {
1243 free(framebuffer
.dev_priv
);
1250 if ( err_extra
!= NULL
) {
1251 fprintf(stderr
, "libGL error: %s failed (%s)\n", err_msg
,
1255 fprintf(stderr
, "libGL error: %s failed\n", err_msg
);
1258 fprintf(stderr
, "libGL error: reverting to (slow) indirect rendering\n");
1265 * \brief Initialize the graphics system.
1267 * \param display_name currently ignored. It is recommended to pass it as NULL.
1268 * \return a pointer to a #Display if the function is able to initialize
1269 * the graphics system, NULL otherwise.
1271 * Allocates a MiniGLXDisplayRec structure and fills in with information from a
1272 * configuration file.
1274 * Calls __miniglx_open_connections() to connect to the server.
1276 * Loads the DRI driver and pulls in Mini GLX specific hooks into a
1277 * DRIDriverRec structure, and the standard DRI \e __driCreateScreen hook.
1278 * Asks the driver for a list of supported visuals. Performs the per-screen
1279 * client-side initialization. Also setups the callbacks in the screen private
1283 * - read config file
1284 * - what about virtualWidth, etc?
1285 * - determine dpy->driverClientMsgSize,
1286 * - allocate dpy->driverClientMsg
1289 XOpenDisplay( const char *display_name
)
1293 dpy
= (Display
*)calloc(1, sizeof(Display
));
1297 dpy
->IsClient
= True
;
1301 if (!__read_config_file( dpy
)) {
1302 fprintf(stderr
, "Couldn't get configuration details\n");
1307 /* Connect to the server and receive driverClientMsg
1309 if (!__miniglx_open_connections(dpy
)) {
1314 /* dlopen the driver .so file
1316 if (!InitDriver(dpy
)) {
1317 fprintf(stderr
, "InitDriver failed\n");
1322 /* Perform the client-side initialization.
1324 * Clearly there is a limit of one on the number of windows in
1325 * existence at any time.
1327 * Need to shut down DRM and free DRI data in XDestroyWindow(), too.
1329 dpy
->driScreen
.private = CallCreateNewScreen(dpy
, 0, &dpy
->driScreen
);
1330 if (!dpy
->driScreen
.private) {
1331 fprintf(stderr
, "%s: __driCreateScreen failed\n", __FUNCTION__
);
1332 dlclose(dpy
->dlHandle
);
1337 /* Anything more to do?
1344 * \brief Release display resources.
1346 * When the application is about to exit, the resources associated with the
1347 * graphics system can be released by calling this function.
1349 * \param dpy display handle. It becomes invalid at this point.
1351 * Destroys the window if any, and destroys the per-screen
1352 * driver private information.
1353 * Calls __miniglx_close_connections().
1355 * If a server, puts the the framebuffer back into the initial state.
1357 * Finally frees the display structure.
1360 XCloseDisplay( Display
*dpy
)
1362 glXMakeCurrent( dpy
, NULL
, NULL
);
1364 if (dpy
->NumWindows
)
1365 XDestroyWindow( dpy
, dpy
->TheWindow
);
1367 /* As this is done in XOpenDisplay, need to undo it here:
1369 dpy
->driScreen
.destroyScreen(dpy
, 0, dpy
->driScreen
.private);
1371 __miniglx_close_connections( dpy
);
1373 if (!dpy
->IsClient
) {
1374 /* put framebuffer back to initial state
1376 (*dpy
->driver
->haltFBDev
)( &dpy
->driverContext
);
1381 dlclose(dpy
->dlHandle
);
1387 * \brief Window creation.
1389 * \param display a display handle, as returned by XOpenDisplay().
1390 * \param parent the parent window for the new window. For Mini GLX this should
1392 * \code RootWindow(display, 0) \endcode
1393 * \param x the window abscissa. For Mini GLX, it should be zero.
1394 * \param y the window ordinate. For Mini GLX, it should be zero.
1395 * \param width the window width. For Mini GLX, this specifies the desired
1396 * screen width such as 1024 or 1280.
1397 * \param height the window height. For Mini GLX, this specifies the desired
1398 * screen height such as 768 or 1024.
1399 * \param border_width the border width. For Mini GLX, it should be zero.
1400 * \param depth the window pixel depth. For Mini GLX, this should be the depth
1401 * found in the #XVisualInfo object returned by glXChooseVisual()
1402 * \param winclass the window class. For Mini GLX this value should be
1404 * \param visual the visual type. It should be the visual field of the
1405 * #XVisualInfo object returned by glXChooseVisual().
1406 * \param valuemask which fields of the XSetWindowAttributes() are to be used.
1407 * For Mini GLX this is typically the bitmask
1408 * \code CWBackPixel | CWBorderPixel | CWColormap \endcode
1409 * \param attributes initial window attributes. The
1410 * XSetWindowAttributes::background_pixel, XSetWindowAttributes::border_pixel
1411 * and XSetWindowAttributes::colormap fields should be set.
1413 * \return a window handle if it succeeds or zero if it fails.
1415 * \note For Mini GLX, windows are full-screen; they cover the entire frame
1416 * buffer. Also, Mini GLX imposes a limit of one window. A second window
1417 * cannot be created until the first one is destroyed.
1419 * This function creates and initializes a ::MiniGLXWindowRec structure after
1420 * ensuring that there is no other window created. Performs the per-drawable
1421 * client-side initialization calling the __DRIscreenRec::createDrawable
1426 XCreateWindow( Display
*dpy
, Window parent
, int x
, int y
,
1427 unsigned int width
, unsigned int height
,
1428 unsigned int border_width
, int depth
, unsigned int winclass
,
1429 Visual
*visual
, unsigned long valuemask
,
1430 XSetWindowAttributes
*attributes
)
1432 const int empty_attribute_list
[1] = { None
};
1439 (void) border_width
;
1445 if (!dpy
->IsClient
) {
1446 fprintf(stderr
, "Server process may not create windows (currently)\n");
1450 if (dpy
->NumWindows
> 0)
1451 return NULL
; /* only allow one window */
1453 assert(dpy
->TheWindow
== NULL
);
1455 win
= malloc(sizeof(struct MiniGLXWindowRec
));
1459 /* In rotated mode, translate incoming x,y,width,height into
1460 * 'normal' coordinates.
1462 if (dpy
->rotateMode
) {
1464 tmp
= width
; width
= height
; height
= tmp
;
1465 tmp
= x
; x
= y
; y
= tmp
;
1468 /* init other per-window fields */
1473 win
->visual
= visual
; /* ptr assignment */
1475 win
->bytesPerPixel
= dpy
->driverContext
.cpp
;
1476 win
->rowStride
= dpy
->driverContext
.shared
.virtualWidth
* win
->bytesPerPixel
;
1477 win
->size
= win
->rowStride
* height
;
1478 win
->frontStart
= dpy
->driverContext
.FBAddress
;
1479 win
->frontBottom
= (GLubyte
*) win
->frontStart
+ (height
-1) * win
->rowStride
;
1481 /* This is incorrect: the hardware driver could put the backbuffer
1482 * just about anywhere. These fields, including the above are
1483 * hardware dependent & don't really belong here.
1485 if (visual
->mode
->doubleBufferMode
) {
1486 win
->backStart
= (GLubyte
*) win
->frontStart
+
1487 win
->rowStride
* dpy
->driverContext
.shared
.virtualHeight
;
1488 win
->backBottom
= (GLubyte
*) win
->backStart
1489 + (height
- 1) * win
->rowStride
;
1490 win
->curBottom
= win
->backBottom
;
1493 /* single buffered */
1494 win
->backStart
= NULL
;
1495 win
->backBottom
= NULL
;
1496 win
->curBottom
= win
->frontBottom
;
1499 dpy
->driScreen
.createNewDrawable(dpy
, visual
->mode
, (int) win
,
1500 &win
->driDrawable
, GLX_WINDOW_BIT
, empty_attribute_list
);
1502 if (!win
->driDrawable
.private) {
1503 fprintf(stderr
, "%s: dri.createDrawable failed\n", __FUNCTION__
);
1509 dpy
->TheWindow
= win
;
1516 * \brief Destroy window.
1518 * \param display display handle.
1519 * \param w window handle.
1521 * This function calls XUnmapWindow() and frees window \p w.
1523 * In case of destroying the current buffer first unbinds the GLX context
1524 * by calling glXMakeCurrent() with no drawable.
1527 XDestroyWindow( Display
*display
, Window win
)
1529 if (display
&& display
->IsClient
&& win
) {
1530 /* check if destroying the current buffer */
1531 Window curDraw
= glXGetCurrentDrawable();
1532 if (win
== curDraw
) {
1533 glXMakeCurrent( display
, NULL
, NULL
);
1536 XUnmapWindow( display
, win
);
1538 /* Destroy the drawable. */
1539 win
->driDrawable
.destroyDrawable(display
, win
->driDrawable
.private);
1542 /* unlink window from display */
1543 display
->NumWindows
--;
1544 assert(display
->NumWindows
== 0);
1545 display
->TheWindow
= NULL
;
1553 * \brief Create color map structure.
1555 * \param dpy the display handle as returned by XOpenDisplay().
1556 * \param w the window on whose screen you want to create a color map. This
1557 * parameter is ignored by Mini GLX but should be the value returned by the
1558 * \code RootWindow(display, 0) \endcode macro.
1559 * \param visual a visual type supported on the screen. This parameter is
1560 * ignored by Mini GLX but should be the XVisualInfo::visual returned by
1561 * glXChooseVisual().
1562 * \param alloc the color map entries to be allocated. This parameter is ignored
1563 * by Mini GLX but should be set to #AllocNone.
1565 * \return the color map.
1567 * This function is only provided to ease porting. Practically a no-op -
1568 * returns a pointer to a dynamically allocated chunk of memory (one byte).
1571 XCreateColormap( Display
*dpy
, Window w
, Visual
*visual
, int alloc
)
1577 return (Colormap
) malloc(1);
1582 * \brief Destroy color map structure.
1584 * \param display The display handle as returned by XOpenDisplay().
1585 * \param colormap the color map to destroy.
1587 * This function is only provided to ease porting. Practically a no-op.
1589 * Frees the memory pointed by \p colormap.
1592 XFreeColormap( Display
*display
, Colormap colormap
)
1601 * \brief Free client data.
1603 * \param data the data that is to be freed.
1605 * Frees the memory pointed by \p data.
1615 * \brief Query available visuals.
1617 * \param dpy the display handle, as returned by XOpenDisplay().
1618 * \param vinfo_mask a bitmask indicating which fields of the \p vinfo_template
1619 * are to be matched. The value must be \c VisualScreenMask.
1620 * \param vinfo_template a template whose fields indicate which visual
1621 * attributes must be matched by the results. The XVisualInfo::screen field of
1622 * this structure must be zero.
1623 * \param nitens_return will hold the number of visuals returned.
1625 * \return the address of an array of all available visuals.
1627 * An example of using XGetVisualInfo() to get all available visuals follows:
1630 * XVisualInfo vinfo_template, *results;
1631 * int nitens_return;
1632 * Display *dpy = XOpenDisplay(NULL);
1633 * vinfo_template.screen = 0;
1634 * results = XGetVisualInfo(dpy, VisualScreenMask, &vinfo_template, &nitens_return);
1637 * Returns the list of all ::XVisualInfo available, one per
1638 * ::__GLcontextMode stored in MiniGLXDisplayRec::modes.
1641 XGetVisualInfo( Display
*dpy
, long vinfo_mask
, XVisualInfo
*vinfo_template
, int *nitens_return
)
1643 const __GLcontextModes
*mode
;
1644 XVisualInfo
*results
;
1648 // ASSERT(vinfo_mask == VisualScreenMask);
1649 ASSERT(vinfo_template
.screen
== 0);
1651 if (vinfo_mask
== VisualIDMask
)
1653 for ( mode
= dpy
->driver_modes
; mode
!= NULL
; mode
= mode
->next
)
1654 if (mode
->visualID
== vinfo_template
->visualid
)
1660 results
= (XVisualInfo
*)calloc(1, n
* sizeof(XVisualInfo
));
1666 visResults
= (Visual
*)calloc(1, n
* sizeof(Visual
));
1673 for ( mode
= dpy
->driver_modes
; mode
!= NULL
; mode
= mode
->next
)
1674 if (mode
->visualID
== vinfo_template
->visualid
)
1676 visResults
[0].mode
=mode
;
1677 visResults
[0].visInfo
= results
;
1678 visResults
[0].dpy
= dpy
;
1679 if (dpy
->driverContext
.bpp
== 32)
1680 visResults
[0].pixelFormat
= PF_B8G8R8A8
; /* XXX: FIX ME */
1682 visResults
[0].pixelFormat
= PF_B5G6R5
; /* XXX: FIX ME */
1684 results
[0].visual
= visResults
;
1685 results
[0].visualid
= mode
->visualID
;
1686 #if defined(__cplusplus) || defined(c_plusplus)
1687 results
[0].c_class
= TrueColor
;
1689 results
[0].class = TrueColor
;
1691 results
[0].depth
= mode
->redBits
+
1695 results
[0].bits_per_rgb
= dpy
->driverContext
.bpp
;
1700 else // if (vinfo_mask == VisualScreenMask)
1703 for ( mode
= dpy
->driver_modes
; mode
!= NULL
; mode
= mode
->next
)
1706 results
= (XVisualInfo
*)calloc(1, n
* sizeof(XVisualInfo
));
1712 visResults
= (Visual
*)calloc(1, n
* sizeof(Visual
));
1719 for ( mode
= dpy
->driver_modes
, i
= 0 ; mode
!= NULL
; mode
= mode
->next
, i
++ ) {
1720 visResults
[i
].mode
= mode
;
1721 visResults
[i
].visInfo
= results
+ i
;
1722 visResults
[i
].dpy
= dpy
;
1724 if (dpy
->driverContext
.bpp
== 32)
1725 visResults
[i
].pixelFormat
= PF_B8G8R8A8
; /* XXX: FIX ME */
1727 visResults
[i
].pixelFormat
= PF_B5G6R5
; /* XXX: FIX ME */
1729 results
[i
].visual
= visResults
+ i
;
1730 results
[i
].visualid
= mode
->visualID
;
1731 #if defined(__cplusplus) || defined(c_plusplus)
1732 results
[i
].c_class
= TrueColor
;
1734 results
[i
].class = TrueColor
;
1736 results
[i
].depth
= mode
->redBits
+
1740 results
[i
].bits_per_rgb
= dpy
->driverContext
.bpp
;
1749 * \brief Return a visual that matches specified attributes.
1751 * \param dpy the display handle, as returned by XOpenDisplay().
1752 * \param screen the screen number. It is currently ignored by Mini GLX and
1754 * \param attribList a list of GLX attributes which describe the desired pixel
1755 * format. It is terminated by the token \c None.
1757 * The attributes are as follows:
1759 * This attribute should always be present in order to maintain compatibility
1762 * If present, only RGBA pixel formats will be considered. Otherwise, only
1763 * color index formats are considered.
1764 * \arg GLX_DOUBLEBUFFER:
1765 * if present, only double-buffered pixel formats will be chosen.
1766 * \arg GLX_RED_SIZE \e n:
1767 * Must be followed by a non-negative integer indicating the minimum number of
1768 * bits per red pixel component that is acceptable.
1769 * \arg GLX_GREEN_SIZE \e n:
1770 * Must be followed by a non-negative integer indicating the minimum number of
1771 * bits per green pixel component that is acceptable.
1772 * \arg GLX_BLUE_SIZE \e n:
1773 * Must be followed by a non-negative integer indicating the minimum number of
1774 * bits per blue pixel component that is acceptable.
1775 * \arg GLX_ALPHA_SIZE \e n:
1776 * Must be followed by a non-negative integer indicating the minimum number of
1777 * bits per alpha pixel component that is acceptable.
1778 * \arg GLX_STENCIL_SIZE \e n:
1779 * Must be followed by a non-negative integer indicating the minimum number of
1780 * bits per stencil value that is acceptable.
1781 * \arg GLX_DEPTH_SIZE \e n:
1782 * Must be followed by a non-negative integer indicating the minimum number of
1783 * bits per depth component that is acceptable.
1785 * This token is used to terminate the attribute list.
1787 * \return a pointer to an #XVisualInfo object which most closely matches the
1788 * requirements of the attribute list. If there is no visual which matches the
1789 * request, \c NULL will be returned.
1791 * \note Visuals with accumulation buffers are not available.
1793 * This function searches the list of available visual configurations in
1794 * MiniGLXDisplayRec::configs for a configuration which best matches the GLX
1795 * attribute list parameter. A new ::XVisualInfo object is created which
1796 * describes the visual configuration. The match criteria is described in the
1800 glXChooseVisual( Display
*dpy
, int screen
, int *attribList
)
1802 const __GLcontextModes
*mode
;
1804 XVisualInfo
*visInfo
;
1806 GLboolean rgbFlag
= GL_FALSE
, dbFlag
= GL_FALSE
, stereoFlag
= GL_FALSE
;
1807 GLint redBits
= 0, greenBits
= 0, blueBits
= 0, alphaBits
= 0;
1808 GLint indexBits
= 0, depthBits
= 0, stencilBits
= 0;
1809 GLint numSamples
= 0;
1813 * XXX in the future, <screen> might be interpreted as a VT
1816 ASSERT(screen
== 0);
1818 vis
= (Visual
*)calloc(1, sizeof(Visual
));
1822 visInfo
= (XVisualInfo
*)malloc(sizeof(XVisualInfo
));
1828 visInfo
->visual
= vis
;
1829 vis
->visInfo
= visInfo
;
1832 /* parse the attribute list */
1833 for (attrib
= attribList
; attrib
&& *attrib
!= None
; attrib
++) {
1834 switch (attrib
[0]) {
1835 case GLX_DOUBLEBUFFER
:
1842 redBits
= attrib
[1];
1845 case GLX_GREEN_SIZE
:
1846 greenBits
= attrib
[1];
1850 blueBits
= attrib
[1];
1853 case GLX_ALPHA_SIZE
:
1854 alphaBits
= attrib
[1];
1857 case GLX_STENCIL_SIZE
:
1858 stencilBits
= attrib
[1];
1861 case GLX_DEPTH_SIZE
:
1862 depthBits
= attrib
[1];
1866 case GLX_ACCUM_RED_SIZE
:
1867 accumRedBits
= attrib
[1];
1870 case GLX_ACCUM_GREEN_SIZE
:
1871 accumGreenBits
= attrib
[1];
1874 case GLX_ACCUM_BLUE_SIZE
:
1875 accumBlueBits
= attrib
[1];
1878 case GLX_ACCUM_ALPHA_SIZE
:
1879 accumAlphaBits
= attrib
[1];
1883 /* ignored for now */
1887 /* unexpected token */
1888 fprintf(stderr
, "unexpected token in glXChooseVisual attrib list\n");
1895 /* search screen configs for suitable visual */
1903 for ( mode
= dpy
->driver_modes
; mode
!= NULL
; mode
= mode
->next
) {
1905 if (mode
->rgbMode
== rgbFlag
&&
1906 mode
->doubleBufferMode
== dbFlag
&&
1907 mode
->redBits
>= redBits
&&
1908 mode
->greenBits
>= greenBits
&&
1909 mode
->blueBits
>= blueBits
&&
1910 mode
->alphaBits
>= alphaBits
&&
1911 mode
->depthBits
>= depthBits
&&
1912 mode
->stencilBits
>= stencilBits
) {
1914 visInfo
->visualid
= i
;
1922 /* compute depth and bpp */
1924 /* XXX maybe support depth 16 someday */
1925 #if defined(__cplusplus) || defined(c_plusplus)
1926 visInfo
->c_class
= TrueColor
;
1928 visInfo
->class = TrueColor
;
1930 visInfo
->depth
= dpy
->driverContext
.bpp
;
1931 visInfo
->bits_per_rgb
= dpy
->driverContext
.bpp
;
1932 if (dpy
->driverContext
.bpp
== 32)
1933 vis
->pixelFormat
= PF_B8G8R8A8
;
1935 vis
->pixelFormat
= PF_B5G6R5
;
1938 /* color index mode */
1939 #if defined(__cplusplus) || defined(c_plusplus)
1940 visInfo
->c_class
= PseudoColor
;
1942 visInfo
->class = PseudoColor
;
1945 visInfo
->bits_per_rgb
= 8; /* bits/pixel */
1946 vis
->pixelFormat
= PF_CI8
;
1954 * \brief Return information about GLX visuals.
1956 * \param dpy the display handle, as returned by XOpenDisplay().
1957 * \param vis the visual to be queried, as returned by glXChooseVisual().
1958 * \param attrib the visual attribute to be returned.
1959 * \param value pointer to an integer in which the result of the query will be
1962 * \return zero if no error occurs, \c GLX_INVALID_ATTRIBUTE if the attribute
1963 * parameter is invalid, or \c GLX_BAD_VISUAL if the \p vis parameter is
1966 * Returns the appropriate attribute of ::__GLXvisualConfig pointed by
1967 * MiniGLXVisualRec::glxConfig of XVisualInfo::visual.
1972 glXGetConfig( Display
*dpy
, XVisualInfo
*vis
, int attrib
, int *value
)
1974 const __GLcontextModes
*mode
= vis
->visual
->mode
;
1977 return GLX_BAD_VISUAL
;
1985 *value
= mode
->rgbMode
;
1987 case GLX_DOUBLEBUFFER
:
1988 *value
= mode
->doubleBufferMode
;
1991 *value
= mode
->redBits
;
1993 case GLX_GREEN_SIZE
:
1994 *value
= mode
->greenBits
;
1997 *value
= mode
->blueBits
;
1999 case GLX_ALPHA_SIZE
:
2000 *value
= mode
->alphaBits
;
2002 case GLX_DEPTH_SIZE
:
2003 *value
= mode
->depthBits
;
2005 case GLX_STENCIL_SIZE
:
2006 *value
= mode
->stencilBits
;
2010 return GLX_BAD_ATTRIBUTE
;
2017 * \brief Create a new GLX rendering context.
2019 * \param dpy the display handle, as returned by XOpenDisplay().
2020 * \param vis the visual that defines the frame buffer resources available to
2021 * the rendering context, as returned by glXChooseVisual().
2022 * \param shareList If non-zero, texture objects and display lists are shared
2023 * with the named rendering context. If zero, texture objects and display lists
2024 * will (initially) be private to this context. They may be shared when a
2025 * subsequent context is created.
2026 * \param direct whether direct or indirect rendering is desired. For Mini GLX
2027 * this value is ignored but it should be set to \c True.
2029 * \return a ::GLXContext handle if it succeeds or zero if it fails due to
2030 * invalid parameter or insufficient resources.
2032 * This function creates and initializes a ::MiniGLXContextRec structure and
2033 * calls the __DRIscreenRec::createContext method to initialize the client
2037 glXCreateContext( Display
*dpy
, XVisualInfo
*vis
,
2038 GLXContext shareList
, Bool direct
)
2045 ctx
= (struct MiniGLXContextRec
*)calloc(1, sizeof(struct MiniGLXContextRec
));
2049 ctx
->vid
= vis
->visualid
;
2052 sharePriv
= shareList
->driContext
.private;
2056 ctx
->driContext
.private = dpy
->driScreen
.createNewContext(dpy
, vis
->visual
->mode
,
2057 GLX_WINDOW_BIT
, sharePriv
, &ctx
->driContext
);
2059 if (!ctx
->driContext
.private) {
2069 * \brief Destroy a GLX context.
2071 * \param dpy the display handle, as returned by XOpenDisplay().
2072 * \param ctx the GLX context to be destroyed.
2074 * This function frees the \p ctx parameter after unbinding the current context
2075 * by calling the __DRIcontextRec::bindContext method with zeros and calling
2076 * the __DRIcontextRec::destroyContext method.
2079 glXDestroyContext( Display
*dpy
, GLXContext ctx
)
2081 GLXContext glxctx
= glXGetCurrentContext();
2084 if (glxctx
== ctx
) {
2085 /* destroying current context */
2086 ctx
->driContext
.bindContext3(dpy
, 0, 0, 0, 0);
2089 ctx
->driContext
.destroyContext(dpy
, 0, ctx
->driContext
.private);
2096 * \brief Bind a GLX context to a window or a pixmap.
2098 * \param dpy the display handle, as returned by XOpenDisplay().
2099 * \param drawable the window or drawable to bind to the rendering context.
2100 * This should be the value returned by XCreateWindow().
2101 * \param ctx the GLX context to be destroyed.
2103 * \return \c True if it succeeds, \c False otherwise to indicate an invalid
2104 * display, window or context parameter.
2106 * The current rendering context may be unbound by calling glXMakeCurrent()
2107 * with the window and context parameters set to zero.
2109 * An application may create any number of rendering contexts and bind them as
2110 * needed. Note that binding a rendering context is generally not a
2111 * light-weight operation. Most simple OpenGL applications create only one
2112 * rendering context.
2114 * This function first unbinds any old context via
2115 * __DRIcontextRec::unbindContext and binds the new one via
2116 * __DRIcontextRec::bindContext.
2118 * If \p drawable is zero it unbinds the GLX context by calling
2119 * __DRIcontextRec::bindContext with zeros.
2122 glXMakeCurrent( Display
*dpy
, GLXDrawable drawable
, GLXContext ctx
)
2124 if (dpy
&& drawable
&& ctx
) {
2125 GLXContext oldContext
= glXGetCurrentContext();
2126 GLXDrawable oldDrawable
= glXGetCurrentDrawable();
2129 oldContext
->driContext
.unbindContext3(dpy
, 0,
2130 (__DRIid
) oldDrawable
, (__DRIid
) oldDrawable
,
2131 &oldContext
->driContext
);
2134 CurrentContext
= ctx
;
2135 ctx
->driContext
.bindContext3(dpy
, 0, (__DRIid
) drawable
,
2136 (__DRIid
) drawable
, &ctx
->driContext
);
2137 ctx
->drawBuffer
= drawable
;
2138 ctx
->curBuffer
= drawable
;
2140 else if (ctx
&& dpy
) {
2142 ctx
->driContext
.bindContext3(dpy
, 0, 0, 0, 0);
2145 CurrentContext
= 0; /* kw: this seems to be intended??? */
2153 * \brief Exchange front and back buffers.
2155 * \param dpy the display handle, as returned by XOpenDisplay().
2156 * \param drawable the drawable whose buffers are to be swapped.
2158 * Any pending rendering commands will be completed before the buffer swap
2161 * Calling glXSwapBuffers() on a window which is single-buffered has no effect.
2163 * This function just calls the __DRIdrawableRec::swapBuffers method to do the
2167 glXSwapBuffers( Display
*dpy
, GLXDrawable drawable
)
2169 if (!dpy
|| !drawable
)
2172 drawable
->driDrawable
.swapBuffers(dpy
, drawable
->driDrawable
.private);
2177 * \brief Return the current context
2179 * \return the current context, as specified by glXMakeCurrent(), or zero if no
2180 * context is currently bound.
2182 * \sa glXCreateContext(), glXMakeCurrent()
2184 * Returns the value of the ::CurrentContext global variable.
2187 glXGetCurrentContext( void )
2189 return CurrentContext
;
2194 * \brief Return the current drawable.
2196 * \return the current drawable, as specified by glXMakeCurrent(), or zero if
2197 * no drawable is currently bound.
2199 * This function gets the current context via glXGetCurrentContext() and
2200 * returns the MiniGLXContextRec::drawBuffer attribute.
2203 glXGetCurrentDrawable( void )
2205 GLXContext glxctx
= glXGetCurrentContext();
2207 return glxctx
->drawBuffer
;
2214 __glXCreateContextWithConfig(__DRInativeDisplay
*dpy
, int screen
,
2215 int fbconfigID
, void *contextID
, drm_context_t
*hHWContext
)
2217 __DRIscreen
*pDRIScreen
;
2218 __DRIscreenPrivate
*psp
;
2220 pDRIScreen
= __glXFindDRIScreen(dpy
, screen
);
2221 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
2225 psp
= (__DRIscreenPrivate
*) pDRIScreen
->private;
2228 if (drmCreateContext(psp
->fd
, hHWContext
)) {
2229 fprintf(stderr
, ">>> drmCreateContext failed\n");
2232 *(void**)contextID
= (void*) *hHWContext
;
2240 __glXGetDrawableInfo(__DRInativeDisplay
*dpy
, int scrn
,
2241 __DRIid draw
, unsigned int * index
, unsigned int * stamp
,
2242 int * x
, int * y
, int * width
, int * height
,
2243 int * numClipRects
, drm_clip_rect_t
** pClipRects
,
2244 int * backX
, int * backY
,
2245 int * numBackClipRects
, drm_clip_rect_t
** pBackClipRects
)
2247 GLXDrawable drawable
= (GLXDrawable
) draw
;
2248 drm_clip_rect_t
* cliprect
;
2249 Display
* display
= (Display
*)dpy
;
2250 __DRIcontextPrivate
*pcp
= (__DRIcontextPrivate
*)CurrentContext
->driContext
.private;
2251 if (drawable
== 0) {
2255 cliprect
= (drm_clip_rect_t
*) _mesa_malloc(sizeof(drm_clip_rect_t
));
2256 cliprect
->x1
= drawable
->x
;
2257 cliprect
->y1
= drawable
->y
;
2258 cliprect
->x2
= drawable
->x
+ drawable
->w
;
2259 cliprect
->y2
= drawable
->y
+ drawable
->h
;
2261 /* the drawable index is by client id */
2262 *index
= display
->clientID
;
2264 *stamp
= pcp
->driScreenPriv
->pSAREA
->drawableTable
[display
->clientID
].stamp
;
2267 *width
= drawable
->w
;
2268 *height
= drawable
->h
;
2270 *pClipRects
= cliprect
;
2272 *backX
= drawable
->x
;
2273 *backY
= drawable
->y
;
2274 *numBackClipRects
= 0;
2275 *pBackClipRects
= 0;
2282 XF86DRIDestroyContext(__DRInativeDisplay
*dpy
, int screen
, __DRIid context_id
)
2289 XF86DRICreateDrawable(__DRInativeDisplay
*dpy
, int screen
, __DRIid drawable
,
2290 drm_drawable_t
*hHWDrawable
)
2297 XF86DRIDestroyDrawable(__DRInativeDisplay
*dpy
, int screen
, __DRIid drawable
)
2304 * \brief Query function address.
2306 * The glXGetProcAddress() function will return the address of any available
2307 * OpenGL or Mini GLX function.
2309 * \param procName name of the function to be returned.
2311 * \return If \p procName is a valid function name, a pointer to that function
2312 * will be returned. Otherwise, \c NULL will be returned.
2314 * The purpose of glXGetProcAddress() is to facilitate using future extensions
2315 * to OpenGL or Mini GLX. If a future version of the library adds new extension
2316 * functions they'll be accessible via glXGetProcAddress(). The alternative is
2317 * to hard-code calls to the new functions in the application but doing so will
2318 * prevent linking the application with older versions of the library.
2320 * Returns the function address by looking up its name in a static (name,
2321 * address) pair list.
2323 void (*glXGetProcAddress(const GLubyte
*procname
))( void )
2325 struct name_address
{
2329 static const struct name_address functions
[] = {
2330 { "glXChooseVisual", (void *) glXChooseVisual
},
2331 { "glXCreateContext", (void *) glXCreateContext
},
2332 { "glXDestroyContext", (void *) glXDestroyContext
},
2333 { "glXMakeCurrent", (void *) glXMakeCurrent
},
2334 { "glXSwapBuffers", (void *) glXSwapBuffers
},
2335 { "glXGetCurrentContext", (void *) glXGetCurrentContext
},
2336 { "glXGetCurrentDrawable", (void *) glXGetCurrentDrawable
},
2337 { "glXGetProcAddress", (void *) glXGetProcAddress
},
2338 { "XOpenDisplay", (void *) XOpenDisplay
},
2339 { "XCloseDisplay", (void *) XCloseDisplay
},
2340 { "XCreateWindow", (void *) XCreateWindow
},
2341 { "XDestroyWindow", (void *) XDestroyWindow
},
2342 { "XMapWindow", (void *) XMapWindow
},
2343 { "XCreateColormap", (void *) XCreateColormap
},
2344 { "XFreeColormap", (void *) XFreeColormap
},
2345 { "XFree", (void *) XFree
},
2346 { "XGetVisualinfo", (void *) XGetVisualInfo
},
2347 { "glXCreatePbuffer", (void *) glXCreatePbuffer
},
2348 { "glXDestroyPbuffer", (void *) glXDestroyPbuffer
},
2349 { "glXChooseFBConfig", (void *) glXChooseFBConfig
},
2350 { "glXGetVisualFromFBConfig", (void *) glXGetVisualFromFBConfig
},
2351 { "__glXCreateContextWithConfig", (void *) __glXCreateContextWithConfig
},
2352 { "__glXGetDrawableInfo", (void *) __glXGetDrawableInfo
},
2353 { "__glXWindowExists", (void *) __glXWindowExists
},
2354 { "__glXCreateContextModes", (void *) _gl_context_modes_create
},
2355 { "__glXFindDRIScreen", (void *)__glXFindDRIScreen
},
2356 { "__glXScrEnableExtension", (void *)__glXScrEnableExtension
},
2359 const struct name_address
*entry
;
2360 for (entry
= functions
; entry
->name
; entry
++) {
2361 if (strcmp(entry
->name
, (const char *) procname
) == 0) {
2365 return _glapi_get_proc_address((const char *) procname
);
2370 * \brief Query the Mini GLX version.
2372 * \param dpy the display handle. It is currently ignored, but should be the
2373 * value returned by XOpenDisplay().
2374 * \param major receives the major version number of Mini GLX.
2375 * \param minor receives the minor version number of Mini GLX.
2377 * \return \c True if the function succeeds, \c False if the function fails due
2378 * to invalid parameters.
2380 * \sa #MINI_GLX_VERSION_1_0.
2382 * Returns the hard-coded Mini GLX version.
2385 glXQueryVersion( Display
*dpy
, int *major
, int *minor
)
2395 * \brief Create a new pbuffer.
2398 glXCreatePbuffer( Display
*dpy
, GLXFBConfig config
, const int *attribList
)
2405 glXDestroyPbuffer( Display
*dpy
, GLXPbuffer pbuf
)
2412 glXChooseFBConfig( Display
*dpy
, int screen
, const int *attribList
,
2415 GLXFBConfig
*f
= (GLXFBConfig
*) malloc(sizeof(GLXFBConfig
));
2416 f
->visInfo
= glXChooseVisual( dpy
, screen
, (int *) attribList
);
2430 glXGetVisualFromFBConfig( Display
*dpy
, GLXFBConfig config
)
2432 /* XVisualInfo and GLXFBConfig are the same structure */
2434 return config
.visInfo
;
2437 void *glXAllocateMemoryMESA(Display
*dpy
, int scrn
,
2438 size_t size
, float readFreq
,
2439 float writeFreq
, float priority
)
2441 if (dpy
->driScreen
.private && dpy
->driScreen
.allocateMemory
) {
2442 return (*dpy
->driScreen
.allocateMemory
)( dpy
, scrn
, size
,
2443 readFreq
, writeFreq
,
2448 void glXFreeMemoryMESA(Display
*dpy
, int scrn
, void *pointer
){
2449 if (dpy
->driScreen
.private && dpy
->driScreen
.freeMemory
) {
2450 (*dpy
->driScreen
.freeMemory
)( dpy
, scrn
, pointer
);
2454 GLuint
glXGetMemoryOffsetMESA( Display
*dpy
, int scrn
,
2455 const void *pointer
)
2457 if (dpy
->driScreen
.private && dpy
->driScreen
.memoryOffset
) {
2458 return (*dpy
->driScreen
.memoryOffset
)( dpy
, scrn
, pointer
);
2463 __glXScrEnableExtension( void *psc
, const char * name
)