-/* xlock-gc.c --- xscreensaver compatibility layer for xlockmore GL modules.
- * xscreensaver, Copyright (c) 1997, 1998 Jamie Zawinski <jwz@jwz.org>
+/* xlock-gl.c --- xscreensaver compatibility layer for xlockmore GL modules.
+ * xscreensaver, Copyright (c) 1997-2002 Jamie Zawinski <jwz@jwz.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
#include "xlockmoreI.h"
#include <GL/gl.h>
+#include <GL/glu.h>
#include <GL/glx.h>
/* Gag -- we use this to turn X errors from glXCreateContext() into
}
}
+
+ /* jwz: the doc for glDrawBuffer says "The initial value is GL_FRONT
+ for single-buffered contexts, and GL_BACK for double-buffered
+ contexts." However, I find that this is not always the case,
+ at least with Mesa 3.4.2 -- sometimes the default seems to be
+ GL_FRONT even when glGet(GL_DOUBLEBUFFER) is true. So, let's
+ make sure.
+
+ Oh, hmm -- maybe this only happens when we are re-using the
+ xscreensaver window, and the previous GL hack happened to die with
+ the other buffer selected? I'm not sure. Anyway, this fixes it.
+ */
+ {
+ GLboolean d = False;
+ glGetBooleanv (GL_DOUBLEBUFFER, &d);
+ if (d)
+ glDrawBuffer (GL_BACK);
+ else
+ glDrawBuffer (GL_FRONT);
+ }
+
+
/* GLXContext is already a pointer type.
Why this function returns a pointer to a pointer, I have no idea...
*/
}
-Visual *
-get_gl_visual (Screen *screen, char *name, char *class)
-{
- char *string = get_string_resource (name, class);
- XVisualInfo *vi = 0;
- Bool done_once = False;
-
- AGAIN:
- if (!string || !*string ||
- !strcmp (string, "best") ||
- !strcmp (string, "color") ||
- !strcmp (string, "default"))
- {
- Display *dpy = DisplayOfScreen (screen);
- int screen_num = screen_number (screen);
- int attrs[20];
- int i = 0;
- Bool dbuf_p = !get_boolean_resource ("noBuffer", "NoBuffer");
-
- done_once = True;
-
- attrs[i++] = GLX_RGBA;
- attrs[i++] = GLX_RED_SIZE; attrs[i++] = 1;
- attrs[i++] = GLX_GREEN_SIZE; attrs[i++] = 1;
- attrs[i++] = GLX_BLUE_SIZE; attrs[i++] = 1;
- attrs[i++] = GLX_DEPTH_SIZE; attrs[i++] = 1;
- if (dbuf_p)
- attrs[i++] = GLX_DOUBLEBUFFER;
- attrs[i++] = 0;
-
- vi = glXChooseVisual (dpy, screen_num, attrs);
- if (vi) goto DONE;
-
- /* Try without double-buffering. */
- attrs[i - 1] = 0;
- vi = glXChooseVisual (dpy, screen_num, attrs);
- if (vi) goto DONE;
-
- /* Try mono. */
- i = 0;
- if (dbuf_p)
- attrs[i++] = GLX_DOUBLEBUFFER;
- attrs[i++] = 0;
- vi = glXChooseVisual (dpy, screen_num, attrs);
- if (vi) goto DONE;
-
- /* Try mono without double-buffering. */
- attrs[0] = 0;
- vi = glXChooseVisual (dpy, screen_num, attrs);
- }
+\f
- DONE:
- {
- Visual *v;
- if (vi)
- {
- v = vi->visual;
- XFree (vi);
- }
- else
- {
- v = get_visual (screen, string, False, True);
- if (!v)
- {
- if (done_once)
- v = DefaultVisualOfScreen (screen);
- else
- {
- free (string);
- string = 0;
- goto AGAIN;
- }
- }
- }
+/* clear away any lingering error codes */
+void
+clear_gl_error (void)
+{
+ while (glGetError() != GL_NO_ERROR)
+ ;
+}
- free (string);
- return v;
+/* report a GL error. */
+void
+check_gl_error (const char *type)
+{
+ char buf[100];
+ GLenum i;
+ const char *e;
+ switch ((i = glGetError())) {
+ case GL_NO_ERROR: return;
+ case GL_INVALID_ENUM: e = "invalid enum"; break;
+ case GL_INVALID_VALUE: e = "invalid value"; break;
+ case GL_INVALID_OPERATION: e = "invalid operation"; break;
+ case GL_STACK_OVERFLOW: e = "stack overflow"; break;
+ case GL_STACK_UNDERFLOW: e = "stack underflow"; break;
+ case GL_OUT_OF_MEMORY: e = "out of memory"; break;
+#ifdef GL_TABLE_TOO_LARGE_EXT
+ case GL_TABLE_TOO_LARGE_EXT: e = "table too large"; break;
+#endif
+#ifdef GL_TEXTURE_TOO_LARGE_EXT
+ case GL_TEXTURE_TOO_LARGE_EXT: e = "texture too large"; break;
+#endif
+ default:
+ e = buf; sprintf (buf, "unknown error %d", (int) i); break;
}
+ fprintf (stderr, "%s: %s error: %s\n", progname, type, e);
+ exit (1);
}