summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Torri <Vincent.Torri@iecn.u-nancy.fr>2006-01-02 11:05:21 +0000
committerVincent Torri <Vincent.Torri@iecn.u-nancy.fr>2006-01-02 11:05:21 +0000
commit290de71fe3b5ba050f37ba078f58422e5332c1ce (patch)
tree3a202c469e3ce798e0b5e440057dc9451acde0c9
parent062ded88366e95f1adc8b32fd8c2832c1a5ef26c (diff)
xcb flames
-rw-r--r--xcb-demo/configure.ac1
-rw-r--r--xcb-demo/tests/Makefile.am6
-rw-r--r--xcb-demo/tests/flames.c482
3 files changed, 488 insertions, 1 deletions
diff --git a/xcb-demo/configure.ac b/xcb-demo/configure.ac
index 63fbc0a..8b512ea 100644
--- a/xcb-demo/configure.ac
+++ b/xcb-demo/configure.ac
@@ -13,5 +13,6 @@ dnl AC_PROG_MAKE_SET
PKG_CHECK_MODULES(XCB, xcb)
PKG_CHECK_MODULES(XCBAUX, xcb-aux)
PKG_CHECK_MODULES(XCBIMAGE, xcb-image)
+PKG_CHECK_MODULES(XCBICCCM, xcb-icccm)
AC_OUTPUT([Makefile tests/Makefile])
diff --git a/xcb-demo/tests/Makefile.am b/xcb-demo/tests/Makefile.am
index 0292cfa..435eb98 100644
--- a/xcb-demo/tests/Makefile.am
+++ b/xcb-demo/tests/Makefile.am
@@ -3,10 +3,14 @@ MAINTAINERCLEANFILES = Makefile.in
INCLUDES = $(XCBAUX_CFLAGS) $(XCBIMAGE_CFLAGS)
-bin_PROGRAMS = julia lissajoux
+bin_PROGRAMS = julia lissajoux flames
julia_LDADD = $(XCBAUX_LIBS) $(XCBIMAGE_LIBS)
julia_SOURCES = julia.c
lissajoux_LDADD = $(XCBAUX_LIBS) $(XCBIMAGE_LIBS) -lm
lissajoux_SOURCES =lissajoux.c
+
+flames_CFLAGS = -O3
+flames_LDADD = $(XCBAUX_LIBS) $(XCBIMAGE_LIBS) $(XCBICCCM_LIBS)
+flames_SOURCES = flames.c
diff --git a/xcb-demo/tests/flames.c b/xcb-demo/tests/flames.c
new file mode 100644
index 0000000..fb1cf2e
--- /dev/null
+++ b/xcb-demo/tests/flames.c
@@ -0,0 +1,482 @@
+/*****************************************************************************/
+/* XCB Flame */
+/*****************************************************************************/
+/* Originally By: */
+/* The Rasterman (Carsten Haitzler) */
+/* Copyright (C) 1996 */
+/*****************************************************************************/
+/* XcB port: */
+/* d'Oursse (Vincent TORRI), 2006 */
+/*****************************************************************************/
+/* This code is Freeware. You may copy it, modify it or do with it as you */
+/* please, but you may not claim copyright on any code wholly or partly */
+/* based on this code. I accept no responisbility for any consequences of */
+/* using this code, be they proper or otherwise. */
+/*****************************************************************************/
+/* Okay, now all the legal mumbo-jumbo is out of the way, I will just say */
+/* this: enjoy this program, do with it as you please and watch out for more */
+/* code releases from The Rasterman running under X... the only way to code. */
+/*****************************************************************************/
+
+/* standard library */
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <assert.h>
+#include <string.h>
+
+#include <X11/X.h>
+#include <X11/XCB/xcb.h>
+#include <X11/XCB/shm.h>
+#include <X11/XCB/xcb_aux.h>
+#include <X11/XCB/xcb_image.h>
+#include <X11/XCB/xcb_icccm.h>
+
+/* some defines for the flame */
+#define HSPREAD 26
+#define VSPREAD 78
+#define VARIANCE 5
+#define VARTREND 2
+#define RESIDUAL 68
+
+/* default width and height of the window */
+#define BG_W 256
+#define BG_H 256
+
+#define IMAX 300
+
+typedef struct
+{
+ struct
+ {
+ XCBConnection *c;
+ XCBDRAWABLE draw;
+ XCBDRAWABLE pixmap;
+ XCBCOLORMAP cmap;
+ CARD8 depth;
+ XCBGCONTEXT gc;
+ }xcb;
+
+ /* the palette */
+ unsigned int pal[IMAX];
+ unsigned int *im;
+ int ims;
+
+ /* the flame arrays */
+ int ws;
+ unsigned int *flame;
+ unsigned int *flame2;
+
+}flame;
+
+static void title_set (flame *f, const char *title);
+static int ilog2 (unsigned int n);
+static void flame_set_palette (flame *f);
+static void flame_set_flame_zero (flame *f);
+static void flame_set_random_flame_base (flame *f);
+static void flame_modify_flame_base (flame *f);
+static void flame_process_flame (flame *f);
+static void flame_draw_flame (flame *f);
+
+flame *
+flame_init ()
+{
+ flame *f;
+ XCBSCREEN *screen;
+ XCBGCONTEXT gc = { 0 };
+ int screen_nbr;
+ CARD32 mask;
+ CARD32 values[2];
+ int size;
+ int flame_width;
+ int flame_height;
+ XCBRECTANGLE rect_coord = { 0, 0, BG_W, BG_H};
+
+ f = (flame *)malloc (sizeof (flame));
+ if (!f)
+ return NULL;
+
+ f->xcb.c = XCBConnect (NULL, &screen_nbr);
+ if (!f->xcb.c)
+ {
+ free (f);
+ return NULL;
+ }
+ screen = XCBAuxGetScreen (f->xcb.c, screen_nbr);
+
+ f->xcb.draw.window = screen->root;
+ f->xcb.gc = XCBGCONTEXTNew (f->xcb.c);
+ mask = GCForeground | GCGraphicsExposures;
+ values[0] = screen->black_pixel;
+ values[1] = 0; /* no graphics exposures */
+ XCBCreateGC (f->xcb.c, f->xcb.gc, f->xcb.draw, mask, values);
+
+ gc = XCBGCONTEXTNew (f->xcb.c);
+ mask = GCForeground | GCGraphicsExposures;
+ values[0] = screen->white_pixel;
+ values[1] = 0; /* no graphics exposures */
+ XCBCreateGC (f->xcb.c, gc, f->xcb.draw, mask, values);
+
+ f->xcb.depth = XCBAuxGetDepth (f->xcb.c, screen);
+ mask = XCBCWBackPixel | XCBCWEventMask;
+ values[0] = screen->white_pixel;
+ values[1] = ExposureMask | ButtonPressMask;
+ f->xcb.draw.window = XCBWINDOWNew (f->xcb.c);
+ XCBCreateWindow (f->xcb.c, f->xcb.depth,
+ f->xcb.draw.window,
+ screen->root,
+ 0, 0, BG_W, BG_H,
+ 0,
+ InputOutput,
+ screen->root_visual,
+ mask, values);
+ title_set (f, "XCB Flames");
+
+ f->xcb.pixmap.pixmap = XCBPIXMAPNew (f->xcb.c);
+ XCBCreatePixmap (f->xcb.c, f->xcb.depth,
+ f->xcb.pixmap.pixmap, f->xcb.draw,
+ BG_W, BG_H);
+ XCBPolyFillRectangle(f->xcb.c, f->xcb.pixmap, gc, 1, &rect_coord);
+
+ XCBMapWindow (f->xcb.c, f->xcb.draw.window);
+ XCBSync (f->xcb.c, 0);
+
+ f->xcb.cmap = XCBCOLORMAPNew (f->xcb.c);
+ XCBCreateColormap (f->xcb.c,
+ AllocNone,
+ f->xcb.cmap,
+ f->xcb.draw.window,
+ screen->root_visual);
+
+ /* Allocation of the flame arrays */
+ flame_width = BG_W >> 1;
+ flame_height = BG_H >> 1;
+ f->ws = ilog2 (flame_width);
+ size = (1 << f->ws) * flame_height * sizeof (unsigned int);
+ f->flame = (unsigned int *)malloc (size);
+ if (! f->flame)
+ {
+ XCBDisconnect (f->xcb.c);
+ free (f);
+ return NULL;
+ }
+ f->flame2 = (unsigned int *)malloc (size);
+ if (! f->flame2)
+ {
+ free (f->flame);
+ XCBDisconnect (f->xcb.c);
+ free (f);
+ return NULL;
+ }
+
+ /* allocation of the image */
+ f->ims = ilog2 (BG_W);
+
+ /* initialization of the palette */
+ flame_set_palette (f);
+
+ return f;
+}
+
+void
+flame_shutdown (flame *f)
+{
+ if (!f)
+ return;
+
+ free (f->flame2);
+ free (f->flame);
+ XCBDisconnect (f->xcb.c);
+ free (f);
+}
+
+int
+main ()
+{
+ flame *f;
+ XCBGenericEvent *e;
+ XCBGCONTEXT gc = { 0 };
+
+ f = flame_init ();
+ if (!f)
+ {
+ printf ("Can't initialize global data\nExiting...\n");
+ return -1;
+ }
+
+ flame_set_flame_zero (f);
+ flame_set_random_flame_base (f);
+
+ while (1)
+ {
+ if ((e = XCBPollForEvent (f->xcb.c, NULL)))
+ {
+ switch (e->response_type)
+ {
+ case XCBExpose:
+ XCBCopyArea(f->xcb.c, f->xcb.pixmap, f->xcb.draw, gc,
+ 0, 0, 0, 0, BG_W, BG_H);
+ XCBSync (f->xcb.c, 0);
+ break;
+ case XCBButtonPress:
+ printf ("Exiting...\n");
+ free (e);
+ goto sortie;
+ }
+ free (e);
+ }
+ flame_draw_flame (f);
+ XCBSync (f->xcb.c, 0);
+ }
+
+ sortie:
+ flame_shutdown (f);
+
+ return 0;
+}
+
+static void title_set (flame *f, const char *title)
+{
+ XCBInternAtomRep *rep;
+ XCBATOM encoding;
+ char *atom_name;
+
+ /* encoding */
+ atom_name = "UTF8_STRING";
+ rep = XCBInternAtomReply (f->xcb.c,
+ XCBInternAtom (f->xcb.c,
+ 0,
+ strlen (atom_name),
+ atom_name),
+ NULL);
+ encoding = rep->atom;
+ free (rep);
+
+ /* ICCCM */
+/* SetWMName (f->xcb.c, f->xcb.draw.window, encoding, strlen (title), title); */
+
+ /* NETWM */
+ atom_name = "_NET_WM_NAME";
+ rep = XCBInternAtomReply (f->xcb.c,
+ XCBInternAtom (f->xcb.c,
+ 0,
+ strlen (atom_name),
+ atom_name),
+ NULL);
+ XCBChangeProperty(f->xcb.c, PropModeReplace,
+ f->xcb.draw.window,
+ rep->atom, encoding, 8, strlen (title), title);
+ free (rep);
+}
+
+static void
+flame_draw_flame (flame *f)
+{
+ XCBImage *image;
+ unsigned int *ptr;
+ int x;
+ int y;
+ int xx;
+ int yy;
+ int cl;
+ int cl1;
+ int cl2;
+ int cl3;
+ int cl4;
+
+ /* modify the base of the flame */
+ flame_modify_flame_base (f);
+ /* process the flame array, propagating the flames up the array */
+ flame_process_flame (f);
+
+ image = XCBImageGet (f->xcb.c, f->xcb.draw,
+ 0, 0, BG_W, BG_H,
+ ((unsigned long)~0L), ZPixmap);
+ f->im = (unsigned int *)image->data;
+
+ for (y = 0 ; y < ((BG_H >> 1) - 1) ; y++)
+ {
+ for (x = 0 ; x < ((BG_W >> 1) - 1) ; x++)
+ {
+ xx = x << 1;
+ yy = y << 1;
+
+ ptr = f->flame2 + (y << f->ws) + x;
+ cl1 = cl = (int)*ptr;
+ ptr = f->flame2 + (y << f->ws) + x + 1;
+ cl2 = (int)*ptr;
+ ptr = f->flame2 + ((y + 1) << f->ws) + x + 1;
+ cl3 = (int)*ptr;
+ ptr = f->flame2 + ((y + 1) << f->ws) + x;
+ cl4 = (int)*ptr;
+
+
+ XCBImagePutPixel (image,
+ xx, yy,
+ f->pal[cl]);
+ XCBImagePutPixel (image,
+ xx + 1, yy,
+ f->pal[((cl1+cl2) >> 1)]);
+ XCBImagePutPixel (image,
+ xx, yy + 1,
+ f->pal[((cl1 + cl3) >> 1)]);
+ XCBImagePutPixel (image,
+ xx + 1, yy + 1,
+ f->pal[((cl1 + cl4) >> 1)]);
+ }
+ }
+ XCBImagePut (f->xcb.c, f->xcb.draw, f->xcb.gc, image,
+ 0, 0, 0, 0, BG_W, BG_H);
+ XCBImageDestroy (image);
+}
+
+/* set the flame palette */
+static void
+flame_set_palette (flame *f)
+{
+ XCBAllocColorCookie cookies[IMAX];
+ XCBAllocColorRep *rep;
+ int i;
+ int r;
+ int g;
+ int b;
+
+ for (i = 0 ; i < IMAX ; i++)
+ {
+ r = i * 3;
+ g = (i - 80) * 3;
+ b = (i - 160) * 3;
+
+ if (r < 0) r = 0;
+ if (r > 255) r = 255;
+ if (g < 0) g = 0;
+ if (g > 255) g = 255;
+ if (b < 0) b = 0;
+ if (b > 255) b = 255;
+
+ cookies[i] = XCBAllocColor (f->xcb.c, f->xcb.cmap,
+ r << 8, g << 8, b << 8);
+ }
+
+ for (i = 0 ; i < IMAX ; i++)
+ {
+ rep = XCBAllocColorReply (f->xcb.c, cookies[i], NULL);
+ f->pal[i] = rep->pixel;
+ free (rep);
+ }
+}
+
+/* set the flame array to zero */
+static void
+flame_set_flame_zero (flame *f)
+{
+ int x;
+ int y;
+ unsigned int *ptr;
+
+ for (y = 0 ; y < (BG_H >> 1) ; y++)
+ {
+ for (x = 0 ; x < (BG_W >> 1) ; x++)
+ {
+ ptr = f->flame + (y << f->ws) + x;
+ *ptr = 0;
+ }
+ }
+}
+
+static void
+flame_set_random_flame_base (flame *f)
+{
+ int x;
+ int y;
+ unsigned int *ptr;
+
+ /* initialize a random number seed from the time, so we get random */
+ /* numbers each time */
+ srand (time(NULL));
+ y = (BG_H >> 1) - 1;
+ for (x = 0 ; x < (BG_W >> 1) ; x++)
+ {
+ ptr = f->flame + (y << f->ws) + x;
+ *ptr = rand ()%IMAX;
+ }
+}
+
+/* modify the base of the flame with random values */
+static void
+flame_modify_flame_base (flame *f)
+{
+ int x;
+ int y;
+ unsigned int *ptr;
+ int val;
+
+ y = (BG_H >> 1) - 1;
+ for (x = 0 ; x < (BG_W >> 1) ; x++)
+ {
+ ptr = f->flame + (y << f->ws) + x;
+ *ptr += ((rand ()%VARIANCE) - VARTREND);
+ val = *ptr;
+ if (val > IMAX) *ptr = 0;
+ if (val < 0) *ptr = 0;
+ }
+}
+
+/* process entire flame array */
+static void
+flame_process_flame (flame *f)
+{
+ int x;
+ int y;
+ unsigned int *ptr;
+ unsigned int *p;
+ unsigned int val;
+ unsigned int tmp;
+
+ for (y = ((BG_H >> 1) - 1) ; y >= 2 ; y--)
+ {
+ for (x = 1 ; x < ((BG_W >> 1) - 1) ; x++)
+ {
+ ptr = f->flame + (y << f->ws) + x;
+ val = (unsigned int)*ptr;
+ if (val > IMAX)
+ *ptr = (unsigned int)IMAX;
+ val = (unsigned int)*ptr;
+ if (val > 0)
+ {
+ tmp = (val * VSPREAD) >> 8;
+ p = ptr - (2 << f->ws);
+ *p = *p + (tmp >> 1);
+ p = ptr - (1 << f->ws);
+ *p = *p + tmp;
+ tmp = (val * HSPREAD) >> 8;
+ p = ptr - (1 << f->ws) - 1;
+ *p = *p + tmp;
+ p = ptr - (1 << f->ws) + 1;
+ *p = *p + tmp;
+ p = ptr - 1;
+ *p = *p + (tmp >>1 );
+ p = ptr + 1;
+ *p = *p + (tmp >> 1);
+ p = f->flame2 + (y << f->ws) + x;
+ *p = val;
+ if (y < ((BG_H >> 1) - 1))
+ *ptr = (val * RESIDUAL) >> 8;
+ }
+ }
+ }
+}
+
+static int
+ilog2 (unsigned int n)
+{
+ int p = -1;
+
+ assert(n > 0);
+ while (n > 0) {
+ p++;
+ n >>= 1;
+ }
+
+ return p;
+}