summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2011-09-29 18:13:16 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2011-09-29 19:11:58 +0100
commit1a1b7653486c9eae58feb461ae05717eea3cf73d (patch)
tree72910cd41aa3d7fd092b16cdc1a3ea702b4f5642
parent85602579e3e4c68ee59e82d87d1167bb827422fc (diff)
Add a fish-demo
-rw-r--r--.gitignore1
-rw-r--r--Makefile5
-rw-r--r--fish-demo.c253
-rw-r--r--fishbg.pngbin0 -> 1358526 bytes
-rw-r--r--fishstrip.pngbin0 -> 1879515 bytes
5 files changed, 258 insertions, 1 deletions
diff --git a/.gitignore b/.gitignore
index dedb3e9..2486426 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+fish-demo
poppler-demo
slideshow-demo
spinner-demo
diff --git a/Makefile b/Makefile
index f409c8b..1570fbd 100644
--- a/Makefile
+++ b/Makefile
@@ -21,6 +21,7 @@ DEFINES+=-DHAVE_XCB=0
endif
GLX:=$(shell pkg-config --exists cairo-gl && echo 1 || echo 0)
+GLX:=0
ifneq ($(GLX),0)
DEFINES+=-DHAVE_GLX=1
SOURCES+=glx.c
@@ -29,7 +30,7 @@ else
DEFINES+=-DHAVE_GLX=0
endif
-all: spinner-demo spiral-demo slideshow-demo tiger-demo
+all: spinner-demo spiral-demo slideshow-demo tiger-demo fish-demo
ifeq ($(shell pkg-config --exists poppler-glib && echo 1), 1)
all: poppler-demo
@@ -49,6 +50,8 @@ poppler-demo: poppler-demo.c $(SOURCES) demo.h Makefile
$(CC) $(DEFINES) $(CFLAGS) -o $@ poppler-demo.c $(SOURCES) $(LIBS)
tiger-demo: tiger-demo.c $(SOURCES) demo.h Makefile tiger.inc
$(CC) $(DEFINES) $(CFLAGS) -o $@ tiger-demo.c $(SOURCES) $(LIBS)
+fish-demo: fish-demo.c $(SOURCES) demo.h Makefile
+ $(CC) $(DEFINES) $(CFLAGS) -o $@ fish-demo.c $(SOURCES) $(LIBS)
clean:
rm -f *-demo
diff --git a/fish-demo.c b/fish-demo.c
new file mode 100644
index 0000000..f85e0e2
--- /dev/null
+++ b/fish-demo.c
@@ -0,0 +1,253 @@
+#include <cairo.h>
+#include <sys/time.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "demo.h"
+
+static int fish_width, fish_height;
+
+struct fish {
+ int x, y, z;
+ int dx, dy, dz;
+ int frame, rgb;
+};
+
+static cairo_pattern_t *create_background(struct device *device)
+{
+ cairo_surface_t *surface, *image;
+ cairo_pattern_t *pattern;
+ int width, height;
+ double sf;
+ cairo_t *cr;
+
+ image = cairo_image_surface_create_from_png("fishbg.png");
+
+ sf = device->height / (double) cairo_image_surface_get_height(image);
+ height = device->height;
+ width = sf * cairo_image_surface_get_width(image);
+
+ surface = cairo_surface_create_similar(device->scanout,
+ CAIRO_CONTENT_COLOR,
+ width, height);
+ cr = cairo_create(surface);
+ cairo_surface_destroy(surface);
+
+ cairo_scale(cr, sf, sf);
+ cairo_set_source_surface(cr, image, 0, 0);
+ cairo_surface_destroy(image);
+ cairo_paint(cr);
+ pattern = cairo_pattern_create_for_surface(cairo_get_target(cr));
+ cairo_destroy (cr);
+
+ cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REFLECT);
+ return pattern;
+}
+
+static cairo_surface_t **create_strip(struct device *device)
+{
+ cairo_surface_t *surface, *image, **strip;
+ int width, height, x, y;
+ cairo_t *cr;
+
+ image = cairo_image_surface_create_from_png("fishstrip.png");
+ width = cairo_image_surface_get_width(image);
+ height = cairo_image_surface_get_height(image);
+ surface = cairo_surface_create_similar(device->scanout,
+ CAIRO_CONTENT_COLOR_ALPHA,
+ width, height);
+ cr = cairo_create(surface);
+ cairo_set_source_surface(cr, image, 0, 0);
+ cairo_paint(cr);
+ cairo_destroy (cr);
+
+ cairo_surface_destroy(image);
+
+ width /= 16;
+ height /= 3;
+
+ fish_width = width;
+ fish_height = height;
+
+ strip = malloc(sizeof(cairo_surface_t*)*48);
+ for (y = 0; y < 3; y++) {
+ for (x = 0; x < 16; x++) {
+ strip[y*16+x] =
+ cairo_surface_create_for_rectangle(surface,
+ x * width,
+ y * height,
+ width,
+ height);
+
+ }
+ }
+
+ return strip;
+}
+
+static void fish_init(struct device *device, struct fish *f)
+{
+ f->x = random() % (device->width + fish_width) - fish_width;
+ f->y = random() % (device->height + fish_height) - fish_height;
+ f->z = 0;
+
+ f->dx = random() % 10 + 1;
+ if (random() % 2)
+ f->dx = -f->dx;
+ f->dy = random() % 10 + 1;
+ if (random() % 2)
+ f->dy = -f->dy;
+ f->dz = 0;
+
+ f->frame = random() % 16;
+ f->rgb = random() % 3;
+}
+
+static void fish_draw(struct device *device, cairo_t *cr, struct fish *f, cairo_surface_t **strip)
+{
+ double sx = f->dx > 0 ? 1 : -1;
+ double tx = f->dx > 0 ? 0 : -fish_width;
+
+ cairo_save(cr);
+ cairo_scale(cr, sx, 1);
+ cairo_set_source_surface(cr, strip[f->rgb*16+f->frame], sx*f->x+tx, f->y);
+ cairo_paint(cr);
+ cairo_restore(cr);
+
+ f->frame = (f->frame+1) % 16;
+ f->x += f->dx;
+ f->y += f->dy;
+
+ if (f->x < -fish_width || f->x >= device->width)
+ f->dx = -f->dx;
+ if (f->y < -fish_height || f->y >= device->height)
+ f->dy = -f->dy;
+}
+
+static void
+fps_draw (struct framebuffer *fb, const char *name,
+ const struct timeval *last,
+ const struct timeval *now)
+{
+#define N_FILTER 25
+ static double filter[25];
+ static int filter_pos;
+ cairo_text_extents_t extents;
+ char buf[80];
+ double fps, avg;
+ int n, max;
+ cairo_t *cr;
+
+ fps = now->tv_sec - last->tv_sec;
+ fps += (now->tv_usec - last->tv_usec) / 1000000.;
+
+ max = N_FILTER;
+ avg = fps;
+ if (filter_pos < max)
+ max = filter_pos;
+ for (n = 0; n < max; n++)
+ avg += filter[n];
+ avg /= max + 1;
+ filter[filter_pos++ % N_FILTER] = fps;
+ if (filter_pos < 5)
+ return;
+
+ cr = cairo_create (fb->surface);
+ cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
+
+ snprintf (buf, sizeof (buf), "%s: %.1f fps", name, 1. / avg);
+ cairo_set_font_size (cr, 18);
+ cairo_text_extents (cr, buf, &extents);
+
+ cairo_rectangle (cr, 4-1, 4-1, extents.width+2, extents.height+2);
+ cairo_set_source_rgba (cr, .0, .0, .0, .85);
+ cairo_fill (cr);
+
+ cairo_move_to (cr, 4 - extents.x_bearing, 4 - extents.y_bearing);
+ cairo_set_source_rgb (cr, .95, .95, .95);
+ cairo_show_text (cr, buf);
+
+ cairo_destroy (cr);
+}
+
+int main (int argc, char **argv)
+{
+ struct device *device;
+ struct timeval start, last_tty, last_fps, now;
+
+ cairo_pattern_t *bg;
+ cairo_surface_t **strip;
+ struct fish *fish;
+ int num_fish = 20, n;
+
+ double delta;
+ int frame = 0;
+ int frames = 0;
+ int benchmark;
+
+ device = device_open(argc, argv);
+ benchmark = device_get_benchmark(argc, argv);
+ if (benchmark == 0)
+ benchmark = 20;
+
+ for (n = 1; n < argc; n++) {
+ if (strncmp(argv[n], "--num-fish=", 11) == 0)
+ num_fish = atoi(argv[n]+11);
+ }
+
+ bg = create_background(device);
+ if (cairo_pattern_status(bg))
+ return 1;
+
+ fish = malloc(sizeof(*fish)*num_fish);
+ for (n = 0; n < num_fish; n++)
+ fish_init(device, &fish[n]);
+
+ strip = create_strip(device);
+
+ gettimeofday(&start, 0); now = last_tty = last_fps = start;
+ do {
+ struct framebuffer *fb = device->get_framebuffer (device);
+ cairo_t *cr;
+
+ cr = cairo_create(fb->surface);
+ cairo_set_source(cr, bg);
+ cairo_paint(cr);
+
+ for (n = 0; n < num_fish; n++)
+ fish_draw(device, cr, &fish[n], strip);
+
+ cairo_destroy(cr);
+
+ gettimeofday(&now, NULL);
+ if (benchmark < 0 && last_fps.tv_sec)
+ fps_draw(fb, device->name, &last_fps, &now);
+ last_fps = now;
+
+ fb->show (fb);
+ fb->destroy (fb);
+
+ if (benchmark < 0) {
+ delta = now.tv_sec - last_tty.tv_sec;
+ delta += (now.tv_usec - last_tty.tv_usec)*1e-6;
+ frames++;
+ if (delta > 5) {
+ printf("%.2f fps\n", frames/delta);
+ last_tty = now;
+ frames = 0;
+ }
+ }
+
+ frame++;
+ if (benchmark > 0) {
+ delta = now.tv_sec - start.tv_sec;
+ delta += (now.tv_usec - start.tv_usec)*1e-6;
+ if (delta > benchmark) {
+ printf("%.2f fps\n", frame / delta);
+ break;
+ }
+ }
+ } while (1);
+
+ return 0;
+}
diff --git a/fishbg.png b/fishbg.png
new file mode 100644
index 0000000..582277e
--- /dev/null
+++ b/fishbg.png
Binary files differ
diff --git a/fishstrip.png b/fishstrip.png
new file mode 100644
index 0000000..344a971
--- /dev/null
+++ b/fishstrip.png
Binary files differ