From 1a1b7653486c9eae58feb461ae05717eea3cf73d Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 29 Sep 2011 18:13:16 +0100 Subject: Add a fish-demo --- .gitignore | 1 + Makefile | 5 +- fish-demo.c | 253 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ fishbg.png | Bin 0 -> 1358526 bytes fishstrip.png | Bin 0 -> 1879515 bytes 5 files changed, 258 insertions(+), 1 deletion(-) create mode 100644 fish-demo.c create mode 100644 fishbg.png create mode 100644 fishstrip.png 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 +#include +#include +#include + +#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 Binary files /dev/null and b/fishbg.png differ diff --git a/fishstrip.png b/fishstrip.png new file mode 100644 index 0000000..344a971 Binary files /dev/null and b/fishstrip.png differ -- cgit v1.2.3