On Wed, 8 Apr 2015 14:20:09 +0100 Ben Avison <[email protected]> wrote:
> --- > .gitignore | 1 + > test/Makefile.sources | 1 + > test/affine-bench.c | 394 > +++++++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 396 insertions(+), 0 deletions(-) > create mode 100644 test/affine-bench.c > > diff --git a/.gitignore b/.gitignore > index 0f11496..7da6b6f 100644 > --- a/.gitignore > +++ b/.gitignore > @@ -46,6 +46,7 @@ demos/tri-test > pixman/pixman-srgb.c > pixman/pixman-version.h > test/a1-trap-test > +test/affine-bench > test/affine-test > test/alpha-loop > test/alphamap > diff --git a/test/Makefile.sources b/test/Makefile.sources > index c20c34b..8b0e855 100644 > --- a/test/Makefile.sources > +++ b/test/Makefile.sources > @@ -37,6 +37,7 @@ OTHERPROGRAMS = \ > radial-perf-test \ > check-formats \ > scaling-bench \ > + affine-bench \ > $(NULL) > > # Utility functions > diff --git a/test/affine-bench.c b/test/affine-bench.c > new file mode 100644 > index 0000000..720d066 > --- /dev/null > +++ b/test/affine-bench.c > @@ -0,0 +1,394 @@ > +/* > + * Copyright © 2014 RISC OS Open Ltd ... > + * Author: Ben Avison ([email protected]) > + */ > + > +#include <stdio.h> > +#include <stdlib.h> > +#include <string.h> > +#include <ctype.h> > +#include <stdint.h> > +#include "utils.h" > + > +#ifdef HAVE_GETTIMEOFDAY > +#include <sys/time.h> > +#else > +#include <time.h> > +#endif > + > +#define WIDTH 1920 > +#define HEIGHT 1080 > +#define MAX_L2CACHE_SIZE (8 * 1024 * 1024) /* How much data to read to flush > all cached data to RAM */ Hi, you asked about reading the cache sizes; I have no idea about that. > +#define PAGE_SIZE (4 * 1024) Hm, sysconf(3) has PAGESIZE query, but I don't know if it is appropriate here. I also tend to forget that Windows might be relevant for Pixman. I think this #define is just fine for now. It clearly documents what the number is. > + > +typedef struct box_48_16 box_48_16_t; ... > +static void > +create_image (uint32_t width, > + uint32_t height, > + pixman_format_code_t format, > + pixman_filter_t filter, > + const pixman_transform_t *t, > + uint32_t **bits, > + pixman_image_t **image) > +{ > + uint32_t stride = (width * PIXMAN_FORMAT_BPP(format) + 31) / 32 * 4; Space before opening paren. > + > + *bits = aligned_malloc (PAGE_SIZE, stride * height); > + memset (*bits, 0xCC, stride * height); > + *image = pixman_image_create_bits (format, width, height, *bits, stride); > + pixman_image_set_repeat (*image, PIXMAN_REPEAT_NORMAL); > + pixman_image_set_filter (*image, filter, NULL, 0); > +} > + > +/* This needs to match the shortest cacheline length we expect to encounter > */ > +#define CACHE_CLEAN_INCREMENT 32 > + > +static void > +flush_cache (void) > +{ > + static const char clean_space[MAX_L2CACHE_SIZE]; > + volatile const char *x = clean_space; > + const char *clean_end = clean_space + sizeof clean_space; Empty line. > + while (x < clean_end) > + { > + (void) *x; > + x += CACHE_CLEAN_INCREMENT; > + } > +} > + > +/* Obtain current time in microseconds modulo 2^32 */ > +uint32_t > +gettimei (void) > +{ > +#ifdef HAVE_GETTIMEOFDAY > + struct timeval tv; > + > + gettimeofday (&tv, NULL); > + return tv.tv_sec * 1000000 + tv.tv_usec; > +#else > + return (uint64_t) clock () * 1000000 / CLOCKS_PER_SEC; > +#endif > +} ... > +int > +parse_fixed_argument (char *arg, pixman_fixed_t *value) > +{ > + char *tailptr; Empty line. > + *value = pixman_double_to_fixed (strtod (arg, &tailptr)); Empty line. > + return *tailptr == '\0'; > +} > + > +int > +parse_arguments (int argc, > + char *argv[], > + pixman_transform_t *t, > + pixman_op_t *op, > + pixman_format_code_t *src_format, > + pixman_format_code_t *mask_format, > + pixman_format_code_t *dest_format) > +{ > + if (!parse_fixed_argument (*argv, &t->matrix[0][0])) > + return 0; > + > + if (*++argv == NULL) > + return 1; > + > + if (!parse_fixed_argument (*argv, &t->matrix[0][1])) > + return 0; > + > + if (*++argv == NULL) > + return 1; > + > + if (!parse_fixed_argument (*argv, &t->matrix[1][0])) > + return 0; > + > + if (*++argv == NULL) > + return 1; > + > + if (!parse_fixed_argument (*argv, &t->matrix[1][1])) > + return 0; > + > + if (*++argv == NULL) > + return 1; > + > + *op = operator_from_string (*argv); > + if (*op == PIXMAN_OP_NONE) > + return 0; > + > + if (*++argv == NULL) > + return 1; > + > + *src_format = format_from_string (*argv); > + if (*src_format == PIXMAN_null) > + return 0; > + > + ++argv; > + if (argv[0] && argv[1]) > + { > + *mask_format = format_from_string (*argv); > + if (*mask_format == PIXMAN_null) > + return 0; > + ++argv; > + } > + if (*argv) > + { > + *dest_format = format_from_string (*argv); > + if (*dest_format == PIXMAN_null) > + return 0; > + } > + return 1; > +} > + > +int > +main (int argc, char *argv[]) > +{ > + pixman_filter_t filter = PIXMAN_FILTER_NEAREST; > + pixman_transform_t t; > + pixman_op_t op = PIXMAN_OP_SRC; > + pixman_format_code_t src_format = PIXMAN_a8r8g8b8; > + pixman_format_code_t mask_format = 0; > + pixman_format_code_t dest_format = PIXMAN_a8r8g8b8; > + > + uint32_t *src, *mask, *dest; > + pixman_image_t *src_image, *mask_image = NULL, *dest_image; > + pixman_box32_t dest_box = { 0, 0, WIDTH, HEIGHT }; > + box_48_16_t transformed = { 0 }; > + int32_t xmin, ymin, xmax, ymax; > + int32_t src_x, src_y; > + > + pixman_transform_init_identity (&t); > + > + ++argv; > + if (*argv && (*argv)[0] == '-' && (*argv)[1] == 'n') > + { > + filter = PIXMAN_FILTER_NEAREST; > + ++argv; > + --argc; > + } > + if (*argv && (*argv)[0] == '-' && (*argv)[1] == 'b') > + { > + filter = PIXMAN_FILTER_BILINEAR; > + ++argv; > + --argc; > + } > + if (argc == 1 || !parse_arguments (argc, argv, &t, &op, &src_format, > &mask_format, &dest_format)) > + { > + printf ("Usage: affine-bench [-n] [-b] axx [axy] [ayx] [ayy] > [combine type]\n"); > + printf (" [src format] [mask format] [dest > format]\n"); > + printf (" -n : nearest scaling (default)\n"); > + printf (" -b : bilinear scaling\n"); > + printf (" axx : x_out:x_in factor\n"); > + printf (" axy : x_out:y_in factor (default 0)\n"); > + printf (" ayx : y_out:x_in factor (default 0)\n"); > + printf (" ayy : y_out:y_in factor (default 1)\n"); > + printf (" combine type : src, over, in etc (default src)\n"); > + printf (" src format : a8r8g8b8, r5g6b6 etc (default a8r8g8b8)\n"); > + printf (" mask format : as for src format, but no mask used if > omitted\n"); > + printf (" dest format : as for src format (default a8r8g8b8)\n"); Hmm. Should I maybe add another, or modify, function to print the list of recognized pixel formats and operators into utils.c? Like list_formats() and list_operators(), but printing also the aliases somehow? Well, it's not important. Maybe one day. Any reason we shouldn't use the same test pattern here as lowlevel-blt-bench is parsing? Just for the op/src/mask/dst. I suppose I could in the future move the pattern parser into utils, and plug in the self-test there. > + return EXIT_FAILURE; > + } > + > + compute_transformed_extents (&t, &dest_box, &transformed); > + /* The source area is expanded by a tiny bit (8/65536th pixel) > + * to match the calculation of the COVER_CLIP flags in analyze_extent() > + */ > + xmin = pixman_fixed_to_int (transformed.x1 - 8 * pixman_fixed_e - > pixman_fixed_1 / 2); > + ymin = pixman_fixed_to_int (transformed.y1 - 8 * pixman_fixed_e - > pixman_fixed_1 / 2); > + xmax = pixman_fixed_to_int (transformed.x2 + 8 * pixman_fixed_e + > pixman_fixed_1 / 2); > + ymax = pixman_fixed_to_int (transformed.y2 + 8 * pixman_fixed_e + > pixman_fixed_1 / 2); > + src_x = -xmin; > + src_y = -ymin; > + > + create_image (xmax - xmin + 64, ymax - ymin + 1, src_format, filter, &t, > &src, &src_image); > + > + if (mask_format) > + { > + create_image (xmax - xmin + 64, ymax - ymin + 1, mask_format, > filter, &t, &mask, &mask_image); > + if ((PIXMAN_FORMAT_R(mask_format) || PIXMAN_FORMAT_G(mask_format) || > PIXMAN_FORMAT_B(mask_format))) > + pixman_image_set_component_alpha (mask_image, 1); Ah, but you use a different way to set CA. Any reason to differ from lowlevel-blt-bench? > + } > + > + create_image (WIDTH + 64, HEIGHT, dest_format, filter, &t, &dest, > &dest_image); > + > + { > + uint32_t n; /* number of iterations in at least 5 seconds */ > + uint32_t t1; /* time taken to do n iterations, microseconds */ > + uint32_t t2; /* calling overhead for n iterations, microseconds */ > + > + flush_cache (); > + bench (op, &t, src_image, mask_image, dest_image, src_x, src_y, > UINT32_MAX, 5000000, &n, &t1, pixman_image_composite_wrapper); > + bench (op, &t, src_image, mask_image, dest_image, src_x, src_y, n, > UINT32_MAX, NULL, &t2, pixman_image_composite_empty); > + /* The result indicates the output rate in megapixels/second */ > + printf ("%6.2f\n", (double) n * WIDTH * HEIGHT / (t1 - t2)); > + } > + > + return EXIT_SUCCESS; > +} This is looking better and better. Once we have discussed all the topics in my earlier email, and landed the lowlevel-blt-bench parser and lookup table stuff, I think it would be time for the final revision of this patch. Thanks, pq _______________________________________________ Pixman mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/pixman
