http://packetstormsecurity.org/UNIX/admin/xscreensaver-3.28.tar.gz
[xscreensaver] / utils / visual-gl.c
1 /* xscreensaver, Copyright (c) 1999, 2000 by Jamie Zawinski <jwz@jwz.org>
2  *
3  * Permission to use, copy, modify, distribute, and sell this software and its
4  * documentation for any purpose is hereby granted without fee, provided that
5  * the above copyright notice appear in all copies and that both that
6  * copyright notice and this permission notice appear in supporting
7  * documentation.  No representations are made about the suitability of this
8  * software for any purpose.  It is provided "as is" without express or 
9  * implied warranty.
10  */
11
12 /* This file contains code for picking the best visual for GL programs by
13    actually asking the GL library to figure it out for us.  The code in
14    visual.c might do a good job of this on most systems, but not on most
15    high end 3D cards (e.g., Silicon Graphics or nVidia.)
16
17    There exists information about visuals which is available to GL, but
18    which is not available via Xlib calls.  So the only way to know
19    which visual to use (other than impirically) is to actually call
20    glXChooseVisual().
21  */
22
23 #include "utils.h"
24 #include "visual.h"
25
26 #ifdef HAVE_GL
27 # include <GL/gl.h>
28 # include <GL/glx.h>
29 #endif /* HAVE_GL */
30
31 extern char *progname;
32
33 Visual *
34 get_gl_visual (Screen *screen)
35 {
36 #ifdef HAVE_GL
37   Display *dpy = DisplayOfScreen (screen);
38   int screen_num = screen_number (screen);
39
40 # define R GLX_RED_SIZE
41 # define G GLX_GREEN_SIZE
42 # define B GLX_BLUE_SIZE
43 # define D GLX_DEPTH_SIZE
44 # define I GLX_BUFFER_SIZE
45 # define DB GLX_DOUBLEBUFFER
46
47   int attrs[][20] = {
48     { GLX_RGBA, R, 8, G, 8, B, 8, D, 8, DB, 0 }, /* rgb double */
49     { GLX_RGBA, R, 4, G, 4, B, 4, D, 4, DB, 0 },
50     { GLX_RGBA, R, 2, G, 2, B, 2, D, 2, DB, 0 },
51     { GLX_RGBA, R, 8, G, 8, B, 8, D, 8,     0 }, /* rgb single */
52     { GLX_RGBA, R, 4, G, 4, B, 4, D, 4,     0 },
53     { GLX_RGBA, R, 2, G, 2, B, 2, D, 2,     0 },
54     { I, 8,                       D, 8, DB, 0 }, /* cmap double */
55     { I, 4,                       D, 4, DB, 0 },
56     { I, 8,                       D, 8,     0 }, /* cmap single */
57     { I, 4,                       D, 4,     0 },
58     { GLX_RGBA, R, 1, G, 1, B, 1, D, 1,     0 }  /* monochrome */
59   };
60
61   int i;
62   for (i = 0; i < sizeof(attrs)/sizeof(*attrs); i++)
63     {
64       XVisualInfo *vi = glXChooseVisual (dpy, screen_num, attrs[i]);
65       if (vi)
66         {
67           Visual *v = vi->visual;
68           XFree (vi);
69           /* describe_gl_visual (stderr, screen, v, False); */
70           return v;
71         }
72     }
73 #endif /* !HAVE_GL */
74
75   return 0;
76 }
77
78
79 void
80 describe_gl_visual (FILE *f, Screen *screen, Visual *visual,
81                     Bool private_cmap_p)
82 {
83   describe_visual (f, screen, visual, private_cmap_p);
84
85 #ifdef HAVE_GL
86   {
87     int status;
88     int value = False;
89
90     Display *dpy = DisplayOfScreen (screen);
91     XVisualInfo vi_in, *vi_out;
92     int out_count;
93
94     vi_in.screen = screen_number (screen);
95     vi_in.visualid = XVisualIDFromVisual (visual);
96     vi_out = XGetVisualInfo (dpy, (VisualScreenMask | VisualIDMask),
97                              &vi_in, &out_count);
98     if (! vi_out) abort ();
99
100     status = glXGetConfig (dpy, vi_out, GLX_USE_GL, &value);
101
102     if (status == GLX_NO_EXTENSION)
103       /* dpy does not support the GLX extension. */
104       return;
105
106     if (status == GLX_BAD_VISUAL || value == False)
107       /* this visual does not support GLX. */
108       return;
109     
110     if (!glXGetConfig (dpy, vi_out, GLX_LEVEL, &value) &&
111         value != 0)
112       printf ("    GLX level:         %d\n", value);
113
114     if (!glXGetConfig (dpy, vi_out, GLX_RGBA, &value) && value)
115       {
116         int r=0, g=0, b=0, a=0;
117         glXGetConfig (dpy, vi_out, GLX_RED_SIZE,   &r);
118         glXGetConfig (dpy, vi_out, GLX_GREEN_SIZE, &g);
119         glXGetConfig (dpy, vi_out, GLX_BLUE_SIZE,  &b);
120         glXGetConfig (dpy, vi_out, GLX_ALPHA_SIZE, &a);
121         printf ("    GLX type:          RGBA (%2d, %2d, %2d, %2d)\n",
122                 r, g, b, a);
123
124         r=0, g=0, b=0, a=0;
125         glXGetConfig (dpy, vi_out, GLX_ACCUM_RED_SIZE,   &r);
126         glXGetConfig (dpy, vi_out, GLX_ACCUM_GREEN_SIZE, &g);
127         glXGetConfig (dpy, vi_out, GLX_ACCUM_BLUE_SIZE,  &b);
128         glXGetConfig (dpy, vi_out, GLX_ACCUM_ALPHA_SIZE, &a);
129         printf ("    GLX accum:         RGBA (%2d, %2d, %2d, %2d)\n",
130                 r, g, b, a);
131       }
132     else
133       {
134         value = 0;
135         glXGetConfig (dpy, vi_out, GLX_BUFFER_SIZE, &value);
136         printf ("    GLX type:          indexed (%d)\n", value);
137       }
138
139 # ifdef GLX_VISUAL_CAVEAT_EXT
140     if (!glXGetConfig (dpy, vi_out, GLX_VISUAL_CAVEAT_EXT, &value) &&
141         value != GLX_NONE_EXT)
142       printf ("    GLX rating:        %s\n",
143               (value == GLX_NONE_EXT ? "none" :
144                value == GLX_SLOW_VISUAL_EXT ? "slow" :
145 #   ifdef GLX_NON_CONFORMANT_EXT
146                value == GLX_NON_CONFORMANT_EXT ? "non-conformant" :
147 #   endif /* GLX_NON_CONFORMANT_EXT */
148                "???"));
149 # endif /* GLX_VISUAL_CAVEAT_EXT */
150
151     if (!glXGetConfig (dpy, vi_out, GLX_DOUBLEBUFFER, &value))
152       printf ("    GLX double-buffer: %s\n", (value ? "yes" : "no"));
153
154     if (!glXGetConfig (dpy, vi_out, GLX_STEREO, &value) &&
155         value)
156       printf ("    GLX stereo:        %s\n", (value ? "yes" : "no"));
157
158     if (!glXGetConfig (dpy, vi_out, GLX_AUX_BUFFERS, &value) &&
159         value != 0)
160       printf ("    GLX aux buffers:   %d\n", value);
161
162     if (!glXGetConfig (dpy, vi_out, GLX_DEPTH_SIZE, &value))
163       printf ("    GLX depth size:    %d\n", value);
164
165     if (!glXGetConfig (dpy, vi_out, GLX_STENCIL_SIZE, &value) &&
166         value != 0)
167       printf ("    GLX stencil size:  %d\n", value);
168
169 # ifdef GLX_SAMPLE_BUFFERS_SGIS
170     if (!glXGetConfig (dpy, vi_out, GLX_SAMPLE_BUFFERS_SGIS, &value) &&
171         value != 0)
172       {
173         int bufs = value;
174         if (!glXGetConfig (dpy, vi_out, GLX_SAMPLES_SGIS, &value))
175           printf ("    GLX multisamplers: %d (%d)\n", bufs, value);
176       }
177 # endif /* GLX_SAMPLE_BUFFERS_SGIS */
178
179     if (!glXGetConfig (dpy, vi_out, GLX_TRANSPARENT_TYPE_EXT, &value) &&
180         value != GLX_NONE_EXT)
181       {
182         if (value == GLX_NONE_EXT)
183           printf ("    GLX transparency:  none\n");
184         else if (value == GLX_TRANSPARENT_INDEX_EXT)
185           {
186             if (!glXGetConfig (dpy, vi_out, GLX_TRANSPARENT_INDEX_VALUE_EXT,
187                                &value))
188               printf ("    GLX transparency:  indexed (%d)\n", value);
189           }
190         else if (value == GLX_TRANSPARENT_RGB_EXT)
191           {
192             int r=0, g=0, b=0, a=0;
193             glXGetConfig (dpy, vi_out, GLX_TRANSPARENT_RED_VALUE_EXT,   &r);
194             glXGetConfig (dpy, vi_out, GLX_TRANSPARENT_GREEN_VALUE_EXT, &g);
195             glXGetConfig (dpy, vi_out, GLX_TRANSPARENT_BLUE_VALUE_EXT,  &b);
196             glXGetConfig (dpy, vi_out, GLX_TRANSPARENT_ALPHA_VALUE_EXT, &a);
197             printf ("    GLX transparency:  RGBA (%2d, %2d, %2d, %2d)\n",
198                     r, g, b, a);
199           }
200       }
201   }
202 #endif  /* HAVE_GL */
203 }
204
205
206 Bool
207 validate_gl_visual (FILE *out, Screen *screen, const char *window_desc,
208                     Visual *visual)
209 {
210 #ifdef HAVE_GL
211   int status;
212   int value = False;
213
214   Display *dpy = DisplayOfScreen (screen);
215   XVisualInfo vi_in, *vi_out;
216   int out_count;
217   unsigned int id;
218
219   vi_in.screen = screen_number (screen);
220   vi_in.visualid = XVisualIDFromVisual (visual);
221   vi_out = XGetVisualInfo (dpy, (VisualScreenMask | VisualIDMask),
222                              &vi_in, &out_count);
223   if (! vi_out) abort ();
224
225   status = glXGetConfig (dpy, vi_out, GLX_USE_GL, &value);
226
227   id = (unsigned int) vi_out->visualid;
228   XFree ((char *) vi_out);
229
230   if (status == GLX_NO_EXTENSION)
231     {
232       fprintf (out, "%s: display \"%s\" does not support the GLX extension.\n",
233                progname, DisplayString (dpy));
234       return False;
235     }
236   else if (status == GLX_BAD_VISUAL || value == False)
237     {
238       fprintf (out,
239                "%s: %s's visual 0x%x does not support the GLX extension.\n",
240                progname, window_desc, id);
241       return False;
242     }
243   else
244     {
245       return True;
246     }
247
248 #else  /* !HAVE_GL */
249
250   fprintf (out, "%s: GL support was not compiled in to this program.\n",
251            progname);
252   return False;
253
254 #endif  /* !HAVE_GL */
255 }