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
;
440 /* Bump size up to next supported mode.
442 if (width
<= 720 && height
<= 480) {
443 width
= 720; height
= 480;
445 else if (width
<= 960 && height
<= 540) {
446 width
= 960; height
= 540;
448 else if (width
<= 800 && height
<= 600) {
449 width
= 800; height
= 600;
451 else if (width
<= 1024 && height
<= 768) {
452 width
= 1024; height
= 768;
454 else if (width
<= 768 && height
<= 1024) {
455 width
= 768; height
= 1024;
457 else if (width
<= 1280 && height
<= 1024) {
458 width
= 1280; height
= 1024;
462 dpy
->driverContext
.shared
.virtualHeight
= height
;
463 dpy
->driverContext
.shared
.virtualWidth
= width
;
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;
882 fname
= getenv("MINIGLX_CONF");
883 if (!fname
) fname
= "/etc/miniglx.conf";
885 file
= fopen(fname
, "r");
887 fprintf(stderr
, "couldn't open config file %s: %s\n", fname
, strerror(errno
));
892 while (!feof(file
)) {
893 char buf
[81], *opt
= buf
, *val
, *tmp1
, *tmp2
;
894 fgets(buf
, sizeof(buf
), file
);
896 /* Parse 'opt = val' -- must be easier ways to do this.
898 while (isspace(*opt
)) opt
++;
900 if (*val
== '#') continue; /* comment */
901 while (!isspace(*val
) && *val
!= '=' && *val
) val
++;
903 while (isspace(*val
)) val
++;
904 if (*val
!= '=') continue;
907 while (isspace(*val
)) val
++;
909 while (!isspace(*tmp2
) && *tmp2
!= '\n' && *tmp2
) tmp2
++;
913 if (strcmp(opt
, "fbdevDevice") == 0)
914 dpy
->fbdevDevice
= strdup(val
);
915 else if (strcmp(opt
, "clientDriverName") == 0)
916 dpy
->clientDriverName
= strdup(val
);
917 else if (strcmp(opt
, "rotateMode") == 0)
918 dpy
->rotateMode
= atoi(val
) ? 1 : 0;
919 else if (strcmp(opt
, "pciBusID") == 0) {
920 if (sscanf(val
, "PCI:%d:%d:%d",
921 &dpy
->driverContext
.pciBus
,
922 &dpy
->driverContext
.pciDevice
,
923 &dpy
->driverContext
.pciFunc
) != 3) {
924 fprintf(stderr
, "malformed bus id: %s\n", val
);
927 dpy
->driverContext
.pciBusID
= strdup(val
);
929 else if (strcmp(opt
, "chipset") == 0) {
930 if (sscanf(val
, "0x%x", &dpy
->driverContext
.chipset
) != 1)
931 fprintf(stderr
, "malformed chipset: %s\n", opt
);
933 else if (strcmp(opt
, "virtualWidth") == 0) {
934 if (sscanf(val
, "%d", &dpy
->driverContext
.shared
.virtualWidth
) != 1)
935 fprintf(stderr
, "malformed virtualWidth: %s\n", opt
);
937 else if (strcmp(opt
, "virtualHeight") == 0) {
938 if (sscanf(val
, "%d", &dpy
->driverContext
.shared
.virtualHeight
) != 1)
939 fprintf(stderr
, "malformed virutalHeight: %s\n", opt
);
941 else if (strcmp(opt
, "bpp") == 0) {
942 if (sscanf(val
, "%d", &dpy
->driverContext
.bpp
) != 1)
943 fprintf(stderr
, "malformed bpp: %s\n", opt
);
944 dpy
->driverContext
.cpp
= dpy
->driverContext
.bpp
/ 8;
946 else if (strcmp(opt
, "agpmode") == 0) {
947 if (sscanf(val
, "%d", &dpy
->driverContext
.agpmode
) != 1)
948 fprintf(stderr
, "malformed agpmode: %s\n", opt
);
950 else if (strcmp(opt
, "isPCI") == 0) {
951 dpy
->driverContext
.isPCI
= atoi(val
) ? 1 : 0;
957 if (dpy
->driverContext
.chipset
== 0 && dpy
->driverContext
.pciBusID
!= 0)
958 dpy
->driverContext
.chipset
= get_chipset_from_busid( dpy
);
964 * Versioned name of the expected \c __driCreateNewScreen function.
966 * The version of the last incompatible loader/driver inteface change is
967 * appended to the name of the \c __driCreateNewScreen function. This
968 * prevents loaders from trying to load drivers that are too old.
971 * Create a macro or something so that this is automatically updated.
973 static const char createNewScreenName
[] = "__driCreateNewScreen_20050727";
976 static int InitDriver( Display
*dpy
)
980 * We're kind of combining the per-display and per-screen information
981 * which was kept separate in XFree86/DRI's libGL.
983 dpy
->dlHandle
= dlopen(dpy
->clientDriverName
, RTLD_NOW
| RTLD_GLOBAL
);
984 if (!dpy
->dlHandle
) {
985 fprintf(stderr
, "Unable to open %s: %s\n", dpy
->clientDriverName
,
990 /* Pull in Mini GLX specific hooks:
992 dpy
->driver
= (struct DRIDriverRec
*) dlsym(dpy
->dlHandle
,
995 fprintf(stderr
, "Couldn't find __driDriver in %s\n",
996 dpy
->clientDriverName
);
1000 /* Pull in standard DRI client-side driver hooks:
1002 dpy
->createNewScreen
= (PFNCREATENEWSCREENFUNC
)
1003 dlsym(dpy
->dlHandle
, createNewScreenName
);
1004 if (!dpy
->createNewScreen
) {
1005 fprintf(stderr
, "Couldn't find %s in %s\n", createNewScreenName
,
1006 dpy
->clientDriverName
);
1013 if (dpy
->dlHandle
) {
1014 dlclose(dpy
->dlHandle
);
1021 /**********************************************************************/
1022 /** \name Public API functions (Xlib and GLX) */
1023 /**********************************************************************/
1028 * \brief Initialize the graphics system.
1030 * \param display_name currently ignored. It is recommended to pass it as NULL.
1031 * \return a pointer to a #Display if the function is able to initialize
1032 * the graphics system, NULL otherwise.
1034 * Allocates a MiniGLXDisplayRec structure and fills in with information from a
1035 * configuration file.
1037 * Calls OpenFBDev() to open the framebuffer device and calls
1038 * DRIDriverRec::initFBDev to do the client-side initialization on it.
1040 * Loads the DRI driver and pulls in Mini GLX specific hooks into a
1041 * DRIDriverRec structure, and the standard DRI \e __driCreateScreen hook.
1042 * Asks the driver for a list of supported visuals. Performs the per-screen
1043 * client-side initialization. Also setups the callbacks in the screen private
1046 * Does the framebuffer device setup. Calls __miniglx_open_connections() to
1050 __miniglx_StartServer( const char *display_name
)
1055 dpy
= (Display
*)calloc(1, sizeof(Display
));
1059 dpy
->IsClient
= False
;
1061 if (!__read_config_file( dpy
)) {
1062 fprintf(stderr
, "Couldn't get configuration details\n");
1067 /* Open the fbdev device
1069 if (!OpenFBDev(dpy
, use_vt
)) {
1070 fprintf(stderr
, "OpenFBDev failed\n");
1075 if (!InitDriver(dpy
)) {
1076 fprintf(stderr
, "InitDriver failed\n");
1081 /* Perform the initialization normally done in the X server
1083 if (!dpy
->driver
->initFBDev( &dpy
->driverContext
)) {
1084 fprintf(stderr
, "%s: __driInitFBDev failed\n", __FUNCTION__
);
1085 dlclose(dpy
->dlHandle
);
1091 if (!SetupFBDev(dpy
)) {
1092 fprintf(stderr
, "SetupFBDev failed\n");
1097 /* unlock here if not using VT -- JDS */
1099 if (dpy
->driver
->restoreHardware
)
1100 dpy
->driver
->restoreHardware( &dpy
->driverContext
);
1101 DRM_UNLOCK( dpy
->driverContext
.drmFD
,
1102 dpy
->driverContext
.pSAREA
,
1103 dpy
->driverContext
.serverContext
);
1107 /* Ready for clients:
1109 if (!__miniglx_open_connections(dpy
)) {
1119 * Implement \c __DRIinterfaceMethods::getProcAddress.
1121 static __DRIfuncPtr
get_proc_address( const char * proc_name
)
1129 * Table of functions exported by the loader to the driver.
1131 static const __DRIinterfaceMethods interface_methods
= {
1134 _gl_context_modes_create
,
1135 _gl_context_modes_destroy
,
1140 __glXCreateContextWithConfig
,
1141 xf86DRI_DestroyContext
,
1143 xf86DRI_CreateDrawable
,
1144 xf86DRI_DestroyDrawable
,
1145 __glXGetDrawableInfo
,
1153 CallCreateNewScreen(Display
*dpy
, int scrn
, __DRIscreen
*psc
)
1156 drm_handle_t hSAREA
;
1160 __DRIversion ddx_version
;
1161 __DRIversion dri_version
;
1162 __DRIversion drm_version
;
1163 __DRIframebuffer framebuffer
;
1166 const char * err_msg
;
1167 const char * err_extra
;
1168 drmVersionPtr version
;
1173 hSAREA
= dpy
->driverContext
.shared
.hSAREA
;
1174 BusID
= dpy
->driverContext
.pciBusID
;
1176 fd
= drmOpen(NULL
, BusID
);
1178 err_msg
= "open DRM";
1179 err_extra
= strerror( -fd
);
1181 if (fd
< 0) goto done
;
1183 err_msg
= "drmGetMagic";
1186 if (drmGetMagic(fd
, &magic
)) goto done
;
1188 dpy
->authorized
= False
;
1189 send_char_msg( dpy
, 0, _Authorize
);
1190 send_msg( dpy
, 0, &magic
, sizeof(magic
));
1192 /* force net buffer flush */
1193 while (!dpy
->authorized
)
1194 handle_fd_events( dpy
, 0 );
1196 version
= drmGetVersion(fd
);
1198 drm_version
.major
= version
->version_major
;
1199 drm_version
.minor
= version
->version_minor
;
1200 drm_version
.patch
= version
->version_patchlevel
;
1201 drmFreeVersion(version
);
1204 drm_version
.major
= -1;
1205 drm_version
.minor
= -1;
1206 drm_version
.patch
= -1;
1210 * Get device name (like "tdfx") and the ddx version numbers.
1211 * We'll check the version in each DRI driver's "createScreen"
1214 ddx_version
.major
= 4;
1215 ddx_version
.minor
= 0;
1216 ddx_version
.patch
= 0;
1219 * Get the DRI X extension version.
1221 dri_version
.major
= 4;
1222 dri_version
.minor
= 0;
1223 dri_version
.patch
= 0;
1226 * Get device-specific info. pDevPriv will point to a struct
1227 * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h)
1228 * that has information about the screen size, depth, pitch,
1229 * ancilliary buffers, DRM mmap handles, etc.
1231 hFB
= dpy
->driverContext
.shared
.hFrameBuffer
;
1232 framebuffer
.size
= dpy
->driverContext
.shared
.fbSize
;
1233 framebuffer
.stride
= dpy
->driverContext
.shared
.fbStride
;
1234 framebuffer
.dev_priv_size
= dpy
->driverContext
.driverClientMsgSize
;
1235 framebuffer
.dev_priv
= dpy
->driverContext
.driverClientMsg
;
1236 framebuffer
.width
= dpy
->driverContext
.shared
.virtualWidth
;
1237 framebuffer
.height
= dpy
->driverContext
.shared
.virtualHeight
;
1240 * Map the framebuffer region.
1242 status
= drmMap(fd
, hFB
, framebuffer
.size
,
1243 (drmAddressPtr
)&framebuffer
.base
);
1245 err_msg
= "drmMap of framebuffer";
1246 err_extra
= strerror( -status
);
1248 if ( status
!= 0 ) goto done
;
1251 * Map the SAREA region. Further mmap regions may be setup in
1252 * each DRI driver's "createScreen" function.
1254 status
= drmMap(fd
, hSAREA
, SAREA_MAX
, &pSAREA
);
1256 err_msg
= "drmMap of sarea";
1257 err_extra
= strerror( -status
);
1259 if ( status
== 0 ) {
1260 err_msg
= "InitDriver";
1262 psp
= dpy
->createNewScreen(dpy
, scrn
, psc
, NULL
,
1270 & interface_methods
,
1271 (__GLcontextModes
**) &dpy
->driver_modes
);
1273 /* fill in dummy visual ids */
1275 __GLcontextModes
*temp
;
1276 temp
= (__GLcontextModes
*)dpy
->driver_modes
;
1280 temp
->visualID
= i
++;
1287 if ( psp
== NULL
) {
1288 if ( pSAREA
!= MAP_FAILED
) {
1289 (void)drmUnmap(pSAREA
, SAREA_MAX
);
1292 if ( framebuffer
.base
!= MAP_FAILED
) {
1293 (void)drmUnmap((drmAddress
)framebuffer
.base
, framebuffer
.size
);
1296 if ( framebuffer
.dev_priv
!= NULL
) {
1297 free(framebuffer
.dev_priv
);
1304 if ( err_extra
!= NULL
) {
1305 fprintf(stderr
, "libGL error: %s failed (%s)\n", err_msg
,
1309 fprintf(stderr
, "libGL error: %s failed\n", err_msg
);
1312 fprintf(stderr
, "libGL error: reverting to (slow) indirect rendering\n");
1319 * \brief Initialize the graphics system.
1321 * \param display_name currently ignored. It is recommended to pass it as NULL.
1322 * \return a pointer to a #Display if the function is able to initialize
1323 * the graphics system, NULL otherwise.
1325 * Allocates a MiniGLXDisplayRec structure and fills in with information from a
1326 * configuration file.
1328 * Calls __miniglx_open_connections() to connect to the server.
1330 * Loads the DRI driver and pulls in Mini GLX specific hooks into a
1331 * DRIDriverRec structure, and the standard DRI \e __driCreateScreen hook.
1332 * Asks the driver for a list of supported visuals. Performs the per-screen
1333 * client-side initialization. Also setups the callbacks in the screen private
1337 * - read config file
1338 * - what about virtualWidth, etc?
1339 * - determine dpy->driverClientMsgSize,
1340 * - allocate dpy->driverClientMsg
1343 XOpenDisplay( const char *display_name
)
1347 dpy
= (Display
*)calloc(1, sizeof(Display
));
1351 dpy
->IsClient
= True
;
1355 if (!__read_config_file( dpy
)) {
1356 fprintf(stderr
, "Couldn't get configuration details\n");
1361 /* Connect to the server and receive driverClientMsg
1363 if (!__miniglx_open_connections(dpy
)) {
1368 /* dlopen the driver .so file
1370 if (!InitDriver(dpy
)) {
1371 fprintf(stderr
, "InitDriver failed\n");
1376 /* Perform the client-side initialization.
1378 * Clearly there is a limit of one on the number of windows in
1379 * existence at any time.
1381 * Need to shut down DRM and free DRI data in XDestroyWindow(), too.
1383 dpy
->driScreen
.private = CallCreateNewScreen(dpy
, 0, &dpy
->driScreen
);
1384 if (!dpy
->driScreen
.private) {
1385 fprintf(stderr
, "%s: __driCreateScreen failed\n", __FUNCTION__
);
1386 dlclose(dpy
->dlHandle
);
1391 /* Anything more to do?
1398 * \brief Release display resources.
1400 * When the application is about to exit, the resources associated with the
1401 * graphics system can be released by calling this function.
1403 * \param dpy display handle. It becomes invalid at this point.
1405 * Destroys the window if any, and destroys the per-screen
1406 * driver private information.
1407 * Calls __miniglx_close_connections().
1409 * If a server, puts the the framebuffer back into the initial state.
1411 * Finally frees the display structure.
1414 XCloseDisplay( Display
*dpy
)
1416 glXMakeCurrent( dpy
, NULL
, NULL
);
1418 if (dpy
->NumWindows
)
1419 XDestroyWindow( dpy
, dpy
->TheWindow
);
1421 /* As this is done in XOpenDisplay, need to undo it here:
1423 dpy
->driScreen
.destroyScreen(dpy
, 0, dpy
->driScreen
.private);
1425 __miniglx_close_connections( dpy
);
1427 if (!dpy
->IsClient
) {
1428 /* put framebuffer back to initial state
1430 (*dpy
->driver
->haltFBDev
)( &dpy
->driverContext
);
1435 dlclose(dpy
->dlHandle
);
1441 * \brief Window creation.
1443 * \param display a display handle, as returned by XOpenDisplay().
1444 * \param parent the parent window for the new window. For Mini GLX this should
1446 * \code RootWindow(display, 0) \endcode
1447 * \param x the window abscissa. For Mini GLX, it should be zero.
1448 * \param y the window ordinate. For Mini GLX, it should be zero.
1449 * \param width the window width. For Mini GLX, this specifies the desired
1450 * screen width such as 1024 or 1280.
1451 * \param height the window height. For Mini GLX, this specifies the desired
1452 * screen height such as 768 or 1024.
1453 * \param border_width the border width. For Mini GLX, it should be zero.
1454 * \param depth the window pixel depth. For Mini GLX, this should be the depth
1455 * found in the #XVisualInfo object returned by glXChooseVisual()
1456 * \param winclass the window class. For Mini GLX this value should be
1458 * \param visual the visual type. It should be the visual field of the
1459 * #XVisualInfo object returned by glXChooseVisual().
1460 * \param valuemask which fields of the XSetWindowAttributes() are to be used.
1461 * For Mini GLX this is typically the bitmask
1462 * \code CWBackPixel | CWBorderPixel | CWColormap \endcode
1463 * \param attributes initial window attributes. The
1464 * XSetWindowAttributes::background_pixel, XSetWindowAttributes::border_pixel
1465 * and XSetWindowAttributes::colormap fields should be set.
1467 * \return a window handle if it succeeds or zero if it fails.
1469 * \note For Mini GLX, windows are full-screen; they cover the entire frame
1470 * buffer. Also, Mini GLX imposes a limit of one window. A second window
1471 * cannot be created until the first one is destroyed.
1473 * This function creates and initializes a ::MiniGLXWindowRec structure after
1474 * ensuring that there is no other window created. Performs the per-drawable
1475 * client-side initialization calling the __DRIscreenRec::createDrawable
1480 XCreateWindow( Display
*dpy
, Window parent
, int x
, int y
,
1481 unsigned int width
, unsigned int height
,
1482 unsigned int border_width
, int depth
, unsigned int winclass
,
1483 Visual
*visual
, unsigned long valuemask
,
1484 XSetWindowAttributes
*attributes
)
1486 const int empty_attribute_list
[1] = { None
};
1493 (void) border_width
;
1499 if (!dpy
->IsClient
) {
1500 fprintf(stderr
, "Server process may not create windows (currently)\n");
1504 if (dpy
->NumWindows
> 0)
1505 return NULL
; /* only allow one window */
1507 assert(dpy
->TheWindow
== NULL
);
1509 win
= malloc(sizeof(struct MiniGLXWindowRec
));
1513 /* In rotated mode, translate incoming x,y,width,height into
1514 * 'normal' coordinates.
1516 if (dpy
->rotateMode
) {
1518 tmp
= width
; width
= height
; height
= tmp
;
1519 tmp
= x
; x
= y
; y
= tmp
;
1522 /* init other per-window fields */
1527 win
->visual
= visual
; /* ptr assignment */
1529 win
->bytesPerPixel
= dpy
->driverContext
.cpp
;
1530 win
->rowStride
= dpy
->driverContext
.shared
.virtualWidth
* win
->bytesPerPixel
;
1531 win
->size
= win
->rowStride
* height
;
1532 win
->frontStart
= dpy
->driverContext
.FBAddress
;
1533 win
->frontBottom
= (GLubyte
*) win
->frontStart
+ (height
-1) * win
->rowStride
;
1535 /* This is incorrect: the hardware driver could put the backbuffer
1536 * just about anywhere. These fields, including the above are
1537 * hardware dependent & don't really belong here.
1539 if (visual
->mode
->doubleBufferMode
) {
1540 win
->backStart
= (GLubyte
*) win
->frontStart
+
1541 win
->rowStride
* dpy
->driverContext
.shared
.virtualHeight
;
1542 win
->backBottom
= (GLubyte
*) win
->backStart
1543 + (height
- 1) * win
->rowStride
;
1544 win
->curBottom
= win
->backBottom
;
1547 /* single buffered */
1548 win
->backStart
= NULL
;
1549 win
->backBottom
= NULL
;
1550 win
->curBottom
= win
->frontBottom
;
1553 dpy
->driScreen
.createNewDrawable(dpy
, visual
->mode
, (int) win
,
1554 &win
->driDrawable
, GLX_WINDOW_BIT
, empty_attribute_list
);
1556 if (!win
->driDrawable
.private) {
1557 fprintf(stderr
, "%s: dri.createDrawable failed\n", __FUNCTION__
);
1563 dpy
->TheWindow
= win
;
1570 * \brief Destroy window.
1572 * \param display display handle.
1573 * \param w window handle.
1575 * This function calls XUnmapWindow() and frees window \p w.
1577 * In case of destroying the current buffer first unbinds the GLX context
1578 * by calling glXMakeCurrent() with no drawable.
1581 XDestroyWindow( Display
*display
, Window win
)
1583 if (display
&& display
->IsClient
&& win
) {
1584 /* check if destroying the current buffer */
1585 Window curDraw
= glXGetCurrentDrawable();
1586 if (win
== curDraw
) {
1587 glXMakeCurrent( display
, NULL
, NULL
);
1590 XUnmapWindow( display
, win
);
1592 /* Destroy the drawable. */
1593 win
->driDrawable
.destroyDrawable(display
, win
->driDrawable
.private);
1596 /* unlink window from display */
1597 display
->NumWindows
--;
1598 assert(display
->NumWindows
== 0);
1599 display
->TheWindow
= NULL
;
1607 * \brief Create color map structure.
1609 * \param dpy the display handle as returned by XOpenDisplay().
1610 * \param w the window on whose screen you want to create a color map. This
1611 * parameter is ignored by Mini GLX but should be the value returned by the
1612 * \code RootWindow(display, 0) \endcode macro.
1613 * \param visual a visual type supported on the screen. This parameter is
1614 * ignored by Mini GLX but should be the XVisualInfo::visual returned by
1615 * glXChooseVisual().
1616 * \param alloc the color map entries to be allocated. This parameter is ignored
1617 * by Mini GLX but should be set to #AllocNone.
1619 * \return the color map.
1621 * This function is only provided to ease porting. Practically a no-op -
1622 * returns a pointer to a dynamically allocated chunk of memory (one byte).
1625 XCreateColormap( Display
*dpy
, Window w
, Visual
*visual
, int alloc
)
1631 return (Colormap
) malloc(1);
1636 * \brief Destroy color map structure.
1638 * \param display The display handle as returned by XOpenDisplay().
1639 * \param colormap the color map to destroy.
1641 * This function is only provided to ease porting. Practically a no-op.
1643 * Frees the memory pointed by \p colormap.
1646 XFreeColormap( Display
*display
, Colormap colormap
)
1655 * \brief Free client data.
1657 * \param data the data that is to be freed.
1659 * Frees the memory pointed by \p data.
1669 * \brief Query available visuals.
1671 * \param dpy the display handle, as returned by XOpenDisplay().
1672 * \param vinfo_mask a bitmask indicating which fields of the \p vinfo_template
1673 * are to be matched. The value must be \c VisualScreenMask.
1674 * \param vinfo_template a template whose fields indicate which visual
1675 * attributes must be matched by the results. The XVisualInfo::screen field of
1676 * this structure must be zero.
1677 * \param nitens_return will hold the number of visuals returned.
1679 * \return the address of an array of all available visuals.
1681 * An example of using XGetVisualInfo() to get all available visuals follows:
1684 * XVisualInfo vinfo_template, *results;
1685 * int nitens_return;
1686 * Display *dpy = XOpenDisplay(NULL);
1687 * vinfo_template.screen = 0;
1688 * results = XGetVisualInfo(dpy, VisualScreenMask, &vinfo_template, &nitens_return);
1691 * Returns the list of all ::XVisualInfo available, one per
1692 * ::__GLcontextMode stored in MiniGLXDisplayRec::modes.
1695 XGetVisualInfo( Display
*dpy
, long vinfo_mask
, XVisualInfo
*vinfo_template
, int *nitens_return
)
1697 const __GLcontextModes
*mode
;
1698 XVisualInfo
*results
;
1702 // ASSERT(vinfo_mask == VisualScreenMask);
1703 ASSERT(vinfo_template
.screen
== 0);
1705 if (vinfo_mask
== VisualIDMask
)
1707 for ( mode
= dpy
->driver_modes
; mode
!= NULL
; mode
= mode
->next
)
1708 if (mode
->visualID
== vinfo_template
->visualid
)
1714 results
= (XVisualInfo
*)calloc(1, n
* sizeof(XVisualInfo
));
1720 visResults
= (Visual
*)calloc(1, n
* sizeof(Visual
));
1727 for ( mode
= dpy
->driver_modes
; mode
!= NULL
; mode
= mode
->next
)
1728 if (mode
->visualID
== vinfo_template
->visualid
)
1730 visResults
[0].mode
=mode
;
1731 visResults
[0].visInfo
= results
;
1732 visResults
[0].dpy
= dpy
;
1733 if (dpy
->driverContext
.bpp
== 32)
1734 visResults
[0].pixelFormat
= PF_B8G8R8A8
; /* XXX: FIX ME */
1736 visResults
[0].pixelFormat
= PF_B5G6R5
; /* XXX: FIX ME */
1738 results
[0].visual
= visResults
;
1739 results
[0].visualid
= mode
->visualID
;
1740 #if defined(__cplusplus) || defined(c_plusplus)
1741 results
[0].c_class
= TrueColor
;
1743 results
[0].class = TrueColor
;
1745 results
[0].depth
= mode
->redBits
+
1749 results
[0].bits_per_rgb
= dpy
->driverContext
.bpp
;
1754 else // if (vinfo_mask == VisualScreenMask)
1757 for ( mode
= dpy
->driver_modes
; mode
!= NULL
; mode
= mode
->next
)
1760 results
= (XVisualInfo
*)calloc(1, n
* sizeof(XVisualInfo
));
1766 visResults
= (Visual
*)calloc(1, n
* sizeof(Visual
));
1773 for ( mode
= dpy
->driver_modes
, i
= 0 ; mode
!= NULL
; mode
= mode
->next
, i
++ ) {
1774 visResults
[i
].mode
= mode
;
1775 visResults
[i
].visInfo
= results
+ i
;
1776 visResults
[i
].dpy
= dpy
;
1778 if (dpy
->driverContext
.bpp
== 32)
1779 visResults
[i
].pixelFormat
= PF_B8G8R8A8
; /* XXX: FIX ME */
1781 visResults
[i
].pixelFormat
= PF_B5G6R5
; /* XXX: FIX ME */
1783 results
[i
].visual
= visResults
+ i
;
1784 results
[i
].visualid
= mode
->visualID
;
1785 #if defined(__cplusplus) || defined(c_plusplus)
1786 results
[i
].c_class
= TrueColor
;
1788 results
[i
].class = TrueColor
;
1790 results
[i
].depth
= mode
->redBits
+
1794 results
[i
].bits_per_rgb
= dpy
->driverContext
.bpp
;
1803 * \brief Return a visual that matches specified attributes.
1805 * \param dpy the display handle, as returned by XOpenDisplay().
1806 * \param screen the screen number. It is currently ignored by Mini GLX and
1808 * \param attribList a list of GLX attributes which describe the desired pixel
1809 * format. It is terminated by the token \c None.
1811 * The attributes are as follows:
1813 * This attribute should always be present in order to maintain compatibility
1816 * If present, only RGBA pixel formats will be considered. Otherwise, only
1817 * color index formats are considered.
1818 * \arg GLX_DOUBLEBUFFER:
1819 * if present, only double-buffered pixel formats will be chosen.
1820 * \arg GLX_RED_SIZE \e n:
1821 * Must be followed by a non-negative integer indicating the minimum number of
1822 * bits per red pixel component that is acceptable.
1823 * \arg GLX_GREEN_SIZE \e n:
1824 * Must be followed by a non-negative integer indicating the minimum number of
1825 * bits per green pixel component that is acceptable.
1826 * \arg GLX_BLUE_SIZE \e n:
1827 * Must be followed by a non-negative integer indicating the minimum number of
1828 * bits per blue pixel component that is acceptable.
1829 * \arg GLX_ALPHA_SIZE \e n:
1830 * Must be followed by a non-negative integer indicating the minimum number of
1831 * bits per alpha pixel component that is acceptable.
1832 * \arg GLX_STENCIL_SIZE \e n:
1833 * Must be followed by a non-negative integer indicating the minimum number of
1834 * bits per stencil value that is acceptable.
1835 * \arg GLX_DEPTH_SIZE \e n:
1836 * Must be followed by a non-negative integer indicating the minimum number of
1837 * bits per depth component that is acceptable.
1839 * This token is used to terminate the attribute list.
1841 * \return a pointer to an #XVisualInfo object which most closely matches the
1842 * requirements of the attribute list. If there is no visual which matches the
1843 * request, \c NULL will be returned.
1845 * \note Visuals with accumulation buffers are not available.
1847 * This function searches the list of available visual configurations in
1848 * MiniGLXDisplayRec::configs for a configuration which best matches the GLX
1849 * attribute list parameter. A new ::XVisualInfo object is created which
1850 * describes the visual configuration. The match criteria is described in the
1854 glXChooseVisual( Display
*dpy
, int screen
, int *attribList
)
1856 const __GLcontextModes
*mode
;
1858 XVisualInfo
*visInfo
;
1860 GLboolean rgbFlag
= GL_FALSE
, dbFlag
= GL_FALSE
, stereoFlag
= GL_FALSE
;
1861 GLint redBits
= 0, greenBits
= 0, blueBits
= 0, alphaBits
= 0;
1862 GLint indexBits
= 0, depthBits
= 0, stencilBits
= 0;
1863 GLint numSamples
= 0;
1867 * XXX in the future, <screen> might be interpreted as a VT
1870 ASSERT(screen
== 0);
1872 vis
= (Visual
*)calloc(1, sizeof(Visual
));
1876 visInfo
= (XVisualInfo
*)malloc(sizeof(XVisualInfo
));
1882 visInfo
->visual
= vis
;
1883 vis
->visInfo
= visInfo
;
1886 /* parse the attribute list */
1887 for (attrib
= attribList
; attrib
&& *attrib
!= None
; attrib
++) {
1888 switch (attrib
[0]) {
1889 case GLX_DOUBLEBUFFER
:
1896 redBits
= attrib
[1];
1899 case GLX_GREEN_SIZE
:
1900 greenBits
= attrib
[1];
1904 blueBits
= attrib
[1];
1907 case GLX_ALPHA_SIZE
:
1908 alphaBits
= attrib
[1];
1911 case GLX_STENCIL_SIZE
:
1912 stencilBits
= attrib
[1];
1915 case GLX_DEPTH_SIZE
:
1916 depthBits
= attrib
[1];
1920 case GLX_ACCUM_RED_SIZE
:
1921 accumRedBits
= attrib
[1];
1924 case GLX_ACCUM_GREEN_SIZE
:
1925 accumGreenBits
= attrib
[1];
1928 case GLX_ACCUM_BLUE_SIZE
:
1929 accumBlueBits
= attrib
[1];
1932 case GLX_ACCUM_ALPHA_SIZE
:
1933 accumAlphaBits
= attrib
[1];
1937 /* ignored for now */
1941 /* unexpected token */
1942 fprintf(stderr
, "unexpected token in glXChooseVisual attrib list\n");
1949 /* search screen configs for suitable visual */
1957 for ( mode
= dpy
->driver_modes
; mode
!= NULL
; mode
= mode
->next
) {
1959 if (mode
->rgbMode
== rgbFlag
&&
1960 mode
->doubleBufferMode
== dbFlag
&&
1961 mode
->redBits
>= redBits
&&
1962 mode
->greenBits
>= greenBits
&&
1963 mode
->blueBits
>= blueBits
&&
1964 mode
->alphaBits
>= alphaBits
&&
1965 mode
->depthBits
>= depthBits
&&
1966 mode
->stencilBits
>= stencilBits
) {
1968 visInfo
->visualid
= i
;
1976 /* compute depth and bpp */
1978 /* XXX maybe support depth 16 someday */
1979 #if defined(__cplusplus) || defined(c_plusplus)
1980 visInfo
->c_class
= TrueColor
;
1982 visInfo
->class = TrueColor
;
1984 visInfo
->depth
= dpy
->driverContext
.bpp
;
1985 visInfo
->bits_per_rgb
= dpy
->driverContext
.bpp
;
1986 if (dpy
->driverContext
.bpp
== 32)
1987 vis
->pixelFormat
= PF_B8G8R8A8
;
1989 vis
->pixelFormat
= PF_B5G6R5
;
1992 /* color index mode */
1993 #if defined(__cplusplus) || defined(c_plusplus)
1994 visInfo
->c_class
= PseudoColor
;
1996 visInfo
->class = PseudoColor
;
1999 visInfo
->bits_per_rgb
= 8; /* bits/pixel */
2000 vis
->pixelFormat
= PF_CI8
;
2008 * \brief Return information about GLX visuals.
2010 * \param dpy the display handle, as returned by XOpenDisplay().
2011 * \param vis the visual to be queried, as returned by glXChooseVisual().
2012 * \param attrib the visual attribute to be returned.
2013 * \param value pointer to an integer in which the result of the query will be
2016 * \return zero if no error occurs, \c GLX_INVALID_ATTRIBUTE if the attribute
2017 * parameter is invalid, or \c GLX_BAD_VISUAL if the \p vis parameter is
2020 * Returns the appropriate attribute of ::__GLXvisualConfig pointed by
2021 * MiniGLXVisualRec::glxConfig of XVisualInfo::visual.
2026 glXGetConfig( Display
*dpy
, XVisualInfo
*vis
, int attrib
, int *value
)
2028 const __GLcontextModes
*mode
= vis
->visual
->mode
;
2031 return GLX_BAD_VISUAL
;
2039 *value
= mode
->rgbMode
;
2041 case GLX_DOUBLEBUFFER
:
2042 *value
= mode
->doubleBufferMode
;
2045 *value
= mode
->redBits
;
2047 case GLX_GREEN_SIZE
:
2048 *value
= mode
->greenBits
;
2051 *value
= mode
->blueBits
;
2053 case GLX_ALPHA_SIZE
:
2054 *value
= mode
->alphaBits
;
2056 case GLX_DEPTH_SIZE
:
2057 *value
= mode
->depthBits
;
2059 case GLX_STENCIL_SIZE
:
2060 *value
= mode
->stencilBits
;
2064 return GLX_BAD_ATTRIBUTE
;
2071 * \brief Create a new GLX rendering context.
2073 * \param dpy the display handle, as returned by XOpenDisplay().
2074 * \param vis the visual that defines the frame buffer resources available to
2075 * the rendering context, as returned by glXChooseVisual().
2076 * \param shareList If non-zero, texture objects and display lists are shared
2077 * with the named rendering context. If zero, texture objects and display lists
2078 * will (initially) be private to this context. They may be shared when a
2079 * subsequent context is created.
2080 * \param direct whether direct or indirect rendering is desired. For Mini GLX
2081 * this value is ignored but it should be set to \c True.
2083 * \return a ::GLXContext handle if it succeeds or zero if it fails due to
2084 * invalid parameter or insufficient resources.
2086 * This function creates and initializes a ::MiniGLXContextRec structure and
2087 * calls the __DRIscreenRec::createContext method to initialize the client
2091 glXCreateContext( Display
*dpy
, XVisualInfo
*vis
,
2092 GLXContext shareList
, Bool direct
)
2099 ctx
= (struct MiniGLXContextRec
*)calloc(1, sizeof(struct MiniGLXContextRec
));
2103 ctx
->vid
= vis
->visualid
;
2106 sharePriv
= shareList
->driContext
.private;
2110 ctx
->driContext
.mode
= vis
->visual
->mode
;
2111 ctx
->driContext
.private = dpy
->driScreen
.createNewContext(dpy
, vis
->visual
->mode
,
2112 GLX_WINDOW_BIT
, sharePriv
, &ctx
->driContext
);
2114 if (!ctx
->driContext
.private) {
2124 * \brief Destroy a GLX context.
2126 * \param dpy the display handle, as returned by XOpenDisplay().
2127 * \param ctx the GLX context to be destroyed.
2129 * This function frees the \p ctx parameter after unbinding the current context
2130 * by calling the __DRIcontextRec::bindContext method with zeros and calling
2131 * the __DRIcontextRec::destroyContext method.
2134 glXDestroyContext( Display
*dpy
, GLXContext ctx
)
2136 GLXContext glxctx
= glXGetCurrentContext();
2139 if (glxctx
== ctx
) {
2140 /* destroying current context */
2141 ctx
->driContext
.bindContext(dpy
, 0, 0, 0, 0);
2144 ctx
->driContext
.destroyContext(dpy
, 0, ctx
->driContext
.private);
2151 * \brief Bind a GLX context to a window or a pixmap.
2153 * \param dpy the display handle, as returned by XOpenDisplay().
2154 * \param drawable the window or drawable to bind to the rendering context.
2155 * This should be the value returned by XCreateWindow().
2156 * \param ctx the GLX context to be destroyed.
2158 * \return \c True if it succeeds, \c False otherwise to indicate an invalid
2159 * display, window or context parameter.
2161 * The current rendering context may be unbound by calling glXMakeCurrent()
2162 * with the window and context parameters set to zero.
2164 * An application may create any number of rendering contexts and bind them as
2165 * needed. Note that binding a rendering context is generally not a
2166 * light-weight operation. Most simple OpenGL applications create only one
2167 * rendering context.
2169 * This function first unbinds any old context via
2170 * __DRIcontextRec::unbindContext and binds the new one via
2171 * __DRIcontextRec::bindContext.
2173 * If \p drawable is zero it unbinds the GLX context by calling
2174 * __DRIcontextRec::bindContext with zeros.
2177 glXMakeCurrent( Display
*dpy
, GLXDrawable drawable
, GLXContext ctx
)
2179 if (dpy
&& drawable
&& ctx
) {
2180 GLXContext oldContext
= glXGetCurrentContext();
2181 GLXDrawable oldDrawable
= glXGetCurrentDrawable();
2184 oldContext
->driContext
.unbindContext(dpy
, 0,
2185 (__DRIid
) oldDrawable
, (__DRIid
) oldDrawable
,
2186 &oldContext
->driContext
);
2189 CurrentContext
= ctx
;
2190 ctx
->driContext
.bindContext(dpy
, 0, (__DRIid
) drawable
,
2191 (__DRIid
) drawable
, &ctx
->driContext
);
2192 ctx
->drawBuffer
= drawable
;
2193 ctx
->curBuffer
= drawable
;
2195 else if (ctx
&& dpy
) {
2197 ctx
->driContext
.bindContext(dpy
, 0, 0, 0, 0);
2200 CurrentContext
= 0; /* kw: this seems to be intended??? */
2208 * \brief Exchange front and back buffers.
2210 * \param dpy the display handle, as returned by XOpenDisplay().
2211 * \param drawable the drawable whose buffers are to be swapped.
2213 * Any pending rendering commands will be completed before the buffer swap
2216 * Calling glXSwapBuffers() on a window which is single-buffered has no effect.
2218 * This function just calls the __DRIdrawableRec::swapBuffers method to do the
2222 glXSwapBuffers( Display
*dpy
, GLXDrawable drawable
)
2224 if (!dpy
|| !drawable
)
2227 drawable
->driDrawable
.swapBuffers(dpy
, drawable
->driDrawable
.private);
2232 * \brief Return the current context
2234 * \return the current context, as specified by glXMakeCurrent(), or zero if no
2235 * context is currently bound.
2237 * \sa glXCreateContext(), glXMakeCurrent()
2239 * Returns the value of the ::CurrentContext global variable.
2242 glXGetCurrentContext( void )
2244 return CurrentContext
;
2249 * \brief Return the current drawable.
2251 * \return the current drawable, as specified by glXMakeCurrent(), or zero if
2252 * no drawable is currently bound.
2254 * This function gets the current context via glXGetCurrentContext() and
2255 * returns the MiniGLXContextRec::drawBuffer attribute.
2258 glXGetCurrentDrawable( void )
2260 GLXContext glxctx
= glXGetCurrentContext();
2262 return glxctx
->drawBuffer
;
2269 __glXCreateContextWithConfig(__DRInativeDisplay
*dpy
, int screen
,
2270 int fbconfigID
, void *contextID
, drm_context_t
*hHWContext
)
2272 __DRIscreen
*pDRIScreen
;
2273 __DRIscreenPrivate
*psp
;
2275 pDRIScreen
= __glXFindDRIScreen(dpy
, screen
);
2276 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
2280 psp
= (__DRIscreenPrivate
*) pDRIScreen
->private;
2283 if (drmCreateContext(psp
->fd
, hHWContext
)) {
2284 fprintf(stderr
, ">>> drmCreateContext failed\n");
2287 *(void**)contextID
= (void*) *hHWContext
;
2295 __glXGetDrawableInfo(__DRInativeDisplay
*dpy
, int scrn
,
2296 __DRIid draw
, unsigned int * index
, unsigned int * stamp
,
2297 int * x
, int * y
, int * width
, int * height
,
2298 int * numClipRects
, drm_clip_rect_t
** pClipRects
,
2299 int * backX
, int * backY
,
2300 int * numBackClipRects
, drm_clip_rect_t
** pBackClipRects
)
2302 GLXDrawable drawable
= (GLXDrawable
) draw
;
2303 drm_clip_rect_t
* cliprect
;
2304 Display
* display
= (Display
*)dpy
;
2305 __DRIcontextPrivate
*pcp
= (__DRIcontextPrivate
*)CurrentContext
->driContext
.private;
2306 if (drawable
== 0) {
2310 cliprect
= (drm_clip_rect_t
*) _mesa_malloc(sizeof(drm_clip_rect_t
));
2311 cliprect
->x1
= drawable
->x
;
2312 cliprect
->y1
= drawable
->y
;
2313 cliprect
->x2
= drawable
->x
+ drawable
->w
;
2314 cliprect
->y2
= drawable
->y
+ drawable
->h
;
2316 /* the drawable index is by client id */
2317 *index
= display
->clientID
;
2319 *stamp
= pcp
->driScreenPriv
->pSAREA
->drawableTable
[display
->clientID
].stamp
;
2322 *width
= drawable
->w
;
2323 *height
= drawable
->h
;
2325 *pClipRects
= cliprect
;
2327 *backX
= drawable
->x
;
2328 *backY
= drawable
->y
;
2329 *numBackClipRects
= 0;
2330 *pBackClipRects
= 0;
2337 xf86DRI_DestroyContext(__DRInativeDisplay
*dpy
, int screen
, __DRIid context_id
)
2344 xf86DRI_CreateDrawable(__DRInativeDisplay
*dpy
, int screen
, __DRIid drawable
,
2345 drm_drawable_t
*hHWDrawable
)
2352 xf86DRI_DestroyDrawable(__DRInativeDisplay
*dpy
, int screen
, __DRIid drawable
)
2359 * \brief Query function address.
2361 * The glXGetProcAddress() function will return the address of any available
2362 * OpenGL or Mini GLX function.
2364 * \param procName name of the function to be returned.
2366 * \return If \p procName is a valid function name, a pointer to that function
2367 * will be returned. Otherwise, \c NULL will be returned.
2369 * The purpose of glXGetProcAddress() is to facilitate using future extensions
2370 * to OpenGL or Mini GLX. If a future version of the library adds new extension
2371 * functions they'll be accessible via glXGetProcAddress(). The alternative is
2372 * to hard-code calls to the new functions in the application but doing so will
2373 * prevent linking the application with older versions of the library.
2375 * Returns the function address by looking up its name in a static (name,
2376 * address) pair list.
2378 void (*glXGetProcAddress(const GLubyte
*procname
))( void )
2380 struct name_address
{
2384 static const struct name_address functions
[] = {
2385 { "glXChooseVisual", (void *) glXChooseVisual
},
2386 { "glXCreateContext", (void *) glXCreateContext
},
2387 { "glXDestroyContext", (void *) glXDestroyContext
},
2388 { "glXMakeCurrent", (void *) glXMakeCurrent
},
2389 { "glXSwapBuffers", (void *) glXSwapBuffers
},
2390 { "glXGetCurrentContext", (void *) glXGetCurrentContext
},
2391 { "glXGetCurrentDrawable", (void *) glXGetCurrentDrawable
},
2392 { "glXGetProcAddress", (void *) glXGetProcAddress
},
2393 { "XOpenDisplay", (void *) XOpenDisplay
},
2394 { "XCloseDisplay", (void *) XCloseDisplay
},
2395 { "XCreateWindow", (void *) XCreateWindow
},
2396 { "XDestroyWindow", (void *) XDestroyWindow
},
2397 { "XMapWindow", (void *) XMapWindow
},
2398 { "XCreateColormap", (void *) XCreateColormap
},
2399 { "XFreeColormap", (void *) XFreeColormap
},
2400 { "XFree", (void *) XFree
},
2401 { "XGetVisualinfo", (void *) XGetVisualInfo
},
2402 { "glXCreatePbuffer", (void *) glXCreatePbuffer
},
2403 { "glXDestroyPbuffer", (void *) glXDestroyPbuffer
},
2404 { "glXChooseFBConfig", (void *) glXChooseFBConfig
},
2405 { "glXGetVisualFromFBConfig", (void *) glXGetVisualFromFBConfig
},
2408 const struct name_address
*entry
;
2409 for (entry
= functions
; entry
->name
; entry
++) {
2410 if (strcmp(entry
->name
, (const char *) procname
) == 0) {
2414 return _glapi_get_proc_address((const char *) procname
);
2419 * \brief Query the Mini GLX version.
2421 * \param dpy the display handle. It is currently ignored, but should be the
2422 * value returned by XOpenDisplay().
2423 * \param major receives the major version number of Mini GLX.
2424 * \param minor receives the minor version number of Mini GLX.
2426 * \return \c True if the function succeeds, \c False if the function fails due
2427 * to invalid parameters.
2429 * \sa #MINI_GLX_VERSION_1_0.
2431 * Returns the hard-coded Mini GLX version.
2434 glXQueryVersion( Display
*dpy
, int *major
, int *minor
)
2444 * \brief Create a new pbuffer.
2447 glXCreatePbuffer( Display
*dpy
, GLXFBConfig config
, const int *attribList
)
2454 glXDestroyPbuffer( Display
*dpy
, GLXPbuffer pbuf
)
2461 glXChooseFBConfig( Display
*dpy
, int screen
, const int *attribList
,
2464 GLXFBConfig
*f
= (GLXFBConfig
*) malloc(sizeof(GLXFBConfig
));
2465 f
->visInfo
= glXChooseVisual( dpy
, screen
, (int *) attribList
);
2479 glXGetVisualFromFBConfig( Display
*dpy
, GLXFBConfig config
)
2481 /* XVisualInfo and GLXFBConfig are the same structure */
2483 return config
.visInfo
;
2486 void *glXAllocateMemoryMESA(Display
*dpy
, int scrn
,
2487 size_t size
, float readFreq
,
2488 float writeFreq
, float priority
)
2490 if (dpy
->driScreen
.private && dpy
->driScreen
.allocateMemory
) {
2491 return (*dpy
->driScreen
.allocateMemory
)( dpy
, scrn
, size
,
2492 readFreq
, writeFreq
,
2499 void glXFreeMemoryMESA(Display
*dpy
, int scrn
, void *pointer
)
2501 if (dpy
->driScreen
.private && dpy
->driScreen
.freeMemory
) {
2502 (*dpy
->driScreen
.freeMemory
)( dpy
, scrn
, pointer
);
2506 GLuint
glXGetMemoryOffsetMESA( Display
*dpy
, int scrn
,
2507 const void *pointer
)
2509 if (dpy
->driScreen
.private && dpy
->driScreen
.memoryOffset
) {
2510 return (*dpy
->driScreen
.memoryOffset
)( dpy
, scrn
, pointer
);
2518 * Get the unadjusted system time (UST). Currently, the UST is measured in
2519 * microseconds since Epoc. The actual resolution of the UST may vary from
2520 * system to system, and the units may vary from release to release.
2521 * Drivers should not call this function directly. They should instead use
2522 * \c glXGetProcAddress to obtain a pointer to the function.
2524 * \param ust Location to store the 64-bit UST
2525 * \returns Zero on success or a negative errno value on failure.
2528 * This function was copied directly from src/glx/x11/glxcmds.c.
2530 static int __glXGetUST( int64_t * ust
)
2534 if ( ust
== NULL
) {
2538 if ( gettimeofday( & tv
, NULL
) == 0 ) {
2539 ust
[0] = (tv
.tv_sec
* 1000000) + tv
.tv_usec
;
2550 * This needs to be implemented for miniGlx.
2552 static GLboolean
__glXGetMscRate(__DRInativeDisplay
* dpy
, __DRIid drawable
,
2553 int32_t * numerator
, int32_t * denominator
)