http://packetstorm.tacticalflex.com/UNIX/admin/xscreensaver-3.27.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
46   int attrs[][20] = {
47    { GLX_RGBA, R, 8, G, 8, B, 8, D, 8, GLX_DOUBLEBUFFER, 0 }, /* rgb double */
48    { GLX_RGBA, R, 4, G, 4, B, 4, D, 4, GLX_DOUBLEBUFFER, 0 },
49    { GLX_RGBA, R, 2, G, 2, B, 2, D, 2, GLX_DOUBLEBUFFER, 0 },
50    { GLX_RGBA, R, 8, G, 8, B, 8, D, 8,                   0 }, /* rgb single */
51    { GLX_RGBA, R, 4, G, 4, B, 4, D, 4,                   0 },
52    { GLX_RGBA, R, 2, G, 2, B, 2, D, 2,                   0 },
53    { I, 8,                       D, 8, GLX_DOUBLEBUFFER, 0 }, /* cmap double */
54    { I, 4,                       D, 4, GLX_DOUBLEBUFFER, 0 },
55    { I, 8,                       D, 8,                   0 }, /* cmap single */
56    { I, 4,                       D, 4,                   0 },
57    { GLX_RGBA, R, 1, G, 1, B, 1, D, 1,                   0 }  /* monochrome */
58   };
59
60   int i;
61   for (i = 0; i < sizeof(attrs)/sizeof(*attrs); i++)
62     {
63       XVisualInfo *vi = glXChooseVisual (dpy, screen_num, attrs[i]);
64       if (vi)
65         {
66           Visual *v = vi->visual;
67           XFree (vi);
68           /* describe_gl_visual (stderr, screen, v, False); */
69           return v;
70         }
71     }
72 #endif /* !HAVE_GL */
73
74   return 0;
75 }
76
77
78 void
79 describe_gl_visual (FILE *f, Screen *screen, Visual *visual,
80                     Bool private_cmap_p)
81 {
82   describe_visual (f, screen, visual, private_cmap_p);
83
84 #ifdef HAVE_GL
85   {
86     int status;
87     int value = False;
88
89     Display *dpy = DisplayOfScreen (screen);
90     XVisualInfo vi_in, *vi_out;
91     int out_count;
92
93     vi_in.screen = screen_number (screen);
94     vi_in.visualid = XVisualIDFromVisual (visual);
95     vi_out = XGetVisualInfo (dpy, (VisualScreenMask | VisualIDMask),
96                              &vi_in, &out_count);
97     if (! vi_out) abort ();
98
99     status = glXGetConfig (dpy, vi_out, GLX_USE_GL, &value);
100
101     if (status == GLX_NO_EXTENSION)
102       /* dpy does not support the GLX extension. */
103       return;
104
105     if (status == GLX_BAD_VISUAL || value == False)
106       /* this visual does not support GLX. */
107       return;
108     
109     if (!glXGetConfig (dpy, vi_out, GLX_LEVEL, &value) &&
110         value != 0)
111       printf ("    GLX level:         %d\n", value);
112
113     if (!glXGetConfig (dpy, vi_out, GLX_RGBA, &value) && value)
114       {
115         int r=0, g=0, b=0, a=0;
116         glXGetConfig (dpy, vi_out, GLX_RED_SIZE,   &r);
117         glXGetConfig (dpy, vi_out, GLX_GREEN_SIZE, &g);
118         glXGetConfig (dpy, vi_out, GLX_BLUE_SIZE,  &b);
119         glXGetConfig (dpy, vi_out, GLX_ALPHA_SIZE, &a);
120         printf ("    GLX type:          RGBA (%2d, %2d, %2d, %2d)\n",
121                 r, g, b, a);
122
123         r=0, g=0, b=0, a=0;
124         glXGetConfig (dpy, vi_out, GLX_ACCUM_RED_SIZE,   &r);
125         glXGetConfig (dpy, vi_out, GLX_ACCUM_GREEN_SIZE, &g);
126         glXGetConfig (dpy, vi_out, GLX_ACCUM_BLUE_SIZE,  &b);
127         glXGetConfig (dpy, vi_out, GLX_ACCUM_ALPHA_SIZE, &a);
128         printf ("    GLX accum:         RGBA (%2d, %2d, %2d, %2d)\n",
129                 r, g, b, a);
130       }
131     else
132       {
133         value = 0;
134         glXGetConfig (dpy, vi_out, GLX_BUFFER_SIZE, &value);
135         printf ("    GLX type:          indexed (%d)\n", value);
136       }
137
138 # ifdef GLX_VISUAL_CAVEAT_EXT
139     if (!glXGetConfig (dpy, vi_out, GLX_VISUAL_CAVEAT_EXT, &value) &&
140         value != GLX_NONE_EXT)
141       printf ("    GLX rating:        %s\n",
142               (value == GLX_NONE_EXT ? "none" :
143                value == GLX_SLOW_VISUAL_EXT ? "slow" :
144 #   ifdef GLX_NON_CONFORMANT_EXT
145                value == GLX_NON_CONFORMANT_EXT ? "non-conformant" :
146 #   endif /* GLX_NON_CONFORMANT_EXT */
147                "???"));
148 # endif /* GLX_VISUAL_CAVEAT_EXT */
149
150     if (!glXGetConfig (dpy, vi_out, GLX_DOUBLEBUFFER, &value))
151       printf ("    GLX double-buffer: %s\n", (value ? "yes" : "no"));
152
153     if (!glXGetConfig (dpy, vi_out, GLX_STEREO, &value) &&
154         value)
155       printf ("    GLX stereo:        %s\n", (value ? "yes" : "no"));
156
157     if (!glXGetConfig (dpy, vi_out, GLX_AUX_BUFFERS, &value) &&
158         value != 0)
159       printf ("    GLX aux buffers:   %d\n", value);
160
161     if (!glXGetConfig (dpy, vi_out, GLX_DEPTH_SIZE, &value))
162       printf ("    GLX depth size:    %d\n", value);
163
164     if (!glXGetConfig (dpy, vi_out, GLX_STENCIL_SIZE, &value) &&
165         value != 0)
166       printf ("    GLX stencil size:  %d\n", value);
167
168 # ifdef GLX_SAMPLE_BUFFERS_SGIS
169     if (!glXGetConfig (dpy, vi_out, GLX_SAMPLE_BUFFERS_SGIS, &value) &&
170         value != 0)
171       {
172         int bufs = value;
173         if (!glXGetConfig (dpy, vi_out, GLX_SAMPLES_SGIS, &value))
174           printf ("    GLX multisamplers: %d (%d)\n", bufs, value);
175       }
176 # endif /* GLX_SAMPLE_BUFFERS_SGIS */
177
178     if (!glXGetConfig (dpy, vi_out, GLX_TRANSPARENT_TYPE_EXT, &value) &&
179         value != GLX_NONE_EXT)
180       {
181         if (value == GLX_NONE_EXT)
182           printf ("    GLX transparency:  none\n");
183         else if (value == GLX_TRANSPARENT_INDEX_EXT)
184           {
185             if (!glXGetConfig (dpy, vi_out, GLX_TRANSPARENT_INDEX_VALUE_EXT,
186                                &value))
187               printf ("    GLX transparency:  indexed (%d)\n", value);
188           }
189         else if (value == GLX_TRANSPARENT_RGB_EXT)
190           {
191             int r=0, g=0, b=0, a=0;
192             glXGetConfig (dpy, vi_out, GLX_TRANSPARENT_RED_VALUE_EXT,   &r);
193             glXGetConfig (dpy, vi_out, GLX_TRANSPARENT_GREEN_VALUE_EXT, &g);
194             glXGetConfig (dpy, vi_out, GLX_TRANSPARENT_BLUE_VALUE_EXT,  &b);
195             glXGetConfig (dpy, vi_out, GLX_TRANSPARENT_ALPHA_VALUE_EXT, &a);
196             printf ("    GLX transparency:  RGBA (%2d, %2d, %2d, %2d)\n",
197                     r, g, b, a);
198           }
199       }
200   }
201 #endif  /* HAVE_GL */
202 }
203
204
205 Bool
206 validate_gl_visual (FILE *out, Screen *screen, const char *window_desc,
207                     Visual *visual)
208 {
209 #ifdef HAVE_GL
210   int status;
211   int value = False;
212
213   Display *dpy = DisplayOfScreen (screen);
214   XVisualInfo vi_in, *vi_out;
215   int out_count;
216   unsigned int id;
217
218   vi_in.screen = screen_number (screen);
219   vi_in.visualid = XVisualIDFromVisual (visual);
220   vi_out = XGetVisualInfo (dpy, (VisualScreenMask | VisualIDMask),
221                              &vi_in, &out_count);
222   if (! vi_out) abort ();
223
224   status = glXGetConfig (dpy, vi_out, GLX_USE_GL, &value);
225
226   id = (unsigned int) vi_out->visualid;
227   XFree ((char *) vi_out);
228
229   if (status == GLX_NO_EXTENSION)
230     {
231       fprintf (out, "%s: display \"%s\" does not support the GLX extension.\n",
232                progname, DisplayString (dpy));
233       return False;
234     }
235   else if (status == GLX_BAD_VISUAL || value == False)
236     {
237       fprintf (out,
238                "%s: %s's visual 0x%x does not support the GLX extension.\n",
239                progname, window_desc, id);
240       return False;
241     }
242   else
243     {
244       return True;
245     }
246
247 #else  /* !HAVE_GL */
248
249   fprintf (out, "%s: GL support was not compiled in to this program.\n",
250            progname);
251   return False;
252
253 #endif  /* !HAVE_GL */
254 }