clients: add wscreensaver

Implement all the required support code for running glmatrix.c.

Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
dev
Pekka Paalanen 13 years ago
parent 8260f460d7
commit 11f53f56db
  1. 1
      clients/.gitignore
  2. 4
      clients/Makefile.am
  3. 29
      clients/glmatrix.c
  4. 148
      clients/wscreensaver-glue.c
  5. 121
      clients/wscreensaver-glue.h
  6. 275
      clients/wscreensaver.c
  7. 60
      clients/wscreensaver.h

@ -17,3 +17,4 @@ desktop-shell-client-protocol.h
desktop-shell-protocol.c desktop-shell-protocol.c
desktop-shell desktop-shell
simple-client simple-client
wscreensaver

@ -23,6 +23,7 @@ clients_programs = \
dnd \ dnd \
smoke \ smoke \
resizor \ resizor \
wscreensaver \
eventdemo eventdemo
desktop_shell = wayland-desktop-shell desktop_shell = wayland-desktop-shell
@ -69,6 +70,9 @@ smoke_LDADD = $(toolkit_libs)
resizor_SOURCES = resizor.c resizor_SOURCES = resizor.c
resizor_LDADD = $(toolkit_libs) resizor_LDADD = $(toolkit_libs)
wscreensaver_SOURCES = wscreensaver.c wscreensaver-glue.c glmatrix.c
wscreensaver_LDADD = $(toolkit_libs) -lGLU
eventdemo_SOURCES = eventdemo.c eventdemo_SOURCES = eventdemo.c
eventdemo_LDADD = $(toolkit_libs) eventdemo_LDADD = $(toolkit_libs)

@ -28,17 +28,14 @@
#undef BELLRAND #undef BELLRAND
#define BELLRAND(n) ((frand((n)) + frand((n)) + frand((n))) / 3) #define BELLRAND(n) ((frand((n)) + frand((n)) + frand((n))) / 3)
#include "xlockmore.h" #include "wscreensaver-glue.h"
#include "xpm-ximage.h"
#ifdef __GNUC__ #ifdef __GNUC__
__extension__ /* don't warn about "string length is greater than the length __extension__ /* don't warn about "string length is greater than the length
ISO C89 compilers are required to support" when including ISO C89 compilers are required to support" when including
the following XPM file... */ the following XPM file... */
#endif #endif
#include "../images/matrix3.xpm" #include "matrix3.xpm"
#ifdef USE_GL /* whole file */
#define DEF_SPEED "1.0" #define DEF_SPEED "1.0"
@ -188,6 +185,7 @@ static Bool do_rotate;
static Bool do_texture; static Bool do_texture;
static char *mode_str; static char *mode_str;
#if 0
static XrmOptionDescRec opts[] = { static XrmOptionDescRec opts[] = {
{ "-speed", ".speed", XrmoptionSepArg, 0 }, { "-speed", ".speed", XrmoptionSepArg, 0 },
{ "-density", ".density", XrmoptionSepArg, 0 }, { "-density", ".density", XrmoptionSepArg, 0 },
@ -222,7 +220,7 @@ static argtype vars[] = {
}; };
ENTRYPOINT ModeSpecOpt matrix_opts = {countof(opts), opts, countof(vars), vars, NULL}; ENTRYPOINT ModeSpecOpt matrix_opts = {countof(opts), opts, countof(vars), vars, NULL};
#endif
/* Re-randomize the state of one strip. /* Re-randomize the state of one strip.
*/ */
@ -589,6 +587,7 @@ reshape_matrix (ModeInfo *mi, int width, int height)
} }
#if 0
ENTRYPOINT Bool ENTRYPOINT Bool
matrix_handle_event (ModeInfo *mi, XEvent *event) matrix_handle_event (ModeInfo *mi, XEvent *event)
{ {
@ -609,7 +608,7 @@ matrix_handle_event (ModeInfo *mi, XEvent *event)
return False; return False;
} }
#endif
#if 0 #if 0
static Bool static Bool
@ -695,8 +694,7 @@ load_textures (ModeInfo *mi, Bool flip_p)
/* The Matrix XPM is 512x598 -- but GL texture sizes must be powers of 2. /* The Matrix XPM is 512x598 -- but GL texture sizes must be powers of 2.
So we waste some padding rows to round up. So we waste some padding rows to round up.
*/ */
xi = xpm_to_ximage (mi->dpy, mi->xgwa.visual, mi->xgwa.colormap, xi = xpm_to_ximage (matrix3_xpm);
matrix3_xpm);
orig_w = xi->width; orig_w = xi->width;
orig_h = xi->height; orig_h = xi->height;
mp->real_char_rows = CHAR_ROWS; mp->real_char_rows = CHAR_ROWS;
@ -990,8 +988,6 @@ ENTRYPOINT void
draw_matrix (ModeInfo *mi) draw_matrix (ModeInfo *mi)
{ {
matrix_configuration *mp = &mps[MI_SCREEN(mi)]; matrix_configuration *mp = &mps[MI_SCREEN(mi)];
Display *dpy = MI_DISPLAY(mi);
Window window = MI_WINDOW(mi);
int i; int i;
if (!mp->glx_context) if (!mp->glx_context)
@ -1057,9 +1053,12 @@ draw_matrix (ModeInfo *mi)
if (mi->fps_p) do_fps (mi); if (mi->fps_p) do_fps (mi);
glFinish(); glFinish();
glXSwapBuffers(dpy, window); glXSwapBuffers(MI_DISPLAY(mi), MI_WINDOW(mi));
} }
XSCREENSAVER_MODULE_2 ("GLMatrix", glmatrix, matrix) WL_EXPORT struct wscreensaver_plugin glmatrix_screensaver = {
"GLMatrix",
#endif /* USE_GL */ init_matrix,
draw_matrix,
reshape_matrix
};

@ -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…
Cancel
Save