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