/* * Copyright © 2009 Nokia Corporation * Copyright © 2010 Movial Creative Technologies Oy * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "utils.h" #define SOLID_FLAG 1 #define CA_FLAG 2 #define L1CACHE_SIZE (8 * 1024) #define L2CACHE_SIZE (128 * 1024) /* This is applied to both L1 and L2 tests - alternatively, you could * parameterise bench_L or split it into two functions. It could be * read at runtime on some architectures, but it only really matters * that it's a number that's an integer divisor of both cacheline * lengths, and further, it only really matters for caches that don't * do allocate0on-write. */ #define CACHELINE_LENGTH (32) /* bytes */ #define WIDTH 1920 #define HEIGHT 1080 #define BUFSIZE (WIDTH * HEIGHT * 4) #define XWIDTH 256 #define XHEIGHT 256 #define TILEWIDTH 32 #define TINYWIDTH 8 #define EXCLUDE_OVERHEAD 1 uint32_t *dst; uint32_t *src; uint32_t *mask; double bandwidth = 0; double bench_memcpy () { int64_t n = 0, total; double t1, t2; int x = 0; t1 = gettime (); while (1) { memcpy (dst, src, BUFSIZE - 64); memcpy (src, dst, BUFSIZE - 64); n += 4 * (BUFSIZE - 64); t2 = gettime (); if (t2 - t1 > 0.5) break; } n = total = n * 5; t1 = gettime (); while (n > 0) { if (++x >= 64) x = 0; memcpy ((char *)dst + 1, (char *)src + x, BUFSIZE - 64); memcpy ((char *)src + 1, (char *)dst + x, BUFSIZE - 64); n -= 4 * (BUFSIZE - 64); } t2 = gettime (); return (double)total / (t2 - t1); } static pixman_bool_t use_scaling = FALSE; static pixman_filter_t filter = PIXMAN_FILTER_NEAREST; /* nearly 1x scale factor */ static pixman_transform_t m = { { { pixman_fixed_1 + 1, 0, 0 }, { 0, pixman_fixed_1, 0 }, { 0, 0, pixman_fixed_1 } } }; static void pixman_image_composite_wrapper (pixman_implementation_t *impl, pixman_composite_info_t *info) { if (use_scaling) { pixman_image_set_filter (info->src_image, filter, NULL, 0); pixman_image_set_transform(info->src_image, &m); } pixman_image_composite (info->op, info->src_image, info->mask_image, info->dest_image, info->src_x, info->src_y, info->mask_x, info->mask_y, info->dest_x, info->dest_y, info->width, info->height); } static void pixman_image_composite_empty (pixman_implementation_t *impl, pixman_composite_info_t *info) { if (use_scaling) { pixman_image_set_filter (info->src_image, filter, NULL, 0); pixman_image_set_transform(info->src_image, &m); } pixman_image_composite (info->op, info->src_image, info->mask_image, info->dest_image, 0, 0, 0, 0, 0, 0, 1, 1); } static inline void call_func (pixman_composite_func_t func, pixman_op_t op, pixman_image_t * src_image, pixman_image_t * mask_image, pixman_image_t * dest_image, int32_t src_x, int32_t src_y, int32_t mask_x, int32_t mask_y, int32_t dest_x, int32_t dest_y, int32_t width, int32_t height) { pixman_composite_info_t info; info.op = op; info.src_image = src_image; info.mask_image = mask_image; info.dest_image = dest_image; info.src_x = src_x; info.src_y = src_y; info.mask_x = mask_x; info.mask_y = mask_y; info.dest_x = dest_x; info.dest_y = dest_y; info.width = width; info.height = height; func (0, &info); } void noinline bench_L (pixman_op_t op, pixman_image_t * src_img, pixman_image_t * mask_img, pixman_image_t * dst_img, int64_t n, pixman_composite_func_t func, int width, int lines_count) { int64_t i, j, k; int x = 0; int q = 0; volatile int qx; for (i = 0; i < n; i++) { /* For caches without allocate-on-write, we need to force the * destination buffer back into the cache on each iteration, * otherwise if they are evicted during the test, they remain * uncached. This doesn't matter for tests which read the * destination buffer, or for caches that do allocate-on-write, * but in those cases this loop just adds constant time, which * should be successfully cancelled out. */ for (j = 0; j < lines_count; j++) { for (k = 0; k < width + 62; k += CACHELINE_LENGTH / sizeof *dst) { q += dst[j * WIDTH + k]; } q += dst[j * WIDTH + width + 62]; } if (++x >= 64) x = 0; call_func (func, op, src_img, mask_img, dst_img, x, 0, x, 0, 63 - x, 0, width, lines_count); } qx = q; } void noinline bench_M (pixman_op_t op, pixman_image_t * src_img, pixman_image_t * mask_img, pixman_image_t * dst_img, int64_t n, pixman_composite_func_t func) { int64_t i; int x = 0; for (i = 0; i < n; i++) { if (++x >= 64) x = 0; call_func (func, op, src_img, mask_img, dst_img, x, 0, x, 0, 1, 0, WIDTH - 64, HEIGHT); } } double noinline bench_HT (pixman_op_t op, pixman_image_t * src_img, pixman_image_t * mask_img, pixman_image_t * dst_img, int64_t n, pixman_composite_func_t func) { double pix_cnt = 0; int x = 0; int y = 0; int64_t i; srand (0); for (i = 0; i < n; i++) { int w = (rand () % (TILEWIDTH * 2)) + 1; int h = (rand () % (TILEWIDTH * 2)) + 1; if (x + w > WIDTH) { x = 0; y += TILEWIDTH * 2; } if (y + h > HEIGHT) { y = 0; } call_func (func, op, src_img, mask_img, dst_img, x, y, x, y, x, y, w, h); x += w; pix_cnt += w * h; } return pix_cnt; } double noinline bench_VT (pixman_op_t op, pixman_image_t * src_img, pixman_image_t * mask_img, pixman_image_t * dst_img, int64_t n, pixman_composite_func_t func) { double pix_cnt = 0; int x = 0; int y = 0; int64_t i; srand (0); for (i = 0; i < n; i++) { int w = (rand () % (TILEWIDTH * 2)) + 1; int h = (rand () % (TILEWIDTH * 2)) + 1; if (y + h > HEIGHT) { y = 0; x += TILEWIDTH * 2; } if (x + w > WIDTH) { x = 0; } call_func (func, op, src_img, mask_img, dst_img, x, y, x, y, x, y, w, h); y += h; pix_cnt += w * h; } return pix_cnt; } double noinline bench_R (pixman_op_t op, pixman_image_t * src_img, pixman_image_t * mask_img, pixman_image_t * dst_img, int64_t n, pixman_composite_func_t func, int maxw, int maxh) { double pix_cnt = 0; int64_t i; if (maxw <= TILEWIDTH * 2 || maxh <= TILEWIDTH * 2) { printf("error: maxw <= TILEWIDTH * 2 || maxh <= TILEWIDTH * 2\n"); return 0; } srand (0); for (i = 0; i < n; i++) { int w = (rand () % (TILEWIDTH * 2)) + 1; int h = (rand () % (TILEWIDTH * 2)) + 1; int sx = rand () % (maxw - TILEWIDTH * 2); int sy = rand () % (maxh - TILEWIDTH * 2); int dx = rand () % (maxw - TILEWIDTH * 2); int dy = rand () % (maxh - TILEWIDTH * 2); call_func (func, op, src_img, mask_img, dst_img, sx, sy, sx, sy, dx, dy, w, h); pix_cnt += w * h; } return pix_cnt; } double noinline bench_RT (pixman_op_t op, pixman_image_t * src_img, pixman_image_t * mask_img, pixman_image_t * dst_img, int64_t n, pixman_composite_func_t func, int maxw, int maxh) { double pix_cnt = 0; int64_t i; if (maxw <= TINYWIDTH * 2 || maxh <= TINYWIDTH * 2) { printf("error: maxw <= TINYWIDTH * 2 || maxh <= TINYWIDTH * 2\n"); return 0; } srand (0); for (i = 0; i < n; i++) { int w = (rand () % (TINYWIDTH * 2)) + 1; int h = (rand () % (TINYWIDTH * 2)) + 1; int sx = rand () % (maxw - TINYWIDTH * 2); int sy = rand () % (maxh - TINYWIDTH * 2); int dx = rand () % (maxw - TINYWIDTH * 2); int dy = rand () % (maxh - TINYWIDTH * 2); call_func (func, op, src_img, mask_img, dst_img, sx, sy, sx, sy, dx, dy, w, h); pix_cnt += w * h; } return pix_cnt; } void bench_composite (char * testname, int src_fmt, int src_flags, int op, int mask_fmt, int mask_flags, int dst_fmt, double npix) { pixman_image_t * src_img; pixman_image_t * dst_img; pixman_image_t * mask_img; pixman_image_t * xsrc_img; pixman_image_t * xdst_img; pixman_image_t * xmask_img; double t1, t2, t3, pix_cnt; int64_t n, l1test_width, nlines; double bytes_per_pix = 0; pixman_bool_t bench_pixbuf = FALSE; pixman_composite_func_t func = pixman_image_composite_wrapper; if (!(src_flags & SOLID_FLAG)) { bytes_per_pix += (src_fmt >> 24) / 8.0; src_img = pixman_image_create_bits (src_fmt, WIDTH, HEIGHT, src, WIDTH * 4); xsrc_img = pixman_image_create_bits (src_fmt, XWIDTH, XHEIGHT, src, XWIDTH * 4); } else { src_img = pixman_image_create_bits (src_fmt, 1, 1, src, 4); xsrc_img = pixman_image_create_bits (src_fmt, 1, 1, src, 4); pixman_image_set_repeat (src_img, PIXMAN_REPEAT_NORMAL); pixman_image_set_repeat (xsrc_img, PIXMAN_REPEAT_NORMAL); } bytes_per_pix += (dst_fmt >> 24) / 8.0; dst_img = pixman_image_create_bits (dst_fmt, WIDTH, HEIGHT, dst, WIDTH * 4); mask_img = NULL; xmask_img = NULL; if (strcmp (testname, "pixbuf") == 0 || strcmp (testname, "rpixbuf") == 0) { bench_pixbuf = TRUE; } if (!(mask_flags & SOLID_FLAG) && mask_fmt != PIXMAN_null) { bytes_per_pix += (mask_fmt >> 24) / ((op == PIXMAN_OP_SRC) ? 8.0 : 4.0); mask_img = pixman_image_create_bits (mask_fmt, WIDTH, HEIGHT, bench_pixbuf ? src : mask, WIDTH * 4); xmask_img = pixman_image_create_bits (mask_fmt, XWIDTH, XHEIGHT, bench_pixbuf ? src : mask, XWIDTH * 4); } else if (mask_fmt != PIXMAN_null) { mask_img = pixman_image_create_bits (mask_fmt, 1, 1, mask, 4); xmask_img = pixman_image_create_bits (mask_fmt, 1, 1, mask, 4 * 4); pixman_image_set_repeat (mask_img, PIXMAN_REPEAT_NORMAL); pixman_image_set_repeat (xmask_img, PIXMAN_REPEAT_NORMAL); } if ((mask_flags & CA_FLAG) && mask_fmt != PIXMAN_null) { pixman_image_set_component_alpha (mask_img, 1); } xdst_img = pixman_image_create_bits (dst_fmt, XWIDTH, XHEIGHT, dst, XWIDTH * 4); printf ("%24s %c", testname, func != pixman_image_composite_wrapper ? '-' : '='); memcpy (dst, src, BUFSIZE); memcpy (src, dst, BUFSIZE); l1test_width = L1CACHE_SIZE / 8 - 64; if (l1test_width < 1) l1test_width = 1; if (l1test_width > WIDTH - 64) l1test_width = WIDTH - 64; n = 1 + npix / (l1test_width * 8); t1 = gettime (); #if EXCLUDE_OVERHEAD bench_L (op, src_img, mask_img, dst_img, n, pixman_image_composite_empty, l1test_width, 1); #endif t2 = gettime (); bench_L (op, src_img, mask_img, dst_img, n, func, l1test_width, 1); t3 = gettime (); printf (" L1:%7.2f", (double)n * l1test_width * 1 / ((t3 - t2) - (t2 - t1)) / 1000000.); fflush (stdout); memcpy (dst, src, BUFSIZE); memcpy (src, dst, BUFSIZE); nlines = (L2CACHE_SIZE / l1test_width) / ((PIXMAN_FORMAT_BPP(src_fmt) + PIXMAN_FORMAT_BPP(dst_fmt)) / 8); if (nlines < 1) nlines = 1; n = 1 + npix / (l1test_width * nlines); t1 = gettime (); #if EXCLUDE_OVERHEAD bench_L (op, src_img, mask_img, dst_img, n, pixman_image_composite_empty, l1test_width, nlines); #endif t2 = gettime (); bench_L (op, src_img, mask_img, dst_img, n, func, l1test_width, nlines); t3 = gettime (); printf (" L2:%7.2f", (double)n * l1test_width * nlines / ((t3 - t2) - (t2 - t1)) / 1000000.); fflush (stdout); memcpy (dst, src, BUFSIZE); memcpy (src, dst, BUFSIZE); n = 1 + npix / (WIDTH * HEIGHT); t1 = gettime (); #if EXCLUDE_OVERHEAD bench_M (op, src_img, mask_img, dst_img, n, pixman_image_composite_empty); #endif t2 = gettime (); bench_M (op, src_img, mask_img, dst_img, n, func); t3 = gettime (); printf (" M:%6.2f (%6.2f%%)", ((double)n * (WIDTH - 64) * HEIGHT / ((t3 - t2) - (t2 - t1))) / 1000000., ((double)n * (WIDTH - 64) * HEIGHT / ((t3 - t2) - (t2 - t1)) * bytes_per_pix) * (100.0 / bandwidth) ); fflush (stdout); memcpy (dst, src, BUFSIZE); memcpy (src, dst, BUFSIZE); n = 1 + npix / (8 * TILEWIDTH * TILEWIDTH); t1 = gettime (); #if EXCLUDE_OVERHEAD pix_cnt = bench_HT (op, src_img, mask_img, dst_img, n, pixman_image_composite_empty); #endif t2 = gettime (); pix_cnt = bench_HT (op, src_img, mask_img, dst_img, n, func); t3 = gettime (); printf (" HT:%6.2f", (double)pix_cnt / ((t3 - t2) - (t2 - t1)) / 1000000.); fflush (stdout); memcpy (dst, src, BUFSIZE); memcpy (src, dst, BUFSIZE); n = 1 + npix / (8 * TILEWIDTH * TILEWIDTH); t1 = gettime (); #if EXCLUDE_OVERHEAD pix_cnt = bench_VT (op, src_img, mask_img, dst_img, n, pixman_image_composite_empty); #endif t2 = gettime (); pix_cnt = bench_VT (op, src_img, mask_img, dst_img, n, func); t3 = gettime (); printf (" VT:%6.2f", (double)pix_cnt / ((t3 - t2) - (t2 - t1)) / 1000000.); fflush (stdout); memcpy (dst, src, BUFSIZE); memcpy (src, dst, BUFSIZE); n = 1 + npix / (8 * TILEWIDTH * TILEWIDTH); t1 = gettime (); #if EXCLUDE_OVERHEAD pix_cnt = bench_R (op, src_img, mask_img, dst_img, n, pixman_image_composite_empty, WIDTH, HEIGHT); #endif t2 = gettime (); pix_cnt = bench_R (op, src_img, mask_img, dst_img, n, func, WIDTH, HEIGHT); t3 = gettime (); printf (" R:%6.2f", (double)pix_cnt / ((t3 - t2) - (t2 - t1)) / 1000000.); fflush (stdout); memcpy (dst, src, BUFSIZE); memcpy (src, dst, BUFSIZE); n = 1 + npix / (16 * TINYWIDTH * TINYWIDTH); t1 = gettime (); #if EXCLUDE_OVERHEAD pix_cnt = bench_RT (op, src_img, mask_img, dst_img, n, pixman_image_composite_empty, WIDTH, HEIGHT); #endif t2 = gettime (); pix_cnt = bench_RT (op, src_img, mask_img, dst_img, n, func, WIDTH, HEIGHT); t3 = gettime (); printf (" RT:%6.2f (%4.0fKops/s)\n", (double)pix_cnt / ((t3 - t2) - (t2 - t1)) / 1000000., (double) n / ((t3 - t2) * 1000)); if (mask_img) { pixman_image_unref (mask_img); pixman_image_unref (xmask_img); } pixman_image_unref (src_img); pixman_image_unref (dst_img); pixman_image_unref (xsrc_img); pixman_image_unref (xdst_img); } #define PIXMAN_OP_OUT_REV (PIXMAN_OP_OUT_REVERSE) struct { char *testname; int src_fmt; int src_flags; int op; int mask_fmt; int mask_flags; int dst_fmt; } tests_tbl[] = { { "add_8_8_8", PIXMAN_a8, 0, PIXMAN_OP_ADD, PIXMAN_a8, 0, PIXMAN_a8 }, { "add_n_8_8", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_ADD, PIXMAN_a8, 0, PIXMAN_a8 }, { "add_n_8_8888", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_ADD, PIXMAN_a8, 0, PIXMAN_a8r8g8b8 }, { "add_n_8_x888", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_ADD, PIXMAN_a8, 0, PIXMAN_x8r8g8b8 }, { "add_n_8_0565", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_ADD, PIXMAN_a8, 0, PIXMAN_r5g6b5 }, { "add_n_8_1555", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_ADD, PIXMAN_a8, 0, PIXMAN_a1r5g5b5 }, { "add_n_8_4444", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_ADD, PIXMAN_a8, 0, PIXMAN_a4r4g4b4 }, { "add_n_8_2222", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_ADD, PIXMAN_a8, 0, PIXMAN_a2r2g2b2 }, { "add_n_8_2x10", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_ADD, PIXMAN_a8, 0, PIXMAN_x2r10g10b10 }, { "add_n_8_2a10", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_ADD, PIXMAN_a8, 0, PIXMAN_a2r10g10b10 }, { "add_n_8", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_ADD, PIXMAN_null, 0, PIXMAN_a8 }, { "add_n_8888", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_ADD, PIXMAN_null, 0, PIXMAN_a8r8g8b8 }, { "add_n_x888", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_ADD, PIXMAN_null, 0, PIXMAN_x8r8g8b8 }, { "add_n_0565", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_ADD, PIXMAN_null, 0, PIXMAN_r5g6b5 }, { "add_n_1555", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_ADD, PIXMAN_null, 0, PIXMAN_a1r5g5b5 }, { "add_n_4444", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_ADD, PIXMAN_null, 0, PIXMAN_a4r4g4b4 }, { "add_n_2222", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_ADD, PIXMAN_null, 0, PIXMAN_a2r2g2b2 }, { "add_n_2x10", PIXMAN_a2r10g10b10, 1, PIXMAN_OP_ADD, PIXMAN_null, 0, PIXMAN_x2r10g10b10 }, { "add_n_2a10", PIXMAN_a2r10g10b10, 1, PIXMAN_OP_ADD, PIXMAN_null, 0, PIXMAN_a2r10g10b10 }, { "add_8_8", PIXMAN_a8, 0, PIXMAN_OP_ADD, PIXMAN_null, 0, PIXMAN_a8 }, { "add_x888_x888", PIXMAN_x8r8g8b8, 0, PIXMAN_OP_ADD, PIXMAN_null, 0, PIXMAN_x8r8g8b8 }, { "add_8888_8888", PIXMAN_a8r8g8b8, 0, PIXMAN_OP_ADD, PIXMAN_null, 0, PIXMAN_a8r8g8b8 }, { "add_8888_0565", PIXMAN_a8r8g8b8, 0, PIXMAN_OP_ADD, PIXMAN_null, 0, PIXMAN_r5g6b5 }, { "add_8888_1555", PIXMAN_a8r8g8b8, 0, PIXMAN_OP_ADD, PIXMAN_null, 0, PIXMAN_a1r5g5b5 }, { "add_8888_4444", PIXMAN_a8r8g8b8, 0, PIXMAN_OP_ADD, PIXMAN_null, 0, PIXMAN_a4r4g4b4 }, { "add_8888_2222", PIXMAN_a8r8g8b8, 0, PIXMAN_OP_ADD, PIXMAN_null, 0, PIXMAN_a2r2g2b2 }, { "add_0565_0565", PIXMAN_r5g6b5, 0, PIXMAN_OP_ADD, PIXMAN_null, 0, PIXMAN_r5g6b5 }, { "add_1555_1555", PIXMAN_a1r5g5b5, 0, PIXMAN_OP_ADD, PIXMAN_null, 0, PIXMAN_a1r5g5b5 }, { "add_0565_2x10", PIXMAN_r5g6b5, 0, PIXMAN_OP_ADD, PIXMAN_null, 0, PIXMAN_x2r10g10b10 }, { "add_2a10_2a10", PIXMAN_a2r10g10b10, 0, PIXMAN_OP_ADD, PIXMAN_null, 0, PIXMAN_a2r10g10b10 }, { "in_n_8_8", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_IN, PIXMAN_a8, 0, PIXMAN_a8 }, { "in_8_8", PIXMAN_a8, 0, PIXMAN_OP_IN, PIXMAN_null, 0, PIXMAN_a8 }, { "src_n_2222", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_a2r2g2b2 }, { "src_n_0565", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_r5g6b5 }, { "src_n_1555", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_a1r5g5b5 }, { "src_n_4444", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_a4r4g4b4 }, { "src_n_x888", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_x8r8g8b8 }, { "src_n_8888", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_a8r8g8b8 }, { "src_n_2x10", PIXMAN_a2r10g10b10, 1, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_x2r10g10b10 }, { "src_n_2a10", PIXMAN_a2r10g10b10, 1, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_a2r10g10b10 }, { "src_8888_0565", PIXMAN_a8r8g8b8, 0, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_r5g6b5 }, { "src_0565_8888", PIXMAN_r5g6b5, 0, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_a8r8g8b8 }, { "src_8888_4444", PIXMAN_a8r8g8b8, 0, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_a4r4g4b4 }, { "src_8888_2222", PIXMAN_a8r8g8b8, 0, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_a2r2g2b2 }, { "src_8888_2x10", PIXMAN_a8r8g8b8, 0, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_x2r10g10b10 }, { "src_8888_2a10", PIXMAN_a8r8g8b8, 0, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_a2r10g10b10 }, { "src_0888_0565", PIXMAN_r8g8b8, 0, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_r5g6b5 }, { "src_0888_8888", PIXMAN_r8g8b8, 0, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_a8r8g8b8 }, { "src_0888_x888", PIXMAN_r8g8b8, 0, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_x8r8g8b8 }, { "src_0888_8888_rev", PIXMAN_b8g8r8, 0, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_x8r8g8b8 }, { "src_0888_0565_rev", PIXMAN_b8g8r8, 0, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_r5g6b5 }, { "src_x888_x888", PIXMAN_x8r8g8b8, 0, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_x8r8g8b8 }, { "src_x888_8888", PIXMAN_x8r8g8b8, 0, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_a8r8g8b8 }, { "src_8888_8888", PIXMAN_a8r8g8b8, 0, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_a8r8g8b8 }, { "src_0565_0565", PIXMAN_r5g6b5, 0, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_r5g6b5 }, { "src_1555_0565", PIXMAN_a1r5g5b5, 0, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_r5g6b5 }, { "src_0565_1555", PIXMAN_r5g6b5, 0, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_a1r5g5b5 }, { "src_8_8", PIXMAN_a8, 0, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_a8 }, { "src_n_8", PIXMAN_a8, 1, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_a8 }, { "src_n_8_0565", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_SRC, PIXMAN_a8, 0, PIXMAN_r5g6b5 }, { "src_n_8_1555", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_SRC, PIXMAN_a8, 0, PIXMAN_a1r5g5b5 }, { "src_n_8_4444", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_SRC, PIXMAN_a8, 0, PIXMAN_a4r4g4b4 }, { "src_n_8_2222", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_SRC, PIXMAN_a8, 0, PIXMAN_a2r2g2b2 }, { "src_n_8_x888", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_SRC, PIXMAN_a8, 0, PIXMAN_x8r8g8b8 }, { "src_n_8_8888", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_SRC, PIXMAN_a8, 0, PIXMAN_a8r8g8b8 }, { "src_n_8_2x10", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_SRC, PIXMAN_a8, 0, PIXMAN_x2r10g10b10 }, { "src_n_8_2a10", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_SRC, PIXMAN_a8, 0, PIXMAN_a2r10g10b10 }, { "src_8888_8_0565", PIXMAN_a8r8g8b8, 0, PIXMAN_OP_SRC, PIXMAN_a8, 0, PIXMAN_r5g6b5 }, { "src_0888_8_0565", PIXMAN_r8g8b8, 0, PIXMAN_OP_SRC, PIXMAN_a8, 0, PIXMAN_r5g6b5 }, { "src_0888_8_8888", PIXMAN_r8g8b8, 0, PIXMAN_OP_SRC, PIXMAN_a8, 0, PIXMAN_a8r8g8b8 }, { "src_0888_8_x888", PIXMAN_r8g8b8, 0, PIXMAN_OP_SRC, PIXMAN_a8, 0, PIXMAN_x8r8g8b8 }, { "src_x888_8_x888", PIXMAN_x8r8g8b8, 0, PIXMAN_OP_SRC, PIXMAN_a8, 0, PIXMAN_x8r8g8b8 }, { "src_x888_8_8888", PIXMAN_x8r8g8b8, 0, PIXMAN_OP_SRC, PIXMAN_a8, 0, PIXMAN_a8r8g8b8 }, { "src_0565_8_0565", PIXMAN_r5g6b5, 0, PIXMAN_OP_SRC, PIXMAN_a8, 0, PIXMAN_r5g6b5 }, { "src_1555_8_0565", PIXMAN_a1r5g5b5, 0, PIXMAN_OP_SRC, PIXMAN_a8, 0, PIXMAN_r5g6b5 }, { "src_0565_8_1555", PIXMAN_r5g6b5, 0, PIXMAN_OP_SRC, PIXMAN_a8, 0, PIXMAN_a1r5g5b5 }, { "over_n_x888", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OVER, PIXMAN_null, 0, PIXMAN_x8r8g8b8 }, { "over_n_8888", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OVER, PIXMAN_null, 0, PIXMAN_a8r8g8b8 }, { "over_n_0565", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OVER, PIXMAN_null, 0, PIXMAN_r5g6b5 }, { "over_n_1555", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OVER, PIXMAN_null, 0, PIXMAN_a1r5g5b5 }, { "over_8888_0565", PIXMAN_a8r8g8b8, 0, PIXMAN_OP_OVER, PIXMAN_null, 0, PIXMAN_r5g6b5 }, { "over_8888_8888", PIXMAN_a8r8g8b8, 0, PIXMAN_OP_OVER, PIXMAN_null, 0, PIXMAN_a8r8g8b8 }, { "over_8888_x888", PIXMAN_a8r8g8b8, 0, PIXMAN_OP_OVER, PIXMAN_null, 0, PIXMAN_x8r8g8b8 }, { "over_x888_8_0565", PIXMAN_x8r8g8b8, 0, PIXMAN_OP_OVER, PIXMAN_a8, 0, PIXMAN_r5g6b5 }, { "over_x888_8_8888", PIXMAN_x8r8g8b8, 0, PIXMAN_OP_OVER, PIXMAN_a8, 0, PIXMAN_a8r8g8b8 }, { "over_n_8_0565", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OVER, PIXMAN_a8, 0, PIXMAN_r5g6b5 }, { "over_n_8_1555", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OVER, PIXMAN_a8, 0, PIXMAN_a1r5g5b5 }, { "over_n_8_4444", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OVER, PIXMAN_a8, 0, PIXMAN_a4r4g4b4 }, { "over_n_8_2222", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OVER, PIXMAN_a8, 0, PIXMAN_a2r2g2b2 }, { "over_n_8_x888", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OVER, PIXMAN_a8, 0, PIXMAN_x8r8g8b8 }, { "over_n_8_8888", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OVER, PIXMAN_a8, 0, PIXMAN_a8r8g8b8 }, { "over_n_8_2x10", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OVER, PIXMAN_a8, 0, PIXMAN_x2r10g10b10 }, { "over_n_8_2a10", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OVER, PIXMAN_a8, 0, PIXMAN_a2r10g10b10 }, { "over_n_8888_8888_ca", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, 2, PIXMAN_a8r8g8b8 }, { "over_n_8888_x888_ca", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, 2, PIXMAN_x8r8g8b8 }, { "over_n_8888_0565_ca", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, 2, PIXMAN_r5g6b5 }, { "over_n_8888_1555_ca", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, 2, PIXMAN_a1r5g5b5 }, { "over_n_8888_4444_ca", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, 2, PIXMAN_a4r4g4b4 }, { "over_n_8888_2222_ca", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, 2, PIXMAN_a2r2g2b2 }, { "over_n_8888_2x10_ca", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, 2, PIXMAN_x2r10g10b10 }, { "over_n_8888_2a10_ca", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, 2, PIXMAN_a2r10g10b10 }, { "over_8888_n_8888", PIXMAN_a8r8g8b8, 0, PIXMAN_OP_OVER, PIXMAN_a8, 1, PIXMAN_a8r8g8b8 }, { "over_8888_n_x888", PIXMAN_a8r8g8b8, 0, PIXMAN_OP_OVER, PIXMAN_a8, 1, PIXMAN_x8r8g8b8 }, { "over_8888_n_0565", PIXMAN_a8r8g8b8, 0, PIXMAN_OP_OVER, PIXMAN_a8, 1, PIXMAN_r5g6b5 }, { "over_8888_n_1555", PIXMAN_a8r8g8b8, 0, PIXMAN_OP_OVER, PIXMAN_a8, 1, PIXMAN_a1r5g5b5 }, { "over_x888_n_8888", PIXMAN_x8r8g8b8, 0, PIXMAN_OP_OVER, PIXMAN_a8, 1, PIXMAN_a8r8g8b8 }, { "outrev_n_8_0565", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OUT_REV, PIXMAN_a8, 0, PIXMAN_r5g6b5 }, { "outrev_n_8_1555", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OUT_REV, PIXMAN_a8, 0, PIXMAN_a1r5g5b5 }, { "outrev_n_8_x888", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OUT_REV, PIXMAN_a8, 0, PIXMAN_x8r8g8b8 }, { "outrev_n_8_8888", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OUT_REV, PIXMAN_a8, 0, PIXMAN_a8r8g8b8 }, { "outrev_n_8888_0565_ca", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OUT_REV, PIXMAN_a8r8g8b8, 2, PIXMAN_r5g6b5 }, { "outrev_n_8888_1555_ca", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OUT_REV, PIXMAN_a8r8g8b8, 2, PIXMAN_a1r5g5b5 }, { "outrev_n_8888_x888_ca", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OUT_REV, PIXMAN_a8r8g8b8, 2, PIXMAN_x8r8g8b8 }, { "outrev_n_8888_8888_ca", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OUT_REV, PIXMAN_a8r8g8b8, 2, PIXMAN_a8r8g8b8 }, { "over_reverse_n_8888", PIXMAN_a8r8g8b8, 0, PIXMAN_OP_OVER_REVERSE, PIXMAN_null, 0, PIXMAN_a8r8g8b8 }, { "pixbuf", PIXMAN_x8b8g8r8, 0, PIXMAN_OP_SRC, PIXMAN_a8b8g8r8, 0, PIXMAN_a8r8g8b8 }, { "rpixbuf", PIXMAN_x8b8g8r8, 0, PIXMAN_OP_SRC, PIXMAN_a8b8g8r8, 0, PIXMAN_a8b8g8r8 }, }; int main (int argc, char *argv[]) { double x; int i; const char *pattern = NULL; for (i = 1; i < argc; i++) { if (argv[i][0] == '-') { if (strchr (argv[i] + 1, 'b')) { use_scaling = TRUE; filter = PIXMAN_FILTER_BILINEAR; } else if (strchr (argv[i] + 1, 'n')) { use_scaling = TRUE; filter = PIXMAN_FILTER_NEAREST; } } else { pattern = argv[i]; } } if (!pattern) { printf ("Usage: lowlevel-blt-bench [-b] [-n] pattern\n"); printf (" -n : benchmark nearest scaling\n"); printf (" -b : benchmark bilinear scaling\n"); return 1; } src = aligned_malloc (4096, BUFSIZE * 3); memset (src, 0xCC, BUFSIZE * 3); dst = src + (BUFSIZE / 4); mask = dst + (BUFSIZE / 4); printf ("Benchmark for a set of most commonly used functions\n"); printf ("---\n"); printf ("All results are presented in millions of pixels per second\n"); printf ("L1 - small Xx1 rectangle (fitting L1 cache), always blitted at the same\n"); printf (" memory location with small drift in horizontal direction\n"); printf ("L2 - small XxY rectangle (fitting L2 cache), always blitted at the same\n"); printf (" memory location with small drift in horizontal direction\n"); printf ("M - large %dx%d rectangle, always blitted at the same\n", WIDTH - 64, HEIGHT); printf (" memory location with small drift in horizontal direction\n"); printf ("HT - random rectangles with %dx%d average size are copied from\n", TILEWIDTH, TILEWIDTH); printf (" one %dx%d buffer to another, traversing from left to right\n", WIDTH, HEIGHT); printf (" and from top to bottom\n"); printf ("VT - random rectangles with %dx%d average size are copied from\n", TILEWIDTH, TILEWIDTH); printf (" one %dx%d buffer to another, traversing from top to bottom\n", WIDTH, HEIGHT); printf (" and from left to right\n"); printf ("R - random rectangles with %dx%d average size are copied from\n", TILEWIDTH, TILEWIDTH); printf (" random locations of one %dx%d buffer to another\n", WIDTH, HEIGHT); printf ("RT - as R, but %dx%d average sized rectangles are copied\n", TINYWIDTH, TINYWIDTH); printf ("---\n"); bandwidth = x = bench_memcpy (); printf ("reference memcpy speed = %.1fMB/s (%.1fMP/s for 32bpp fills)\n", x / 1000000., x / 4000000); if (use_scaling) { printf ("---\n"); if (filter == PIXMAN_FILTER_BILINEAR) printf ("BILINEAR scaling\n"); else if (filter == PIXMAN_FILTER_NEAREST) printf ("NEAREST scaling\n"); else printf ("UNKNOWN scaling\n"); } printf ("---\n"); for (i = 0; i < ARRAY_LENGTH (tests_tbl); i++) { if (strcmp (pattern, "all") == 0 || strcmp (tests_tbl[i].testname, pattern) == 0) { bench_composite (tests_tbl[i].testname, tests_tbl[i].src_fmt, tests_tbl[i].src_flags, tests_tbl[i].op, tests_tbl[i].mask_fmt, tests_tbl[i].mask_flags, tests_tbl[i].dst_fmt, bandwidth/8); } } free (src); return 0; }