http://packetstorm.tacticalflex.com/UNIX/admin/xscreensaver-3.27.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/glx.h>
23
24 /* Gag -- we use this to turn X errors from glXCreateContext() into
25    something that will actually make sense to the user.
26  */
27 static XErrorHandler orig_ehandler = 0;
28 static Bool got_error = 0;
29
30 static int
31 BadValue_ehandler (Display *dpy, XErrorEvent *error)
32 {
33   if (error->error_code == BadValue)
34     {
35       got_error = True;
36       return 0;
37     }
38   else
39     return orig_ehandler (dpy, error);
40 }
41
42
43 GLXContext *
44 init_GL(ModeInfo * mi)
45 {
46   Display *dpy = mi->dpy;
47   Window window = mi->window;
48   Screen *screen = mi->xgwa.screen;
49   Visual *visual = mi->xgwa.visual;
50   GLXContext glx_context = 0;
51   XVisualInfo vi_in, *vi_out;
52   int out_count;
53
54   vi_in.screen = screen_number (screen);
55   vi_in.visualid = XVisualIDFromVisual (visual);
56   vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
57                            &vi_in, &out_count);
58   if (! vi_out) abort ();
59
60   {
61     XSync (dpy, False);
62     orig_ehandler = XSetErrorHandler (BadValue_ehandler);
63     glx_context = glXCreateContext (dpy, vi_out, 0, GL_TRUE);
64     XSync (dpy, False);
65     XSetErrorHandler (orig_ehandler);
66     if (got_error)
67       glx_context = 0;
68   }
69
70   XFree((char *) vi_out);
71
72   if (!glx_context)
73     {
74       fprintf(stderr, "%s: couldn't create GL context for visual 0x%x.\n",
75               progname, (unsigned int) XVisualIDFromVisual (visual));
76       exit(1);
77     }
78
79   glXMakeCurrent (dpy, window, glx_context);
80
81   {
82     GLboolean rgba_mode = 0;
83     glGetBooleanv(GL_RGBA_MODE, &rgba_mode);
84     if (!rgba_mode)
85       {
86         glIndexi (WhitePixelOfScreen (screen));
87         glClearIndex (BlackPixelOfScreen (screen));
88       }
89   }
90
91   /* GLXContext is already a pointer type.
92      Why this function returns a pointer to a pointer, I have no idea...
93    */
94   {
95     GLXContext *ptr = (GLXContext *) malloc(sizeof(GLXContext));
96     *ptr = glx_context;
97     return ptr;
98   }
99 }
100
101
102 \f
103
104 /* clear away any lingering error codes */
105 void
106 clear_gl_error (void)
107 {
108   while (glGetError() != GL_NO_ERROR)
109     ;
110 }
111
112 /* report a GL error. */
113 void
114 check_gl_error (const char *type)
115 {
116   char buf[100];
117   GLenum i;
118   const char *e;
119   switch ((i = glGetError())) {
120   case GL_NO_ERROR: return;
121   case GL_INVALID_ENUM:          e = "invalid enum";      break;
122   case GL_INVALID_VALUE:         e = "invalid value";     break;
123   case GL_INVALID_OPERATION:     e = "invalid operation"; break;
124   case GL_STACK_OVERFLOW:        e = "stack overflow";    break;
125   case GL_STACK_UNDERFLOW:       e = "stack underflow";   break;
126   case GL_OUT_OF_MEMORY:         e = "out of memory";     break;
127 #ifdef GL_TABLE_TOO_LARGE_EXT
128   case GL_TABLE_TOO_LARGE_EXT:   e = "table too large";   break;
129 #endif
130 #ifdef GL_TEXTURE_TOO_LARGE_EXT
131   case GL_TEXTURE_TOO_LARGE_EXT: e = "texture too large"; break;
132 #endif
133   default:
134     e = buf; sprintf (buf, "unknown error %d", (int) i); break;
135   }
136   fprintf (stderr, "%s: %s error: %s\n", progname, type, e);
137   exit (1);
138 }