From d3a98cf6cbc3bd0b9efc570f58e8812c03931c18 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Tue, 16 Oct 2018 10:08:48 +0200 Subject: Original 5.40 --- hacks/glx/xlock-gl-utils.c | 230 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 230 insertions(+) create mode 100644 hacks/glx/xlock-gl-utils.c (limited to 'hacks/glx/xlock-gl-utils.c') diff --git a/hacks/glx/xlock-gl-utils.c b/hacks/glx/xlock-gl-utils.c new file mode 100644 index 0000000..36d724c --- /dev/null +++ b/hacks/glx/xlock-gl-utils.c @@ -0,0 +1,230 @@ +/* xlock-gl.c --- xscreensaver compatibility layer for xlockmore GL modules. + * xscreensaver, Copyright (c) 1997-2015 Jamie Zawinski + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation. No representations are made about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * This file, along with xlockmore.h, make it possible to compile an xlockmore + * GL module into a standalone program, and thus use it with xscreensaver. + * By Jamie Zawinski on 31-May-97. + */ + +#include +#include "xlockmoreI.h" +#include "texfont.h" + +#ifndef isupper +# define isupper(c) ((c) >= 'A' && (c) <= 'Z') +#endif +#ifndef _tolower +# define _tolower(c) ((c) - 'A' + 'a') +#endif + + +/* Gag -- we use this to turn X errors from glXCreateContext() into + something that will actually make sense to the user. + */ +static XErrorHandler orig_ehandler = 0; +static Bool got_error = 0; + +static int +BadValue_ehandler (Display *dpy, XErrorEvent *error) +{ + if (error->error_code == BadValue) + { + got_error = True; + return 0; + } + else + return orig_ehandler (dpy, error); +} + + +GLXContext * +init_GL(ModeInfo * mi) +{ + Display *dpy = mi->dpy; + Window window = mi->window; + Screen *screen = mi->xgwa.screen; + Visual *visual = mi->xgwa.visual; + XVisualInfo vi_in, *vi_out; + int out_count; + + if (mi->glx_context) { + glXMakeCurrent (dpy, window, mi->glx_context); + return &mi->glx_context; + } + +# ifdef HAVE_JWZGLES + jwzgles_make_current(jwzgles_make_state(state)); +# endif + + vi_in.screen = screen_number (screen); + vi_in.visualid = XVisualIDFromVisual (visual); + vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask, + &vi_in, &out_count); + if (! vi_out) abort (); + + { + XSync (dpy, False); + orig_ehandler = XSetErrorHandler (BadValue_ehandler); + mi->glx_context = glXCreateContext (dpy, vi_out, 0, GL_TRUE); + XSync (dpy, False); + XSetErrorHandler (orig_ehandler); + if (got_error) + mi->glx_context = 0; + } + + XFree((char *) vi_out); + + if (!mi->glx_context) + { + fprintf(stderr, "%s: couldn't create GL context for visual 0x%x.\n", + progname, (unsigned int) XVisualIDFromVisual (visual)); + exit(1); + } + + glXMakeCurrent (dpy, window, mi->glx_context); + + { + GLboolean rgba_mode = 0; + glGetBooleanv(GL_RGBA_MODE, &rgba_mode); + if (!rgba_mode) + { + glIndexi (WhitePixelOfScreen (screen)); + glClearIndex (BlackPixelOfScreen (screen)); + } + } + + + /* 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); + } + + /* Sometimes glDrawBuffer() throws "invalid op". Dunno why. Ignore. */ + clear_gl_error (); + + /* Process the -background argument. */ + { + char *s = get_string_resource(mi->dpy, "background", "Background"); + XColor c = { 0, }; + if (! XParseColor (dpy, mi->xgwa.colormap, s, &c)) + fprintf (stderr, "%s: can't parse color %s; using black.\n", + progname, s); + glClearColor (c.red / 65535.0, + c.green / 65535.0, + c.blue / 65535.0, + 1.0); + } + + glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + /* GLXContext is already a pointer type. + Why this function returns a pointer to a pointer, I have no idea... + */ + return &mi->glx_context; +} + + + +/* clear away any lingering error codes */ +void +clear_gl_error (void) +{ + while (glGetError() != GL_NO_ERROR) + ; +} + +/* 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_INVALID_FRAMEBUFFER_OPERATION + case GL_INVALID_FRAMEBUFFER_OPERATION: + e = "invalid framebuffer operation"; + break; +#endif +#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); +} + + +/* Callback in xscreensaver_function_table, via xlockmore.c. + */ +Visual * +xlockmore_pick_gl_visual (Screen *screen) +{ + /* pick the "best" visual by interrogating the GL library instead of + by asking Xlib. GL knows better. + */ + Visual *v = 0; + Display *dpy = DisplayOfScreen (screen); + char *string = get_string_resource (dpy, "visualID", "VisualID"); + char *s; + + if (string) + for (s = string; *s; s++) + if (isupper (*s)) *s = _tolower (*s); + + if (!string || !*string || + !strcmp (string, "gl") || + !strcmp (string, "best") || + !strcmp (string, "color") || + !strcmp (string, "default")) + v = get_gl_visual (screen); /* from ../utils/visual-gl.c */ + + if (string) + free (string); + + return v; +} + + +/* Callback in xscreensaver_function_table, via xlockmore.c. + */ +Bool +xlockmore_validate_gl_visual (Screen *screen, const char *name, Visual *visual) +{ + return validate_gl_visual (stderr, screen, name, visual); +} -- cgit v1.2.3-55-g7522