Implement all the required support code for running glmatrix.c. Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>dev
parent
8260f460d7
commit
11f53f56db
@ -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] = 0x00ffffff; |
||||
else if (cstr[0] != '#' || !(cstr[1] != '\0' && *end == '\0')) { |
||||
fprintf(stderr, "%s: error interpreting XPM color '%s'\n", |
||||
progname, cstr); |
||||
return; |
||||
} |
||||
|
||||
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); |
||||
} |
@ -0,0 +1,121 @@ |
||||
/*
|
||||
* 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. |
||||
*/ |
||||
|
||||
#ifndef WSCREENSAVER_GLUE_H |
||||
#define WSCREENSAVER_GLUE_H |
||||
|
||||
/*
|
||||
* This file is glue, that tries to avoid changing glmatrix.c from the |
||||
* original too much, hopefully easing the porting of other (GL) |
||||
* xscreensaver "hacks". |
||||
*/ |
||||
|
||||
#include "wscreensaver.h" |
||||
|
||||
#include <stdbool.h> |
||||
#include <string.h> |
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
#include <stdint.h> |
||||
#include <time.h> |
||||
#include <math.h> |
||||
#include <assert.h> |
||||
|
||||
#include <GL/gl.h> |
||||
#include <GL/glu.h> |
||||
|
||||
#include "wayland-util.h" |
||||
#include "window.h" |
||||
|
||||
#define ENTRYPOINT static |
||||
|
||||
typedef bool Bool; |
||||
#define True true |
||||
#define False false |
||||
|
||||
typedef struct ModeInfo ModeInfo; |
||||
|
||||
#define MI_DISPLAY(mi) NULL |
||||
#define MI_WINDOW(mi) (mi) |
||||
#define MI_SCREEN(mi) ((mi)->instance_number) |
||||
#define MI_WIDTH(mi) ((mi)->width) |
||||
#define MI_HEIGHT(mi) ((mi)->height) |
||||
#define MI_IS_WIREFRAME(mi) 0 |
||||
#define MI_NUM_SCREENS(mi) 16 |
||||
|
||||
typedef EGLContext GLXContext; |
||||
|
||||
double frand(double f); |
||||
void clear_gl_error(void); |
||||
void check_gl_error(const char *msg); |
||||
|
||||
static inline void |
||||
glXMakeCurrent(void *dummy, ModeInfo *mi, EGLContext ctx) |
||||
{ |
||||
assert(mi->eglctx == ctx); |
||||
} |
||||
|
||||
static inline void |
||||
glXSwapBuffers(void *dummy, ModeInfo *mi) |
||||
{ |
||||
mi->swap_buffers = 1; |
||||
} |
||||
|
||||
static inline void |
||||
do_fps(ModeInfo *mi) |
||||
{ |
||||
} |
||||
|
||||
/* just enough XImage to satisfy glmatrix.c */ |
||||
|
||||
typedef struct _XImage { |
||||
int width; |
||||
int height; |
||||
char *data; |
||||
int bytes_per_line; |
||||
} XImage; |
||||
|
||||
XImage *xpm_to_ximage(char **xpm_data); |
||||
void XDestroyImage(XImage *xi); |
||||
|
||||
static inline unsigned long |
||||
XGetPixel(XImage *xi, int x, int y) |
||||
{ |
||||
return *(uint32_t *)(xi->data + xi->bytes_per_line * y + 4 * x); |
||||
} |
||||
|
||||
static inline void |
||||
XPutPixel(XImage *xi, int x, int y, unsigned long pixel) |
||||
{ |
||||
*(uint32_t *)(xi->data + xi->bytes_per_line * y + 4 * x) = pixel; |
||||
} |
||||
|
||||
/*
|
||||
* override glViewport from the plugin, so we can set it up properly |
||||
* rendering to a regular decorated Wayland window. |
||||
*/ |
||||
#ifdef glViewport |
||||
#undef glViewport |
||||
#endif |
||||
#define glViewport(x,y,w,h) do {} while (0) |
||||
|
||||
#endif /* WSCREENSAVER_GLUE_H */ |
@ -0,0 +1,275 @@ |
||||
/*
|
||||
* 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 "config.h" |
||||
|
||||
#include "wscreensaver.h" |
||||
|
||||
#include <stdlib.h> |
||||
#include <stdio.h> |
||||
#include <string.h> |
||||
#include <sys/time.h> |
||||
|
||||
#include <GL/gl.h> |
||||
#include <EGL/eglext.h> |
||||
|
||||
#include "wayland-util.h" |
||||
#include "wayland-client.h" |
||||
|
||||
#include "window.h" |
||||
|
||||
extern struct wscreensaver_plugin glmatrix_screensaver; |
||||
|
||||
static const struct wscreensaver_plugin * const plugins[] = { |
||||
&glmatrix_screensaver, |
||||
NULL |
||||
}; |
||||
|
||||
const char *progname = NULL; |
||||
|
||||
struct wscreensaver { |
||||
struct display *display; |
||||
|
||||
/* per output, if fullscreen mode */ |
||||
struct ModeInfo *modeinfo; |
||||
|
||||
struct { |
||||
EGLDisplay display; |
||||
EGLConfig config; |
||||
} egl; |
||||
|
||||
const struct wscreensaver_plugin *plugin; |
||||
}; |
||||
|
||||
static void |
||||
draw_instance(struct ModeInfo *mi) |
||||
{ |
||||
struct wscreensaver *wscr = mi->priv; |
||||
struct rectangle drawarea; |
||||
struct rectangle winarea; |
||||
int bottom; |
||||
|
||||
mi->swap_buffers = 0; |
||||
|
||||
window_draw(mi->window); |
||||
|
||||
window_get_child_allocation(mi->window, &drawarea); |
||||
window_get_allocation(mi->window, &winarea); |
||||
|
||||
if (display_acquire_window_surface(wscr->display, |
||||
mi->window, |
||||
mi->eglctx) < 0) { |
||||
fprintf(stderr, "%s: unable to acquire window surface", |
||||
progname); |
||||
return; |
||||
} |
||||
|
||||
bottom = winarea.height - (drawarea.height + drawarea.y); |
||||
glViewport(drawarea.x, bottom, drawarea.width, drawarea.height); |
||||
glScissor(drawarea.x, bottom, drawarea.width, drawarea.height); |
||||
glEnable(GL_SCISSOR_TEST); |
||||
|
||||
if (mi->width != drawarea.width || mi->height != drawarea.height) { |
||||
mi->width = drawarea.width; |
||||
mi->height = drawarea.height; |
||||
wscr->plugin->reshape(mi, mi->width, mi->height); |
||||
} |
||||
|
||||
wscr->plugin->draw(mi); |
||||
|
||||
if (mi->swap_buffers == 0) |
||||
fprintf(stderr, "%s: swapBuffers not called\n", progname); |
||||
|
||||
display_release_window_surface(wscr->display, mi->window); |
||||
window_flush(mi->window); |
||||
} |
||||
|
||||
static void |
||||
frame_callback(void *data, struct wl_callback *callback, uint32_t time) |
||||
{ |
||||
struct ModeInfo *mi = data; |
||||
static const struct wl_callback_listener listener = { |
||||
frame_callback |
||||
}; |
||||
|
||||
draw_instance(mi); |
||||
|
||||
if (callback) |
||||
wl_callback_destroy(callback); |
||||
|
||||
callback = wl_surface_frame(window_get_wl_surface(mi->window)); |
||||
wl_callback_add_listener(callback, &listener, mi); |
||||
} |
||||
|
||||
static void |
||||
init_frand(void) |
||||
{ |
||||
struct timeval tv; |
||||
gettimeofday(&tv, NULL); |
||||
srandom(tv.tv_sec * 100 + tv.tv_usec / 10000); |
||||
} |
||||
|
||||
WL_EXPORT EGLContext * |
||||
init_GL(struct ModeInfo *mi) |
||||
{ |
||||
struct wscreensaver *wscr = mi->priv; |
||||
EGLContext *pctx; |
||||
|
||||
pctx = malloc(sizeof *pctx); |
||||
if (!pctx) |
||||
return NULL; |
||||
|
||||
if (mi->eglctx != EGL_NO_CONTEXT) { |
||||
fprintf(stderr, "%s: multiple GL contexts are not supported", |
||||
progname); |
||||
goto errout; |
||||
} |
||||
|
||||
mi->eglctx = eglCreateContext(wscr->egl.display, wscr->egl.config, |
||||
EGL_NO_CONTEXT, NULL); |
||||
if (mi->eglctx == EGL_NO_CONTEXT) { |
||||
fprintf(stderr, "%s: init_GL failed to create EGL context\n", |
||||
progname); |
||||
goto errout; |
||||
} |
||||
|
||||
if (!eglMakeCurrent(wscr->egl.display, NULL, NULL, mi->eglctx)) { |
||||
fprintf(stderr, "%s: init_GL failed on eglMakeCurrent\n", |
||||
progname); |
||||
goto errout; |
||||
} |
||||
|
||||
glClearColor(0.0, 0.0, 0.0, 1.0); |
||||
|
||||
*pctx = mi->eglctx; |
||||
return pctx; |
||||
|
||||
errout: |
||||
free(pctx); |
||||
return NULL; |
||||
} |
||||
|
||||
static struct ModeInfo * |
||||
create_modeinfo(struct wscreensaver *wscr, struct window *window) |
||||
{ |
||||
struct ModeInfo *mi; |
||||
struct rectangle drawarea; |
||||
|
||||
mi = calloc(1, sizeof *mi); |
||||
if (!mi) |
||||
return NULL; |
||||
|
||||
window_get_child_allocation(window, &drawarea); |
||||
|
||||
mi->priv = wscr; |
||||
mi->eglctx = EGL_NO_CONTEXT; |
||||
|
||||
mi->window = window; |
||||
|
||||
mi->instance_number = 0; /* XXX */ |
||||
mi->width = drawarea.width; |
||||
mi->height = drawarea.height; |
||||
|
||||
return mi; |
||||
} |
||||
|
||||
static struct ModeInfo * |
||||
create_wscreensaver_instance(struct wscreensaver *wscr) |
||||
{ |
||||
struct ModeInfo *mi; |
||||
struct window *window; |
||||
|
||||
window = window_create(wscr->display, 400, 300); |
||||
if (!window) { |
||||
fprintf(stderr, "%s: creating a window failed.\n", progname); |
||||
return NULL; |
||||
} |
||||
|
||||
window_set_transparent(window, 0); |
||||
window_set_title(window, progname); |
||||
|
||||
mi = create_modeinfo(wscr, window); |
||||
if (!mi) |
||||
return NULL; |
||||
|
||||
wscr->plugin->init(mi); |
||||
|
||||
frame_callback(mi, NULL, 0); |
||||
return mi; |
||||
} |
||||
|
||||
/* returns error message, or NULL if success */ |
||||
static const char * |
||||
init_wscreensaver(struct wscreensaver *wscr, struct display *display) |
||||
{ |
||||
int size; |
||||
const char prefix[] = "wscreensaver::"; |
||||
char *str; |
||||
|
||||
wscr->display = display; |
||||
wscr->plugin = plugins[0]; |
||||
|
||||
size = sizeof(prefix) + strlen(wscr->plugin->name); |
||||
str = malloc(size); |
||||
if (!str) |
||||
return "out of memory"; |
||||
snprintf(str, size, "%s%s", prefix, wscr->plugin->name); |
||||
progname = str; |
||||
|
||||
wscr->egl.display = display_get_egl_display(wscr->display); |
||||
if (!wscr->egl.display) |
||||
return "no EGL display"; |
||||
|
||||
eglBindAPI(EGL_OPENGL_API); |
||||
wscr->egl.config = display_get_rgb_egl_config(wscr->display); |
||||
|
||||
wscr->modeinfo = create_wscreensaver_instance(wscr); |
||||
|
||||
return NULL; |
||||
} |
||||
|
||||
int main(int argc, char *argv[]) |
||||
{ |
||||
struct display *d; |
||||
struct wscreensaver wscr = { 0 }; |
||||
const char *msg; |
||||
|
||||
init_frand(); |
||||
|
||||
d = display_create(&argc, &argv, NULL); |
||||
if (d == NULL) { |
||||
fprintf(stderr, "failed to create display: %m\n"); |
||||
return EXIT_FAILURE; |
||||
} |
||||
|
||||
msg = init_wscreensaver(&wscr, d); |
||||
if (msg) { |
||||
fprintf(stderr, "wscreensaver init failed: %s\n", msg); |
||||
return EXIT_FAILURE; |
||||
} |
||||
|
||||
display_run(d); |
||||
|
||||
free((void *)progname); |
||||
|
||||
return EXIT_SUCCESS; |
||||
} |
@ -0,0 +1,60 @@ |
||||
/*
|
||||
* 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. |
||||
*/ |
||||
|
||||
#ifndef WSCREENSAVER_H |
||||
#define WSCREENSAVER_H |
||||
|
||||
#define MESA_EGL_NO_X11_HEADERS |
||||
#include <EGL/egl.h> |
||||
|
||||
extern const char *progname; |
||||
|
||||
struct wscreensaver; |
||||
|
||||
struct ModeInfo { |
||||
struct wscreensaver *priv; |
||||
EGLContext eglctx; |
||||
int swap_buffers; |
||||
|
||||
struct window *window; |
||||
|
||||
int instance_number; |
||||
unsigned width; |
||||
unsigned height; |
||||
|
||||
unsigned long polygon_count; |
||||
int fps_p; |
||||
}; |
||||
|
||||
struct wscreensaver_plugin { |
||||
const char *name; |
||||
void (*init)(struct ModeInfo *mi); |
||||
void (*draw)(struct ModeInfo *mi); |
||||
void (*reshape)(struct ModeInfo *mi, int w, int h); |
||||
/* void (*refresh)(struct ModeInfo *mi);
|
||||
void (*finish)(struct ModeInfo *mi);*/ |
||||
}; |
||||
|
||||
EGLContext * |
||||
init_GL(struct ModeInfo *mi); |
||||
|
||||
#endif /* WSCREENSAVER_H */ |
Loading…
Reference in new issue