[Pixman] [PATCH 2/2] pixman: Add tests for xrgb/argb formats.

Maarten Lankhorst maarten.lankhorst at linux.intel.com
Wed Aug 1 12:41:34 UTC 2018


Signed-off-by: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
---
 test/alphamap.c    | 73 +++++++++++++++++++++++++++++++-------------
 test/stress-test.c | 75 +++++++++++++++++++++++++++++++++------------
 test/utils.c       | 76 ++++++++++++++++++++++++++++++++++++++++++++++
 test/utils.h       |  2 ++
 4 files changed, 186 insertions(+), 40 deletions(-)

diff --git a/test/alphamap.c b/test/alphamap.c
index 4d09076fbcf3..150d33eed5b5 100644
--- a/test/alphamap.c
+++ b/test/alphamap.c
@@ -10,7 +10,8 @@ static const pixman_format_code_t formats[] =
     PIXMAN_a8r8g8b8,
     PIXMAN_a2r10g10b10,
     PIXMAN_a4r4g4b4,
-    PIXMAN_a8
+    PIXMAN_a8,
+    PIXMAN_rgba_float,
 };
 
 static const pixman_format_code_t alpha_formats[] =
@@ -18,7 +19,8 @@ static const pixman_format_code_t alpha_formats[] =
     PIXMAN_null,
     PIXMAN_a8,
     PIXMAN_a2r10g10b10,
-    PIXMAN_a4r4g4b4
+    PIXMAN_a4r4g4b4,
+    PIXMAN_rgba_float,
 };
 
 static const int origins[] =
@@ -41,7 +43,10 @@ make_image (pixman_format_code_t format)
     uint8_t bpp = PIXMAN_FORMAT_BPP (format) / 8;
     pixman_image_t *image;
 
-    bits = (uint32_t *)make_random_bytes (WIDTH * HEIGHT * bpp);
+    if (format != PIXMAN_rgba_float)
+	bits = (uint32_t *)make_random_bytes (WIDTH * HEIGHT * bpp);
+    else
+	bits = (uint32_t *)make_random_floats (WIDTH * HEIGHT * bpp);
 
     image = pixman_image_create_bits (format, WIDTH, HEIGHT, bits, WIDTH * bpp);
 
@@ -51,11 +56,11 @@ make_image (pixman_format_code_t format)
     return image;
 }
 
-static uint8_t
+static float
 get_alpha (pixman_image_t *image, int x, int y, int orig_x, int orig_y)
 {
     uint8_t *bits;
-    uint8_t r;
+    uint32_t r;
 
     if (image->common.alpha_map)
     {
@@ -69,7 +74,7 @@ get_alpha (pixman_image_t *image, int x, int y, int orig_x, int orig_y)
 	}
 	else
 	{
-	    return 0;
+	    return 0.f;
 	}
     }
 
@@ -78,28 +83,32 @@ get_alpha (pixman_image_t *image, int x, int y, int orig_x, int orig_y)
     if (image->bits.format == PIXMAN_a8)
     {
 	r = bits[y * WIDTH + x];
+	return r / 255.f;
     }
     else if (image->bits.format == PIXMAN_a2r10g10b10)
     {
 	r = ((uint32_t *)bits)[y * WIDTH + x] >> 30;
-	r |= r << 2;
-	r |= r << 4;
+	return r / 3.f;
     }
     else if (image->bits.format == PIXMAN_a8r8g8b8)
     {
 	r = ((uint32_t *)bits)[y * WIDTH + x] >> 24;
+	return r / 255.f;
     }
     else if (image->bits.format == PIXMAN_a4r4g4b4)
     {
 	r = ((uint16_t *)bits)[y * WIDTH + x] >> 12;
-	r |= r << 4;
+	return r / 15.f;
+    }
+    else if (image->bits.format == PIXMAN_rgba_float)
+    {
+	return ((float *)bits)[y * WIDTH * 4 + x * 4 + 3];
     }
     else
     {
 	assert (0);
+	return 0.f;
     }
-
-    return r;
 }
 
 static uint16_t
