http://packetstormsecurity.org/UNIX/admin/xscreensaver-3.31.tar.gz
[xscreensaver] / hacks / glx / xlock-gl.c
1 /* xlock-gl.c --- xscreensaver compatibility layer for xlockmore GL modules.
2  * xscreensaver, Copyright (c) 1997, 1998, 1999 Jamie Zawinski <jwz@jwz.org>
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation.  No representations are made about the suitability of this
9  * software for any purpose.  It is provided "as is" without express or 
10  * implied warranty.
11  *
12  * This file, along with xlockmore.h, make it possible to compile an xlockmore
13  * GL module into a standalone program, and thus use it with xscreensaver.
14  * By Jamie Zawinski <jwz@jwz.org> on 31-May-97.
15  */
16
17 #include <stdio.h>
18 #include "screenhack.h"
19 #include "xlockmoreI.h"
20
21 #include <GL/gl.h>
22 #include <GL/glu.h>
23 #include <GL/glx.h>
24
25 /* Gag -- we use this to turn X errors from glXCreateContext() into
26    something that will actually make sense to the user.
27  */
28 static XErrorHandler orig_ehandler = 0;
29 static Bool got_error = 0;
30
31 static int
32 BadValue_ehandler (Display *dpy, XErrorEvent *error)
33 {
34   if (error->error_code == BadValue)
35     {
36       got_error = True;
37       return 0;
38     }
39   else
40     return orig_ehandler (dpy, error);
41 }
42
43
44 GLXContext *
45 init_GL(ModeInfo * mi)
46 {
47   Display *dpy = mi->dpy;
48   Window window = mi->window;
49   Screen *screen = mi->xgwa.screen;
50   Visual *visual = mi->xgwa.visual;
51   GLXContext glx_context = 0;
52   XVisualInfo vi_in, *vi_out;
53   int out_count;
54
55   vi_in.screen = screen_number (screen);
56   vi_in.visualid = XVisualIDFromVisual (visual);
57   vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
58                            &vi_in, &out_count);
59   if (! vi_out) abort ();
60
61   {
62     XSync (dpy, False);
63     orig_ehandler = XSetErrorHandler (BadValue_ehandler);
64     glx_context = glXCreateContext (dpy, vi_out, 0, GL_TRUE);
65     XSync (dpy, False);
66     XSetErrorHandler (orig_ehandler);
67     if (got_error)
68       glx_context = 0;
69   }
70
71   XFree((char *) vi_out);
72
73   if (!glx_context)
74     {
75       fprintf(stderr, "%s: couldn't create GL context for visual 0x%x.\n",
76               progname, (unsigned int) XVisualIDFromVisual (visual));
77       exit(1);
78     }
79
80   glXMakeCurrent (dpy, window, glx_context);
81
82   {
83     GLboolean rgba_mode = 0;
84     glGetBooleanv(GL_RGBA_MODE, &rgba_mode);
85     if (!rgba_mode)
86       {
87         glIndexi (WhitePixelOfScreen (screen));
88         glClearIndex (BlackPixelOfScreen (screen));
89       }
90   }
91
92   /* GLXContext is already a pointer type.
93      Why this function returns a pointer to a pointer, I have no idea...
94    */
95   {
96     GLXContext *ptr = (GLXContext *) malloc(sizeof(GLXContext));
97     *ptr = glx_context;
98     return ptr;
99   }
100 }
101
102
103 \f
104
105 /* clear away any lingering error codes */
106 void
107 clear_gl_error (void)
108 {
109   while (glGetError() != GL_NO_ERROR)
110     ;
111 }
112
113 /* report a GL error. */
114 void
115 check_gl_error (const char *type)
116 {
117   char buf[100];
118   GLenum i;
119   const char *e;
120   switch ((i = glGetError())) {
121   case GL_NO_ERROR: return;
122   case GL_INVALID_ENUM:          e = "invalid enum";      break;
123   case GL_INVALID_VALUE:         e = "invalid value";     break;
124   case GL_INVALID_OPERATION:     e = "invalid operation"; break;
125   case GL_STACK_OVERFLOW:        e = "stack overflow";    break;
126   case GL_STACK_UNDERFLOW:       e = "stack underflow";   break;
127   case GL_OUT_OF_MEMORY:         e = "out of memory";     break;
128 #ifdef GL_TABLE_TOO_LARGE_EXT
129   case GL_TABLE_TOO_LARGE_EXT:   e = "table too large";   break;
130 #endif
131 #ifdef GL_TEXTURE_TOO_LARGE_EXT
132   case GL_TEXTURE_TOO_LARGE_EXT: e = "texture too large"; break;
133 #endif
134   default:
135     e = buf; sprintf (buf, "unknown error %d", (int) i); break;
136   }
137   fprintf (stderr, "%s: %s error: %s\n", progname, type, e);
138   exit (1);
139 }