add more functionality to miniglx for glitz
[mesa.git] / src / glx / mini / miniglx.c
1 /**
2 * \file miniglx.c
3 * \brief Mini GLX interface functions.
4 * \author Brian Paul
5 *
6 * The Mini GLX interface is a subset of the GLX interface, plus a
7 * minimal set of Xlib functions.
8 */
9
10 /*
11 * Mesa 3-D graphics library
12 * Version: 6.0.1
13 *
14 * Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
15 *
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:
22 *
23 * The above copyright notice and this permission notice shall be included
24 * in all copies or substantial portions of the Software.
25 *
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.
32 */
33
34
35 /**
36 * \mainpage Mini GLX
37 *
38 * \section miniglxIntro Introduction
39 *
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
42 * functions.
43 *
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.
48 *
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.
52 *
53 *
54 * \section miniglxDoxygen About Doxygen
55 *
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.
58 *
59 * For a list of all functions, types, constants, etc.
60 * select <b>File Members</b>.
61 *
62 *
63 * \section miniglxReferences References
64 *
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
73 *
74 */
75
76 /**
77 * \page datatypes Notes on the XVisualInfo, Visual, and __GLXvisualConfig data types
78 *
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.
92 */
93
94
95 #include <assert.h>
96 #include <errno.h>
97 #include <signal.h>
98 #include <stdio.h>
99 #include <stdlib.h>
100 #include <string.h>
101 #include <dlfcn.h>
102 #include <fcntl.h>
103 #include <unistd.h>
104 #include <sys/ioctl.h>
105 #include <sys/mman.h>
106 #include <sys/types.h>
107 #include <linux/kd.h>
108 #include <linux/vt.h>
109
110 #include "miniglxP.h"
111 #include "dri_util.h"
112
113 #include "imports.h"
114 #include "glcontextmodes.h"
115 #include "glapi.h"
116
117
118 extern GLboolean __glXCreateContextWithConfig(__DRInativeDisplay *dpy,
119 int screen, int fbconfigID, void *contextID,
120 drm_context_t *hHWContext);
121
122 extern GLboolean __glXGetDrawableInfo(__DRInativeDisplay *dpy, int scrn,
123 __DRIid draw, unsigned int * index, unsigned int * stamp,
124 int * x, int * y, int * width, int * height,
125 int * numClipRects, drm_clip_rect_t ** pClipRects,
126 int * backX, int * backY,
127 int * numBackClipRects, drm_clip_rect_t ** pBackClipRects);
128
129
130 /** Wrapper around either malloc() */
131 void *
132 _mesa_malloc(size_t bytes)
133 {
134 return malloc(bytes);
135 }
136
137 /** Wrapper around either calloc() */
138 void *
139 _mesa_calloc(size_t bytes)
140 {
141 return calloc(1, bytes);
142 }
143
144 /** Wrapper around either free() */
145 void
146 _mesa_free(void *ptr)
147 {
148 free(ptr);
149 }
150
151
152 /**
153 * \brief Current GLX context.
154 *
155 * \sa glXGetCurrentContext().
156 */
157 static GLXContext CurrentContext = NULL;
158
159
160
161 static Display *SignalDisplay = 0;
162
163 static void SwitchVT(int sig)
164 {
165 fprintf(stderr, "SwitchVT %d dpy %p\n", sig, SignalDisplay);
166
167 if (SignalDisplay) {
168 SignalDisplay->vtSignalFlag = 1;
169 switch( sig )
170 {
171 case SIGUSR1: /* vt has been released */
172 SignalDisplay->haveVT = 0;
173 break;
174 case SIGUSR2: /* vt has been acquired */
175 SignalDisplay->haveVT = 1;
176 break;
177 }
178 }
179 }
180
181 /**********************************************************************/
182 /** \name Framebuffer device functions */
183 /**********************************************************************/
184 /*@{*/
185
186 /**
187 * \brief Do the first part of setting up the framebuffer device.
188 *
189 * \param dpy the display handle.
190 * \param use_vt use a VT for display or not
191 *
192 * \return GL_TRUE on success, or GL_FALSE on failure.
193 *
194 * \sa This is called during XOpenDisplay().
195 *
196 * \internal
197 * Gets the VT number, opens the respective console TTY device. Saves its state
198 * to restore when exiting and goes into graphics mode.
199 *
200 * Opens the framebuffer device and make a copy of the original variable screen
201 * information and gets the fixed screen information. Maps the framebuffer and
202 * MMIO region into the process address space.
203 */
204 static GLboolean
205 OpenFBDev( Display *dpy, int use_vt )
206 {
207 char ttystr[1000];
208 int fd, vtnumber, ttyfd;
209
210 assert(dpy);
211
212 if (geteuid()) {
213 fprintf(stderr, "error: you need to be root\n");
214 return GL_FALSE;
215 }
216
217 if (use_vt) {
218
219 /* open /dev/tty0 and get the VT number */
220 if ((fd = open("/dev/tty0", O_WRONLY, 0)) < 0) {
221 fprintf(stderr, "error opening /dev/tty0\n");
222 return GL_FALSE;
223 }
224 if (ioctl(fd, VT_OPENQRY, &vtnumber) < 0 || vtnumber < 0) {
225 fprintf(stderr, "error: couldn't get a free vt\n");
226 return GL_FALSE;
227 }
228
229 fprintf(stderr, "*** got vt nr: %d\n", vtnumber);
230 close(fd);
231
232 /* open the console tty */
233 sprintf(ttystr, "/dev/tty%d", vtnumber); /* /dev/tty1-64 */
234 dpy->ConsoleFD = open(ttystr, O_RDWR | O_NDELAY, 0);
235 if (dpy->ConsoleFD < 0) {
236 fprintf(stderr, "error couldn't open console fd\n");
237 return GL_FALSE;
238 }
239
240 /* save current vt number */
241 {
242 struct vt_stat vts;
243 if (ioctl(dpy->ConsoleFD, VT_GETSTATE, &vts) == 0)
244 dpy->OriginalVT = vts.v_active;
245 }
246
247 /* disconnect from controlling tty */
248 ttyfd = open("/dev/tty", O_RDWR);
249 if (ttyfd >= 0) {
250 ioctl(ttyfd, TIOCNOTTY, 0);
251 close(ttyfd);
252 }
253
254 /* some magic to restore the vt when we exit */
255 {
256 struct vt_mode vt;
257 struct sigaction sig_tty;
258
259 /* Set-up tty signal handler to catch the signal we request below */
260 SignalDisplay = dpy;
261 memset( &sig_tty, 0, sizeof( sig_tty ) );
262 sig_tty.sa_handler = SwitchVT;
263 sigemptyset( &sig_tty.sa_mask );
264 if( sigaction( SIGUSR1, &sig_tty, &dpy->OrigSigUsr1 ) ||
265 sigaction( SIGUSR2, &sig_tty, &dpy->OrigSigUsr2 ) )
266 {
267 fprintf(stderr, "error: can't set up signal handler (%s)",
268 strerror(errno) );
269 return GL_FALSE;
270 }
271
272
273
274 vt.mode = VT_PROCESS;
275 vt.waitv = 0;
276 vt.relsig = SIGUSR1;
277 vt.acqsig = SIGUSR2;
278 if (ioctl(dpy->ConsoleFD, VT_SETMODE, &vt) < 0) {
279 fprintf(stderr, "error: ioctl(VT_SETMODE) failed: %s\n",
280 strerror(errno));
281 return GL_FALSE;
282 }
283
284
285 if (ioctl(dpy->ConsoleFD, VT_ACTIVATE, vtnumber) != 0)
286 printf("ioctl VT_ACTIVATE: %s\n", strerror(errno));
287 if (ioctl(dpy->ConsoleFD, VT_WAITACTIVE, vtnumber) != 0)
288 printf("ioctl VT_WAITACTIVE: %s\n", strerror(errno));
289
290 if (ioctl(dpy->ConsoleFD, VT_GETMODE, &vt) < 0) {
291 fprintf(stderr, "error: ioctl VT_GETMODE: %s\n", strerror(errno));
292 return GL_FALSE;
293 }
294
295
296
297 }
298
299 /* go into graphics mode */
300 if (ioctl(dpy->ConsoleFD, KDSETMODE, KD_GRAPHICS) < 0) {
301 fprintf(stderr, "error: ioctl(KDSETMODE, KD_GRAPHICS) failed: %s\n",
302 strerror(errno));
303 return GL_FALSE;
304 }
305 }
306
307 /* open the framebuffer device */
308 dpy->FrameBufferFD = open(dpy->fbdevDevice, O_RDWR);
309 if (dpy->FrameBufferFD < 0) {
310 fprintf(stderr, "Error opening /dev/fb0: %s\n", strerror(errno));
311 return GL_FALSE;
312 }
313
314 /* get the original variable screen info */
315 if (ioctl(dpy->FrameBufferFD, FBIOGET_VSCREENINFO, &dpy->OrigVarInfo)) {
316 fprintf(stderr, "error: ioctl(FBIOGET_VSCREENINFO) failed: %s\n",
317 strerror(errno));
318 return GL_FALSE;
319 }
320
321 /* make copy */
322 dpy->VarInfo = dpy->OrigVarInfo; /* structure copy */
323
324 /* Turn off hw accels (otherwise mmap of mmio region will be
325 * refused)
326 */
327 dpy->VarInfo.accel_flags = 0;
328 if (ioctl(dpy->FrameBufferFD, FBIOPUT_VSCREENINFO, &dpy->VarInfo)) {
329 fprintf(stderr, "error: ioctl(FBIOPUT_VSCREENINFO) failed: %s\n",
330 strerror(errno));
331 return GL_FALSE;
332 }
333
334
335
336 /* Get the fixed screen info */
337 if (ioctl(dpy->FrameBufferFD, FBIOGET_FSCREENINFO, &dpy->FixedInfo)) {
338 fprintf(stderr, "error: ioctl(FBIOGET_FSCREENINFO) failed: %s\n",
339 strerror(errno));
340 return GL_FALSE;
341 }
342
343
344
345 /* mmap the framebuffer into our address space */
346 dpy->driverContext.FBStart = dpy->FixedInfo.smem_start;
347 dpy->driverContext.FBSize = dpy->FixedInfo.smem_len;
348 dpy->driverContext.shared.fbSize = dpy->FixedInfo.smem_len;
349 dpy->driverContext.FBAddress = (caddr_t) mmap(0, /* start */
350 dpy->driverContext.shared.fbSize, /* bytes */
351 PROT_READ | PROT_WRITE, /* prot */
352 MAP_SHARED, /* flags */
353 dpy->FrameBufferFD, /* fd */
354 0 /* offset */);
355 if (dpy->driverContext.FBAddress == (caddr_t) - 1) {
356 fprintf(stderr, "error: unable to mmap framebuffer: %s\n",
357 strerror(errno));
358 return GL_FALSE;
359 }
360
361 /* mmap the MMIO region into our address space */
362 dpy->driverContext.MMIOStart = dpy->FixedInfo.mmio_start;
363 dpy->driverContext.MMIOSize = dpy->FixedInfo.mmio_len;
364 dpy->driverContext.MMIOAddress = (caddr_t) mmap(0, /* start */
365 dpy->driverContext.MMIOSize, /* bytes */
366 PROT_READ | PROT_WRITE, /* prot */
367 MAP_SHARED, /* flags */
368 dpy->FrameBufferFD, /* fd */
369 dpy->FixedInfo.smem_len /* offset */);
370 if (dpy->driverContext.MMIOAddress == (caddr_t) - 1) {
371 fprintf(stderr, "error: unable to mmap mmio region: %s\n",
372 strerror(errno));
373 return GL_FALSE;
374 }
375
376 fprintf(stderr, "got MMIOAddress %p offset %d\n",
377 dpy->driverContext.MMIOAddress,
378 dpy->FixedInfo.smem_len);
379
380 return GL_TRUE;
381 }
382
383
384
385
386 /**
387 * \brief Setup up the desired framebuffer device mode.
388 *
389 * \param dpy the display handle.
390 *
391 * \return GL_TRUE on success, or GL_FALSE on failure.
392 *
393 * \sa This is called during __miniglx_StartServer().
394 *
395 * \internal
396 *
397 * Bumps the size of the window the the next supported mode. Sets the
398 * variable screen information according to the desired mode and asks
399 * the driver to validate the mode. Certifies that a DirectColor or
400 * TrueColor visual is used from the updated fixed screen information.
401 * In the case of DirectColor visuals, sets up an 'identity' colormap to
402 * mimic a TrueColor visual.
403 *
404 * Calls the driver hooks 'ValidateMode' and 'PostValidateMode' to
405 * allow the driver to make modifications to the chosen mode according
406 * to hardware constraints, or to save and restore videocard registers
407 * that may be clobbered by the fbdev driver.
408 *
409 * \todo Timings are hard-coded in the source for a set of supported modes.
410 */
411 static GLboolean
412 SetupFBDev( Display *dpy )
413 {
414 int width, height;
415
416 assert(dpy);
417
418 width = dpy->driverContext.shared.virtualWidth;
419 height = dpy->driverContext.shared.virtualHeight;
420
421 /* Bump size up to next supported mode.
422 */
423 if (width <= 720 && height <= 480) {
424 width = 720; height = 480;
425 }
426 else if (width <= 960 && height <= 540) {
427 width = 960; height = 540;
428 }
429 else if (width <= 800 && height <= 600) {
430 width = 800; height = 600;
431 }
432 else if (width <= 1024 && height <= 768) {
433 width = 1024; height = 768;
434 }
435 else if (width <= 768 && height <= 1024) {
436 width = 768; height = 1024;
437 }
438 else if (width <= 1280 && height <= 1024) {
439 width = 1280; height = 1024;
440 }
441
442
443 dpy->driverContext.shared.virtualHeight = height;
444 dpy->driverContext.shared.virtualWidth = width;
445 dpy->driverContext.shared.fbStride = width * (dpy->driverContext.bpp / 8);
446
447 /* set the depth, resolution, etc */
448 dpy->VarInfo = dpy->OrigVarInfo;
449 dpy->VarInfo.bits_per_pixel = dpy->driverContext.bpp;
450 dpy->VarInfo.xres_virtual = dpy->driverContext.shared.virtualWidth;
451 dpy->VarInfo.yres_virtual = dpy->driverContext.shared.virtualHeight;
452 dpy->VarInfo.xres = width;
453 dpy->VarInfo.yres = height;
454 dpy->VarInfo.xoffset = 0;
455 dpy->VarInfo.yoffset = 0;
456 dpy->VarInfo.nonstd = 0;
457 dpy->VarInfo.vmode &= ~FB_VMODE_YWRAP; /* turn off scrolling */
458
459 if (dpy->VarInfo.bits_per_pixel == 32) {
460 dpy->VarInfo.red.offset = 16;
461 dpy->VarInfo.green.offset = 8;
462 dpy->VarInfo.blue.offset = 0;
463 dpy->VarInfo.transp.offset = 24;
464 dpy->VarInfo.red.length = 8;
465 dpy->VarInfo.green.length = 8;
466 dpy->VarInfo.blue.length = 8;
467 dpy->VarInfo.transp.length = 8;
468 }
469 else if (dpy->VarInfo.bits_per_pixel == 16) {
470 dpy->VarInfo.red.offset = 11;
471 dpy->VarInfo.green.offset = 5;
472 dpy->VarInfo.blue.offset = 0;
473 dpy->VarInfo.red.length = 5;
474 dpy->VarInfo.green.length = 6;
475 dpy->VarInfo.blue.length = 5;
476 dpy->VarInfo.transp.offset = 0;
477 dpy->VarInfo.transp.length = 0;
478 }
479 else {
480 fprintf(stderr, "Only 32bpp and 16bpp modes supported at the moment\n");
481 return 0;
482 }
483
484 if (!dpy->driver->validateMode( &dpy->driverContext )) {
485 fprintf(stderr, "Driver validateMode() failed\n");
486 return 0;
487 }
488
489 /* These should be calculated with the gtf.c program, and then we could
490 remove all this... AlanH. */
491 if (dpy->VarInfo.xres == 1280 &&
492 dpy->VarInfo.yres == 1024) {
493 /* timing values taken from /etc/fb.modes (1280x1024 @ 75Hz) */
494 dpy->VarInfo.pixclock = 7408;
495 dpy->VarInfo.left_margin = 248;
496 dpy->VarInfo.right_margin = 16;
497 dpy->VarInfo.upper_margin = 38;
498 dpy->VarInfo.lower_margin = 1;
499 dpy->VarInfo.hsync_len = 144;
500 dpy->VarInfo.vsync_len = 3;
501 }
502 else if (dpy->VarInfo.xres == 1024 &&
503 dpy->VarInfo.yres == 768) {
504 /* timing values taken from /etc/fb.modes (1024x768 @ 75Hz) */
505 dpy->VarInfo.pixclock = 12699;
506 dpy->VarInfo.left_margin = 176;
507 dpy->VarInfo.right_margin = 16;
508 dpy->VarInfo.upper_margin = 28;
509 dpy->VarInfo.lower_margin = 1;
510 dpy->VarInfo.hsync_len = 96;
511 dpy->VarInfo.vsync_len = 3;
512 }
513 else if (dpy->VarInfo.xres == 800 &&
514 dpy->VarInfo.yres == 600) {
515 /* timing values taken from /etc/fb.modes (800x600 @ 75Hz) */
516 dpy->VarInfo.pixclock = 27778;
517 dpy->VarInfo.left_margin = 128;
518 dpy->VarInfo.right_margin = 24;
519 dpy->VarInfo.upper_margin = 22;
520 dpy->VarInfo.lower_margin = 1;
521 dpy->VarInfo.hsync_len = 72;
522 dpy->VarInfo.vsync_len = 2;
523 }
524 else if (dpy->VarInfo.xres == 720 &&
525 dpy->VarInfo.yres == 480) {
526 dpy->VarInfo.pixclock = 37202;
527 dpy->VarInfo.left_margin = 88;
528 dpy->VarInfo.right_margin = 16;
529 dpy->VarInfo.upper_margin = 14;
530 dpy->VarInfo.lower_margin = 1;
531 dpy->VarInfo.hsync_len = 72;
532 dpy->VarInfo.vsync_len = 3;
533 }
534 else if (dpy->VarInfo.xres == 960 &&
535 dpy->VarInfo.yres == 540) {
536 dpy->VarInfo.pixclock = 24273;
537 dpy->VarInfo.left_margin = 128;
538 dpy->VarInfo.right_margin = 32;
539 dpy->VarInfo.upper_margin = 16;
540 dpy->VarInfo.lower_margin = 1;
541 dpy->VarInfo.hsync_len = 96;
542 dpy->VarInfo.vsync_len = 3;
543 }
544 else if (dpy->VarInfo.xres == 768 &&
545 dpy->VarInfo.yres == 1024) {
546 /* timing values for 768x1024 @ 75Hz */
547 dpy->VarInfo.pixclock = 11993;
548 dpy->VarInfo.left_margin = 136;
549 dpy->VarInfo.right_margin = 32;
550 dpy->VarInfo.upper_margin = 41;
551 dpy->VarInfo.lower_margin = 1;
552 dpy->VarInfo.hsync_len = 80;
553 dpy->VarInfo.vsync_len = 3;
554 }
555 else {
556 /* XXX need timings for other screen sizes */
557 fprintf(stderr, "XXXX screen size %d x %d not supported at this time!\n",
558 dpy->VarInfo.xres, dpy->VarInfo.yres);
559 return GL_FALSE;
560 }
561
562 fprintf(stderr, "[miniglx] Setting mode: visible %dx%d virtual %dx%dx%d\n",
563 dpy->VarInfo.xres, dpy->VarInfo.yres,
564 dpy->VarInfo.xres_virtual, dpy->VarInfo.yres_virtual,
565 dpy->VarInfo.bits_per_pixel);
566
567 /* set variable screen info */
568 if (ioctl(dpy->FrameBufferFD, FBIOPUT_VSCREENINFO, &dpy->VarInfo)) {
569 fprintf(stderr, "error: ioctl(FBIOPUT_VSCREENINFO) failed: %s\n",
570 strerror(errno));
571 return GL_FALSE;
572 }
573
574 /* get the variable screen info, in case it has been modified */
575 if (ioctl(dpy->FrameBufferFD, FBIOGET_VSCREENINFO, &dpy->VarInfo)) {
576 fprintf(stderr, "error: ioctl(FBIOGET_VSCREENINFO) failed: %s\n",
577 strerror(errno));
578 return GL_FALSE;
579 }
580
581
582 fprintf(stderr, "[miniglx] Readback mode: visible %dx%d virtual %dx%dx%d\n",
583 dpy->VarInfo.xres, dpy->VarInfo.yres,
584 dpy->VarInfo.xres_virtual, dpy->VarInfo.yres_virtual,
585 dpy->VarInfo.bits_per_pixel);
586
587 /* Get the fixed screen info */
588 if (ioctl(dpy->FrameBufferFD, FBIOGET_FSCREENINFO, &dpy->FixedInfo)) {
589 fprintf(stderr, "error: ioctl(FBIOGET_FSCREENINFO) failed: %s\n",
590 strerror(errno));
591 return GL_FALSE;
592 }
593
594 if (dpy->FixedInfo.visual != FB_VISUAL_TRUECOLOR &&
595 dpy->FixedInfo.visual != FB_VISUAL_DIRECTCOLOR) {
596 fprintf(stderr, "non-TRUECOLOR visuals not supported.\n");
597 return GL_FALSE;
598 }
599
600 if (dpy->FixedInfo.visual == FB_VISUAL_DIRECTCOLOR) {
601 struct fb_cmap cmap;
602 unsigned short red[256], green[256], blue[256];
603 int rcols = 1 << dpy->VarInfo.red.length;
604 int gcols = 1 << dpy->VarInfo.green.length;
605 int bcols = 1 << dpy->VarInfo.blue.length;
606 int i;
607
608 cmap.start = 0;
609 cmap.len = gcols;
610 cmap.red = red;
611 cmap.green = green;
612 cmap.blue = blue;
613 cmap.transp = NULL;
614
615 for (i = 0; i < rcols ; i++)
616 red[i] = (65536/(rcols-1)) * i;
617
618 for (i = 0; i < gcols ; i++)
619 green[i] = (65536/(gcols-1)) * i;
620
621 for (i = 0; i < bcols ; i++)
622 blue[i] = (65536/(bcols-1)) * i;
623
624 if (ioctl(dpy->FrameBufferFD, FBIOPUTCMAP, (void *) &cmap) < 0) {
625 fprintf(stderr, "ioctl(FBIOPUTCMAP) failed [%d]\n", i);
626 exit(1);
627 }
628 }
629
630 /* May need to restore regs fbdev has clobbered:
631 */
632 if (!dpy->driver->postValidateMode( &dpy->driverContext )) {
633 fprintf(stderr, "Driver postValidateMode() failed\n");
634 return 0;
635 }
636
637 return GL_TRUE;
638 }
639
640
641 /**
642 * \brief Restore the framebuffer device to state it was in before we started
643 *
644 * Undoes the work done by SetupFBDev().
645 *
646 * \param dpy the display handle.
647 *
648 * \return GL_TRUE on success, or GL_FALSE on failure.
649 *
650 * \sa Called from XDestroyWindow().
651 *
652 * \internal
653 * Restores the original variable screen info.
654 */
655 static GLboolean
656 RestoreFBDev( Display *dpy )
657 {
658 /* restore original variable screen info */
659 if (ioctl(dpy->FrameBufferFD, FBIOPUT_VSCREENINFO, &dpy->OrigVarInfo)) {
660 fprintf(stderr, "ioctl(FBIOPUT_VSCREENINFO failed): %s\n",
661 strerror(errno));
662 return GL_FALSE;
663 }
664 dpy->VarInfo = dpy->OrigVarInfo;
665
666 return GL_TRUE;
667 }
668
669
670 /**
671 * \brief Close the framebuffer device.
672 *
673 * \param dpy the display handle.
674 *
675 * \sa Called from XCloseDisplay().
676 *
677 * \internal
678 * Unmaps the framebuffer and MMIO region. Restores the text mode and the
679 * original virtual terminal. Closes the console and framebuffer devices.
680 */
681 static void
682 CloseFBDev( Display *dpy )
683 {
684 struct vt_mode VT;
685
686 munmap(dpy->driverContext.FBAddress, dpy->driverContext.FBSize);
687 munmap(dpy->driverContext.MMIOAddress, dpy->driverContext.MMIOSize);
688
689 if (dpy->ConsoleFD) {
690 /* restore text mode */
691 ioctl(dpy->ConsoleFD, KDSETMODE, KD_TEXT);
692
693 /* set vt */
694 if (ioctl(dpy->ConsoleFD, VT_GETMODE, &VT) != -1) {
695 VT.mode = VT_AUTO;
696 ioctl(dpy->ConsoleFD, VT_SETMODE, &VT);
697 }
698
699 /* restore original vt */
700 if (dpy->OriginalVT >= 0) {
701 ioctl(dpy->ConsoleFD, VT_ACTIVATE, dpy->OriginalVT);
702 dpy->OriginalVT = -1;
703 }
704
705 close(dpy->ConsoleFD);
706 }
707 close(dpy->FrameBufferFD);
708 }
709
710 /*@}*/
711
712
713 /**********************************************************************/
714 /** \name Misc functions needed for DRI drivers */
715 /**********************************************************************/
716 /*@{*/
717
718 /**
719 * \brief Find the DRI screen dependent methods associated with the display.
720 *
721 * \param dpy a display handle, as returned by XOpenDisplay().
722 * \param scrn the screen number. Not referenced.
723 *
724 * \returns a pointer to a __DRIscreenRec structure.
725 *
726 * \internal
727 * Returns the MiniGLXDisplayRec::driScreen attribute.
728 */
729 __DRIscreen *
730 __glXFindDRIScreen(__DRInativeDisplay *dpy, int scrn)
731 {
732 (void) scrn;
733 return &((Display*)dpy)->driScreen;
734 }
735
736 /**
737 * \brief Validate a drawable.
738 *
739 * \param dpy a display handle, as returned by XOpenDisplay().
740 * \param draw drawable to validate.
741 *
742 * \internal
743 * Since Mini GLX only supports one window, compares the specified drawable with
744 * the MiniGLXDisplayRec::TheWindow attribute.
745 */
746 Bool
747 __glXWindowExists(__DRInativeDisplay *dpy, GLXDrawable draw)
748 {
749 Display* display = (Display*)dpy;
750 if (display->TheWindow == draw)
751 return True;
752 else
753 return False;
754 }
755
756 /**
757 * \brief Get current thread ID.
758 *
759 * \return thread ID.
760 *
761 * \internal
762 * Always returns 0.
763 */
764 /*unsigned long
765 _glthread_GetID(void)
766 {
767 return 0;
768 }*/
769
770 /*@}*/
771
772
773 /**
774 * \brief Scan Linux /prog/bus/pci/devices file to determine hardware
775 * chipset based on supplied bus ID.
776 *
777 * \return probed chipset (non-zero) on success, zero otherwise.
778 *
779 * \internal
780 */
781 static int get_chipset_from_busid( Display *dpy )
782 {
783 char buf[0x200];
784 FILE *file;
785 const char *fname = "/proc/bus/pci/devices";
786 int retval = 0;
787
788 if (!(file = fopen(fname,"r"))) {
789 fprintf(stderr, "couldn't open %s: %s\n", fname, strerror(errno));
790 return 0;
791 }
792
793 while (fgets(buf, sizeof(buf)-1, file)) {
794 unsigned int nr, bus, dev, fn, vendor, device, encode;
795 nr = sscanf(buf, "%04x\t%04x%04x", &encode,
796 &vendor, &device);
797
798 bus = encode >> 8;
799 dev = (encode & 0xFF) >> 3;
800 fn = encode & 0x7;
801
802 if (nr != 3)
803 break;
804
805 if (bus == dpy->driverContext.pciBus &&
806 dev == dpy->driverContext.pciDevice &&
807 fn == dpy->driverContext.pciFunc) {
808 retval = device;
809 break;
810 }
811 }
812
813 fclose(file);
814
815 if (retval)
816 fprintf(stderr, "[miniglx] probed chipset 0x%x\n", retval);
817 else
818 fprintf(stderr, "[miniglx] failed to probe chipset\n");
819
820 return retval;
821 }
822
823
824 /**
825 * \brief Read settings from a configuration file.
826 *
827 * The configuration file is usually "/etc/miniglx.conf", but can be overridden
828 * with the MINIGLX_CONF environment variable.
829 *
830 * The format consists in \code option = value \endcode lines. The option names
831 * corresponds to the fields in MiniGLXDisplayRec.
832 *
833 * \param dpy the display handle as.
834 *
835 * \return non-zero on success, zero otherwise.
836 *
837 * \internal
838 * Sets some defaults. Opens and parses the the Mini GLX configuration file and
839 * fills in the MiniGLXDisplayRec field that corresponds for each option.
840 */
841 static int __read_config_file( Display *dpy )
842 {
843 FILE *file;
844 const char *fname;
845
846 /* Fallback/defaults
847 */
848 dpy->fbdevDevice = "/dev/fb0";
849 dpy->clientDriverName = "fb_dri.so";
850 dpy->driverContext.pciBus = 0;
851 dpy->driverContext.pciDevice = 0;
852 dpy->driverContext.pciFunc = 0;
853 dpy->driverContext.chipset = 0;
854 dpy->driverContext.pciBusID = 0;
855 dpy->driverContext.shared.virtualWidth = 1280;
856 dpy->driverContext.shared.virtualHeight = 1024;
857 dpy->driverContext.bpp = 32;
858 dpy->driverContext.cpp = 4;
859 dpy->rotateMode = 0;
860 dpy->driverContext.agpmode = 1;
861 dpy->driverContext.isPCI = 0;
862
863 fname = getenv("MINIGLX_CONF");
864 if (!fname) fname = "/etc/miniglx.conf";
865
866 file = fopen(fname, "r");
867 if (!file) {
868 fprintf(stderr, "couldn't open config file %s: %s\n", fname, strerror(errno));
869 return 0;
870 }
871
872
873 while (!feof(file)) {
874 char buf[81], *opt = buf, *val, *tmp1, *tmp2;
875 fgets(buf, sizeof(buf), file);
876
877 /* Parse 'opt = val' -- must be easier ways to do this.
878 */
879 while (isspace(*opt)) opt++;
880 val = opt;
881 if (*val == '#') continue; /* comment */
882 while (!isspace(*val) && *val != '=' && *val) val++;
883 tmp1 = val;
884 while (isspace(*val)) val++;
885 if (*val != '=') continue;
886 *tmp1 = 0;
887 val++;
888 while (isspace(*val)) val++;
889 tmp2 = val;
890 while (!isspace(*tmp2) && *tmp2 != '\n' && *tmp2) tmp2++;
891 *tmp2 = 0;
892
893
894 if (strcmp(opt, "fbdevDevice") == 0)
895 dpy->fbdevDevice = strdup(val);
896 else if (strcmp(opt, "clientDriverName") == 0)
897 dpy->clientDriverName = strdup(val);
898 else if (strcmp(opt, "rotateMode") == 0)
899 dpy->rotateMode = atoi(val) ? 1 : 0;
900 else if (strcmp(opt, "pciBusID") == 0) {
901 if (sscanf(val, "PCI:%d:%d:%d",
902 &dpy->driverContext.pciBus,
903 &dpy->driverContext.pciDevice,
904 &dpy->driverContext.pciFunc) != 3) {
905 fprintf(stderr, "malformed bus id: %s\n", val);
906 continue;
907 }
908 dpy->driverContext.pciBusID = strdup(val);
909 }
910 else if (strcmp(opt, "chipset") == 0) {
911 if (sscanf(val, "0x%x", &dpy->driverContext.chipset) != 1)
912 fprintf(stderr, "malformed chipset: %s\n", opt);
913 }
914 else if (strcmp(opt, "virtualWidth") == 0) {
915 if (sscanf(val, "%d", &dpy->driverContext.shared.virtualWidth) != 1)
916 fprintf(stderr, "malformed virtualWidth: %s\n", opt);
917 }
918 else if (strcmp(opt, "virtualHeight") == 0) {
919 if (sscanf(val, "%d", &dpy->driverContext.shared.virtualHeight) != 1)
920 fprintf(stderr, "malformed virutalHeight: %s\n", opt);
921 }
922 else if (strcmp(opt, "bpp") == 0) {
923 if (sscanf(val, "%d", &dpy->driverContext.bpp) != 1)
924 fprintf(stderr, "malformed bpp: %s\n", opt);
925 dpy->driverContext.cpp = dpy->driverContext.bpp / 8;
926 }
927 else if (strcmp(opt, "agpmode") == 0) {
928 if (sscanf(val, "%d", &dpy->driverContext.agpmode) != 1)
929 fprintf(stderr, "malformed agpmode: %s\n", opt);
930 }
931 else if (strcmp(opt, "isPCI") == 0) {
932 dpy->driverContext.isPCI = atoi(val) ? 1 : 0;
933 }
934 }
935
936 fclose(file);
937
938 if (dpy->driverContext.chipset == 0 && dpy->driverContext.pciBusID != 0)
939 dpy->driverContext.chipset = get_chipset_from_busid( dpy );
940
941 return 1;
942 }
943
944 static int InitDriver( Display *dpy )
945 {
946 /*
947 * Begin DRI setup.
948 * We're kind of combining the per-display and per-screen information
949 * which was kept separate in XFree86/DRI's libGL.
950 */
951 dpy->dlHandle = dlopen(dpy->clientDriverName, RTLD_NOW | RTLD_GLOBAL);
952 if (!dpy->dlHandle) {
953 fprintf(stderr, "Unable to open %s: %s\n", dpy->clientDriverName,
954 dlerror());
955 goto failed;
956 }
957
958 /* Pull in Mini GLX specific hooks:
959 */
960 dpy->driver = (struct DRIDriverRec *) dlsym(dpy->dlHandle,
961 "__driDriver");
962 if (!dpy->driver) {
963 fprintf(stderr, "Couldn't find __driDriver in %s\n",
964 dpy->clientDriverName);
965 goto failed;
966 }
967
968 /* Pull in standard DRI client-side driver hooks:
969 */
970 dpy->createNewScreen = (PFNCREATENEWSCREENFUNC)
971 dlsym(dpy->dlHandle, "__driCreateNewScreen");
972 if (!dpy->createNewScreen) {
973 fprintf(stderr, "Couldn't find __driCreateScreen in %s\n",
974 dpy->clientDriverName);
975 goto failed;
976 }
977
978 return GL_TRUE;
979
980 failed:
981 if (dpy->dlHandle) {
982 dlclose(dpy->dlHandle);
983 dpy->dlHandle = 0;
984 }
985 return GL_FALSE;
986 }
987
988
989 /**********************************************************************/
990 /** \name Public API functions (Xlib and GLX) */
991 /**********************************************************************/
992 /*@{*/
993
994
995 /**
996 * \brief Initialize the graphics system.
997 *
998 * \param display_name currently ignored. It is recommended to pass it as NULL.
999 * \return a pointer to a #Display if the function is able to initialize
1000 * the graphics system, NULL otherwise.
1001 *
1002 * Allocates a MiniGLXDisplayRec structure and fills in with information from a
1003 * configuration file.
1004 *
1005 * Calls OpenFBDev() to open the framebuffer device and calls
1006 * DRIDriverRec::initFBDev to do the client-side initialization on it.
1007 *
1008 * Loads the DRI driver and pulls in Mini GLX specific hooks into a
1009 * DRIDriverRec structure, and the standard DRI \e __driCreateScreen hook.
1010 * Asks the driver for a list of supported visuals. Performs the per-screen
1011 * client-side initialization. Also setups the callbacks in the screen private
1012 * information.
1013 *
1014 * Does the framebuffer device setup. Calls __miniglx_open_connections() to
1015 * serve clients.
1016 */
1017 Display *
1018 __miniglx_StartServer( const char *display_name )
1019 {
1020 Display *dpy;
1021 int use_vt = 0;
1022
1023 dpy = (Display *)calloc(1, sizeof(Display));
1024 if (!dpy)
1025 return NULL;
1026
1027 dpy->IsClient = False;
1028
1029 if (!__read_config_file( dpy )) {
1030 fprintf(stderr, "Couldn't get configuration details\n");
1031 free(dpy);
1032 return NULL;
1033 }
1034
1035 /* Open the fbdev device
1036 */
1037 if (!OpenFBDev(dpy, use_vt)) {
1038 fprintf(stderr, "OpenFBDev failed\n");
1039 free(dpy);
1040 return NULL;
1041 }
1042
1043 if (!InitDriver(dpy)) {
1044 fprintf(stderr, "InitDriver failed\n");
1045 free(dpy);
1046 return NULL;
1047 }
1048
1049 /* Perform the initialization normally done in the X server
1050 */
1051 if (!dpy->driver->initFBDev( &dpy->driverContext )) {
1052 fprintf(stderr, "%s: __driInitFBDev failed\n", __FUNCTION__);
1053 dlclose(dpy->dlHandle);
1054 return GL_FALSE;
1055 }
1056
1057 /* do fbdev setup
1058 */
1059 if (!SetupFBDev(dpy)) {
1060 fprintf(stderr, "SetupFBDev failed\n");
1061 free(dpy);
1062 return NULL;
1063 }
1064
1065 /* unlock here if not using VT -- JDS */
1066 if (!use_vt) {
1067 if (dpy->driver->restoreHardware)
1068 dpy->driver->restoreHardware( &dpy->driverContext );
1069 DRM_UNLOCK( dpy->driverContext.drmFD,
1070 dpy->driverContext.pSAREA,
1071 dpy->driverContext.serverContext );
1072 dpy->hwActive = 1;
1073 }
1074
1075 /* Ready for clients:
1076 */
1077 if (!__miniglx_open_connections(dpy)) {
1078 free(dpy);
1079 return NULL;
1080 }
1081
1082 return dpy;
1083 }
1084
1085
1086 static void *
1087 CallCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc)
1088 {
1089 int directCapable;
1090 void *psp = NULL;
1091 drm_handle_t hSAREA;
1092 drmAddress pSAREA;
1093 const char *BusID;
1094 int i;
1095 __DRIversion ddx_version;
1096 __DRIversion dri_version;
1097 __DRIversion drm_version;
1098 __DRIframebuffer framebuffer;
1099 int fd = -1;
1100 int status;
1101 const char * err_msg;
1102 const char * err_extra;
1103 drmVersionPtr version;
1104 drm_handle_t hFB;
1105 int junk;
1106
1107 err_msg = "XF86DRIOpenConnection";
1108 err_extra = NULL;
1109
1110 hSAREA = dpy->driverContext.shared.hSAREA;
1111 BusID = dpy->driverContext.pciBusID;
1112
1113 fd = drmOpen(NULL, BusID);
1114
1115 err_msg = "open DRM";
1116 err_extra = strerror( -fd );
1117
1118 if (fd < 0) goto done;
1119
1120 drm_magic_t magic;
1121
1122 err_msg = "drmGetMagic";
1123 err_extra = NULL;
1124
1125 if (drmGetMagic(fd, &magic)) goto done;
1126
1127 dpy->authorized = False;
1128 send_char_msg( dpy, 0, _Authorize );
1129 send_msg( dpy, 0, &magic, sizeof(magic));
1130
1131 /* force net buffer flush */
1132 while (!dpy->authorized)
1133 handle_fd_events( dpy, 0 );
1134
1135 version = drmGetVersion(fd);
1136 if (version) {
1137 drm_version.major = version->version_major;
1138 drm_version.minor = version->version_minor;
1139 drm_version.patch = version->version_patchlevel;
1140 drmFreeVersion(version);
1141 }
1142 else {
1143 drm_version.major = -1;
1144 drm_version.minor = -1;
1145 drm_version.patch = -1;
1146 }
1147
1148 /*
1149 * Get device name (like "tdfx") and the ddx version numbers.
1150 * We'll check the version in each DRI driver's "createScreen"
1151 * function.
1152 */
1153 err_msg = "XF86DRIGetClientDriverName";
1154 ddx_version.major = 4;
1155 ddx_version.minor = 0;
1156 ddx_version.patch = 0;
1157
1158 /*
1159 * Get the DRI X extension version.
1160 */
1161 err_msg = "XF86DRIQueryVersion";
1162 dri_version.major = 4;
1163 dri_version.minor = 0;
1164 dri_version.patch = 0;
1165
1166 /*
1167 * Get device-specific info. pDevPriv will point to a struct
1168 * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h)
1169 * that has information about the screen size, depth, pitch,
1170 * ancilliary buffers, DRM mmap handles, etc.
1171 */
1172 err_msg = "XF86DRIGetDeviceInfo";
1173 hFB = dpy->driverContext.shared.hFrameBuffer;
1174 framebuffer.size = dpy->driverContext.shared.fbSize;
1175 framebuffer.stride = dpy->driverContext.shared.fbStride;
1176 framebuffer.dev_priv_size = dpy->driverContext.driverClientMsgSize;
1177 framebuffer.dev_priv = dpy->driverContext.driverClientMsg;
1178 framebuffer.width = dpy->driverContext.shared.virtualWidth;
1179 framebuffer.height = dpy->driverContext.shared.virtualHeight;
1180
1181 /*
1182 * Map the framebuffer region.
1183 */
1184 status = drmMap(fd, hFB, framebuffer.size,
1185 (drmAddressPtr)&framebuffer.base);
1186
1187 err_msg = "drmMap of framebuffer";
1188 err_extra = strerror( -status );
1189
1190 if ( status != 0 ) goto done;
1191
1192 /*
1193 * Map the SAREA region. Further mmap regions may be setup in
1194 * each DRI driver's "createScreen" function.
1195 */
1196 status = drmMap(fd, hSAREA, SAREA_MAX, &pSAREA);
1197
1198 err_msg = "drmMap of sarea";
1199 err_extra = strerror( -status );
1200
1201 if ( status == 0 ) {
1202 PFNGLXGETINTERNALVERSIONPROC get_ver;
1203
1204 get_ver = (PFNGLXGETINTERNALVERSIONPROC)
1205 glXGetProcAddress( (const GLubyte *) "__glXGetInternalVersion" );
1206
1207 err_msg = "InitDriver";
1208 err_extra = NULL;
1209 psp = dpy->createNewScreen(dpy, scrn, psc, NULL,
1210 & ddx_version,
1211 & dri_version,
1212 & drm_version,
1213 & framebuffer,
1214 pSAREA,
1215 fd,
1216 (get_ver != NULL) ? (*get_ver)() : 20040602,
1217 (__GLcontextModes **) &dpy->driver_modes);
1218
1219 /* fill in dummy visual ids */
1220 {
1221 __GLcontextModes *temp;
1222 temp = (__GLcontextModes *)dpy->driver_modes;
1223 i = 1;
1224 while (temp)
1225 {
1226 temp->visualID = i++;
1227 temp=temp->next;
1228 }
1229 }
1230 }
1231
1232 done:
1233 if ( psp == NULL ) {
1234 if ( pSAREA != MAP_FAILED ) {
1235 (void)drmUnmap(pSAREA, SAREA_MAX);
1236 }
1237
1238 if ( framebuffer.base != MAP_FAILED ) {
1239 (void)drmUnmap((drmAddress)framebuffer.base, framebuffer.size);
1240 }
1241
1242 if ( framebuffer.dev_priv != NULL ) {
1243 free(framebuffer.dev_priv);
1244 }
1245
1246 if ( fd >= 0 ) {
1247 (void)drmClose(fd);
1248 }
1249
1250 if ( err_extra != NULL ) {
1251 fprintf(stderr, "libGL error: %s failed (%s)\n", err_msg,
1252 err_extra);
1253 }
1254 else {
1255 fprintf(stderr, "libGL error: %s failed\n", err_msg );
1256 }
1257
1258 fprintf(stderr, "libGL error: reverting to (slow) indirect rendering\n");
1259 }
1260
1261 return psp;
1262 }
1263
1264 /**
1265 * \brief Initialize the graphics system.
1266 *
1267 * \param display_name currently ignored. It is recommended to pass it as NULL.
1268 * \return a pointer to a #Display if the function is able to initialize
1269 * the graphics system, NULL otherwise.
1270 *
1271 * Allocates a MiniGLXDisplayRec structure and fills in with information from a
1272 * configuration file.
1273 *
1274 * Calls __miniglx_open_connections() to connect to the server.
1275 *
1276 * Loads the DRI driver and pulls in Mini GLX specific hooks into a
1277 * DRIDriverRec structure, and the standard DRI \e __driCreateScreen hook.
1278 * Asks the driver for a list of supported visuals. Performs the per-screen
1279 * client-side initialization. Also setups the callbacks in the screen private
1280 * information.
1281 *
1282 * \todo
1283 * - read config file
1284 * - what about virtualWidth, etc?
1285 * - determine dpy->driverClientMsgSize,
1286 * - allocate dpy->driverClientMsg
1287 */
1288 Display *
1289 XOpenDisplay( const char *display_name )
1290 {
1291 Display *dpy;
1292
1293 dpy = (Display *)calloc(1, sizeof(Display));
1294 if (!dpy)
1295 return NULL;
1296
1297 dpy->IsClient = True;
1298
1299 /* read config file
1300 */
1301 if (!__read_config_file( dpy )) {
1302 fprintf(stderr, "Couldn't get configuration details\n");
1303 free(dpy);
1304 return NULL;
1305 }
1306
1307 /* Connect to the server and receive driverClientMsg
1308 */
1309 if (!__miniglx_open_connections(dpy)) {
1310 free(dpy);
1311 return NULL;
1312 }
1313
1314 /* dlopen the driver .so file
1315 */
1316 if (!InitDriver(dpy)) {
1317 fprintf(stderr, "InitDriver failed\n");
1318 free(dpy);
1319 return NULL;
1320 }
1321
1322 /* Perform the client-side initialization.
1323 *
1324 * Clearly there is a limit of one on the number of windows in
1325 * existence at any time.
1326 *
1327 * Need to shut down DRM and free DRI data in XDestroyWindow(), too.
1328 */
1329 dpy->driScreen.private = CallCreateNewScreen(dpy, 0, &dpy->driScreen);
1330 if (!dpy->driScreen.private) {
1331 fprintf(stderr, "%s: __driCreateScreen failed\n", __FUNCTION__);
1332 dlclose(dpy->dlHandle);
1333 free(dpy);
1334 return NULL;
1335 }
1336
1337 /* Anything more to do?
1338 */
1339 return dpy;
1340 }
1341
1342
1343 /**
1344 * \brief Release display resources.
1345 *
1346 * When the application is about to exit, the resources associated with the
1347 * graphics system can be released by calling this function.
1348 *
1349 * \param dpy display handle. It becomes invalid at this point.
1350 *
1351 * Destroys the window if any, and destroys the per-screen
1352 * driver private information.
1353 * Calls __miniglx_close_connections().
1354 *
1355 * If a server, puts the the framebuffer back into the initial state.
1356 *
1357 * Finally frees the display structure.
1358 */
1359 void
1360 XCloseDisplay( Display *dpy )
1361 {
1362 glXMakeCurrent( dpy, NULL, NULL);
1363
1364 if (dpy->NumWindows)
1365 XDestroyWindow( dpy, dpy->TheWindow );
1366
1367 /* As this is done in XOpenDisplay, need to undo it here:
1368 */
1369 dpy->driScreen.destroyScreen(dpy, 0, dpy->driScreen.private);
1370
1371 __miniglx_close_connections( dpy );
1372
1373 if (!dpy->IsClient) {
1374 /* put framebuffer back to initial state
1375 */
1376 (*dpy->driver->haltFBDev)( &dpy->driverContext );
1377 RestoreFBDev(dpy);
1378 CloseFBDev(dpy);
1379 }
1380
1381 dlclose(dpy->dlHandle);
1382 free(dpy);
1383 }
1384
1385
1386 /**
1387 * \brief Window creation.
1388 *
1389 * \param display a display handle, as returned by XOpenDisplay().
1390 * \param parent the parent window for the new window. For Mini GLX this should
1391 * be
1392 * \code RootWindow(display, 0) \endcode
1393 * \param x the window abscissa. For Mini GLX, it should be zero.
1394 * \param y the window ordinate. For Mini GLX, it should be zero.
1395 * \param width the window width. For Mini GLX, this specifies the desired
1396 * screen width such as 1024 or 1280.
1397 * \param height the window height. For Mini GLX, this specifies the desired
1398 * screen height such as 768 or 1024.
1399 * \param border_width the border width. For Mini GLX, it should be zero.
1400 * \param depth the window pixel depth. For Mini GLX, this should be the depth
1401 * found in the #XVisualInfo object returned by glXChooseVisual()
1402 * \param winclass the window class. For Mini GLX this value should be
1403 * #InputOutput.
1404 * \param visual the visual type. It should be the visual field of the
1405 * #XVisualInfo object returned by glXChooseVisual().
1406 * \param valuemask which fields of the XSetWindowAttributes() are to be used.
1407 * For Mini GLX this is typically the bitmask
1408 * \code CWBackPixel | CWBorderPixel | CWColormap \endcode
1409 * \param attributes initial window attributes. The
1410 * XSetWindowAttributes::background_pixel, XSetWindowAttributes::border_pixel
1411 * and XSetWindowAttributes::colormap fields should be set.
1412 *
1413 * \return a window handle if it succeeds or zero if it fails.
1414 *
1415 * \note For Mini GLX, windows are full-screen; they cover the entire frame
1416 * buffer. Also, Mini GLX imposes a limit of one window. A second window
1417 * cannot be created until the first one is destroyed.
1418 *
1419 * This function creates and initializes a ::MiniGLXWindowRec structure after
1420 * ensuring that there is no other window created. Performs the per-drawable
1421 * client-side initialization calling the __DRIscreenRec::createDrawable
1422 * method.
1423 *
1424 */
1425 Window
1426 XCreateWindow( Display *dpy, Window parent, int x, int y,
1427 unsigned int width, unsigned int height,
1428 unsigned int border_width, int depth, unsigned int winclass,
1429 Visual *visual, unsigned long valuemask,
1430 XSetWindowAttributes *attributes )
1431 {
1432 const int empty_attribute_list[1] = { None };
1433
1434 Window win;
1435
1436 /* ignored */
1437 (void) x;
1438 (void) y;
1439 (void) border_width;
1440 (void) depth;
1441 (void) winclass;
1442 (void) valuemask;
1443 (void) attributes;
1444
1445 if (!dpy->IsClient) {
1446 fprintf(stderr, "Server process may not create windows (currently)\n");
1447 return NULL;
1448 }
1449
1450 if (dpy->NumWindows > 0)
1451 return NULL; /* only allow one window */
1452
1453 assert(dpy->TheWindow == NULL);
1454
1455 win = malloc(sizeof(struct MiniGLXWindowRec));
1456 if (!win)
1457 return NULL;
1458
1459 /* In rotated mode, translate incoming x,y,width,height into
1460 * 'normal' coordinates.
1461 */
1462 if (dpy->rotateMode) {
1463 int tmp;
1464 tmp = width; width = height; height = tmp;
1465 tmp = x; x = y; y = tmp;
1466 }
1467
1468 /* init other per-window fields */
1469 win->x = 0;
1470 win->y = 0;
1471 win->w = width;
1472 win->h = height;
1473 win->visual = visual; /* ptr assignment */
1474
1475 win->bytesPerPixel = dpy->driverContext.cpp;
1476 win->rowStride = dpy->driverContext.shared.virtualWidth * win->bytesPerPixel;
1477 win->size = win->rowStride * height;
1478 win->frontStart = dpy->driverContext.FBAddress;
1479 win->frontBottom = (GLubyte *) win->frontStart + (height-1) * win->rowStride;
1480
1481 /* This is incorrect: the hardware driver could put the backbuffer
1482 * just about anywhere. These fields, including the above are
1483 * hardware dependent & don't really belong here.
1484 */
1485 if (visual->mode->doubleBufferMode) {
1486 win->backStart = (GLubyte *) win->frontStart +
1487 win->rowStride * dpy->driverContext.shared.virtualHeight;
1488 win->backBottom = (GLubyte *) win->backStart
1489 + (height - 1) * win->rowStride;
1490 win->curBottom = win->backBottom;
1491 }
1492 else {
1493 /* single buffered */
1494 win->backStart = NULL;
1495 win->backBottom = NULL;
1496 win->curBottom = win->frontBottom;
1497 }
1498
1499 dpy->driScreen.createNewDrawable(dpy, visual->mode, (int) win,
1500 &win->driDrawable, GLX_WINDOW_BIT, empty_attribute_list);
1501
1502 if (!win->driDrawable.private) {
1503 fprintf(stderr, "%s: dri.createDrawable failed\n", __FUNCTION__);
1504 free(win);
1505 return NULL;
1506 }
1507
1508 dpy->NumWindows++;
1509 dpy->TheWindow = win;
1510
1511 return win;
1512 }
1513
1514
1515 /**
1516 * \brief Destroy window.
1517 *
1518 * \param display display handle.
1519 * \param w window handle.
1520 *
1521 * This function calls XUnmapWindow() and frees window \p w.
1522 *
1523 * In case of destroying the current buffer first unbinds the GLX context
1524 * by calling glXMakeCurrent() with no drawable.
1525 */
1526 void
1527 XDestroyWindow( Display *display, Window win )
1528 {
1529 if (display && display->IsClient && win) {
1530 /* check if destroying the current buffer */
1531 Window curDraw = glXGetCurrentDrawable();
1532 if (win == curDraw) {
1533 glXMakeCurrent( display, NULL, NULL);
1534 }
1535
1536 XUnmapWindow( display, win );
1537
1538 /* Destroy the drawable. */
1539 win->driDrawable.destroyDrawable(display, win->driDrawable.private);
1540 free(win);
1541
1542 /* unlink window from display */
1543 display->NumWindows--;
1544 assert(display->NumWindows == 0);
1545 display->TheWindow = NULL;
1546 }
1547 }
1548
1549
1550
1551
1552 /**
1553 * \brief Create color map structure.
1554 *
1555 * \param dpy the display handle as returned by XOpenDisplay().
1556 * \param w the window on whose screen you want to create a color map. This
1557 * parameter is ignored by Mini GLX but should be the value returned by the
1558 * \code RootWindow(display, 0) \endcode macro.
1559 * \param visual a visual type supported on the screen. This parameter is
1560 * ignored by Mini GLX but should be the XVisualInfo::visual returned by
1561 * glXChooseVisual().
1562 * \param alloc the color map entries to be allocated. This parameter is ignored
1563 * by Mini GLX but should be set to #AllocNone.
1564 *
1565 * \return the color map.
1566 *
1567 * This function is only provided to ease porting. Practically a no-op -
1568 * returns a pointer to a dynamically allocated chunk of memory (one byte).
1569 */
1570 Colormap
1571 XCreateColormap( Display *dpy, Window w, Visual *visual, int alloc )
1572 {
1573 (void) dpy;
1574 (void) w;
1575 (void) visual;
1576 (void) alloc;
1577 return (Colormap) malloc(1);
1578 }
1579
1580
1581 /**
1582 * \brief Destroy color map structure.
1583 *
1584 * \param display The display handle as returned by XOpenDisplay().
1585 * \param colormap the color map to destroy.
1586 *
1587 * This function is only provided to ease porting. Practically a no-op.
1588 *
1589 * Frees the memory pointed by \p colormap.
1590 */
1591 void
1592 XFreeColormap( Display *display, Colormap colormap )
1593 {
1594 (void) display;
1595 (void) colormap;
1596 free(colormap);
1597 }
1598
1599
1600 /**
1601 * \brief Free client data.
1602 *
1603 * \param data the data that is to be freed.
1604 *
1605 * Frees the memory pointed by \p data.
1606 */
1607 void
1608 XFree( void *data )
1609 {
1610 free(data);
1611 }
1612
1613
1614 /**
1615 * \brief Query available visuals.
1616 *
1617 * \param dpy the display handle, as returned by XOpenDisplay().
1618 * \param vinfo_mask a bitmask indicating which fields of the \p vinfo_template
1619 * are to be matched. The value must be \c VisualScreenMask.
1620 * \param vinfo_template a template whose fields indicate which visual
1621 * attributes must be matched by the results. The XVisualInfo::screen field of
1622 * this structure must be zero.
1623 * \param nitens_return will hold the number of visuals returned.
1624 *
1625 * \return the address of an array of all available visuals.
1626 *
1627 * An example of using XGetVisualInfo() to get all available visuals follows:
1628 *
1629 * \code
1630 * XVisualInfo vinfo_template, *results;
1631 * int nitens_return;
1632 * Display *dpy = XOpenDisplay(NULL);
1633 * vinfo_template.screen = 0;
1634 * results = XGetVisualInfo(dpy, VisualScreenMask, &vinfo_template, &nitens_return);
1635 * \endcode
1636 *
1637 * Returns the list of all ::XVisualInfo available, one per
1638 * ::__GLcontextMode stored in MiniGLXDisplayRec::modes.
1639 */
1640 XVisualInfo *
1641 XGetVisualInfo( Display *dpy, long vinfo_mask, XVisualInfo *vinfo_template, int *nitens_return )
1642 {
1643 const __GLcontextModes *mode;
1644 XVisualInfo *results;
1645 Visual *visResults;
1646 int i, n=0;
1647
1648 // ASSERT(vinfo_mask == VisualScreenMask);
1649 ASSERT(vinfo_template.screen == 0);
1650
1651 if (vinfo_mask == VisualIDMask)
1652 {
1653 for ( mode = dpy->driver_modes ; mode != NULL ; mode= mode->next )
1654 if (mode->visualID == vinfo_template->visualid)
1655 n=1;
1656
1657 if (n==0)
1658 return NULL;
1659
1660 results = (XVisualInfo *)calloc(1, n * sizeof(XVisualInfo));
1661 if (!results) {
1662 *nitens_return = 0;
1663 return NULL;
1664 }
1665
1666 visResults = (Visual *)calloc(1, n * sizeof(Visual));
1667 if (!results) {
1668 free(results);
1669 *nitens_return = 0;
1670 return NULL;
1671 }
1672
1673 for ( mode = dpy->driver_modes ; mode != NULL ; mode= mode->next )
1674 if (mode->visualID == vinfo_template->visualid)
1675 {
1676 visResults[0].mode=mode;
1677 visResults[0].visInfo = results;
1678 visResults[0].dpy = dpy;
1679 if (dpy->driverContext.bpp == 32)
1680 visResults[0].pixelFormat = PF_B8G8R8A8; /* XXX: FIX ME */
1681 else
1682 visResults[0].pixelFormat = PF_B5G6R5; /* XXX: FIX ME */
1683
1684 results[0].visual = visResults;
1685 results[0].visualid = mode->visualID;
1686 #if defined(__cplusplus) || defined(c_plusplus)
1687 results[0].c_class = TrueColor;
1688 #else
1689 results[0].class = TrueColor;
1690 #endif
1691 results[0].depth = mode->redBits +
1692 mode->redBits +
1693 mode->redBits +
1694 mode->redBits;
1695 results[0].bits_per_rgb = dpy->driverContext.bpp;
1696
1697 }
1698
1699 }
1700 else // if (vinfo_mask == VisualScreenMask)
1701 {
1702 n = 0;
1703 for ( mode = dpy->driver_modes ; mode != NULL ; mode = mode->next )
1704 n++;
1705
1706 results = (XVisualInfo *)calloc(1, n * sizeof(XVisualInfo));
1707 if (!results) {
1708 *nitens_return = 0;
1709 return NULL;
1710 }
1711
1712 visResults = (Visual *)calloc(1, n * sizeof(Visual));
1713 if (!results) {
1714 free(results);
1715 *nitens_return = 0;
1716 return NULL;
1717 }
1718
1719 for ( mode = dpy->driver_modes, i = 0 ; mode != NULL ; mode = mode->next, i++ ) {
1720 visResults[i].mode = mode;
1721 visResults[i].visInfo = results + i;
1722 visResults[i].dpy = dpy;
1723
1724 if (dpy->driverContext.bpp == 32)
1725 visResults[i].pixelFormat = PF_B8G8R8A8; /* XXX: FIX ME */
1726 else
1727 visResults[i].pixelFormat = PF_B5G6R5; /* XXX: FIX ME */
1728
1729 results[i].visual = visResults + i;
1730 results[i].visualid = mode->visualID;
1731 #if defined(__cplusplus) || defined(c_plusplus)
1732 results[i].c_class = TrueColor;
1733 #else
1734 results[i].class = TrueColor;
1735 #endif
1736 results[i].depth = mode->redBits +
1737 mode->redBits +
1738 mode->redBits +
1739 mode->redBits;
1740 results[i].bits_per_rgb = dpy->driverContext.bpp;
1741 }
1742 }
1743 *nitens_return = n;
1744 return results;
1745 }
1746
1747
1748 /**
1749 * \brief Return a visual that matches specified attributes.
1750 *
1751 * \param dpy the display handle, as returned by XOpenDisplay().
1752 * \param screen the screen number. It is currently ignored by Mini GLX and
1753 * should be zero.
1754 * \param attribList a list of GLX attributes which describe the desired pixel
1755 * format. It is terminated by the token \c None.
1756 *
1757 * The attributes are as follows:
1758 * \arg GLX_USE_GL:
1759 * This attribute should always be present in order to maintain compatibility
1760 * with GLX.
1761 * \arg GLX_RGBA:
1762 * If present, only RGBA pixel formats will be considered. Otherwise, only
1763 * color index formats are considered.
1764 * \arg GLX_DOUBLEBUFFER:
1765 * if present, only double-buffered pixel formats will be chosen.
1766 * \arg GLX_RED_SIZE \e n:
1767 * Must be followed by a non-negative integer indicating the minimum number of
1768 * bits per red pixel component that is acceptable.
1769 * \arg GLX_GREEN_SIZE \e n:
1770 * Must be followed by a non-negative integer indicating the minimum number of
1771 * bits per green pixel component that is acceptable.
1772 * \arg GLX_BLUE_SIZE \e n:
1773 * Must be followed by a non-negative integer indicating the minimum number of
1774 * bits per blue pixel component that is acceptable.
1775 * \arg GLX_ALPHA_SIZE \e n:
1776 * Must be followed by a non-negative integer indicating the minimum number of
1777 * bits per alpha pixel component that is acceptable.
1778 * \arg GLX_STENCIL_SIZE \e n:
1779 * Must be followed by a non-negative integer indicating the minimum number of
1780 * bits per stencil value that is acceptable.
1781 * \arg GLX_DEPTH_SIZE \e n:
1782 * Must be followed by a non-negative integer indicating the minimum number of
1783 * bits per depth component that is acceptable.
1784 * \arg None:
1785 * This token is used to terminate the attribute list.
1786 *
1787 * \return a pointer to an #XVisualInfo object which most closely matches the
1788 * requirements of the attribute list. If there is no visual which matches the
1789 * request, \c NULL will be returned.
1790 *
1791 * \note Visuals with accumulation buffers are not available.
1792 *
1793 * This function searches the list of available visual configurations in
1794 * MiniGLXDisplayRec::configs for a configuration which best matches the GLX
1795 * attribute list parameter. A new ::XVisualInfo object is created which
1796 * describes the visual configuration. The match criteria is described in the
1797 * specification.
1798 */
1799 XVisualInfo*
1800 glXChooseVisual( Display *dpy, int screen, int *attribList )
1801 {
1802 const __GLcontextModes *mode;
1803 Visual *vis;
1804 XVisualInfo *visInfo;
1805 const int *attrib;
1806 GLboolean rgbFlag = GL_FALSE, dbFlag = GL_FALSE, stereoFlag = GL_FALSE;
1807 GLint redBits = 0, greenBits = 0, blueBits = 0, alphaBits = 0;
1808 GLint indexBits = 0, depthBits = 0, stencilBits = 0;
1809 GLint numSamples = 0;
1810 int i=0;
1811
1812 /*
1813 * XXX in the future, <screen> might be interpreted as a VT
1814 */
1815 ASSERT(dpy);
1816 ASSERT(screen == 0);
1817
1818 vis = (Visual *)calloc(1, sizeof(Visual));
1819 if (!vis)
1820 return NULL;
1821
1822 visInfo = (XVisualInfo *)malloc(sizeof(XVisualInfo));
1823 if (!visInfo) {
1824 free(vis);
1825 return NULL;
1826 }
1827
1828 visInfo->visual = vis;
1829 vis->visInfo = visInfo;
1830 vis->dpy = dpy;
1831
1832 /* parse the attribute list */
1833 for (attrib = attribList; attrib && *attrib != None; attrib++) {
1834 switch (attrib[0]) {
1835 case GLX_DOUBLEBUFFER:
1836 dbFlag = GL_TRUE;
1837 break;
1838 case GLX_RGBA:
1839 rgbFlag = GL_TRUE;
1840 break;
1841 case GLX_RED_SIZE:
1842 redBits = attrib[1];
1843 attrib++;
1844 break;
1845 case GLX_GREEN_SIZE:
1846 greenBits = attrib[1];
1847 attrib++;
1848 break;
1849 case GLX_BLUE_SIZE:
1850 blueBits = attrib[1];
1851 attrib++;
1852 break;
1853 case GLX_ALPHA_SIZE:
1854 alphaBits = attrib[1];
1855 attrib++;
1856 break;
1857 case GLX_STENCIL_SIZE:
1858 stencilBits = attrib[1];
1859 attrib++;
1860 break;
1861 case GLX_DEPTH_SIZE:
1862 depthBits = attrib[1];
1863 attrib++;
1864 break;
1865 #if 0
1866 case GLX_ACCUM_RED_SIZE:
1867 accumRedBits = attrib[1];
1868 attrib++;
1869 break;
1870 case GLX_ACCUM_GREEN_SIZE:
1871 accumGreenBits = attrib[1];
1872 attrib++;
1873 break;
1874 case GLX_ACCUM_BLUE_SIZE:
1875 accumBlueBits = attrib[1];
1876 attrib++;
1877 break;
1878 case GLX_ACCUM_ALPHA_SIZE:
1879 accumAlphaBits = attrib[1];
1880 attrib++;
1881 break;
1882 case GLX_LEVEL:
1883 /* ignored for now */
1884 break;
1885 #endif
1886 default:
1887 /* unexpected token */
1888 fprintf(stderr, "unexpected token in glXChooseVisual attrib list\n");
1889 free(vis);
1890 free(visInfo);
1891 return NULL;
1892 }
1893 }
1894
1895 /* search screen configs for suitable visual */
1896 (void) numSamples;
1897 (void) indexBits;
1898 (void) redBits;
1899 (void) greenBits;
1900 (void) blueBits;
1901 (void) alphaBits;
1902 (void) stereoFlag;
1903 for ( mode = dpy->driver_modes ; mode != NULL ; mode = mode->next ) {
1904 i++;
1905 if (mode->rgbMode == rgbFlag &&
1906 mode->doubleBufferMode == dbFlag &&
1907 mode->redBits >= redBits &&
1908 mode->greenBits >= greenBits &&
1909 mode->blueBits >= blueBits &&
1910 mode->alphaBits >= alphaBits &&
1911 mode->depthBits >= depthBits &&
1912 mode->stencilBits >= stencilBits) {
1913 /* found it */
1914 visInfo->visualid = i;
1915 vis->mode = mode;
1916 break;
1917 }
1918 }
1919 if (!vis->mode)
1920 return NULL;
1921
1922 /* compute depth and bpp */
1923 if (rgbFlag) {
1924 /* XXX maybe support depth 16 someday */
1925 #if defined(__cplusplus) || defined(c_plusplus)
1926 visInfo->c_class = TrueColor;
1927 #else
1928 visInfo->class = TrueColor;
1929 #endif
1930 visInfo->depth = dpy->driverContext.bpp;
1931 visInfo->bits_per_rgb = dpy->driverContext.bpp;
1932 if (dpy->driverContext.bpp == 32)
1933 vis->pixelFormat = PF_B8G8R8A8;
1934 else
1935 vis->pixelFormat = PF_B5G6R5;
1936 }
1937 else {
1938 /* color index mode */
1939 #if defined(__cplusplus) || defined(c_plusplus)
1940 visInfo->c_class = PseudoColor;
1941 #else
1942 visInfo->class = PseudoColor;
1943 #endif
1944 visInfo->depth = 8;
1945 visInfo->bits_per_rgb = 8; /* bits/pixel */
1946 vis->pixelFormat = PF_CI8;
1947 }
1948
1949 return visInfo;
1950 }
1951
1952
1953 /**
1954 * \brief Return information about GLX visuals.
1955 *
1956 * \param dpy the display handle, as returned by XOpenDisplay().
1957 * \param vis the visual to be queried, as returned by glXChooseVisual().
1958 * \param attrib the visual attribute to be returned.
1959 * \param value pointer to an integer in which the result of the query will be
1960 * stored.
1961 *
1962 * \return zero if no error occurs, \c GLX_INVALID_ATTRIBUTE if the attribute
1963 * parameter is invalid, or \c GLX_BAD_VISUAL if the \p vis parameter is
1964 * invalid.
1965 *
1966 * Returns the appropriate attribute of ::__GLXvisualConfig pointed by
1967 * MiniGLXVisualRec::glxConfig of XVisualInfo::visual.
1968 *
1969 * \sa data types.
1970 */
1971 int
1972 glXGetConfig( Display *dpy, XVisualInfo *vis, int attrib, int *value )
1973 {
1974 const __GLcontextModes *mode = vis->visual->mode;
1975 if (!mode) {
1976 *value = 0;
1977 return GLX_BAD_VISUAL;
1978 }
1979
1980 switch (attrib) {
1981 case GLX_USE_GL:
1982 *value = True;
1983 return 0;
1984 case GLX_RGBA:
1985 *value = mode->rgbMode;
1986 return 0;
1987 case GLX_DOUBLEBUFFER:
1988 *value = mode->doubleBufferMode;
1989 return 0;
1990 case GLX_RED_SIZE:
1991 *value = mode->redBits;
1992 return 0;
1993 case GLX_GREEN_SIZE:
1994 *value = mode->greenBits;
1995 return 0;
1996 case GLX_BLUE_SIZE:
1997 *value = mode->blueBits;
1998 return 0;
1999 case GLX_ALPHA_SIZE:
2000 *value = mode->alphaBits;
2001 return 0;
2002 case GLX_DEPTH_SIZE:
2003 *value = mode->depthBits;
2004 return 0;
2005 case GLX_STENCIL_SIZE:
2006 *value = mode->stencilBits;
2007 return 0;
2008 default:
2009 *value = 0;
2010 return GLX_BAD_ATTRIBUTE;
2011 }
2012 return 0;
2013 }
2014
2015
2016 /**
2017 * \brief Create a new GLX rendering context.
2018 *
2019 * \param dpy the display handle, as returned by XOpenDisplay().
2020 * \param vis the visual that defines the frame buffer resources available to
2021 * the rendering context, as returned by glXChooseVisual().
2022 * \param shareList If non-zero, texture objects and display lists are shared
2023 * with the named rendering context. If zero, texture objects and display lists
2024 * will (initially) be private to this context. They may be shared when a
2025 * subsequent context is created.
2026 * \param direct whether direct or indirect rendering is desired. For Mini GLX
2027 * this value is ignored but it should be set to \c True.
2028 *
2029 * \return a ::GLXContext handle if it succeeds or zero if it fails due to
2030 * invalid parameter or insufficient resources.
2031 *
2032 * This function creates and initializes a ::MiniGLXContextRec structure and
2033 * calls the __DRIscreenRec::createContext method to initialize the client
2034 * private data.
2035 */
2036 GLXContext
2037 glXCreateContext( Display *dpy, XVisualInfo *vis,
2038 GLXContext shareList, Bool direct )
2039 {
2040 GLXContext ctx;
2041 void *sharePriv;
2042
2043 ASSERT(vis);
2044
2045 ctx = (struct MiniGLXContextRec *)calloc(1, sizeof(struct MiniGLXContextRec));
2046 if (!ctx)
2047 return NULL;
2048
2049 ctx->vid = vis->visualid;
2050
2051 if (shareList)
2052 sharePriv = shareList->driContext.private;
2053 else
2054 sharePriv = NULL;
2055
2056 ctx->driContext.private = dpy->driScreen.createNewContext(dpy, vis->visual->mode,
2057 GLX_WINDOW_BIT, sharePriv, &ctx->driContext);
2058
2059 if (!ctx->driContext.private) {
2060 free(ctx);
2061 return NULL;
2062 }
2063
2064 return ctx;
2065 }
2066
2067
2068 /**
2069 * \brief Destroy a GLX context.
2070 *
2071 * \param dpy the display handle, as returned by XOpenDisplay().
2072 * \param ctx the GLX context to be destroyed.
2073 *
2074 * This function frees the \p ctx parameter after unbinding the current context
2075 * by calling the __DRIcontextRec::bindContext method with zeros and calling
2076 * the __DRIcontextRec::destroyContext method.
2077 */
2078 void
2079 glXDestroyContext( Display *dpy, GLXContext ctx )
2080 {
2081 GLXContext glxctx = glXGetCurrentContext();
2082
2083 if (ctx) {
2084 if (glxctx == ctx) {
2085 /* destroying current context */
2086 ctx->driContext.bindContext3(dpy, 0, 0, 0, 0);
2087 CurrentContext = 0;
2088 }
2089 ctx->driContext.destroyContext(dpy, 0, ctx->driContext.private);
2090 free(ctx);
2091 }
2092 }
2093
2094
2095 /**
2096 * \brief Bind a GLX context to a window or a pixmap.
2097 *
2098 * \param dpy the display handle, as returned by XOpenDisplay().
2099 * \param drawable the window or drawable to bind to the rendering context.
2100 * This should be the value returned by XCreateWindow().
2101 * \param ctx the GLX context to be destroyed.
2102 *
2103 * \return \c True if it succeeds, \c False otherwise to indicate an invalid
2104 * display, window or context parameter.
2105 *
2106 * The current rendering context may be unbound by calling glXMakeCurrent()
2107 * with the window and context parameters set to zero.
2108 *
2109 * An application may create any number of rendering contexts and bind them as
2110 * needed. Note that binding a rendering context is generally not a
2111 * light-weight operation. Most simple OpenGL applications create only one
2112 * rendering context.
2113 *
2114 * This function first unbinds any old context via
2115 * __DRIcontextRec::unbindContext and binds the new one via
2116 * __DRIcontextRec::bindContext.
2117 *
2118 * If \p drawable is zero it unbinds the GLX context by calling
2119 * __DRIcontextRec::bindContext with zeros.
2120 */
2121 Bool
2122 glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx)
2123 {
2124 if (dpy && drawable && ctx) {
2125 GLXContext oldContext = glXGetCurrentContext();
2126 GLXDrawable oldDrawable = glXGetCurrentDrawable();
2127 /* unbind old */
2128 if (oldContext) {
2129 oldContext->driContext.unbindContext3(dpy, 0,
2130 (__DRIid) oldDrawable, (__DRIid) oldDrawable,
2131 &oldContext->driContext);
2132 }
2133 /* bind new */
2134 CurrentContext = ctx;
2135 ctx->driContext.bindContext3(dpy, 0, (__DRIid) drawable,
2136 (__DRIid) drawable, &ctx->driContext);
2137 ctx->drawBuffer = drawable;
2138 ctx->curBuffer = drawable;
2139 }
2140 else if (ctx && dpy) {
2141 /* unbind */
2142 ctx->driContext.bindContext3(dpy, 0, 0, 0, 0);
2143 }
2144 else if (dpy) {
2145 CurrentContext = 0; /* kw: this seems to be intended??? */
2146 }
2147
2148 return True;
2149 }
2150
2151
2152 /**
2153 * \brief Exchange front and back buffers.
2154 *
2155 * \param dpy the display handle, as returned by XOpenDisplay().
2156 * \param drawable the drawable whose buffers are to be swapped.
2157 *
2158 * Any pending rendering commands will be completed before the buffer swap
2159 * takes place.
2160 *
2161 * Calling glXSwapBuffers() on a window which is single-buffered has no effect.
2162 *
2163 * This function just calls the __DRIdrawableRec::swapBuffers method to do the
2164 * work.
2165 */
2166 void
2167 glXSwapBuffers( Display *dpy, GLXDrawable drawable )
2168 {
2169 if (!dpy || !drawable)
2170 return;
2171
2172 drawable->driDrawable.swapBuffers(dpy, drawable->driDrawable.private);
2173 }
2174
2175
2176 /**
2177 * \brief Return the current context
2178 *
2179 * \return the current context, as specified by glXMakeCurrent(), or zero if no
2180 * context is currently bound.
2181 *
2182 * \sa glXCreateContext(), glXMakeCurrent()
2183 *
2184 * Returns the value of the ::CurrentContext global variable.
2185 */
2186 GLXContext
2187 glXGetCurrentContext( void )
2188 {
2189 return CurrentContext;
2190 }
2191
2192
2193 /**
2194 * \brief Return the current drawable.
2195 *
2196 * \return the current drawable, as specified by glXMakeCurrent(), or zero if
2197 * no drawable is currently bound.
2198 *
2199 * This function gets the current context via glXGetCurrentContext() and
2200 * returns the MiniGLXContextRec::drawBuffer attribute.
2201 */
2202 GLXDrawable
2203 glXGetCurrentDrawable( void )
2204 {
2205 GLXContext glxctx = glXGetCurrentContext();
2206 if (glxctx)
2207 return glxctx->drawBuffer;
2208 else
2209 return NULL;
2210 }
2211
2212
2213 GLboolean
2214 __glXCreateContextWithConfig(__DRInativeDisplay *dpy, int screen,
2215 int fbconfigID, void *contextID, drm_context_t *hHWContext)
2216 {
2217 __DRIscreen *pDRIScreen;
2218 __DRIscreenPrivate *psp;
2219
2220 pDRIScreen = __glXFindDRIScreen(dpy, screen);
2221 if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) {
2222 return GL_FALSE;
2223 }
2224
2225 psp = (__DRIscreenPrivate *) pDRIScreen->private;
2226
2227 if (psp->fd) {
2228 if (drmCreateContext(psp->fd, hHWContext)) {
2229 fprintf(stderr, ">>> drmCreateContext failed\n");
2230 return GL_FALSE;
2231 }
2232 *(void**)contextID = (void*) *hHWContext;
2233 }
2234
2235 return GL_TRUE;
2236 }
2237
2238
2239 GLboolean
2240 __glXGetDrawableInfo(__DRInativeDisplay *dpy, int scrn,
2241 __DRIid draw, unsigned int * index, unsigned int * stamp,
2242 int * x, int * y, int * width, int * height,
2243 int * numClipRects, drm_clip_rect_t ** pClipRects,
2244 int * backX, int * backY,
2245 int * numBackClipRects, drm_clip_rect_t ** pBackClipRects)
2246 {
2247 GLXDrawable drawable = (GLXDrawable) draw;
2248 drm_clip_rect_t * cliprect;
2249 Display* display = (Display*)dpy;
2250 __DRIcontextPrivate *pcp = (__DRIcontextPrivate *)CurrentContext->driContext.private;
2251 if (drawable == 0) {
2252 return GL_FALSE;
2253 }
2254
2255 cliprect = (drm_clip_rect_t*) _mesa_malloc(sizeof(drm_clip_rect_t));
2256 cliprect->x1 = drawable->x;
2257 cliprect->y1 = drawable->y;
2258 cliprect->x2 = drawable->x + drawable->w;
2259 cliprect->y2 = drawable->y + drawable->h;
2260
2261 /* the drawable index is by client id */
2262 *index = display->clientID;
2263
2264 *stamp = pcp->driScreenPriv->pSAREA->drawableTable[display->clientID].stamp;
2265 *x = drawable->x;
2266 *y = drawable->y;
2267 *width = drawable->w;
2268 *height = drawable->h;
2269 *numClipRects = 1;
2270 *pClipRects = cliprect;
2271
2272 *backX = drawable->x;
2273 *backY = drawable->y;
2274 *numBackClipRects = 0;
2275 *pBackClipRects = 0;
2276
2277 return GL_TRUE;
2278 }
2279
2280
2281 GLboolean
2282 XF86DRIDestroyContext(__DRInativeDisplay *dpy, int screen, __DRIid context_id )
2283 {
2284 return GL_TRUE;
2285 }
2286
2287
2288 GLboolean
2289 XF86DRICreateDrawable(__DRInativeDisplay *dpy, int screen, __DRIid drawable,
2290 drm_drawable_t *hHWDrawable )
2291 {
2292 return GL_TRUE;
2293 }
2294
2295
2296 GLboolean
2297 XF86DRIDestroyDrawable(__DRInativeDisplay *dpy, int screen, __DRIid drawable)
2298 {
2299 return GL_TRUE;
2300 }
2301
2302
2303 /**
2304 * \brief Query function address.
2305 *
2306 * The glXGetProcAddress() function will return the address of any available
2307 * OpenGL or Mini GLX function.
2308 *
2309 * \param procName name of the function to be returned.
2310 *
2311 * \return If \p procName is a valid function name, a pointer to that function
2312 * will be returned. Otherwise, \c NULL will be returned.
2313 *
2314 * The purpose of glXGetProcAddress() is to facilitate using future extensions
2315 * to OpenGL or Mini GLX. If a future version of the library adds new extension
2316 * functions they'll be accessible via glXGetProcAddress(). The alternative is
2317 * to hard-code calls to the new functions in the application but doing so will
2318 * prevent linking the application with older versions of the library.
2319 *
2320 * Returns the function address by looking up its name in a static (name,
2321 * address) pair list.
2322 */
2323 void (*glXGetProcAddress(const GLubyte *procname))( void )
2324 {
2325 struct name_address {
2326 const char *name;
2327 const void *func;
2328 };
2329 static const struct name_address functions[] = {
2330 { "glXChooseVisual", (void *) glXChooseVisual },
2331 { "glXCreateContext", (void *) glXCreateContext },
2332 { "glXDestroyContext", (void *) glXDestroyContext },
2333 { "glXMakeCurrent", (void *) glXMakeCurrent },
2334 { "glXSwapBuffers", (void *) glXSwapBuffers },
2335 { "glXGetCurrentContext", (void *) glXGetCurrentContext },
2336 { "glXGetCurrentDrawable", (void *) glXGetCurrentDrawable },
2337 { "glXGetProcAddress", (void *) glXGetProcAddress },
2338 { "XOpenDisplay", (void *) XOpenDisplay },
2339 { "XCloseDisplay", (void *) XCloseDisplay },
2340 { "XCreateWindow", (void *) XCreateWindow },
2341 { "XDestroyWindow", (void *) XDestroyWindow },
2342 { "XMapWindow", (void *) XMapWindow },
2343 { "XCreateColormap", (void *) XCreateColormap },
2344 { "XFreeColormap", (void *) XFreeColormap },
2345 { "XFree", (void *) XFree },
2346 { "XGetVisualinfo", (void *) XGetVisualInfo },
2347 { "glXCreatePbuffer", (void *) glXCreatePbuffer },
2348 { "glXDestroyPbuffer", (void *) glXDestroyPbuffer },
2349 { "glXChooseFBConfig", (void *) glXChooseFBConfig },
2350 { "glXGetVisualFromFBConfig", (void *) glXGetVisualFromFBConfig },
2351 { "__glXCreateContextWithConfig", (void *) __glXCreateContextWithConfig },
2352 { "__glXGetDrawableInfo", (void *) __glXGetDrawableInfo },
2353 { "__glXWindowExists", (void *) __glXWindowExists },
2354 { "__glXCreateContextModes", (void *) _gl_context_modes_create },
2355 { "__glXFindDRIScreen", (void *)__glXFindDRIScreen },
2356 { "__glXScrEnableExtension", (void *)__glXScrEnableExtension },
2357 { NULL, NULL }
2358 };
2359 const struct name_address *entry;
2360 for (entry = functions; entry->name; entry++) {
2361 if (strcmp(entry->name, (const char *) procname) == 0) {
2362 return entry->func;
2363 }
2364 }
2365 return _glapi_get_proc_address((const char *) procname);
2366 }
2367
2368
2369 /**
2370 * \brief Query the Mini GLX version.
2371 *
2372 * \param dpy the display handle. It is currently ignored, but should be the
2373 * value returned by XOpenDisplay().
2374 * \param major receives the major version number of Mini GLX.
2375 * \param minor receives the minor version number of Mini GLX.
2376 *
2377 * \return \c True if the function succeeds, \c False if the function fails due
2378 * to invalid parameters.
2379 *
2380 * \sa #MINI_GLX_VERSION_1_0.
2381 *
2382 * Returns the hard-coded Mini GLX version.
2383 */
2384 Bool
2385 glXQueryVersion( Display *dpy, int *major, int *minor )
2386 {
2387 (void) dpy;
2388 *major = 1;
2389 *minor = 0;
2390 return True;
2391 }
2392
2393
2394 /**
2395 * \brief Create a new pbuffer.
2396 */
2397 GLXPbuffer
2398 glXCreatePbuffer( Display *dpy, GLXFBConfig config, const int *attribList )
2399 {
2400 return NULL;
2401 }
2402
2403
2404 void
2405 glXDestroyPbuffer( Display *dpy, GLXPbuffer pbuf )
2406 {
2407 free(pbuf);
2408 }
2409
2410
2411 GLXFBConfig *
2412 glXChooseFBConfig( Display *dpy, int screen, const int *attribList,
2413 int *nitems )
2414 {
2415 GLXFBConfig *f = (GLXFBConfig *) malloc(sizeof(GLXFBConfig));
2416 f->visInfo = glXChooseVisual( dpy, screen, (int *) attribList );
2417 if (f->visInfo) {
2418 *nitems = 1;
2419 return f;
2420 }
2421 else {
2422 *nitems = 0;
2423 free(f);
2424 return NULL;
2425 }
2426 }
2427
2428
2429 XVisualInfo *
2430 glXGetVisualFromFBConfig( Display *dpy, GLXFBConfig config )
2431 {
2432 /* XVisualInfo and GLXFBConfig are the same structure */
2433 (void) dpy;
2434 return config.visInfo;
2435 }
2436
2437 void *glXAllocateMemoryMESA(Display *dpy, int scrn,
2438 size_t size, float readFreq,
2439 float writeFreq, float priority)
2440 {
2441 if (dpy->driScreen.private && dpy->driScreen.allocateMemory) {
2442 return (*dpy->driScreen.allocateMemory)( dpy, scrn, size,
2443 readFreq, writeFreq,
2444 priority );
2445 }
2446 }
2447
2448 void glXFreeMemoryMESA(Display *dpy, int scrn, void *pointer){
2449 if (dpy->driScreen.private && dpy->driScreen.freeMemory) {
2450 (*dpy->driScreen.freeMemory)( dpy, scrn, pointer );
2451 }
2452 }
2453
2454 GLuint glXGetMemoryOffsetMESA( Display *dpy, int scrn,
2455 const void *pointer )
2456 {
2457 if (dpy->driScreen.private && dpy->driScreen.memoryOffset) {
2458 return (*dpy->driScreen.memoryOffset)( dpy, scrn, pointer );
2459 }
2460 }
2461
2462 void
2463 __glXScrEnableExtension( void *psc, const char * name )
2464 {
2465
2466 }
2467
2468
2469 /*@}*/