summaryrefslogtreecommitdiff
path: root/clients/wscreensaver-glue.c
diff options
context:
space:
mode:
Diffstat (limited to 'clients/wscreensaver-glue.c')
-rw-r--r--clients/wscreensaver-glue.c148
1 files changed, 148 insertions, 0 deletions
diff --git a/clients/wscreensaver-glue.c b/clients/wscreensaver-glue.c
new file mode 100644
index 00000000..55d0a8c7
--- /dev/null
+++ b/clients/wscreensaver-glue.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright © 2011 Collabora, Ltd.
+ *
+ * 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, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include "wscreensaver-glue.h"
+
+double frand(double f)
+{
+ double r = random();
+ return r * f / (double)RAND_MAX;
+}
+
+void clear_gl_error(void)
+{
+ while (glGetError() != GL_NO_ERROR)
+ ;
+}
+
+void check_gl_error(const char *msg)
+{
+ const char *emsg;
+ int err = glGetError();
+
+ switch (err)
+ {
+ case GL_NO_ERROR:
+ return;
+
+ #define ERR(tok) case tok: emsg = #tok; break;
+ ERR(GL_INVALID_ENUM)
+ ERR(GL_INVALID_VALUE)
+ ERR(GL_INVALID_OPERATION)
+ ERR(GL_STACK_OVERFLOW)
+ ERR(GL_STACK_UNDERFLOW)
+ ERR(GL_OUT_OF_MEMORY)
+ #undef ERR
+
+ default:
+ fprintf(stderr, "%s: %s: unknown GL error 0x%04x\n",
+ progname, msg, err);
+ exit(1);
+ }
+
+ fprintf(stderr, "%s: %s: GL error %s\n", progname, msg, emsg);
+ exit(1);
+}
+
+static void
+read_xpm_color(uint32_t *ctable, const char *line)
+{
+ unsigned char key;
+ char cstr[10];
+ char *end;
+ uint32_t value;
+
+ if (sscanf(line, "%1c c %9s", &key, cstr) < 2) {
+ fprintf(stderr, "%s: error in XPM color definition '%s'\n",
+ progname, line);
+ return;
+ }
+
+ value = strtol(&cstr[1], &end, 16);
+
+ if (strcmp(cstr, "None") == 0)
+ ctable[key] = 0x00000000;
+ else if (cstr[0] != '#' || !(cstr[1] != '\0' && *end == '\0')) {
+ fprintf(stderr, "%s: error interpreting XPM color '%s'\n",
+ progname, cstr);
+ return;
+ } else {
+ ctable[key] = value | 0xff000000;
+ }
+}
+
+static void
+read_xpm_row(char *data, const char *line, uint32_t *ctable, int width)
+{
+ uint32_t *pixel = (uint32_t *)data;
+ uint8_t *p = (uint8_t *)line;
+ int i;
+
+ for (i = 0; i < width; ++i)
+ pixel[i] = ctable[p[i]];
+}
+
+XImage *xpm_to_ximage(char **xpm_data)
+{
+ XImage *xi;
+ int colors;
+ int cpp;
+ int i;
+ uint32_t ctable[256] = { 0 };
+
+ xi = malloc(sizeof *xi);
+ if (!xi)
+ return NULL;
+ xi->data = NULL;
+
+ if (sscanf(xpm_data[0], "%d %d %d %d", &xi->width,
+ &xi->height, &colors, &cpp) < 4)
+ goto errout;
+
+ if (xi->width < 1 || xi->height < 1 || cpp != 1)
+ goto errout;
+
+ xi->bytes_per_line = xi->width * sizeof(uint32_t);
+ xi->data = malloc(xi->height * xi->bytes_per_line);
+ if (!xi->data)
+ goto errout;
+
+ for (i = 0; i < colors; ++i)
+ read_xpm_color(ctable, xpm_data[i + 1]);
+
+ for (i = 0; i < xi->height; ++i)
+ read_xpm_row(xi->data + i * xi->bytes_per_line,
+ xpm_data[i + colors + 1], ctable, xi->width);
+
+ return xi;
+
+errout:
+ fprintf(stderr, "%s: error processing XPM data.\n", progname);
+ XDestroyImage(xi);
+ return NULL;
+}
+
+void XDestroyImage(XImage *xi)
+{
+ free(xi->data);
+ free(xi);
+}