http://packetstormsecurity.org/UNIX/admin/xscreensaver-3.34.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 #   ifdef GLX_NON_CONFORMANT_EXT
143       printf ("    GLX rating:        %s\n",
144               (value == GLX_NONE_EXT ? "none" :
145                value == GLX_SLOW_VISUAL_EXT ? "slow" :
146                value == GLX_NON_CONFORMANT_EXT ? "non-conformant" :
147                "???"));
148 #   else      
149       printf ("    GLX rating:        %s\n",
150               (value == GLX_NONE_EXT ? "none" :
151                value == GLX_SLOW_VISUAL_EXT ? "slow" :
152                "???"));
153 #   endif /* GLX_NON_CONFORMANT_EXT */
154 # endif /* GLX_VISUAL_CAVEAT_EXT */
155
156     if (!glXGetConfig (dpy, vi_out, GLX_DOUBLEBUFFER, &value))
157       printf ("    GLX double-buffer: %s\n", (value ? "yes" : "no"));
158
159     if (!glXGetConfig (dpy, vi_out, GLX_STEREO, &value) &&
160         value)
161       printf ("    GLX stereo:        %s\n", (value ? "yes" : "no"));
162
163     if (!glXGetConfig (dpy, vi_out, GLX_AUX_BUFFERS, &value) &&
164         value != 0)
165       printf ("    GLX aux buffers:   %d\n", value);
166
167     if (!glXGetConfig (dpy, vi_out, GLX_DEPTH_SIZE, &value))
168       printf ("    GLX depth size:    %d\n", value);
169
170     if (!glXGetConfig (dpy, vi_out, GLX_STENCIL_SIZE, &value) &&
171         value != 0)
172       printf ("    GLX stencil size:  %d\n", value);
173
174 # ifdef GLX_SAMPLE_BUFFERS_SGIS
175     if (!glXGetConfig (dpy, vi_out, GLX_SAMPLE_BUFFERS_SGIS, &value) &&
176         value != 0)
177       {
178         int bufs = value;
179         if (!glXGetConfig (dpy, vi_out, GLX_SAMPLES_SGIS, &value))
180           printf ("    GLX multisamplers: %d (%d)\n", bufs, value);
181       }
182 # endif /* GLX_SAMPLE_BUFFERS_SGIS */
183
184     if (!glXGetConfig (dpy, vi_out, GLX_TRANSPARENT_TYPE_EXT, &value) &&
185         value != GLX_NONE_EXT)
186       {
187         if (value == GLX_NONE_EXT)
188           printf ("    GLX transparency:  none\n");
189         else if (value == GLX_TRANSPARENT_INDEX_EXT)
190           {
191             if (!glXGetConfig (dpy, vi_out, GLX_TRANSPARENT_INDEX_VALUE_EXT,
192                                &value))
193               printf ("    GLX transparency:  indexed (%d)\n", value);
194           }
195         else if (value == GLX_TRANSPARENT_RGB_EXT)
196           {
197             int r=0, g=0, b=0, a=0;
198             glXGetConfig (dpy, vi_out, GLX_TRANSPARENT_RED_VALUE_EXT,   &r);
199             glXGetConfig (dpy, vi_out, GLX_TRANSPARENT_GREEN_VALUE_EXT, &g);
200             glXGetConfig (dpy, vi_out, GLX_TRANSPARENT_BLUE_VALUE_EXT,  &b);
201             glXGetConfig (dpy, vi_out, GLX_TRANSPARENT_ALPHA_VALUE_EXT, &a);
202             printf ("    GLX transparency:  RGBA (%2d, %2d, %2d, %2d)\n",
203                     r, g, b, a);
204           }
205       }
206   }
207 #endif  /* HAVE_GL */
208 }
209
210
211 Bool
212 validate_gl_visual (FILE *out, Screen *screen, const char *window_desc,
213                     Visual *visual)
214 {
215 #ifdef HAVE_GL
216   int status;
217   int value = False;
218
219   Display *dpy = DisplayOfScreen (screen);
220   XVisualInfo vi_in, *vi_out;
221   int out_count;
222   unsigned int id;
223
224   vi_in.screen = screen_number (screen);
225   vi_in.visualid = XVisualIDFromVisual (visual);
226   vi_out = XGetVisualInfo (dpy, (VisualScreenMask | VisualIDMask),
227                              &vi_in, &out_count);
228   if (! vi_out) abort ();
229
230   status = glXGetConfig (dpy, vi_out, GLX_USE_GL, &value);
231
232   id = (unsigned int) vi_out->visualid;
233   XFree ((char *) vi_out);
234
235   if (status == GLX_NO_EXTENSION)
236     {
237       fprintf (out, "%s: display \"%s\" does not support the GLX extension.\n",
238                progname, DisplayString (dpy));
239       return False;
240     }
241   else if (status == GLX_BAD_VISUAL || value == False)
242     {
243       fprintf (out,
244                "%s: %s's visual 0x%x does not support the GLX extension.\n",
245                progname, window_desc, id);
246       return False;
247     }
248   else
249     {
250       return True;
251     }
252
253 #else  /* !HAVE_GL */
254
255   fprintf (out, "%s: GL support was not compiled in to this program.\n",
256            progname);
257   return False;
258
259 #endif  /* !HAVE_GL */
260 }