3 * \brief Mini GLX interface functions.
6 * The Mini GLX interface is a subset of the GLX interface, plus a
7 * minimal set of Xlib functions.
11 * Mesa 3-D graphics library
14 * Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
16 * Permission is hereby granted, free of charge, to any person obtaining a
17 * copy of this software and associated documentation files (the "Software"),
18 * to deal in the Software without restriction, including without limitation
19 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
20 * and/or sell copies of the Software, and to permit persons to whom the
21 * Software is furnished to do so, subject to the following conditions:
23 * The above copyright notice and this permission notice shall be included
24 * in all copies or substantial portions of the Software.
26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
27 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
29 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
30 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38 * \section miniglxIntro Introduction
40 * The Mini GLX interface facilitates OpenGL rendering on embedded devices. The
41 * interface is a subset of the GLX interface, plus a minimal set of Xlib-like
44 * Programs written to the Mini GLX specification should run unchanged
45 * on systems with the X Window System and the GLX extension (after
46 * recompilation). The intention is to allow flexibility for
47 * prototyping and testing.
49 * The files in the src/miniglx/ directory are compiled to build the
50 * libGL.so library. This is the library which applications link with.
51 * libGL.so in turn, loads the hardware-specific device driver.
54 * \section miniglxDoxygen About Doxygen
56 * For a list of all files, select <b>File List</b>. Choose a file from
57 * the list for a list of all functions in the file.
59 * For a list of all functions, types, constants, etc.
60 * select <b>File Members</b>.
63 * \section miniglxReferences References
65 * - <A HREF="file:../../docs/MiniGLX.html">Mini GLX Specification</A>,
66 * Tungsten Graphics, Inc.
67 * - OpenGL Graphics with the X Window System, Silicon Graphics, Inc.,
68 * ftp://ftp.sgi.com/opengl/doc/opengl1.2/glx1.3.ps
69 * - Xlib - C Language X Interface, X Consortium Standard, X Version 11,
70 * Release 6.4, ftp://ftp.x.org/pub/R6.4/xc/doc/hardcopy/X11/xlib.PS.gz
71 * - XFree86 Man pages, The XFree86 Project, Inc.,
72 * http://www.xfree86.org/current/manindex3.html
77 * \page datatypes Notes on the XVisualInfo, Visual, and __GLXvisualConfig data types
79 * -# X (unfortunately) has two (or three) data types which
80 * describe visuals. Ideally, there would just be one.
81 * -# We need the #__GLXvisualConfig type to augment #XVisualInfo and #Visual
82 * because we need to describe the GLX-specific attributes of visuals.
83 * -# In this interface there is a one-to-one-to-one correspondence between
84 * the three types and they're all interconnected.
85 * -# The #XVisualInfo type has a pointer to a #Visual. The #Visual structure
86 * (aka MiniGLXVisualRec) has a pointer to the #__GLXvisualConfig. The
87 * #Visual structure also has a pointer pointing back to the #XVisualInfo.
88 * -# The #XVisualInfo structure is the only one who's contents are public.
89 * -# The glXChooseVisual() and XGetVisualInfo() are the only functions that
90 * return #XVisualInfo structures. They can be freed with XFree(), though
91 * there is a small memory leak.
104 #include <sys/ioctl.h>
105 #include <sys/mman.h>
106 #include <sys/types.h>
107 #include <sys/time.h> /* for gettimeofday */
108 #include <linux/kd.h>
109 #include <linux/vt.h>
111 #include "miniglxP.h"
112 #include "dri_util.h"
115 #include "glcontextmodes.h"
119 static GLboolean
__glXCreateContextWithConfig(__DRInativeDisplay
*dpy
,
120 int screen
, int fbconfigID
, void *contextID
,
121 drm_context_t
*hHWContext
);
123 static GLboolean
__glXGetDrawableInfo(__DRInativeDisplay
*dpy
, int scrn
,
124 __DRIid draw
, unsigned int * index
, unsigned int * stamp
,
125 int * x
, int * y
, int * width
, int * height
,
126 int * numClipRects
, drm_clip_rect_t
** pClipRects
,
127 int * backX
, int * backY
,
128 int * numBackClipRects
, drm_clip_rect_t
** pBackClipRects
);
130 static __DRIscreen
* __glXFindDRIScreen(__DRInativeDisplay
*dpy
, int scrn
);
132 static GLboolean
__glXWindowExists(__DRInativeDisplay
*dpy
, __DRIid draw
);
134 static int __glXGetUST( int64_t * ust
);
136 static GLboolean
__glXGetMscRate(__DRInativeDisplay
* dpy
, __DRIid drawable
,
137 int32_t * numerator
, int32_t * denominator
);
139 static GLboolean
xf86DRI_DestroyContext(__DRInativeDisplay
*dpy
, int screen
,
140 __DRIid context_id
);
142 static GLboolean
xf86DRI_CreateDrawable(__DRInativeDisplay
*dpy
, int screen
,
143 __DRIid drawable
, drm_drawable_t
*hHWDrawable
);
145 static GLboolean
xf86DRI_DestroyDrawable(__DRInativeDisplay
*dpy
, int screen
,
149 /** Wrapper around either malloc() */
151 _mesa_malloc(size_t bytes
)
153 return malloc(bytes
);
156 /** Wrapper around either calloc() */
158 _mesa_calloc(size_t bytes
)
160 return calloc(1, bytes
);
163 /** Wrapper around either free() */
165 _mesa_free(void *ptr
)
172 * \brief Current GLX context.
174 * \sa glXGetCurrentContext().
176 static GLXContext CurrentContext
= NULL
;
180 static Display
*SignalDisplay
= 0;
182 static void SwitchVT(int sig
)
184 fprintf(stderr
, "SwitchVT %d dpy %p\n", sig
, SignalDisplay
);
187 SignalDisplay
->vtSignalFlag
= 1;
190 case SIGUSR1
: /* vt has been released */
191 SignalDisplay
->haveVT
= 0;
193 case SIGUSR2
: /* vt has been acquired */
194 SignalDisplay
->haveVT
= 1;
200 /**********************************************************************/
201 /** \name Framebuffer device functions */
202 /**********************************************************************/
206 * \brief Do the first part of setting up the framebuffer device.
208 * \param dpy the display handle.
209 * \param use_vt use a VT for display or not
211 * \return GL_TRUE on success, or GL_FALSE on failure.
213 * \sa This is called during XOpenDisplay().
216 * Gets the VT number, opens the respective console TTY device. Saves its state
217 * to restore when exiting and goes into graphics mode.
219 * Opens the framebuffer device and make a copy of the original variable screen
220 * information and gets the fixed screen information. Maps the framebuffer and
221 * MMIO region into the process address space.
224 OpenFBDev( Display
*dpy
, int use_vt
)
227 int fd
, vtnumber
, ttyfd
;
232 fprintf(stderr
, "error: you need to be root\n");
238 /* open /dev/tty0 and get the VT number */
239 if ((fd
= open("/dev/tty0", O_WRONLY
, 0)) < 0) {
240 fprintf(stderr
, "error opening /dev/tty0\n");
243 if (ioctl(fd
, VT_OPENQRY
, &vtnumber
) < 0 || vtnumber
< 0) {
244 fprintf(stderr
, "error: couldn't get a free vt\n");
248 fprintf(stderr
, "*** got vt nr: %d\n", vtnumber
);
251 /* open the console tty */
252 sprintf(ttystr
, "/dev/tty%d", vtnumber
); /* /dev/tty1-64 */
253 dpy
->ConsoleFD
= open(ttystr
, O_RDWR
| O_NDELAY
, 0);
254 if (dpy
->ConsoleFD
< 0) {
255 fprintf(stderr
, "error couldn't open console fd\n");
259 /* save current vt number */
262 if (ioctl(dpy
->ConsoleFD
, VT_GETSTATE
, &vts
) == 0)
263 dpy
->OriginalVT
= vts
.v_active
;
266 /* disconnect from controlling tty */
267 ttyfd
= open("/dev/tty", O_RDWR
);
269 ioctl(ttyfd
, TIOCNOTTY
, 0);
273 /* some magic to restore the vt when we exit */
276 struct sigaction sig_tty
;
278 /* Set-up tty signal handler to catch the signal we request below */
280 memset( &sig_tty
, 0, sizeof( sig_tty
) );
281 sig_tty
.sa_handler
= SwitchVT
;
282 sigemptyset( &sig_tty
.sa_mask
);
283 if( sigaction( SIGUSR1
, &sig_tty
, &dpy
->OrigSigUsr1
) ||
284 sigaction( SIGUSR2
, &sig_tty
, &dpy
->OrigSigUsr2
) )
286 fprintf(stderr
, "error: can't set up signal handler (%s)",
293 vt
.mode
= VT_PROCESS
;
297 if (ioctl(dpy
->ConsoleFD
, VT_SETMODE
, &vt
) < 0) {
298 fprintf(stderr
, "error: ioctl(VT_SETMODE) failed: %s\n",
304 if (ioctl(dpy
->ConsoleFD
, VT_ACTIVATE
, vtnumber
) != 0)
305 printf("ioctl VT_ACTIVATE: %s\n", strerror(errno
));
306 if (ioctl(dpy
->ConsoleFD
, VT_WAITACTIVE
, vtnumber
) != 0)
307 printf("ioctl VT_WAITACTIVE: %s\n", strerror(errno
));
309 if (ioctl(dpy
->ConsoleFD
, VT_GETMODE
, &vt
) < 0) {
310 fprintf(stderr
, "error: ioctl VT_GETMODE: %s\n", strerror(errno
));
318 /* go into graphics mode */
319 if (ioctl(dpy
->ConsoleFD
, KDSETMODE
, KD_GRAPHICS
) < 0) {
320 fprintf(stderr
, "error: ioctl(KDSETMODE, KD_GRAPHICS) failed: %s\n",
326 /* open the framebuffer device */
327 dpy
->FrameBufferFD
= open(dpy
->fbdevDevice
, O_RDWR
);
328 if (dpy
->FrameBufferFD
< 0) {
329 fprintf(stderr
, "Error opening /dev/fb0: %s\n", strerror(errno
));
333 /* get the original variable screen info */
334 if (ioctl(dpy
->FrameBufferFD
, FBIOGET_VSCREENINFO
, &dpy
->OrigVarInfo
)) {
335 fprintf(stderr
, "error: ioctl(FBIOGET_VSCREENINFO) failed: %s\n",
341 dpy
->VarInfo
= dpy
->OrigVarInfo
; /* structure copy */
343 /* Turn off hw accels (otherwise mmap of mmio region will be
346 dpy
->VarInfo
.accel_flags
= 0;
347 if (ioctl(dpy
->FrameBufferFD
, FBIOPUT_VSCREENINFO
, &dpy
->VarInfo
)) {
348 fprintf(stderr
, "error: ioctl(FBIOPUT_VSCREENINFO) failed: %s\n",
355 /* Get the fixed screen info */
356 if (ioctl(dpy
->FrameBufferFD
, FBIOGET_FSCREENINFO
, &dpy
->FixedInfo
)) {
357 fprintf(stderr
, "error: ioctl(FBIOGET_FSCREENINFO) failed: %s\n",
364 /* mmap the framebuffer into our address space */
365 dpy
->driverContext
.FBStart
= dpy
->FixedInfo
.smem_start
;
366 dpy
->driverContext
.FBSize
= dpy
->FixedInfo
.smem_len
;
367 dpy
->driverContext
.shared
.fbSize
= dpy
->FixedInfo
.smem_len
;
368 dpy
->driverContext
.FBAddress
= (caddr_t
) mmap(0, /* start */
369 dpy
->driverContext
.shared
.fbSize
, /* bytes */
370 PROT_READ
| PROT_WRITE
, /* prot */
371 MAP_SHARED
, /* flags */
372 dpy
->FrameBufferFD
, /* fd */
374 if (dpy
->driverContext
.FBAddress
== (caddr_t
) - 1) {
375 fprintf(stderr
, "error: unable to mmap framebuffer: %s\n",
380 /* mmap the MMIO region into our address space */
381 dpy
->driverContext
.MMIOStart
= dpy
->FixedInfo
.mmio_start
;
382 dpy
->driverContext
.MMIOSize
= dpy
->FixedInfo
.mmio_len
;
383 dpy
->driverContext
.MMIOAddress
= (caddr_t
) mmap(0, /* start */
384 dpy
->driverContext
.MMIOSize
, /* bytes */
385 PROT_READ
| PROT_WRITE
, /* prot */
386 MAP_SHARED
, /* flags */
387 dpy
->FrameBufferFD
, /* fd */
388 dpy
->FixedInfo
.smem_len
/* offset */);
389 if (dpy
->driverContext
.MMIOAddress
== (caddr_t
) - 1) {
390 fprintf(stderr
, "error: unable to mmap mmio region: %s\n",
395 fprintf(stderr
, "got MMIOAddress %p offset %d\n",
396 dpy
->driverContext
.MMIOAddress
,
397 dpy
->FixedInfo
.smem_len
);
406 * \brief Setup up the desired framebuffer device mode.
408 * \param dpy the display handle.
410 * \return GL_TRUE on success, or GL_FALSE on failure.
412 * \sa This is called during __miniglx_StartServer().
416 * Bumps the size of the window the the next supported mode. Sets the
417 * variable screen information according to the desired mode and asks
418 * the driver to validate the mode. Certifies that a DirectColor or
419 * TrueColor visual is used from the updated fixed screen information.
420 * In the case of DirectColor visuals, sets up an 'identity' colormap to
421 * mimic a TrueColor visual.
423 * Calls the driver hooks 'ValidateMode' and 'PostValidateMode' to
424 * allow the driver to make modifications to the chosen mode according
425 * to hardware constraints, or to save and restore videocard registers
426 * that may be clobbered by the fbdev driver.
428 * \todo Timings are hard-coded in the source for a set of supported modes.
431 SetupFBDev( Display
*dpy
)
437 width
= dpy
->driverContext
.shared
.virtualWidth
;
438 height
= dpy
->driverContext
.shared
.virtualHeight
;
442 /* Bump size up to next supported mode.
444 if (width
<= 720 && height
<= 480) {
445 width
= 720; height
= 480;
447 else if (width
<= 960 && height
<= 540) {
448 width
= 960; height
= 540;
450 else if (width
<= 800 && height
<= 600) {
451 width
= 800; height
= 600;
453 else if (width
<= 1024 && height
<= 768) {
454 width
= 1024; height
= 768;
456 else if (width
<= 768 && height
<= 1024) {
457 width
= 768; height
= 1024;
459 else if (width
<= 1280 && height
<= 1024) {
460 width
= 1280; height
= 1024;
464 dpy
->driverContext
.shared
.fbStride
= width
* (dpy
->driverContext
.bpp
/ 8);
466 /* set the depth, resolution, etc */
467 dpy
->VarInfo
= dpy
->OrigVarInfo
;
468 dpy
->VarInfo
.bits_per_pixel
= dpy
->driverContext
.bpp
;
469 dpy
->VarInfo
.xres_virtual
= dpy
->driverContext
.shared
.virtualWidth
;
470 dpy
->VarInfo
.yres_virtual
= dpy
->driverContext
.shared
.virtualHeight
;
471 dpy
->VarInfo
.xres
= width
;
472 dpy
->VarInfo
.yres
= height
;
473 dpy
->VarInfo
.xoffset
= 0;
474 dpy
->VarInfo
.yoffset
= 0;
475 dpy
->VarInfo
.nonstd
= 0;
476 dpy
->VarInfo
.vmode
&= ~FB_VMODE_YWRAP
; /* turn off scrolling */
478 if (dpy
->VarInfo
.bits_per_pixel
== 32) {
479 dpy
->VarInfo
.red
.offset
= 16;
480 dpy
->VarInfo
.green
.offset
= 8;
481 dpy
->VarInfo
.blue
.offset
= 0;
482 dpy
->VarInfo
.transp
.offset
= 24;
483 dpy
->VarInfo
.red
.length
= 8;
484 dpy
->VarInfo
.green
.length
= 8;
485 dpy
->VarInfo
.blue
.length
= 8;
486 dpy
->VarInfo
.transp
.length
= 8;
488 else if (dpy
->VarInfo
.bits_per_pixel
== 16) {
489 dpy
->VarInfo
.red
.offset
= 11;
490 dpy
->VarInfo
.green
.offset
= 5;
491 dpy
->VarInfo
.blue
.offset
= 0;
492 dpy
->VarInfo
.red
.length
= 5;
493 dpy
->VarInfo
.green
.length
= 6;
494 dpy
->VarInfo
.blue
.length
= 5;
495 dpy
->VarInfo
.transp
.offset
= 0;
496 dpy
->VarInfo
.transp
.length
= 0;
499 fprintf(stderr
, "Only 32bpp and 16bpp modes supported at the moment\n");
503 if (!dpy
->driver
->validateMode( &dpy
->driverContext
)) {
504 fprintf(stderr
, "Driver validateMode() failed\n");
508 /* These should be calculated with the gtf.c program, and then we could
509 remove all this... AlanH. */
510 if (dpy
->VarInfo
.xres
== 1280 &&
511 dpy
->VarInfo
.yres
== 1024) {
512 /* timing values taken from /etc/fb.modes (1280x1024 @ 75Hz) */
513 dpy
->VarInfo
.pixclock
= 7408;
514 dpy
->VarInfo
.left_margin
= 248;
515 dpy
->VarInfo
.right_margin
= 16;
516 dpy
->VarInfo
.upper_margin
= 38;
517 dpy
->VarInfo
.lower_margin
= 1;
518 dpy
->VarInfo
.hsync_len
= 144;
519 dpy
->VarInfo
.vsync_len
= 3;
521 else if (dpy
->VarInfo
.xres
== 1024 &&
522 dpy
->VarInfo
.yres
== 768) {
523 /* timing values taken from /etc/fb.modes (1024x768 @ 75Hz) */
524 dpy
->VarInfo
.pixclock
= 12699;
525 dpy
->VarInfo
.left_margin
= 176;
526 dpy
->VarInfo
.right_margin
= 16;
527 dpy
->VarInfo
.upper_margin
= 28;
528 dpy
->VarInfo
.lower_margin
= 1;
529 dpy
->VarInfo
.hsync_len
= 96;
530 dpy
->VarInfo
.vsync_len
= 3;
532 else if (dpy
->VarInfo
.xres
== 800 &&
533 dpy
->VarInfo
.yres
== 600) {
534 /* timing values taken from /etc/fb.modes (800x600 @ 75Hz) */
535 dpy
->VarInfo
.pixclock
= 27778;
536 dpy
->VarInfo
.left_margin
= 128;
537 dpy
->VarInfo
.right_margin
= 24;
538 dpy
->VarInfo
.upper_margin
= 22;
539 dpy
->VarInfo
.lower_margin
= 1;
540 dpy
->VarInfo
.hsync_len
= 72;
541 dpy
->VarInfo
.vsync_len
= 2;
543 else if (dpy
->VarInfo
.xres
== 720 &&
544 dpy
->VarInfo
.yres
== 480) {
545 dpy
->VarInfo
.pixclock
= 37202;
546 dpy
->VarInfo
.left_margin
= 88;
547 dpy
->VarInfo
.right_margin
= 16;
548 dpy
->VarInfo
.upper_margin
= 14;
549 dpy
->VarInfo
.lower_margin
= 1;
550 dpy
->VarInfo
.hsync_len
= 72;
551 dpy
->VarInfo
.vsync_len
= 3;
553 else if (dpy
->VarInfo
.xres
== 960 &&
554 dpy
->VarInfo
.yres
== 540) {
555 dpy
->VarInfo
.pixclock
= 24273;
556 dpy
->VarInfo
.left_margin
= 128;
557 dpy
->VarInfo
.right_margin
= 32;
558 dpy
->VarInfo
.upper_margin
= 16;
559 dpy
->VarInfo
.lower_margin
= 1;
560 dpy
->VarInfo
.hsync_len
= 96;
561 dpy
->VarInfo
.vsync_len
= 3;
563 else if (dpy
->VarInfo
.xres
== 768 &&
564 dpy
->VarInfo
.yres
== 1024) {
565 /* timing values for 768x1024 @ 75Hz */
566 dpy
->VarInfo
.pixclock
= 11993;
567 dpy
->VarInfo
.left_margin
= 136;
568 dpy
->VarInfo
.right_margin
= 32;
569 dpy
->VarInfo
.upper_margin
= 41;
570 dpy
->VarInfo
.lower_margin
= 1;
571 dpy
->VarInfo
.hsync_len
= 80;
572 dpy
->VarInfo
.vsync_len
= 3;
575 /* XXX need timings for other screen sizes */
576 fprintf(stderr
, "XXXX screen size %d x %d not supported at this time!\n",
577 dpy
->VarInfo
.xres
, dpy
->VarInfo
.yres
);
581 fprintf(stderr
, "[miniglx] Setting mode: visible %dx%d virtual %dx%dx%d\n",
582 dpy
->VarInfo
.xres
, dpy
->VarInfo
.yres
,
583 dpy
->VarInfo
.xres_virtual
, dpy
->VarInfo
.yres_virtual
,
584 dpy
->VarInfo
.bits_per_pixel
);
586 /* set variable screen info */
587 if (ioctl(dpy
->FrameBufferFD
, FBIOPUT_VSCREENINFO
, &dpy
->VarInfo
)) {
588 fprintf(stderr
, "error: ioctl(FBIOPUT_VSCREENINFO) failed: %s\n",
593 /* get the variable screen info, in case it has been modified */
594 if (ioctl(dpy
->FrameBufferFD
, FBIOGET_VSCREENINFO
, &dpy
->VarInfo
)) {
595 fprintf(stderr
, "error: ioctl(FBIOGET_VSCREENINFO) failed: %s\n",
601 fprintf(stderr
, "[miniglx] Readback mode: visible %dx%d virtual %dx%dx%d\n",
602 dpy
->VarInfo
.xres
, dpy
->VarInfo
.yres
,
603 dpy
->VarInfo
.xres_virtual
, dpy
->VarInfo
.yres_virtual
,
604 dpy
->VarInfo
.bits_per_pixel
);
606 /* Get the fixed screen info */
607 if (ioctl(dpy
->FrameBufferFD
, FBIOGET_FSCREENINFO
, &dpy
->FixedInfo
)) {
608 fprintf(stderr
, "error: ioctl(FBIOGET_FSCREENINFO) failed: %s\n",
613 if (dpy
->FixedInfo
.visual
!= FB_VISUAL_TRUECOLOR
&&
614 dpy
->FixedInfo
.visual
!= FB_VISUAL_DIRECTCOLOR
) {
615 fprintf(stderr
, "non-TRUECOLOR visuals not supported.\n");
619 if (dpy
->FixedInfo
.visual
== FB_VISUAL_DIRECTCOLOR
) {
621 unsigned short red
[256], green
[256], blue
[256];
622 int rcols
= 1 << dpy
->VarInfo
.red
.length
;
623 int gcols
= 1 << dpy
->VarInfo
.green
.length
;
624 int bcols
= 1 << dpy
->VarInfo
.blue
.length
;
634 for (i
= 0; i
< rcols
; i
++)
635 red
[i
] = (65536/(rcols
-1)) * i
;
637 for (i
= 0; i
< gcols
; i
++)
638 green
[i
] = (65536/(gcols
-1)) * i
;
640 for (i
= 0; i
< bcols
; i
++)
641 blue
[i
] = (65536/(bcols
-1)) * i
;
643 if (ioctl(dpy
->FrameBufferFD
, FBIOPUTCMAP
, (void *) &cmap
) < 0) {
644 fprintf(stderr
, "ioctl(FBIOPUTCMAP) failed [%d]\n", i
);
649 /* May need to restore regs fbdev has clobbered:
651 if (!dpy
->driver
->postValidateMode( &dpy
->driverContext
)) {
652 fprintf(stderr
, "Driver postValidateMode() failed\n");
661 * \brief Restore the framebuffer device to state it was in before we started
663 * Undoes the work done by SetupFBDev().
665 * \param dpy the display handle.
667 * \return GL_TRUE on success, or GL_FALSE on failure.
669 * \sa Called from XDestroyWindow().
672 * Restores the original variable screen info.
675 RestoreFBDev( Display
*dpy
)
677 /* restore original variable screen info */
678 if (ioctl(dpy
->FrameBufferFD
, FBIOPUT_VSCREENINFO
, &dpy
->OrigVarInfo
)) {
679 fprintf(stderr
, "ioctl(FBIOPUT_VSCREENINFO failed): %s\n",
683 dpy
->VarInfo
= dpy
->OrigVarInfo
;
690 * \brief Close the framebuffer device.
692 * \param dpy the display handle.
694 * \sa Called from XCloseDisplay().
697 * Unmaps the framebuffer and MMIO region. Restores the text mode and the
698 * original virtual terminal. Closes the console and framebuffer devices.
701 CloseFBDev( Display
*dpy
)
705 munmap(dpy
->driverContext
.FBAddress
, dpy
->driverContext
.FBSize
);
706 munmap(dpy
->driverContext
.MMIOAddress
, dpy
->driverContext
.MMIOSize
);
708 if (dpy
->ConsoleFD
) {
709 /* restore text mode */
710 ioctl(dpy
->ConsoleFD
, KDSETMODE
, KD_TEXT
);
713 if (ioctl(dpy
->ConsoleFD
, VT_GETMODE
, &VT
) != -1) {
715 ioctl(dpy
->ConsoleFD
, VT_SETMODE
, &VT
);
718 /* restore original vt */
719 if (dpy
->OriginalVT
>= 0) {
720 ioctl(dpy
->ConsoleFD
, VT_ACTIVATE
, dpy
->OriginalVT
);
721 dpy
->OriginalVT
= -1;
724 close(dpy
->ConsoleFD
);
726 close(dpy
->FrameBufferFD
);
732 /**********************************************************************/
733 /** \name Misc functions needed for DRI drivers */
734 /**********************************************************************/
738 * \brief Find the DRI screen dependent methods associated with the display.
740 * \param dpy a display handle, as returned by XOpenDisplay().
741 * \param scrn the screen number. Not referenced.
743 * \returns a pointer to a __DRIscreenRec structure.
746 * Returns the MiniGLXDisplayRec::driScreen attribute.
749 __glXFindDRIScreen(__DRInativeDisplay
*dpy
, int scrn
)
752 return &((Display
*)dpy
)->driScreen
;
756 * \brief Validate a drawable.
758 * \param dpy a display handle, as returned by XOpenDisplay().
759 * \param draw drawable to validate.
762 * Since Mini GLX only supports one window, compares the specified drawable with
763 * the MiniGLXDisplayRec::TheWindow attribute.
766 __glXWindowExists(__DRInativeDisplay
*dpy
, __DRIid draw
)
768 const Display
* const display
= (Display
*)dpy
;
769 if (display
->TheWindow
== (Window
) draw
)
776 * \brief Get current thread ID.
784 _glthread_GetID(void)
793 * \brief Scan Linux /prog/bus/pci/devices file to determine hardware
794 * chipset based on supplied bus ID.
796 * \return probed chipset (non-zero) on success, zero otherwise.
800 static int get_chipset_from_busid( Display
*dpy
)
804 const char *fname
= "/proc/bus/pci/devices";
807 if (!(file
= fopen(fname
,"r"))) {
808 fprintf(stderr
, "couldn't open %s: %s\n", fname
, strerror(errno
));
812 while (fgets(buf
, sizeof(buf
)-1, file
)) {
813 unsigned int nr
, bus
, dev
, fn
, vendor
, device
, encode
;
814 nr
= sscanf(buf
, "%04x\t%04x%04x", &encode
,
818 dev
= (encode
& 0xFF) >> 3;
824 if (bus
== dpy
->driverContext
.pciBus
&&
825 dev
== dpy
->driverContext
.pciDevice
&&
826 fn
== dpy
->driverContext
.pciFunc
) {
835 fprintf(stderr
, "[miniglx] probed chipset 0x%x\n", retval
);
837 fprintf(stderr
, "[miniglx] failed to probe chipset\n");
844 * \brief Read settings from a configuration file.
846 * The configuration file is usually "/etc/miniglx.conf", but can be overridden
847 * with the MINIGLX_CONF environment variable.
849 * The format consists in \code option = value \endcode lines. The option names
850 * corresponds to the fields in MiniGLXDisplayRec.
852 * \param dpy the display handle as.
854 * \return non-zero on success, zero otherwise.
857 * Sets some defaults. Opens and parses the the Mini GLX configuration file and
858 * fills in the MiniGLXDisplayRec field that corresponds for each option.
860 static int __read_config_file( Display
*dpy
)
867 dpy
->fbdevDevice
= "/dev/fb0";
868 dpy
->clientDriverName
= "fb_dri.so";
869 dpy
->driverContext
.pciBus
= 0;
870 dpy
->driverContext
.pciDevice
= 0;
871 dpy
->driverContext
.pciFunc
= 0;
872 dpy
->driverContext
.chipset
= 0;
873 dpy
->driverContext
.pciBusID
= 0;
874 dpy
->driverContext
.shared
.virtualWidth
= 1280;
875 dpy
->driverContext
.shared
.virtualHeight
= 1024;
876 dpy
->driverContext
.bpp
= 32;
877 dpy
->driverContext
.cpp
= 4;
879 dpy
->driverContext
.agpmode
= 1;
880 dpy
->driverContext
.isPCI
= 0;
881 dpy
->driverContext
.colorTiling
= 0;
883 fname
= getenv("MINIGLX_CONF");
884 if (!fname
) fname
= "/etc/miniglx.conf";
886 file
= fopen(fname
, "r");
888 fprintf(stderr
, "couldn't open config file %s: %s\n", fname
, strerror(errno
));
893 while (!feof(file
)) {
894 char buf
[81], *opt
= buf
, *val
, *tmp1
, *tmp2
;
895 fgets(buf
, sizeof(buf
), file
);
897 /* Parse 'opt = val' -- must be easier ways to do this.
899 while (isspace(*opt
)) opt
++;
901 if (*val
== '#') continue; /* comment */
902 while (!isspace(*val
) && *val
!= '=' && *val
) val
++;
904 while (isspace(*val
)) val
++;
905 if (*val
!= '=') continue;
908 while (isspace(*val
)) val
++;
910 while (!isspace(*tmp2
) && *tmp2
!= '\n' && *tmp2
) tmp2
++;
914 if (strcmp(opt
, "fbdevDevice") == 0)
915 dpy
->fbdevDevice
= strdup(val
);
916 else if (strcmp(opt
, "clientDriverName") == 0)
917 dpy
->clientDriverName
= strdup(val
);
918 else if (strcmp(opt
, "rotateMode") == 0)
919 dpy
->rotateMode
= atoi(val
) ? 1 : 0;
920 else if (strcmp(opt
, "pciBusID") == 0) {
921 if (sscanf(val
, "PCI:%d:%d:%d",
922 &dpy
->driverContext
.pciBus
,
923 &dpy
->driverContext
.pciDevice
,
924 &dpy
->driverContext
.pciFunc
) != 3) {
925 fprintf(stderr
, "malformed bus id: %s\n", val
);
928 dpy
->driverContext
.pciBusID
= strdup(val
);
930 else if (strcmp(opt
, "chipset") == 0) {
931 if (sscanf(val
, "0x%x", &dpy
->driverContext
.chipset
) != 1)
932 fprintf(stderr
, "malformed chipset: %s\n", opt
);
934 else if (strcmp(opt
, "virtualWidth") == 0) {
935 if (sscanf(val
, "%d", &dpy
->driverContext
.shared
.virtualWidth
) != 1)
936 fprintf(stderr
, "malformed virtualWidth: %s\n", opt
);
938 else if (strcmp(opt
, "virtualHeight") == 0) {
939 if (sscanf(val
, "%d", &dpy
->driverContext
.shared
.virtualHeight
) != 1)
940 fprintf(stderr
, "malformed virutalHeight: %s\n", opt
);
942 else if (strcmp(opt
, "bpp") == 0) {
943 if (sscanf(val
, "%d", &dpy
->driverContext
.bpp
) != 1)
944 fprintf(stderr
, "malformed bpp: %s\n", opt
);
945 dpy
->driverContext
.cpp
= dpy
->driverContext
.bpp
/ 8;
947 else if (strcmp(opt
, "agpmode") == 0) {
948 if (sscanf(val
, "%d", &dpy
->driverContext
.agpmode
) != 1)
949 fprintf(stderr
, "malformed agpmode: %s\n", opt
);
951 else if (strcmp(opt
, "isPCI") == 0) {
952 dpy
->driverContext
.isPCI
= atoi(val
) ? 1 : 0;
954 else if (strcmp(opt
, "colorTiling") == 0) {
955 dpy
->driverContext
.colorTiling
= atoi(val
) ? 1 : 0;
961 if (dpy
->driverContext
.chipset
== 0 && dpy
->driverContext
.pciBusID
!= 0)
962 dpy
->driverContext
.chipset
= get_chipset_from_busid( dpy
);
968 * Versioned name of the expected \c __driCreateNewScreen function.
970 * The version of the last incompatible loader/driver inteface change is
971 * appended to the name of the \c __driCreateNewScreen function. This
972 * prevents loaders from trying to load drivers that are too old.
975 * Create a macro or something so that this is automatically updated.
977 static const char createNewScreenName
[] = "__driCreateNewScreen_20050727";
980 static int InitDriver( Display
*dpy
)
984 * We're kind of combining the per-display and per-screen information
985 * which was kept separate in XFree86/DRI's libGL.
987 dpy
->dlHandle
= dlopen(dpy
->clientDriverName
, RTLD_NOW
| RTLD_GLOBAL
);
988 if (!dpy
->dlHandle
) {
989 fprintf(stderr
, "Unable to open %s: %s\n", dpy
->clientDriverName
,
994 /* Pull in Mini GLX specific hooks:
996 dpy
->driver
= (struct DRIDriverRec
*) dlsym(dpy
->dlHandle
,
999 fprintf(stderr
, "Couldn't find __driDriver in %s\n",
1000 dpy
->clientDriverName
);
1004 /* Pull in standard DRI client-side driver hooks:
1006 dpy
->createNewScreen
= (PFNCREATENEWSCREENFUNC
)
1007 dlsym(dpy
->dlHandle
, createNewScreenName
);
1008 if (!dpy
->createNewScreen
) {
1009 fprintf(stderr
, "Couldn't find %s in %s\n", createNewScreenName
,
1010 dpy
->clientDriverName
);
1017 if (dpy
->dlHandle
) {
1018 dlclose(dpy
->dlHandle
);
1025 /**********************************************************************/
1026 /** \name Public API functions (Xlib and GLX) */
1027 /**********************************************************************/
1032 * \brief Initialize the graphics system.
1034 * \param display_name currently ignored. It is recommended to pass it as NULL.
1035 * \return a pointer to a #Display if the function is able to initialize
1036 * the graphics system, NULL otherwise.
1038 * Allocates a MiniGLXDisplayRec structure and fills in with information from a
1039 * configuration file.
1041 * Calls OpenFBDev() to open the framebuffer device and calls
1042 * DRIDriverRec::initFBDev to do the client-side initialization on it.
1044 * Loads the DRI driver and pulls in Mini GLX specific hooks into a
1045 * DRIDriverRec structure, and the standard DRI \e __driCreateScreen hook.
1046 * Asks the driver for a list of supported visuals. Performs the per-screen
1047 * client-side initialization. Also setups the callbacks in the screen private
1050 * Does the framebuffer device setup. Calls __miniglx_open_connections() to
1054 __miniglx_StartServer( const char *display_name
)
1059 dpy
= (Display
*)calloc(1, sizeof(Display
));
1063 dpy
->IsClient
= False
;
1065 if (!__read_config_file( dpy
)) {
1066 fprintf(stderr
, "Couldn't get configuration details\n");
1071 /* Open the fbdev device
1073 if (!OpenFBDev(dpy
, use_vt
)) {
1074 fprintf(stderr
, "OpenFBDev failed\n");
1079 if (!InitDriver(dpy
)) {
1080 fprintf(stderr
, "InitDriver failed\n");
1085 /* Perform the initialization normally done in the X server
1087 if (!dpy
->driver
->initFBDev( &dpy
->driverContext
)) {
1088 fprintf(stderr
, "%s: __driInitFBDev failed\n", __FUNCTION__
);
1089 dlclose(dpy
->dlHandle
);
1095 if (!SetupFBDev(dpy
)) {
1096 fprintf(stderr
, "SetupFBDev failed\n");
1101 /* unlock here if not using VT -- JDS */
1103 if (dpy
->driver
->restoreHardware
)
1104 dpy
->driver
->restoreHardware( &dpy
->driverContext
);
1105 DRM_UNLOCK( dpy
->driverContext
.drmFD
,
1106 dpy
->driverContext
.pSAREA
,
1107 dpy
->driverContext
.serverContext
);
1111 /* Ready for clients:
1113 if (!__miniglx_open_connections(dpy
)) {
1123 * Implement \c __DRIinterfaceMethods::getProcAddress.
1125 static __DRIfuncPtr
get_proc_address( const char * proc_name
)
1133 * Table of functions exported by the loader to the driver.
1135 static const __DRIinterfaceMethods interface_methods
= {
1138 _gl_context_modes_create
,
1139 _gl_context_modes_destroy
,
1144 __glXCreateContextWithConfig
,
1145 xf86DRI_DestroyContext
,
1147 xf86DRI_CreateDrawable
,
1148 xf86DRI_DestroyDrawable
,
1149 __glXGetDrawableInfo
,
1157 CallCreateNewScreen(Display
*dpy
, int scrn
, __DRIscreen
*psc
)
1160 drm_handle_t hSAREA
;
1164 __DRIversion ddx_version
;
1165 __DRIversion dri_version
;
1166 __DRIversion drm_version
;
1167 __DRIframebuffer framebuffer
;
1170 const char * err_msg
;
1171 const char * err_extra
;
1172 drmVersionPtr version
;
1177 hSAREA
= dpy
->driverContext
.shared
.hSAREA
;
1178 BusID
= dpy
->driverContext
.pciBusID
;
1180 fd
= drmOpen(NULL
, BusID
);
1182 err_msg
= "open DRM";
1183 err_extra
= strerror( -fd
);
1185 if (fd
< 0) goto done
;
1187 err_msg
= "drmGetMagic";
1190 if (drmGetMagic(fd
, &magic
)) goto done
;
1192 dpy
->authorized
= False
;
1193 send_char_msg( dpy
, 0, _Authorize
);
1194 send_msg( dpy
, 0, &magic
, sizeof(magic
));
1196 /* force net buffer flush */
1197 while (!dpy
->authorized
)
1198 handle_fd_events( dpy
, 0 );
1200 version
= drmGetVersion(fd
);
1202 drm_version
.major
= version
->version_major
;
1203 drm_version
.minor
= version
->version_minor
;
1204 drm_version
.patch
= version
->version_patchlevel
;
1205 drmFreeVersion(version
);
1208 drm_version
.major
= -1;
1209 drm_version
.minor
= -1;
1210 drm_version
.patch
= -1;
1214 * Get device name (like "tdfx") and the ddx version numbers.
1215 * We'll check the version in each DRI driver's "createScreen"
1218 ddx_version
.major
= 4;
1219 ddx_version
.minor
= 0;
1220 ddx_version
.patch
= 0;
1223 * Get the DRI X extension version.
1225 dri_version
.major
= 4;
1226 dri_version
.minor
= 0;
1227 dri_version
.patch
= 0;
1230 * Get device-specific info. pDevPriv will point to a struct
1231 * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h)
1232 * that has information about the screen size, depth, pitch,
1233 * ancilliary buffers, DRM mmap handles, etc.
1235 hFB
= dpy
->driverContext
.shared
.hFrameBuffer
;
1236 framebuffer
.size
= dpy
->driverContext
.shared
.fbSize
;
1237 framebuffer
.stride
= dpy
->driverContext
.shared
.fbStride
;
1238 framebuffer
.dev_priv_size
= dpy
->driverContext
.driverClientMsgSize
;
1239 framebuffer
.dev_priv
= dpy
->driverContext
.driverClientMsg
;
1240 framebuffer
.width
= dpy
->driverContext
.shared
.virtualWidth
;
1241 framebuffer
.height
= dpy
->driverContext
.shared
.virtualHeight
;
1244 * Map the framebuffer region.
1246 status
= drmMap(fd
, hFB
, framebuffer
.size
,
1247 (drmAddressPtr
)&framebuffer
.base
);
1249 err_msg
= "drmMap of framebuffer";
1250 err_extra
= strerror( -status
);
1252 if ( status
!= 0 ) goto done
;
1255 * Map the SAREA region. Further mmap regions may be setup in
1256 * each DRI driver's "createScreen" function.
1258 status
= drmMap(fd
, hSAREA
, SAREA_MAX
, &pSAREA
);
1260 err_msg
= "drmMap of sarea";
1261 err_extra
= strerror( -status
);
1263 if ( status
== 0 ) {
1264 err_msg
= "InitDriver";
1266 psp
= dpy
->createNewScreen(dpy
, scrn
, psc
, NULL
,
1274 & interface_methods
,
1275 (__GLcontextModes
**) &dpy
->driver_modes
);
1277 /* fill in dummy visual ids */
1279 __GLcontextModes
*temp
;
1280 temp
= (__GLcontextModes
*)dpy
->driver_modes
;
1284 temp
->visualID
= i
++;
1291 if ( psp
== NULL
) {
1292 if ( pSAREA
!= MAP_FAILED
) {
1293 (void)drmUnmap(pSAREA
, SAREA_MAX
);
1296 if ( framebuffer
.base
!= MAP_FAILED
) {
1297 (void)drmUnmap((drmAddress
)framebuffer
.base
, framebuffer
.size
);
1300 if ( framebuffer
.dev_priv
!= NULL
) {
1301 free(framebuffer
.dev_priv
);
1308 if ( err_extra
!= NULL
) {
1309 fprintf(stderr
, "libGL error: %s failed (%s)\n", err_msg
,
1313 fprintf(stderr
, "libGL error: %s failed\n", err_msg
);
1316 fprintf(stderr
, "libGL error: reverting to (slow) indirect rendering\n");
1323 * \brief Initialize the graphics system.
1325 * \param display_name currently ignored. It is recommended to pass it as NULL.
1326 * \return a pointer to a #Display if the function is able to initialize
1327 * the graphics system, NULL otherwise.
1329 * Allocates a MiniGLXDisplayRec structure and fills in with information from a
1330 * configuration file.
1332 * Calls __miniglx_open_connections() to connect to the server.
1334 * Loads the DRI driver and pulls in Mini GLX specific hooks into a
1335 * DRIDriverRec structure, and the standard DRI \e __driCreateScreen hook.
1336 * Asks the driver for a list of supported visuals. Performs the per-screen
1337 * client-side initialization. Also setups the callbacks in the screen private
1341 * - read config file
1342 * - what about virtualWidth, etc?
1343 * - determine dpy->driverClientMsgSize,
1344 * - allocate dpy->driverClientMsg
1347 XOpenDisplay( const char *display_name
)
1351 dpy
= (Display
*)calloc(1, sizeof(Display
));
1355 dpy
->IsClient
= True
;
1359 if (!__read_config_file( dpy
)) {
1360 fprintf(stderr
, "Couldn't get configuration details\n");
1365 /* Connect to the server and receive driverClientMsg
1367 if (!__miniglx_open_connections(dpy
)) {
1372 /* dlopen the driver .so file
1374 if (!InitDriver(dpy
)) {
1375 fprintf(stderr
, "InitDriver failed\n");
1380 /* Perform the client-side initialization.
1382 * Clearly there is a limit of one on the number of windows in
1383 * existence at any time.
1385 * Need to shut down DRM and free DRI data in XDestroyWindow(), too.
1387 dpy
->driScreen
.private = CallCreateNewScreen(dpy
, 0, &dpy
->driScreen
);
1388 if (!dpy
->driScreen
.private) {
1389 fprintf(stderr
, "%s: __driCreateScreen failed\n", __FUNCTION__
);
1390 dlclose(dpy
->dlHandle
);
1395 /* Anything more to do?
1402 * \brief Release display resources.
1404 * When the application is about to exit, the resources associated with the
1405 * graphics system can be released by calling this function.
1407 * \param dpy display handle. It becomes invalid at this point.
1409 * Destroys the window if any, and destroys the per-screen
1410 * driver private information.
1411 * Calls __miniglx_close_connections().
1413 * If a server, puts the the framebuffer back into the initial state.
1415 * Finally frees the display structure.
1418 XCloseDisplay( Display
*dpy
)
1420 glXMakeCurrent( dpy
, NULL
, NULL
);
1422 if (dpy
->NumWindows
)
1423 XDestroyWindow( dpy
, dpy
->TheWindow
);
1425 /* As this is done in XOpenDisplay, need to undo it here:
1427 dpy
->driScreen
.destroyScreen(dpy
, 0, dpy
->driScreen
.private);
1429 __miniglx_close_connections( dpy
);
1431 if (!dpy
->IsClient
) {
1432 /* put framebuffer back to initial state
1434 (*dpy
->driver
->haltFBDev
)( &dpy
->driverContext
);
1439 dlclose(dpy
->dlHandle
);
1445 * \brief Window creation.
1447 * \param display a display handle, as returned by XOpenDisplay().
1448 * \param parent the parent window for the new window. For Mini GLX this should
1450 * \code RootWindow(display, 0) \endcode
1451 * \param x the window abscissa. For Mini GLX, it should be zero.
1452 * \param y the window ordinate. For Mini GLX, it should be zero.
1453 * \param width the window width. For Mini GLX, this specifies the desired
1454 * screen width such as 1024 or 1280.
1455 * \param height the window height. For Mini GLX, this specifies the desired
1456 * screen height such as 768 or 1024.
1457 * \param border_width the border width. For Mini GLX, it should be zero.
1458 * \param depth the window pixel depth. For Mini GLX, this should be the depth
1459 * found in the #XVisualInfo object returned by glXChooseVisual()
1460 * \param winclass the window class. For Mini GLX this value should be
1462 * \param visual the visual type. It should be the visual field of the
1463 * #XVisualInfo object returned by glXChooseVisual().
1464 * \param valuemask which fields of the XSetWindowAttributes() are to be used.
1465 * For Mini GLX this is typically the bitmask
1466 * \code CWBackPixel | CWBorderPixel | CWColormap \endcode
1467 * \param attributes initial window attributes. The
1468 * XSetWindowAttributes::background_pixel, XSetWindowAttributes::border_pixel
1469 * and XSetWindowAttributes::colormap fields should be set.
1471 * \return a window handle if it succeeds or zero if it fails.
1473 * \note For Mini GLX, windows are full-screen; they cover the entire frame
1474 * buffer. Also, Mini GLX imposes a limit of one window. A second window
1475 * cannot be created until the first one is destroyed.
1477 * This function creates and initializes a ::MiniGLXWindowRec structure after
1478 * ensuring that there is no other window created. Performs the per-drawable
1479 * client-side initialization calling the __DRIscreenRec::createDrawable
1484 XCreateWindow( Display
*dpy
, Window parent
, int x
, int y
,
1485 unsigned int width
, unsigned int height
,
1486 unsigned int border_width
, int depth
, unsigned int winclass
,
1487 Visual
*visual
, unsigned long valuemask
,
1488 XSetWindowAttributes
*attributes
)
1490 const int empty_attribute_list
[1] = { None
};
1497 (void) border_width
;
1503 if (!dpy
->IsClient
) {
1504 fprintf(stderr
, "Server process may not create windows (currently)\n");
1508 if (dpy
->NumWindows
> 0)
1509 return NULL
; /* only allow one window */
1511 assert(dpy
->TheWindow
== NULL
);
1513 win
= malloc(sizeof(struct MiniGLXWindowRec
));
1517 /* In rotated mode, translate incoming x,y,width,height into
1518 * 'normal' coordinates.
1520 if (dpy
->rotateMode
) {
1522 tmp
= width
; width
= height
; height
= tmp
;
1523 tmp
= x
; x
= y
; y
= tmp
;
1526 /* init other per-window fields */
1531 win
->visual
= visual
; /* ptr assignment */
1533 win
->bytesPerPixel
= dpy
->driverContext
.cpp
;
1534 win
->rowStride
= dpy
->driverContext
.shared
.virtualWidth
* win
->bytesPerPixel
;
1535 win
->size
= win
->rowStride
* height
;
1536 win
->frontStart
= dpy
->driverContext
.FBAddress
;
1537 win
->frontBottom
= (GLubyte
*) win
->frontStart
+ (height
-1) * win
->rowStride
;
1539 /* This is incorrect: the hardware driver could put the backbuffer
1540 * just about anywhere. These fields, including the above are
1541 * hardware dependent & don't really belong here.
1543 if (visual
->mode
->doubleBufferMode
) {
1544 win
->backStart
= (GLubyte
*) win
->frontStart
+
1545 win
->rowStride
* dpy
->driverContext
.shared
.virtualHeight
;
1546 win
->backBottom
= (GLubyte
*) win
->backStart
1547 + (height
- 1) * win
->rowStride
;
1548 win
->curBottom
= win
->backBottom
;
1551 /* single buffered */
1552 win
->backStart
= NULL
;
1553 win
->backBottom
= NULL
;
1554 win
->curBottom
= win
->frontBottom
;
1557 dpy
->driScreen
.createNewDrawable(dpy
, visual
->mode
, (int) win
,
1558 &win
->driDrawable
, GLX_WINDOW_BIT
, empty_attribute_list
);
1560 if (!win
->driDrawable
.private) {
1561 fprintf(stderr
, "%s: dri.createDrawable failed\n", __FUNCTION__
);
1567 dpy
->TheWindow
= win
;
1574 * \brief Destroy window.
1576 * \param display display handle.
1577 * \param w window handle.
1579 * This function calls XUnmapWindow() and frees window \p w.
1581 * In case of destroying the current buffer first unbinds the GLX context
1582 * by calling glXMakeCurrent() with no drawable.
1585 XDestroyWindow( Display
*display
, Window win
)
1587 if (display
&& display
->IsClient
&& win
) {
1588 /* check if destroying the current buffer */
1589 Window curDraw
= glXGetCurrentDrawable();
1590 if (win
== curDraw
) {
1591 glXMakeCurrent( display
, NULL
, NULL
);
1594 XUnmapWindow( display
, win
);
1596 /* Destroy the drawable. */
1597 win
->driDrawable
.destroyDrawable(display
, win
->driDrawable
.private);
1600 /* unlink window from display */
1601 display
->NumWindows
--;
1602 assert(display
->NumWindows
== 0);
1603 display
->TheWindow
= NULL
;
1611 * \brief Create color map structure.
1613 * \param dpy the display handle as returned by XOpenDisplay().
1614 * \param w the window on whose screen you want to create a color map. This
1615 * parameter is ignored by Mini GLX but should be the value returned by the
1616 * \code RootWindow(display, 0) \endcode macro.
1617 * \param visual a visual type supported on the screen. This parameter is
1618 * ignored by Mini GLX but should be the XVisualInfo::visual returned by
1619 * glXChooseVisual().
1620 * \param alloc the color map entries to be allocated. This parameter is ignored
1621 * by Mini GLX but should be set to #AllocNone.
1623 * \return the color map.
1625 * This function is only provided to ease porting. Practically a no-op -
1626 * returns a pointer to a dynamically allocated chunk of memory (one byte).
1629 XCreateColormap( Display
*dpy
, Window w
, Visual
*visual
, int alloc
)
1635 return (Colormap
) malloc(1);
1640 * \brief Destroy color map structure.
1642 * \param display The display handle as returned by XOpenDisplay().
1643 * \param colormap the color map to destroy.
1645 * This function is only provided to ease porting. Practically a no-op.
1647 * Frees the memory pointed by \p colormap.
1650 XFreeColormap( Display
*display
, Colormap colormap
)
1659 * \brief Free client data.
1661 * \param data the data that is to be freed.
1663 * Frees the memory pointed by \p data.
1673 * \brief Query available visuals.
1675 * \param dpy the display handle, as returned by XOpenDisplay().
1676 * \param vinfo_mask a bitmask indicating which fields of the \p vinfo_template
1677 * are to be matched. The value must be \c VisualScreenMask.
1678 * \param vinfo_template a template whose fields indicate which visual
1679 * attributes must be matched by the results. The XVisualInfo::screen field of
1680 * this structure must be zero.
1681 * \param nitens_return will hold the number of visuals returned.
1683 * \return the address of an array of all available visuals.
1685 * An example of using XGetVisualInfo() to get all available visuals follows:
1688 * XVisualInfo vinfo_template, *results;
1689 * int nitens_return;
1690 * Display *dpy = XOpenDisplay(NULL);
1691 * vinfo_template.screen = 0;
1692 * results = XGetVisualInfo(dpy, VisualScreenMask, &vinfo_template, &nitens_return);
1695 * Returns the list of all ::XVisualInfo available, one per
1696 * ::__GLcontextMode stored in MiniGLXDisplayRec::modes.
1699 XGetVisualInfo( Display
*dpy
, long vinfo_mask
, XVisualInfo
*vinfo_template
, int *nitens_return
)
1701 const __GLcontextModes
*mode
;
1702 XVisualInfo
*results
;
1706 // ASSERT(vinfo_mask == VisualScreenMask);
1707 ASSERT(vinfo_template
.screen
== 0);
1709 if (vinfo_mask
== VisualIDMask
)
1711 for ( mode
= dpy
->driver_modes
; mode
!= NULL
; mode
= mode
->next
)
1712 if (mode
->visualID
== vinfo_template
->visualid
)
1718 results
= (XVisualInfo
*)calloc(1, n
* sizeof(XVisualInfo
));
1724 visResults
= (Visual
*)calloc(1, n
* sizeof(Visual
));
1731 for ( mode
= dpy
->driver_modes
; mode
!= NULL
; mode
= mode
->next
)
1732 if (mode
->visualID
== vinfo_template
->visualid
)
1734 visResults
[0].mode
=mode
;
1735 visResults
[0].visInfo
= results
;
1736 visResults
[0].dpy
= dpy
;
1737 if (dpy
->driverContext
.bpp
== 32)
1738 visResults
[0].pixelFormat
= PF_B8G8R8A8
; /* XXX: FIX ME */
1740 visResults
[0].pixelFormat
= PF_B5G6R5
; /* XXX: FIX ME */
1742 results
[0].visual
= visResults
;
1743 results
[0].visualid
= mode
->visualID
;
1744 #if defined(__cplusplus) || defined(c_plusplus)
1745 results
[0].c_class
= TrueColor
;
1747 results
[0].class = TrueColor
;
1749 results
[0].depth
= mode
->redBits
+
1753 results
[0].bits_per_rgb
= dpy
->driverContext
.bpp
;
1758 else // if (vinfo_mask == VisualScreenMask)
1761 for ( mode
= dpy
->driver_modes
; mode
!= NULL
; mode
= mode
->next
)
1764 results
= (XVisualInfo
*)calloc(1, n
* sizeof(XVisualInfo
));
1770 visResults
= (Visual
*)calloc(1, n
* sizeof(Visual
));
1777 for ( mode
= dpy
->driver_modes
, i
= 0 ; mode
!= NULL
; mode
= mode
->next
, i
++ ) {
1778 visResults
[i
].mode
= mode
;
1779 visResults
[i
].visInfo
= results
+ i
;
1780 visResults
[i
].dpy
= dpy
;
1782 if (dpy
->driverContext
.bpp
== 32)
1783 visResults
[i
].pixelFormat
= PF_B8G8R8A8
; /* XXX: FIX ME */
1785 visResults
[i
].pixelFormat
= PF_B5G6R5
; /* XXX: FIX ME */
1787 results
[i
].visual
= visResults
+ i
;
1788 results
[i
].visualid
= mode
->visualID
;
1789 #if defined(__cplusplus) || defined(c_plusplus)
1790 results
[i
].c_class
= TrueColor
;
1792 results
[i
].class = TrueColor
;
1794 results
[i
].depth
= mode
->redBits
+
1798 results
[i
].bits_per_rgb
= dpy
->driverContext
.bpp
;
1807 * \brief Return a visual that matches specified attributes.
1809 * \param dpy the display handle, as returned by XOpenDisplay().
1810 * \param screen the screen number. It is currently ignored by Mini GLX and
1812 * \param attribList a list of GLX attributes which describe the desired pixel
1813 * format. It is terminated by the token \c None.
1815 * The attributes are as follows:
1817 * This attribute should always be present in order to maintain compatibility
1820 * If present, only RGBA pixel formats will be considered. Otherwise, only
1821 * color index formats are considered.
1822 * \arg GLX_DOUBLEBUFFER:
1823 * if present, only double-buffered pixel formats will be chosen.
1824 * \arg GLX_RED_SIZE \e n:
1825 * Must be followed by a non-negative integer indicating the minimum number of
1826 * bits per red pixel component that is acceptable.
1827 * \arg GLX_GREEN_SIZE \e n:
1828 * Must be followed by a non-negative integer indicating the minimum number of
1829 * bits per green pixel component that is acceptable.
1830 * \arg GLX_BLUE_SIZE \e n:
1831 * Must be followed by a non-negative integer indicating the minimum number of
1832 * bits per blue pixel component that is acceptable.
1833 * \arg GLX_ALPHA_SIZE \e n:
1834 * Must be followed by a non-negative integer indicating the minimum number of
1835 * bits per alpha pixel component that is acceptable.
1836 * \arg GLX_STENCIL_SIZE \e n:
1837 * Must be followed by a non-negative integer indicating the minimum number of
1838 * bits per stencil value that is acceptable.
1839 * \arg GLX_DEPTH_SIZE \e n:
1840 * Must be followed by a non-negative integer indicating the minimum number of
1841 * bits per depth component that is acceptable.
1843 * This token is used to terminate the attribute list.
1845 * \return a pointer to an #XVisualInfo object which most closely matches the
1846 * requirements of the attribute list. If there is no visual which matches the
1847 * request, \c NULL will be returned.
1849 * \note Visuals with accumulation buffers are not available.
1851 * This function searches the list of available visual configurations in
1852 * MiniGLXDisplayRec::configs for a configuration which best matches the GLX
1853 * attribute list parameter. A new ::XVisualInfo object is created which
1854 * describes the visual configuration. The match criteria is described in the
1858 glXChooseVisual( Display
*dpy
, int screen
, int *attribList
)
1860 const __GLcontextModes
*mode
;
1862 XVisualInfo
*visInfo
;
1864 GLboolean rgbFlag
= GL_FALSE
, dbFlag
= GL_FALSE
, stereoFlag
= GL_FALSE
;
1865 GLint redBits
= 0, greenBits
= 0, blueBits
= 0, alphaBits
= 0;
1866 GLint indexBits
= 0, depthBits
= 0, stencilBits
= 0;
1867 GLint numSamples
= 0;
1871 * XXX in the future, <screen> might be interpreted as a VT
1874 ASSERT(screen
== 0);
1876 vis
= (Visual
*)calloc(1, sizeof(Visual
));
1880 visInfo
= (XVisualInfo
*)malloc(sizeof(XVisualInfo
));
1886 visInfo
->visual
= vis
;
1887 vis
->visInfo
= visInfo
;
1890 /* parse the attribute list */
1891 for (attrib
= attribList
; attrib
&& *attrib
!= None
; attrib
++) {
1892 switch (attrib
[0]) {
1893 case GLX_DOUBLEBUFFER
:
1900 redBits
= attrib
[1];
1903 case GLX_GREEN_SIZE
:
1904 greenBits
= attrib
[1];
1908 blueBits
= attrib
[1];
1911 case GLX_ALPHA_SIZE
:
1912 alphaBits
= attrib
[1];
1915 case GLX_STENCIL_SIZE
:
1916 stencilBits
= attrib
[1];
1919 case GLX_DEPTH_SIZE
:
1920 depthBits
= attrib
[1];
1924 case GLX_ACCUM_RED_SIZE
:
1925 accumRedBits
= attrib
[1];
1928 case GLX_ACCUM_GREEN_SIZE
:
1929 accumGreenBits
= attrib
[1];
1932 case GLX_ACCUM_BLUE_SIZE
:
1933 accumBlueBits
= attrib
[1];
1936 case GLX_ACCUM_ALPHA_SIZE
:
1937 accumAlphaBits
= attrib
[1];
1941 /* ignored for now */
1945 /* unexpected token */
1946 fprintf(stderr
, "unexpected token in glXChooseVisual attrib list\n");
1953 /* search screen configs for suitable visual */
1961 for ( mode
= dpy
->driver_modes
; mode
!= NULL
; mode
= mode
->next
) {
1963 if (mode
->rgbMode
== rgbFlag
&&
1964 mode
->doubleBufferMode
== dbFlag
&&
1965 mode
->redBits
>= redBits
&&
1966 mode
->greenBits
>= greenBits
&&
1967 mode
->blueBits
>= blueBits
&&
1968 mode
->alphaBits
>= alphaBits
&&
1969 mode
->depthBits
>= depthBits
&&
1970 mode
->stencilBits
>= stencilBits
) {
1972 visInfo
->visualid
= i
;
1980 /* compute depth and bpp */
1982 /* XXX maybe support depth 16 someday */
1983 #if defined(__cplusplus) || defined(c_plusplus)
1984 visInfo
->c_class
= TrueColor
;
1986 visInfo
->class = TrueColor
;
1988 visInfo
->depth
= dpy
->driverContext
.bpp
;
1989 visInfo
->bits_per_rgb
= dpy
->driverContext
.bpp
;
1990 if (dpy
->driverContext
.bpp
== 32)
1991 vis
->pixelFormat
= PF_B8G8R8A8
;
1993 vis
->pixelFormat
= PF_B5G6R5
;
1996 /* color index mode */
1997 #if defined(__cplusplus) || defined(c_plusplus)
1998 visInfo
->c_class
= PseudoColor
;
2000 visInfo
->class = PseudoColor
;
2003 visInfo
->bits_per_rgb
= 8; /* bits/pixel */
2004 vis
->pixelFormat
= PF_CI8
;
2012 * \brief Return information about GLX visuals.
2014 * \param dpy the display handle, as returned by XOpenDisplay().
2015 * \param vis the visual to be queried, as returned by glXChooseVisual().
2016 * \param attrib the visual attribute to be returned.
2017 * \param value pointer to an integer in which the result of the query will be
2020 * \return zero if no error occurs, \c GLX_INVALID_ATTRIBUTE if the attribute
2021 * parameter is invalid, or \c GLX_BAD_VISUAL if the \p vis parameter is
2024 * Returns the appropriate attribute of ::__GLXvisualConfig pointed by
2025 * MiniGLXVisualRec::glxConfig of XVisualInfo::visual.
2030 glXGetConfig( Display
*dpy
, XVisualInfo
*vis
, int attrib
, int *value
)
2032 const __GLcontextModes
*mode
= vis
->visual
->mode
;
2035 return GLX_BAD_VISUAL
;
2043 *value
= mode
->rgbMode
;
2045 case GLX_DOUBLEBUFFER
:
2046 *value
= mode
->doubleBufferMode
;
2049 *value
= mode
->redBits
;
2051 case GLX_GREEN_SIZE
:
2052 *value
= mode
->greenBits
;
2055 *value
= mode
->blueBits
;
2057 case GLX_ALPHA_SIZE
:
2058 *value
= mode
->alphaBits
;
2060 case GLX_DEPTH_SIZE
:
2061 *value
= mode
->depthBits
;
2063 case GLX_STENCIL_SIZE
:
2064 *value
= mode
->stencilBits
;
2068 return GLX_BAD_ATTRIBUTE
;
2075 * \brief Create a new GLX rendering context.
2077 * \param dpy the display handle, as returned by XOpenDisplay().
2078 * \param vis the visual that defines the frame buffer resources available to
2079 * the rendering context, as returned by glXChooseVisual().
2080 * \param shareList If non-zero, texture objects and display lists are shared
2081 * with the named rendering context. If zero, texture objects and display lists
2082 * will (initially) be private to this context. They may be shared when a
2083 * subsequent context is created.
2084 * \param direct whether direct or indirect rendering is desired. For Mini GLX
2085 * this value is ignored but it should be set to \c True.
2087 * \return a ::GLXContext handle if it succeeds or zero if it fails due to
2088 * invalid parameter or insufficient resources.
2090 * This function creates and initializes a ::MiniGLXContextRec structure and
2091 * calls the __DRIscreenRec::createContext method to initialize the client
2095 glXCreateContext( Display
*dpy
, XVisualInfo
*vis
,
2096 GLXContext shareList
, Bool direct
)
2103 ctx
= (struct MiniGLXContextRec
*)calloc(1, sizeof(struct MiniGLXContextRec
));
2107 ctx
->vid
= vis
->visualid
;
2110 sharePriv
= shareList
->driContext
.private;
2114 ctx
->driContext
.mode
= vis
->visual
->mode
;
2115 ctx
->driContext
.private = dpy
->driScreen
.createNewContext(dpy
, vis
->visual
->mode
,
2116 GLX_WINDOW_BIT
, sharePriv
, &ctx
->driContext
);
2118 if (!ctx
->driContext
.private) {
2128 * \brief Destroy a GLX context.
2130 * \param dpy the display handle, as returned by XOpenDisplay().
2131 * \param ctx the GLX context to be destroyed.
2133 * This function frees the \p ctx parameter after unbinding the current context
2134 * by calling the __DRIcontextRec::bindContext method with zeros and calling
2135 * the __DRIcontextRec::destroyContext method.
2138 glXDestroyContext( Display
*dpy
, GLXContext ctx
)
2140 GLXContext glxctx
= glXGetCurrentContext();
2143 if (glxctx
== ctx
) {
2144 /* destroying current context */
2145 ctx
->driContext
.bindContext(dpy
, 0, 0, 0, 0);
2148 ctx
->driContext
.destroyContext(dpy
, 0, ctx
->driContext
.private);
2155 * \brief Bind a GLX context to a window or a pixmap.
2157 * \param dpy the display handle, as returned by XOpenDisplay().
2158 * \param drawable the window or drawable to bind to the rendering context.
2159 * This should be the value returned by XCreateWindow().
2160 * \param ctx the GLX context to be destroyed.
2162 * \return \c True if it succeeds, \c False otherwise to indicate an invalid
2163 * display, window or context parameter.
2165 * The current rendering context may be unbound by calling glXMakeCurrent()
2166 * with the window and context parameters set to zero.
2168 * An application may create any number of rendering contexts and bind them as
2169 * needed. Note that binding a rendering context is generally not a
2170 * light-weight operation. Most simple OpenGL applications create only one
2171 * rendering context.
2173 * This function first unbinds any old context via
2174 * __DRIcontextRec::unbindContext and binds the new one via
2175 * __DRIcontextRec::bindContext.
2177 * If \p drawable is zero it unbinds the GLX context by calling
2178 * __DRIcontextRec::bindContext with zeros.
2181 glXMakeCurrent( Display
*dpy
, GLXDrawable drawable
, GLXContext ctx
)
2183 if (dpy
&& drawable
&& ctx
) {
2184 GLXContext oldContext
= glXGetCurrentContext();
2185 GLXDrawable oldDrawable
= glXGetCurrentDrawable();
2188 oldContext
->driContext
.unbindContext(dpy
, 0,
2189 (__DRIid
) oldDrawable
, (__DRIid
) oldDrawable
,
2190 &oldContext
->driContext
);
2193 CurrentContext
= ctx
;
2194 ctx
->driContext
.bindContext(dpy
, 0, (__DRIid
) drawable
,
2195 (__DRIid
) drawable
, &ctx
->driContext
);
2196 ctx
->drawBuffer
= drawable
;
2197 ctx
->curBuffer
= drawable
;
2199 else if (ctx
&& dpy
) {
2201 ctx
->driContext
.bindContext(dpy
, 0, 0, 0, 0);
2204 CurrentContext
= 0; /* kw: this seems to be intended??? */
2212 * \brief Exchange front and back buffers.
2214 * \param dpy the display handle, as returned by XOpenDisplay().
2215 * \param drawable the drawable whose buffers are to be swapped.
2217 * Any pending rendering commands will be completed before the buffer swap
2220 * Calling glXSwapBuffers() on a window which is single-buffered has no effect.
2222 * This function just calls the __DRIdrawableRec::swapBuffers method to do the
2226 glXSwapBuffers( Display
*dpy
, GLXDrawable drawable
)
2228 if (!dpy
|| !drawable
)
2231 drawable
->driDrawable
.swapBuffers(dpy
, drawable
->driDrawable
.private);
2236 * \brief Return the current context
2238 * \return the current context, as specified by glXMakeCurrent(), or zero if no
2239 * context is currently bound.
2241 * \sa glXCreateContext(), glXMakeCurrent()
2243 * Returns the value of the ::CurrentContext global variable.
2246 glXGetCurrentContext( void )
2248 return CurrentContext
;
2253 * \brief Return the current drawable.
2255 * \return the current drawable, as specified by glXMakeCurrent(), or zero if
2256 * no drawable is currently bound.
2258 * This function gets the current context via glXGetCurrentContext() and
2259 * returns the MiniGLXContextRec::drawBuffer attribute.
2262 glXGetCurrentDrawable( void )
2264 GLXContext glxctx
= glXGetCurrentContext();
2266 return glxctx
->drawBuffer
;
2273 __glXCreateContextWithConfig(__DRInativeDisplay
*dpy
, int screen
,
2274 int fbconfigID
, void *contextID
, drm_context_t
*hHWContext
)
2276 __DRIscreen
*pDRIScreen
;
2277 __DRIscreenPrivate
*psp
;
2279 pDRIScreen
= __glXFindDRIScreen(dpy
, screen
);
2280 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
2284 psp
= (__DRIscreenPrivate
*) pDRIScreen
->private;
2287 if (drmCreateContext(psp
->fd
, hHWContext
)) {
2288 fprintf(stderr
, ">>> drmCreateContext failed\n");
2291 *(void**)contextID
= (void*) *hHWContext
;
2299 __glXGetDrawableInfo(__DRInativeDisplay
*dpy
, int scrn
,
2300 __DRIid draw
, unsigned int * index
, unsigned int * stamp
,
2301 int * x
, int * y
, int * width
, int * height
,
2302 int * numClipRects
, drm_clip_rect_t
** pClipRects
,
2303 int * backX
, int * backY
,
2304 int * numBackClipRects
, drm_clip_rect_t
** pBackClipRects
)
2306 GLXDrawable drawable
= (GLXDrawable
) draw
;
2307 drm_clip_rect_t
* cliprect
;
2308 Display
* display
= (Display
*)dpy
;
2309 __DRIcontextPrivate
*pcp
= (__DRIcontextPrivate
*)CurrentContext
->driContext
.private;
2310 if (drawable
== 0) {
2314 cliprect
= (drm_clip_rect_t
*) _mesa_malloc(sizeof(drm_clip_rect_t
));
2315 cliprect
->x1
= drawable
->x
;
2316 cliprect
->y1
= drawable
->y
;
2317 cliprect
->x2
= drawable
->x
+ drawable
->w
;
2318 cliprect
->y2
= drawable
->y
+ drawable
->h
;
2320 /* the drawable index is by client id */
2321 *index
= display
->clientID
;
2323 *stamp
= pcp
->driScreenPriv
->pSAREA
->drawableTable
[display
->clientID
].stamp
;
2326 *width
= drawable
->w
;
2327 *height
= drawable
->h
;
2329 *pClipRects
= cliprect
;
2331 *backX
= drawable
->x
;
2332 *backY
= drawable
->y
;
2333 *numBackClipRects
= 0;
2334 *pBackClipRects
= 0;
2341 xf86DRI_DestroyContext(__DRInativeDisplay
*dpy
, int screen
, __DRIid context_id
)
2348 xf86DRI_CreateDrawable(__DRInativeDisplay
*dpy
, int screen
, __DRIid drawable
,
2349 drm_drawable_t
*hHWDrawable
)
2356 xf86DRI_DestroyDrawable(__DRInativeDisplay
*dpy
, int screen
, __DRIid drawable
)
2363 * \brief Query function address.
2365 * The glXGetProcAddress() function will return the address of any available
2366 * OpenGL or Mini GLX function.
2368 * \param procName name of the function to be returned.
2370 * \return If \p procName is a valid function name, a pointer to that function
2371 * will be returned. Otherwise, \c NULL will be returned.
2373 * The purpose of glXGetProcAddress() is to facilitate using future extensions
2374 * to OpenGL or Mini GLX. If a future version of the library adds new extension
2375 * functions they'll be accessible via glXGetProcAddress(). The alternative is
2376 * to hard-code calls to the new functions in the application but doing so will
2377 * prevent linking the application with older versions of the library.
2379 * Returns the function address by looking up its name in a static (name,
2380 * address) pair list.
2382 void (*glXGetProcAddress(const GLubyte
*procname
))( void )
2384 struct name_address
{
2388 static const struct name_address functions
[] = {
2389 { "glXChooseVisual", (void *) glXChooseVisual
},
2390 { "glXCreateContext", (void *) glXCreateContext
},
2391 { "glXDestroyContext", (void *) glXDestroyContext
},
2392 { "glXMakeCurrent", (void *) glXMakeCurrent
},
2393 { "glXSwapBuffers", (void *) glXSwapBuffers
},
2394 { "glXGetCurrentContext", (void *) glXGetCurrentContext
},
2395 { "glXGetCurrentDrawable", (void *) glXGetCurrentDrawable
},
2396 { "glXGetProcAddress", (void *) glXGetProcAddress
},
2397 { "XOpenDisplay", (void *) XOpenDisplay
},
2398 { "XCloseDisplay", (void *) XCloseDisplay
},
2399 { "XCreateWindow", (void *) XCreateWindow
},
2400 { "XDestroyWindow", (void *) XDestroyWindow
},
2401 { "XMapWindow", (void *) XMapWindow
},
2402 { "XCreateColormap", (void *) XCreateColormap
},
2403 { "XFreeColormap", (void *) XFreeColormap
},
2404 { "XFree", (void *) XFree
},
2405 { "XGetVisualinfo", (void *) XGetVisualInfo
},
2406 { "glXCreatePbuffer", (void *) glXCreatePbuffer
},
2407 { "glXDestroyPbuffer", (void *) glXDestroyPbuffer
},
2408 { "glXChooseFBConfig", (void *) glXChooseFBConfig
},
2409 { "glXGetVisualFromFBConfig", (void *) glXGetVisualFromFBConfig
},
2412 const struct name_address
*entry
;
2413 for (entry
= functions
; entry
->name
; entry
++) {
2414 if (strcmp(entry
->name
, (const char *) procname
) == 0) {
2418 return _glapi_get_proc_address((const char *) procname
);
2423 * \brief Query the Mini GLX version.
2425 * \param dpy the display handle. It is currently ignored, but should be the
2426 * value returned by XOpenDisplay().
2427 * \param major receives the major version number of Mini GLX.
2428 * \param minor receives the minor version number of Mini GLX.
2430 * \return \c True if the function succeeds, \c False if the function fails due
2431 * to invalid parameters.
2433 * \sa #MINI_GLX_VERSION_1_0.
2435 * Returns the hard-coded Mini GLX version.
2438 glXQueryVersion( Display
*dpy
, int *major
, int *minor
)
2448 * \brief Create a new pbuffer.
2451 glXCreatePbuffer( Display
*dpy
, GLXFBConfig config
, const int *attribList
)
2458 glXDestroyPbuffer( Display
*dpy
, GLXPbuffer pbuf
)
2465 glXChooseFBConfig( Display
*dpy
, int screen
, const int *attribList
,
2468 GLXFBConfig
*f
= (GLXFBConfig
*) malloc(sizeof(GLXFBConfig
));
2469 f
->visInfo
= glXChooseVisual( dpy
, screen
, (int *) attribList
);
2483 glXGetVisualFromFBConfig( Display
*dpy
, GLXFBConfig config
)
2485 /* XVisualInfo and GLXFBConfig are the same structure */
2487 return config
.visInfo
;
2490 void *glXAllocateMemoryMESA(Display
*dpy
, int scrn
,
2491 size_t size
, float readFreq
,
2492 float writeFreq
, float priority
)
2494 if (dpy
->driScreen
.private && dpy
->driScreen
.allocateMemory
) {
2495 return (*dpy
->driScreen
.allocateMemory
)( dpy
, scrn
, size
,
2496 readFreq
, writeFreq
,
2503 void glXFreeMemoryMESA(Display
*dpy
, int scrn
, void *pointer
)
2505 if (dpy
->driScreen
.private && dpy
->driScreen
.freeMemory
) {
2506 (*dpy
->driScreen
.freeMemory
)( dpy
, scrn
, pointer
);
2510 GLuint
glXGetMemoryOffsetMESA( Display
*dpy
, int scrn
,
2511 const void *pointer
)
2513 if (dpy
->driScreen
.private && dpy
->driScreen
.memoryOffset
) {
2514 return (*dpy
->driScreen
.memoryOffset
)( dpy
, scrn
, pointer
);
2522 * Get the unadjusted system time (UST). Currently, the UST is measured in
2523 * microseconds since Epoc. The actual resolution of the UST may vary from
2524 * system to system, and the units may vary from release to release.
2525 * Drivers should not call this function directly. They should instead use
2526 * \c glXGetProcAddress to obtain a pointer to the function.
2528 * \param ust Location to store the 64-bit UST
2529 * \returns Zero on success or a negative errno value on failure.
2532 * This function was copied directly from src/glx/x11/glxcmds.c.
2534 static int __glXGetUST( int64_t * ust
)
2538 if ( ust
== NULL
) {
2542 if ( gettimeofday( & tv
, NULL
) == 0 ) {
2543 ust
[0] = (tv
.tv_sec
* 1000000) + tv
.tv_usec
;
2554 * This needs to be implemented for miniGlx.
2556 static GLboolean
__glXGetMscRate(__DRInativeDisplay
* dpy
, __DRIid drawable
,
2557 int32_t * numerator
, int32_t * denominator
)