weston/clients/wscreensaver-glue.c

150 lines
3.5 KiB
C

/*
* Copyright © 2011 Collabora, Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE 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);
}