@@ -133,6 +142,11 @@ get_red (pixman_image_t *image, int x, int y, int orig_x, int orig_y)
 	r |= r << 4;
 	r |= r << 8;
     }
+    else if (image->bits.format == PIXMAN_rgba_float)
+    {
+	double tmp = ((float *)bits)[y * WIDTH * 4 + x * 4];
+	return tmp * 65535.;
+    }
     else
     {
 	assert (0);
@@ -141,6 +155,23 @@ get_red (pixman_image_t *image, int x, int y, int orig_x, int orig_y)
     return r;
 }
 
+static float get_alpha_err(pixman_format_code_t sf, pixman_format_code_t saf,
+			   pixman_format_code_t df, pixman_format_code_t daf)
+{
+	pixman_format_code_t s = saf != PIXMAN_null ? saf : sf;
+	pixman_format_code_t d = daf != PIXMAN_null ? daf : df;
+
+	/* There are cases where we go through the 8 bit compositing
+	 * path even with 10bpc and higher formats.
+	 */
+	if (PIXMAN_FORMAT_A(s) == PIXMAN_FORMAT_A(d))
+		return 1.f / 255.f;
+	else if (PIXMAN_FORMAT_A(s) > PIXMAN_FORMAT_A(d))
+		return 1.f / ((1 << PIXMAN_FORMAT_A(d)) - 1);
+	else
+		return 1.f / ((1 << PIXMAN_FORMAT_A(s)) - 1);
+}
+
 static int
 run_test (int s, int d, int sa, int da, int soff, int doff)
 {
@@ -151,15 +182,11 @@ run_test (int s, int d, int sa, int da, int soff, int doff)
     pixman_image_t *src, *dst, *orig_dst, *alpha, *orig_alpha;
     pixman_transform_t t1;
     int j, k;
-    int n_alpha_bits, n_red_bits;
+    int n_red_bits;
 
     soff = origins[soff];
     doff = origins[doff];
 
-    n_alpha_bits = PIXMAN_FORMAT_A (df);
-    if (daf != PIXMAN_null)
-	n_alpha_bits = PIXMAN_FORMAT_A (daf);
-
     n_red_bits = PIXMAN_FORMAT_R (df);
 
     /* Source */
@@ -211,21 +238,25 @@ run_test (int s, int d, int sa, int da, int soff, int doff)
     {
 	for (k = MAX (doff, 0); k < MIN (WIDTH, WIDTH + doff); ++k)
 	{
-	    uint8_t sa, da, oda, refa;
+	    float sa, da, oda, refa;
 	    uint16_t sr, dr, odr, refr;
+	    float err;
+
+	    err = get_alpha_err(sf, saf, df, daf);
 
 	    sa = get_alpha (src, k, j, soff, soff);
 	    da = get_alpha (dst, k, j, doff, doff);
 	    oda = get_alpha (orig_dst, k, j, doff, doff);
 
-	    if (sa + oda > 255)
-		refa = 255;
+	    if (sa + oda > 1.f)
+		refa = 1.f;
 	    else
 		refa = sa + oda;
 
-	    if (da >> (8 - n_alpha_bits) != refa >> (8 - n_alpha_bits))
+	    if (da - err > refa ||
+	        da + err < refa)
 	    {
-		printf ("\nWrong alpha value at (%d, %d). Should be 0x%x; got 0x%x. Source was 0x%x, original dest was 0x%x\n",
+		printf ("\nWrong alpha value at (%d, %d). Should be %g; got %g. Source was %g, original dest was %g\n",
 			k, j, refa, da, sa, oda);
 
 		printf ("src: %s, alpha: %s, origin %d %d\ndst: %s, alpha: %s, origin: %d %d\n\n",
diff --git a/test/stress-test.c b/test/stress-test.c
index 85d12932c9aa..6b4f7d606f72 100644
--- a/test/stress-test.c
+++ b/test/stress-test.c
@@ -11,6 +11,8 @@
 
 static const pixman_format_code_t image_formats[] =
 {
+    PIXMAN_rgba_float,
+    PIXMAN_rgb_float,
     PIXMAN_a8r8g8b8,
     PIXMAN_x8r8g8b8,
     PIXMAN_r5g6b5,
@@ -100,6 +102,14 @@ get_size (void)
     }
 }
 
+static uint32_t
+real_reader (const void *src, int size);
+
+static void *xor_ptr(const void *ptr)
+{
+	return (void *)(((intptr_t)ptr) ^ (intptr_t)0x8000000080000000);
+}
+
 static void
 destroy (pixman_image_t *image, void *data)
 {
@@ -114,6 +124,9 @@ destroy (pixman_image_t *image, void *data)
 	    if (image->bits.rowstride < 0)
 		bits -= (- image->bits.rowstride * (image->bits.height - 1));
 
+	    if (image->bits.read_func == real_reader)
+		bits = xor_ptr(bits);
+
 	    fence_free (bits);
 	}
     }
@@ -124,6 +137,7 @@ destroy (pixman_image_t *image, void *data)
 static uint32_t
 real_reader (const void *src, int size)
 {
+    src = xor_ptr(src);
     switch (size)
     {
     case 1:
@@ -141,6 +155,7 @@ real_reader (const void *src, int size)
 static void
 real_writer (void *src, uint32_t value, int size)
 {
+    src = xor_ptr(src);
     switch (size)
     {
     case 1:
@@ -247,9 +262,20 @@ create_random_bits_image (alpha_preference_t alpha_preference)
     pixman_filter_t filter;
     pixman_fixed_t *coefficients = NULL;
     int n_coefficients = 0;
+    int align_add, align_mask;
 
     /* format */
     format = random_format (alpha_preference);
+    switch (PIXMAN_FORMAT_BPP (format)) {
+    case 128:
+	align_mask = 15;
+	align_add = align_mask + prng_rand_n (65);
+	break;
+    default:
+	align_mask = 3;
+	align_add = align_mask + prng_rand_n (17);
+	break;
+    }
 
     indexed = NULL;
     if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR)
@@ -291,9 +317,12 @@ create_random_bits_image (alpha_preference_t alpha_preference)
     {
     default:
     case 0:
-	stride = (width * PIXMAN_FORMAT_BPP (format) + 7) / 8 + prng_rand_n (17);
-	stride = (stride + 3) & (~3);
-	bits = (uint32_t *)make_random_bytes (height * stride);
+	stride = (width * PIXMAN_FORMAT_BPP (format) + 7) / 8;
+	stride = (stride + align_add) & (~align_mask);
+	if (format == PIXMAN_rgb_float || format == PIXMAN_rgba_float)
+	    bits = (uint32_t *)make_random_floats (height * stride);
+	else
+	    bits = (uint32_t *)make_random_bytes (height * stride);
 	break;
 
     case 1:
@@ -302,8 +331,8 @@ create_random_bits_image (alpha_preference_t alpha_preference)
 	break;
 
     case 2: /* Zero-filled */
-	stride = (width * PIXMAN_FORMAT_BPP (format) + 7) / 8 + prng_rand_n (17);
-	stride = (stride + 3) & (~3);
+	stride = (width * PIXMAN_FORMAT_BPP (format) + 7) / 8;
+	stride = (stride + align_add) & (~align_mask);
 	bits = fence_malloc (height * stride);
 	if (!bits)
 	    return NULL;
@@ -311,8 +340,8 @@ create_random_bits_image (alpha_preference_t alpha_preference)
 	break;
 
     case 3: /* Filled with 0xFF */
-	stride = (width * PIXMAN_FORMAT_BPP (format) + 7) / 8 + prng_rand_n (17);
-	stride = (stride + 3) & (~3);
+	stride = (width * PIXMAN_FORMAT_BPP (format) + 7) / 8;
+	stride = (stride + align_add) & (~align_mask);
 	bits = fence_malloc (height * stride);
 	if (!bits)
 	    return NULL;
@@ -320,27 +349,35 @@ create_random_bits_image (alpha_preference_t alpha_preference)
 	break;
 
     case 4: /* bits is a bad pointer, has read/write functions */
-	stride = 232;
-	bits = (void *)0x01;
-	read_func = fake_reader;
-	write_func = fake_writer;
-	break;
+	if (PIXMAN_FORMAT_BPP (format) <= 32) {
+	    stride = 232;
+	    bits = (void *)0x01;
+	    read_func = fake_reader;
+	    write_func = fake_writer;
+	    break;
+	}
 
     case 5: /* bits is a real pointer, has read/write functions */
-	stride = (width * PIXMAN_FORMAT_BPP (format) + 7) / 8 + prng_rand_n (17);
-	stride = (stride + 3) & (~3);
+	stride = (width * PIXMAN_FORMAT_BPP (format) + 7) / 8;
+	stride = (stride + align_add) & (~align_mask);
 	bits = fence_malloc (height * stride);
 	if (!bits)
 	    return NULL;
 	memset (bits, 0xff, height * stride);
-	read_func = real_reader;
-	write_func = real_writer;
+	if (PIXMAN_FORMAT_BPP (format) <= 32) {
+	    bits = xor_ptr(bits);
+	    read_func = real_reader;
+	    write_func = real_writer;
+	}
 	break;
 
     case 6: /* bits is a real pointer, stride is negative */
-	stride = (width * PIXMAN_FORMAT_BPP (format) + 7) / 8 + prng_rand_n (17);
-	stride = (stride + 3) & (~3);
-	bits = (uint32_t *)make_random_bytes (height * stride);
+	stride = (width * PIXMAN_FORMAT_BPP (format) + 7) / 8;
+	stride = (stride + align_add) & (~align_mask);
+	if (format == PIXMAN_rgb_float || format == PIXMAN_rgba_float)
+	    bits = (uint32_t *)make_random_floats (height * stride);
+	else
+	    bits = (uint32_t *)make_random_bytes (height * stride);
 	if (!bits)
 	    return NULL;
 	bits += ((height - 1) * stride) / 4;
diff --git a/test/utils.c b/test/utils.c
index f8e42a5d3f3d..4eeb068497ec 100644
--- a/test/utils.c
+++ b/test/utils.c
@@ -595,6 +595,21 @@ make_random_bytes (int n_bytes)
     return bytes;
 }
 
+float *
+make_random_floats (int n_bytes)
+{
+    uint8_t *bytes = fence_malloc (n_bytes);
+    float *vals = (float *)bytes;
+
+    if (!bytes)
+	return 0;
+
+    for (n_bytes /= 4; n_bytes; vals++, n_bytes--)
+	*vals = (float)rand() / (float)RAND_MAX;
+
+    return (float *)bytes;
+}
+
 void
 a8r8g8b8_to_rgba_np (uint32_t *dst, uint32_t *src, int n_pixels)
 {
@@ -1180,6 +1195,11 @@ static const format_entry_t format_list[] =
      * Aliases are not listed by list_formats ().
      */
 
+/* 128bpp formats */
+    ENTRY (rgba_float),
+/* 96bpp formats */
+    ENTRY (rgb_float),
+
 /* 32bpp formats */
     ENTRY (a8r8g8b8),
     ALIAS (a8r8g8b8,		"8888"),
@@ -1914,6 +1934,10 @@ pixel_checker_init (pixel_checker_t *checker, pixman_format_code_t format)
 
     checker->format = format;
 
+    if (format == PIXMAN_rgba_float ||
+	format == PIXMAN_rgb_float)
+	return;
+
     switch (PIXMAN_FORMAT_TYPE (format))
     {
     case PIXMAN_TYPE_A:
@@ -1970,10 +1994,19 @@ pixel_checker_init (pixel_checker_t *checker, pixman_format_code_t format)
     checker->bw = PIXMAN_FORMAT_B (format);
 }
 
+static void
+pixel_checker_require_uint32_format (const pixel_checker_t *checker)
+{
+    assert (checker->format != PIXMAN_rgba_float &&
+	    checker->format != PIXMAN_rgb_float);
+}
+
 void
 pixel_checker_split_pixel (const pixel_checker_t *checker, uint32_t pixel,
 			   int *a, int *r, int *g, int *b)
 {
+    pixel_checker_require_uint32_format(checker);
+
     *a = (pixel & checker->am) >> checker->as;
     *r = (pixel & checker->rm) >> checker->rs;
     *g = (pixel & checker->gm) >> checker->gs;
@@ -1987,6 +2020,8 @@ pixel_checker_get_masks (const pixel_checker_t *checker,
                          uint32_t              *gm,
                          uint32_t              *bm)
 {
+    pixel_checker_require_uint32_format(checker);
+
     if (am)
         *am = checker->am;
     if (rm)
@@ -2003,6 +2038,8 @@ pixel_checker_convert_pixel_to_color (const pixel_checker_t *checker,
 {
     int a, r, g, b;
 
+    pixel_checker_require_uint32_format(checker);
+
     pixel_checker_split_pixel (checker, pixel, &a, &r, &g, &b);
 
     if (checker->am == 0)
@@ -2078,6 +2115,8 @@ void
 pixel_checker_get_max (const pixel_checker_t *checker, color_t *color,
 		       int *am, int *rm, int *gm, int *bm)
 {
+    pixel_checker_require_uint32_format(checker);
+
     get_limits (checker, DEVIATION, color, am, rm, gm, bm);
 }
 
@@ -2085,6 +2124,8 @@ void
 pixel_checker_get_min (const pixel_checker_t *checker, color_t *color,
 		       int *am, int *rm, int *gm, int *bm)
 {
+    pixel_checker_require_uint32_format(checker);
+
     get_limits (checker, - DEVIATION, color, am, rm, gm, bm);
 }
 
@@ -2096,6 +2137,8 @@ pixel_checker_check (const pixel_checker_t *checker, uint32_t pixel,
     int32_t ai, ri, gi, bi;
     pixman_bool_t result;
 
+    pixel_checker_require_uint32_format(checker);
+
     pixel_checker_get_min (checker, color, &a_lo, &r_lo, &g_lo, &b_lo);
     pixel_checker_get_max (checker, color, &a_hi, &r_hi, &g_hi, &b_hi);
     pixel_checker_split_pixel (checker, pixel, &ai, &ri, &gi, &bi);
@@ -2108,3 +2151,36 @@ pixel_checker_check (const pixel_checker_t *checker, uint32_t pixel,
 
     return result;
 }
+
+static void
+color_limits (const pixel_checker_t *checker,
+	      double limit, const color_t *color, color_t *out)
+{
+    if (PIXMAN_FORMAT_A(checker->format))
+	out->a = color->a + limit;
+    else
+	out->a = 1.;
+
+    out->r = color->r + limit;
+    out->g = color->g + limit;
+    out->b = color->b + limit;
+}
+
+pixman_bool_t
+pixel_checker_check_color (const pixel_checker_t *checker,
+			   const color_t *actual, const color_t *reference)
+{
+    color_t min, max;
+    pixman_bool_t result;
+
+    color_limits(checker, -DEVIATION, reference, &min);
+    color_limits(checker, DEVIATION, reference, &max);
+
+    result =
+	actual->a >= min.a && actual->a <= max.a &&
+	actual->r >= min.r && actual->r <= max.r &&
+	actual->g >= min.g && actual->g <= max.g &&
+	actual->b >= min.b && actual->b <= max.b;
+
+    return result;
+}
diff --git a/test/utils.h b/test/utils.h
index e299d1d066ed..e5ac945ab3f8 100644
--- a/test/utils.h
+++ b/test/utils.h
@@ -119,6 +119,8 @@ fence_get_page_size ();
 /* Generate n_bytes random bytes in fence_malloced memory */
 uint8_t *
 make_random_bytes (int n_bytes);
+float *
+make_random_floats (int n_bytes);
 
 /* Return current time in seconds */
 double
-- 
2.18.0



More information about the Pixman mailing list