pixman/test/tolerance-test.c
Siarhei Siamashka 56622140e3 test: Fix OpenMP clauses for the tolerance-test
Compiling with the Intel Compiler reveals a problem:

tolerance-test.c(350): error: index variable "i" of for statement following an OpenMP for pragma must be private
  #       pragma omp parallel for default(none) shared(i) private (result)
  ^

In addition to this, the 'result' variable also should not be private
(otherwise its value does not survive after the end of the loop). It
needs to be either shared or use the reduction clause to describe how
the results from multiple threads are combined together. Reduction
seems to be more appropriate here.
2014-04-02 12:46:09 +03:00

361 lines
9.7 KiB
C

#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <float.h>
#include <math.h>
#include "utils.h"
#define MAX_WIDTH 16
#define MAX_HEIGHT 16
#define MAX_STRIDE 4
static const pixman_format_code_t formats[] =
{
PIXMAN_a2r10g10b10,
PIXMAN_x2r10g10b10,
PIXMAN_a8r8g8b8,
PIXMAN_a4r4g4b4,
PIXMAN_a2r2g2b2,
PIXMAN_r5g6b5,
PIXMAN_r3g3b2,
};
static const pixman_op_t operators[] =
{
PIXMAN_OP_CLEAR,
PIXMAN_OP_SRC,
PIXMAN_OP_DST,
PIXMAN_OP_OVER,
PIXMAN_OP_OVER_REVERSE,
PIXMAN_OP_IN,
PIXMAN_OP_IN_REVERSE,
PIXMAN_OP_OUT,
PIXMAN_OP_OUT_REVERSE,
PIXMAN_OP_ATOP,
PIXMAN_OP_ATOP_REVERSE,
PIXMAN_OP_XOR,
PIXMAN_OP_ADD,
PIXMAN_OP_SATURATE,
PIXMAN_OP_DISJOINT_CLEAR,
PIXMAN_OP_DISJOINT_SRC,
PIXMAN_OP_DISJOINT_DST,
PIXMAN_OP_DISJOINT_OVER,
PIXMAN_OP_DISJOINT_OVER_REVERSE,
PIXMAN_OP_DISJOINT_IN,
PIXMAN_OP_DISJOINT_IN_REVERSE,
PIXMAN_OP_DISJOINT_OUT,
PIXMAN_OP_DISJOINT_OUT_REVERSE,
PIXMAN_OP_DISJOINT_ATOP,
PIXMAN_OP_DISJOINT_ATOP_REVERSE,
PIXMAN_OP_DISJOINT_XOR,
PIXMAN_OP_CONJOINT_CLEAR,
PIXMAN_OP_CONJOINT_SRC,
PIXMAN_OP_CONJOINT_DST,
PIXMAN_OP_CONJOINT_OVER,
PIXMAN_OP_CONJOINT_OVER_REVERSE,
PIXMAN_OP_CONJOINT_IN,
PIXMAN_OP_CONJOINT_IN_REVERSE,
PIXMAN_OP_CONJOINT_OUT,
PIXMAN_OP_CONJOINT_OUT_REVERSE,
PIXMAN_OP_CONJOINT_ATOP,
PIXMAN_OP_CONJOINT_ATOP_REVERSE,
PIXMAN_OP_CONJOINT_XOR,
PIXMAN_OP_MULTIPLY,
PIXMAN_OP_SCREEN,
PIXMAN_OP_OVERLAY,
PIXMAN_OP_DARKEN,
PIXMAN_OP_LIGHTEN,
PIXMAN_OP_COLOR_DODGE,
PIXMAN_OP_COLOR_BURN,
PIXMAN_OP_HARD_LIGHT,
PIXMAN_OP_SOFT_LIGHT,
PIXMAN_OP_DIFFERENCE,
PIXMAN_OP_EXCLUSION,
};
#define RANDOM_ELT(array) \
(array[prng_rand_n (ARRAY_LENGTH (array))])
static void
free_bits (pixman_image_t *image, void *data)
{
free (image->bits.bits);
}
static pixman_image_t *
create_image (pixman_image_t **clone)
{
pixman_format_code_t format = RANDOM_ELT (formats);
pixman_image_t *image;
int width = prng_rand_n (MAX_WIDTH);
int height = prng_rand_n (MAX_HEIGHT);
int stride = ((width * (PIXMAN_FORMAT_BPP (format) / 8)) + 3) & ~3;
uint32_t *bytes = malloc (stride * height);
prng_randmemset (bytes, stride * height, RANDMEMSET_MORE_00_AND_FF);
image = pixman_image_create_bits (
format, width, height, bytes, stride);
pixman_image_set_destroy_function (image, free_bits, NULL);
assert (image);
if (clone)
{
uint32_t *bytes_dup = malloc (stride * height);
memcpy (bytes_dup, bytes, stride * height);
*clone = pixman_image_create_bits (
format, width, height, bytes_dup, stride);
pixman_image_set_destroy_function (*clone, free_bits, NULL);
}
return image;
}
static pixman_bool_t
access (pixman_image_t *image, int x, int y, uint32_t *pixel)
{
int bytes_per_pixel;
int stride;
uint8_t *location;
if (x < 0 || x >= image->bits.width || y < 0 || y >= image->bits.height)
return FALSE;
bytes_per_pixel = PIXMAN_FORMAT_BPP (image->bits.format) / 8;
stride = image->bits.rowstride * 4;
location = (uint8_t *)image->bits.bits + y * stride + x * bytes_per_pixel;
if (bytes_per_pixel == 4)
*pixel = *(uint32_t *)location;
else if (bytes_per_pixel == 2)
*pixel = *(uint16_t *)location;
else if (bytes_per_pixel == 1)
*pixel = *(uint8_t *)location;
else
assert (0);
return TRUE;
}
static void
get_color (pixel_checker_t *checker,
pixman_image_t *image,
int x, int y,
color_t *color,
uint32_t *pixel)
{
if (!access (image, x, y, pixel))
{
color->a = 0.0;
color->r = 0.0;
color->g = 0.0;
color->b = 0.0;
}
else
{
pixel_checker_convert_pixel_to_color (
checker, *pixel, color);
}
}
static pixman_bool_t
verify (int test_no,
pixman_op_t op,
pixman_image_t *source,
pixman_image_t *mask,
pixman_image_t *dest,
pixman_image_t *orig_dest,
int x, int y,
int width, int height,
pixman_bool_t component_alpha)
{
pixel_checker_t dest_checker, src_checker, mask_checker;
int i, j;
pixel_checker_init (&src_checker, source->bits.format);
pixel_checker_init (&dest_checker, dest->bits.format);
pixel_checker_init (&mask_checker, mask->bits.format);
assert (dest->bits.format == orig_dest->bits.format);
for (j = y; j < y + height; ++j)
{
for (i = x; i < x + width; ++i)
{
color_t src_color, mask_color, orig_dest_color, result;
uint32_t dest_pixel, orig_dest_pixel, src_pixel, mask_pixel;
access (dest, i, j, &dest_pixel);
get_color (&src_checker,
source, i - x, j - y,
&src_color, &src_pixel);
get_color (&mask_checker,
mask, i - x, j - y,
&mask_color, &mask_pixel);
get_color (&dest_checker,
orig_dest, i, j,
&orig_dest_color, &orig_dest_pixel);
do_composite (op,
&src_color, &mask_color, &orig_dest_color,
&result, component_alpha);
if (!pixel_checker_check (&dest_checker, dest_pixel, &result))
{
int a, r, g, b;
printf ("--------- Test 0x%x failed ---------\n", test_no);
printf (" operator: %s (%s alpha)\n", operator_name (op),
component_alpha? "component" : "unified");
printf (" dest_x, dest_y: %d %d\n", x, y);
printf (" width, height: %d %d\n", width, height);
printf (" source: format: %-14s size: %2d x %2d\n",
format_name (source->bits.format),
source->bits.width, source->bits.height);
printf (" mask: format: %-14s size: %2d x %2d\n",
format_name (mask->bits.format),
mask->bits.width, mask->bits.height);
printf (" dest: format: %-14s size: %2d x %2d\n",
format_name (dest->bits.format),
dest->bits.width, dest->bits.height);
printf (" -- Failed pixel: (%d, %d) --\n", i, j);
printf (" source ARGB: %f %f %f %f (pixel: %x)\n",
src_color.a, src_color.r, src_color.g, src_color.b,
src_pixel);
printf (" mask ARGB: %f %f %f %f (pixel: %x)\n",
mask_color.a, mask_color.r, mask_color.g, mask_color.b,
mask_pixel);
printf (" dest ARGB: %f %f %f %f (pixel: %x)\n",
orig_dest_color.a, orig_dest_color.r, orig_dest_color.g, orig_dest_color.b,
orig_dest_pixel);
printf (" expected ARGB: %f %f %f %f\n",
result.a, result.r, result.g, result.b);
pixel_checker_get_min (&dest_checker, &result, &a, &r, &g, &b);
printf (" min acceptable: %8d %8d %8d %8d\n", a, r, g, b);
pixel_checker_split_pixel (&dest_checker, dest_pixel, &a, &r, &g, &b);
printf (" got: %8d %8d %8d %8d (pixel: %x)\n", a, r, g, b, dest_pixel);
pixel_checker_get_max (&dest_checker, &result, &a, &r, &g, &b);
printf (" max acceptable: %8d %8d %8d %8d\n", a, r, g, b);
printf ("\n");
printf (" { %s,\n", operator_name (op));
printf (" PIXMAN_%s,\t0x%x,\n", format_name (source->bits.format), src_pixel);
printf (" PIXMAN_%s,\t0x%x,\n", format_name (mask->bits.format), mask_pixel);
printf (" PIXMAN_%s,\t0x%x\n", format_name (dest->bits.format), orig_dest_pixel);
printf (" },\n");
return FALSE;
}
}
}
return TRUE;
}
static pixman_bool_t
do_check (int i)
{
pixman_image_t *source, *dest, *mask;
pixman_op_t op;
int x, y, width, height;
pixman_image_t *dest_copy;
pixman_bool_t result = TRUE;
pixman_bool_t component_alpha;
prng_srand (i);
op = RANDOM_ELT (operators);
x = prng_rand_n (MAX_WIDTH);
y = prng_rand_n (MAX_HEIGHT);
width = prng_rand_n (MAX_WIDTH) + 4;
height = prng_rand_n (MAX_HEIGHT) + 4;
source = create_image (NULL);
mask = create_image (NULL);
dest = create_image (&dest_copy);
if (x >= dest->bits.width)
x = dest->bits.width / 2;
if (y >= dest->bits.height)
y = dest->bits.height / 2;
if (x + width > dest->bits.width)
width = dest->bits.width - x;
if (y + height > dest->bits.height)
height = dest->bits.height - y;
component_alpha = prng_rand_n (2);
pixman_image_set_component_alpha (mask, component_alpha);
pixman_image_composite32 (op, source, mask, dest,
0, 0, 0, 0,
x, y, width, height);
if (!verify (i, op, source, mask, dest, dest_copy,
x, y, width, height, component_alpha))
{
result = FALSE;
}
pixman_image_unref (source);
pixman_image_unref (mask);
pixman_image_unref (dest);
pixman_image_unref (dest_copy);
return result;
}
#define N_TESTS 10000000
int
main (int argc, const char *argv[])
{
int i;
int result = 0;
if (argc == 2)
{
if (strcmp (argv[1], "--forever") == 0)
{
uint32_t n;
prng_srand (time (0));
n = prng_rand();
for (;;)
do_check (n++);
}
else
{
do_check (strtol (argv[1], NULL, 0));
}
}
else
{
#ifdef USE_OPENMP
# pragma omp parallel for default(none) reduction(|:result)
#endif
for (i = 0; i < N_TESTS; ++i)
{
if (!do_check (i))
result |= 1;
}
}
return result;
}