Home | History | Annotate | Download | only in test
      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include "utils.h"
      4 
      5 #define WIDTH 48
      6 #define HEIGHT 48
      7 
      8 static const pixman_format_code_t formats[] =
      9 {
     10     PIXMAN_a8r8g8b8,
     11     PIXMAN_a2r10g10b10,
     12     PIXMAN_a4r4g4b4,
     13     PIXMAN_a8
     14 };
     15 
     16 static const pixman_format_code_t alpha_formats[] =
     17 {
     18     PIXMAN_null,
     19     PIXMAN_a8,
     20     PIXMAN_a2r10g10b10,
     21     PIXMAN_a4r4g4b4
     22 };
     23 
     24 static const int origins[] =
     25 {
     26     0, 10, -100
     27 };
     28 
     29 static void
     30 on_destroy (pixman_image_t *image, void *data)
     31 {
     32     uint32_t *bits = pixman_image_get_data (image);
     33 
     34     fence_free (bits);
     35 }
     36 
     37 static pixman_image_t *
     38 make_image (pixman_format_code_t format)
     39 {
     40     uint32_t *bits;
     41     uint8_t bpp = PIXMAN_FORMAT_BPP (format) / 8;
     42     pixman_image_t *image;
     43 
     44     bits = (uint32_t *)make_random_bytes (WIDTH * HEIGHT * bpp);
     45 
     46     image = pixman_image_create_bits (format, WIDTH, HEIGHT, bits, WIDTH * bpp);
     47 
     48     if (image && bits)
     49 	pixman_image_set_destroy_function (image, on_destroy, NULL);
     50 
     51     return image;
     52 }
     53 
     54 static uint8_t
     55 get_alpha (pixman_image_t *image, int x, int y, int orig_x, int orig_y)
     56 {
     57     uint8_t *bits;
     58     uint8_t r;
     59 
     60     if (image->common.alpha_map)
     61     {
     62 	if (x - orig_x >= 0 && x - orig_x < WIDTH &&
     63 	    y - orig_y >= 0 && y - orig_y < HEIGHT)
     64 	{
     65 	    image = (pixman_image_t *)image->common.alpha_map;
     66 
     67 	    x -= orig_x;
     68 	    y -= orig_y;
     69 	}
     70 	else
     71 	{
     72 	    return 0;
     73 	}
     74     }
     75 
     76     bits = (uint8_t *)image->bits.bits;
     77 
     78     if (image->bits.format == PIXMAN_a8)
     79     {
     80 	r = bits[y * WIDTH + x];
     81     }
     82     else if (image->bits.format == PIXMAN_a2r10g10b10)
     83     {
     84 	r = ((uint32_t *)bits)[y * WIDTH + x] >> 30;
     85 	r |= r << 2;
     86 	r |= r << 4;
     87     }
     88     else if (image->bits.format == PIXMAN_a8r8g8b8)
     89     {
     90 	r = ((uint32_t *)bits)[y * WIDTH + x] >> 24;
     91     }
     92     else if (image->bits.format == PIXMAN_a4r4g4b4)
     93     {
     94 	r = ((uint16_t *)bits)[y * WIDTH + x] >> 12;
     95 	r |= r << 4;
     96     }
     97     else
     98     {
     99 	assert (0);
    100     }
    101 
    102     return r;
    103 }
    104 
    105 static uint16_t
    106 get_red (pixman_image_t *image, int x, int y, int orig_x, int orig_y)
    107 {
    108     uint8_t *bits;
    109     uint16_t r;
    110 
    111     bits = (uint8_t *)image->bits.bits;
    112 
    113     if (image->bits.format == PIXMAN_a8)
    114     {
    115 	r = 0x00;
    116     }
    117     else if (image->bits.format == PIXMAN_a2r10g10b10)
    118     {
    119 	r = ((uint32_t *)bits)[y * WIDTH + x] >> 14;
    120 	r &= 0xffc0;
    121 	r |= (r >> 10);
    122     }
    123     else if (image->bits.format == PIXMAN_a8r8g8b8)
    124     {
    125 	r = ((uint32_t *)bits)[y * WIDTH + x] >> 16;
    126 	r &= 0xff;
    127 	r |= r << 8;
    128     }
    129     else if (image->bits.format == PIXMAN_a4r4g4b4)
    130     {
    131 	r = ((uint16_t *)bits)[y * WIDTH + x] >> 8;
    132 	r &= 0xf;
    133 	r |= r << 4;
    134 	r |= r << 8;
    135     }
    136     else
    137     {
    138 	assert (0);
    139     }
    140 
    141     return r;
    142 }
    143 
    144 static int
    145 run_test (int s, int d, int sa, int da, int soff, int doff)
    146 {
    147     pixman_format_code_t sf = formats[s];
    148     pixman_format_code_t df = formats[d];
    149     pixman_format_code_t saf = alpha_formats[sa];
    150     pixman_format_code_t daf = alpha_formats[da];
    151     pixman_image_t *src, *dst, *orig_dst, *alpha, *orig_alpha;
    152     pixman_transform_t t1;
    153     int j, k;
    154     int n_alpha_bits, n_red_bits;
    155 
    156     soff = origins[soff];
    157     doff = origins[doff];
    158 
    159     n_alpha_bits = PIXMAN_FORMAT_A (df);
    160     if (daf != PIXMAN_null)
    161 	n_alpha_bits = PIXMAN_FORMAT_A (daf);
    162 
    163     n_red_bits = PIXMAN_FORMAT_R (df);
    164 
    165     /* Source */
    166     src = make_image (sf);
    167     if (saf != PIXMAN_null)
    168     {
    169 	alpha = make_image (saf);
    170 	pixman_image_set_alpha_map (src, alpha, soff, soff);
    171 	pixman_image_unref (alpha);
    172     }
    173 
    174     /* Destination */
    175     orig_dst = make_image (df);
    176     dst = make_image (df);
    177     pixman_image_composite (PIXMAN_OP_SRC, orig_dst, NULL, dst,
    178 			    0, 0, 0, 0, 0, 0, WIDTH, HEIGHT);
    179 
    180     if (daf != PIXMAN_null)
    181     {
    182 	orig_alpha = make_image (daf);
    183 	alpha = make_image (daf);
    184 
    185 	pixman_image_composite (PIXMAN_OP_SRC, orig_alpha, NULL, alpha,
    186 				0, 0, 0, 0, 0, 0, WIDTH, HEIGHT);
    187 
    188 	pixman_image_set_alpha_map (orig_dst, orig_alpha, doff, doff);
    189 	pixman_image_set_alpha_map (dst, alpha, doff, doff);
    190 
    191 	pixman_image_unref (orig_alpha);
    192 	pixman_image_unref (alpha);
    193     }
    194 
    195     /* Transformations, repeats and filters on destinations should be ignored,
    196      * so just set some random ones.
    197      */
    198     pixman_transform_init_identity (&t1);
    199     pixman_transform_scale (&t1, NULL, pixman_int_to_fixed (100), pixman_int_to_fixed (11));
    200     pixman_transform_rotate (&t1, NULL, pixman_double_to_fixed (0.5), pixman_double_to_fixed (0.11));
    201     pixman_transform_translate (&t1, NULL, pixman_int_to_fixed (11), pixman_int_to_fixed (17));
    202 
    203     pixman_image_set_transform (dst, &t1);
    204     pixman_image_set_filter (dst, PIXMAN_FILTER_BILINEAR, NULL, 0);
    205     pixman_image_set_repeat (dst, PIXMAN_REPEAT_REFLECT);
    206 
    207     pixman_image_composite (PIXMAN_OP_ADD, src, NULL, dst,
    208 			    0, 0, 0, 0, 0, 0, WIDTH, HEIGHT);
    209 
    210     for (j = MAX (doff, 0); j < MIN (HEIGHT, HEIGHT + doff); ++j)
    211     {
    212 	for (k = MAX (doff, 0); k < MIN (WIDTH, WIDTH + doff); ++k)
    213 	{
    214 	    uint8_t sa, da, oda, refa;
    215 	    uint16_t sr, dr, odr, refr;
    216 
    217 	    sa = get_alpha (src, k, j, soff, soff);
    218 	    da = get_alpha (dst, k, j, doff, doff);
    219 	    oda = get_alpha (orig_dst, k, j, doff, doff);
    220 
    221 	    if (sa + oda > 255)
    222 		refa = 255;
    223 	    else
    224 		refa = sa + oda;
    225 
    226 	    if (da >> (8 - n_alpha_bits) != refa >> (8 - n_alpha_bits))
    227 	    {
    228 		printf ("\nWrong alpha value at (%d, %d). Should be 0x%x; got 0x%x. Source was 0x%x, original dest was 0x%x\n",
    229 			k, j, refa, da, sa, oda);
    230 
    231 		printf ("src: %s, alpha: %s, origin %d %d\ndst: %s, alpha: %s, origin: %d %d\n\n",
    232 			format_name (sf),
    233 			format_name (saf),
    234 			soff, soff,
    235 			format_name (df),
    236 			format_name (daf),
    237 			doff, doff);
    238 		return 1;
    239 	    }
    240 
    241 	    /* There are cases where we go through the 8 bit compositing
    242 	     * path even with 10bpc formats. This results in incorrect
    243 	     * results here, so only do the red check for narrow formats
    244 	     */
    245 	    if (n_red_bits <= 8)
    246 	    {
    247 		sr = get_red (src, k, j, soff, soff);
    248 		dr = get_red (dst, k, j, doff, doff);
    249 		odr = get_red (orig_dst, k, j, doff, doff);
    250 
    251 		if (sr + odr > 0xffff)
    252 		    refr = 0xffff;
    253 		else
    254 		    refr = sr + odr;
    255 
    256 		if (abs ((dr >> (16 - n_red_bits)) - (refr >> (16 - n_red_bits))) > 1)
    257 		{
    258 		    printf ("%d red bits\n", n_red_bits);
    259 		    printf ("\nWrong red value at (%d, %d). Should be 0x%x; got 0x%x. Source was 0x%x, original dest was 0x%x\n",
    260 			    k, j, refr, dr, sr, odr);
    261 
    262 		    printf ("src: %s, alpha: %s, origin %d %d\ndst: %s, alpha: %s, origin: %d %d\n\n",
    263 			    format_name (sf),
    264 			    format_name (saf),
    265 			    soff, soff,
    266 			    format_name (df),
    267 			    format_name (daf),
    268 			    doff, doff);
    269 		    return 1;
    270 		}
    271 	    }
    272 	}
    273     }
    274 
    275     pixman_image_set_alpha_map (src, NULL, 0, 0);
    276     pixman_image_set_alpha_map (dst, NULL, 0, 0);
    277     pixman_image_set_alpha_map (orig_dst, NULL, 0, 0);
    278 
    279     pixman_image_unref (src);
    280     pixman_image_unref (dst);
    281     pixman_image_unref (orig_dst);
    282 
    283     return 0;
    284 }
    285 
    286 int
    287 main (int argc, char **argv)
    288 {
    289     int i, j, a, b, x, y;
    290 
    291     prng_srand (0);
    292 
    293     for (i = 0; i < ARRAY_LENGTH (formats); ++i)
    294     {
    295 	for (j = 0; j < ARRAY_LENGTH (formats); ++j)
    296 	{
    297 	    for (a = 0; a < ARRAY_LENGTH (alpha_formats); ++a)
    298 	    {
    299 		for (b = 0; b < ARRAY_LENGTH (alpha_formats); ++b)
    300 		{
    301 		    for (x = 0; x < ARRAY_LENGTH (origins); ++x)
    302 		    {
    303 			for (y = 0; y < ARRAY_LENGTH (origins); ++y)
    304 			{
    305 			    if (run_test (i, j, a, b, x, y) != 0)
    306 				return 1;
    307 			}
    308 		    }
    309 		}
    310 	    }
    311 	}
    312     }
    313 
    314     return 0;
    315 }
    316