1952204abSmrg#include <stdio.h> 2952204abSmrg#include <stdlib.h> 3952204abSmrg#include "utils.h" 4952204abSmrg 59ad247e8Sjmcneill#define WIDTH 48 69ad247e8Sjmcneill#define HEIGHT 48 7952204abSmrg 81b18d63aSmrgstatic const pixman_format_code_t formats[] = 91b18d63aSmrg{ 101b18d63aSmrg PIXMAN_a8r8g8b8, 111b18d63aSmrg PIXMAN_a2r10g10b10, 121b18d63aSmrg PIXMAN_a4r4g4b4, 134f2886e8Smrg PIXMAN_a8, 144f2886e8Smrg PIXMAN_rgba_float, 151b18d63aSmrg}; 161b18d63aSmrg 171b18d63aSmrgstatic const pixman_format_code_t alpha_formats[] = 181b18d63aSmrg{ 191b18d63aSmrg PIXMAN_null, 201b18d63aSmrg PIXMAN_a8, 211b18d63aSmrg PIXMAN_a2r10g10b10, 224f2886e8Smrg PIXMAN_a4r4g4b4, 234f2886e8Smrg PIXMAN_rgba_float, 241b18d63aSmrg}; 251b18d63aSmrg 261b18d63aSmrgstatic const int origins[] = 271b18d63aSmrg{ 281b18d63aSmrg 0, 10, -100 291b18d63aSmrg}; 301b18d63aSmrg 311b18d63aSmrgstatic void 321b18d63aSmrgon_destroy (pixman_image_t *image, void *data) 331b18d63aSmrg{ 341b18d63aSmrg uint32_t *bits = pixman_image_get_data (image); 351b18d63aSmrg 361b18d63aSmrg fence_free (bits); 371b18d63aSmrg} 381b18d63aSmrg 391b18d63aSmrgstatic pixman_image_t * 401b18d63aSmrgmake_image (pixman_format_code_t format) 411b18d63aSmrg{ 421b18d63aSmrg uint32_t *bits; 431b18d63aSmrg uint8_t bpp = PIXMAN_FORMAT_BPP (format) / 8; 441b18d63aSmrg pixman_image_t *image; 451b18d63aSmrg 464f2886e8Smrg if (format != PIXMAN_rgba_float) 474f2886e8Smrg bits = (uint32_t *)make_random_bytes (WIDTH * HEIGHT * bpp); 484f2886e8Smrg else 494f2886e8Smrg bits = (uint32_t *)make_random_floats (WIDTH * HEIGHT * bpp); 501b18d63aSmrg 511b18d63aSmrg image = pixman_image_create_bits (format, WIDTH, HEIGHT, bits, WIDTH * bpp); 521b18d63aSmrg 531b18d63aSmrg if (image && bits) 541b18d63aSmrg pixman_image_set_destroy_function (image, on_destroy, NULL); 551b18d63aSmrg 561b18d63aSmrg return image; 571b18d63aSmrg} 581b18d63aSmrg 594f2886e8Smrgstatic float 601b18d63aSmrgget_alpha (pixman_image_t *image, int x, int y, int orig_x, int orig_y) 61952204abSmrg{ 621b18d63aSmrg uint8_t *bits; 634f2886e8Smrg uint32_t r; 641b18d63aSmrg 651b18d63aSmrg if (image->common.alpha_map) 661b18d63aSmrg { 671b18d63aSmrg if (x - orig_x >= 0 && x - orig_x < WIDTH && 681b18d63aSmrg y - orig_y >= 0 && y - orig_y < HEIGHT) 691b18d63aSmrg { 701b18d63aSmrg image = (pixman_image_t *)image->common.alpha_map; 711b18d63aSmrg 721b18d63aSmrg x -= orig_x; 731b18d63aSmrg y -= orig_y; 741b18d63aSmrg } 751b18d63aSmrg else 761b18d63aSmrg { 774f2886e8Smrg return 0.f; 781b18d63aSmrg } 791b18d63aSmrg } 80952204abSmrg 811b18d63aSmrg bits = (uint8_t *)image->bits.bits; 82952204abSmrg 831b18d63aSmrg if (image->bits.format == PIXMAN_a8) 841b18d63aSmrg { 851b18d63aSmrg r = bits[y * WIDTH + x]; 864f2886e8Smrg return r / 255.f; 871b18d63aSmrg } 881b18d63aSmrg else if (image->bits.format == PIXMAN_a2r10g10b10) 891b18d63aSmrg { 901b18d63aSmrg r = ((uint32_t *)bits)[y * WIDTH + x] >> 30; 914f2886e8Smrg return r / 3.f; 921b18d63aSmrg } 931b18d63aSmrg else if (image->bits.format == PIXMAN_a8r8g8b8) 941b18d63aSmrg { 951b18d63aSmrg r = ((uint32_t *)bits)[y * WIDTH + x] >> 24; 964f2886e8Smrg return r / 255.f; 971b18d63aSmrg } 981b18d63aSmrg else if (image->bits.format == PIXMAN_a4r4g4b4) 99952204abSmrg { 1001b18d63aSmrg r = ((uint16_t *)bits)[y * WIDTH + x] >> 12; 1014f2886e8Smrg return r / 15.f; 1024f2886e8Smrg } 1034f2886e8Smrg else if (image->bits.format == PIXMAN_rgba_float) 1044f2886e8Smrg { 1054f2886e8Smrg return ((float *)bits)[y * WIDTH * 4 + x * 4 + 3]; 1061b18d63aSmrg } 1071b18d63aSmrg else 1081b18d63aSmrg { 1091b18d63aSmrg assert (0); 1104f2886e8Smrg return 0.f; 1111b18d63aSmrg } 1121b18d63aSmrg} 113952204abSmrg 1149ad247e8Sjmcneillstatic uint16_t 1159ad247e8Sjmcneillget_red (pixman_image_t *image, int x, int y, int orig_x, int orig_y) 1169ad247e8Sjmcneill{ 1179ad247e8Sjmcneill uint8_t *bits; 1189ad247e8Sjmcneill uint16_t r; 1199ad247e8Sjmcneill 1209ad247e8Sjmcneill bits = (uint8_t *)image->bits.bits; 1219ad247e8Sjmcneill 1229ad247e8Sjmcneill if (image->bits.format == PIXMAN_a8) 1239ad247e8Sjmcneill { 1249ad247e8Sjmcneill r = 0x00; 1259ad247e8Sjmcneill } 1269ad247e8Sjmcneill else if (image->bits.format == PIXMAN_a2r10g10b10) 1279ad247e8Sjmcneill { 1289ad247e8Sjmcneill r = ((uint32_t *)bits)[y * WIDTH + x] >> 14; 1299ad247e8Sjmcneill r &= 0xffc0; 1309ad247e8Sjmcneill r |= (r >> 10); 1319ad247e8Sjmcneill } 1329ad247e8Sjmcneill else if (image->bits.format == PIXMAN_a8r8g8b8) 1339ad247e8Sjmcneill { 1349ad247e8Sjmcneill r = ((uint32_t *)bits)[y * WIDTH + x] >> 16; 1359ad247e8Sjmcneill r &= 0xff; 1369ad247e8Sjmcneill r |= r << 8; 1379ad247e8Sjmcneill } 1389ad247e8Sjmcneill else if (image->bits.format == PIXMAN_a4r4g4b4) 1399ad247e8Sjmcneill { 1409ad247e8Sjmcneill r = ((uint16_t *)bits)[y * WIDTH + x] >> 8; 1419ad247e8Sjmcneill r &= 0xf; 1429ad247e8Sjmcneill r |= r << 4; 1439ad247e8Sjmcneill r |= r << 8; 1449ad247e8Sjmcneill } 1454f2886e8Smrg else if (image->bits.format == PIXMAN_rgba_float) 1464f2886e8Smrg { 1474f2886e8Smrg double tmp = ((float *)bits)[y * WIDTH * 4 + x * 4]; 1484f2886e8Smrg return tmp * 65535.; 1494f2886e8Smrg } 1509ad247e8Sjmcneill else 1519ad247e8Sjmcneill { 1529ad247e8Sjmcneill assert (0); 1539ad247e8Sjmcneill } 1549ad247e8Sjmcneill 1559ad247e8Sjmcneill return r; 1569ad247e8Sjmcneill} 157952204abSmrg 1584f2886e8Smrgstatic float get_alpha_err(pixman_format_code_t sf, pixman_format_code_t saf, 1594f2886e8Smrg pixman_format_code_t df, pixman_format_code_t daf) 1604f2886e8Smrg{ 1614f2886e8Smrg pixman_format_code_t s = saf != PIXMAN_null ? saf : sf; 1624f2886e8Smrg pixman_format_code_t d = daf != PIXMAN_null ? daf : df; 1634f2886e8Smrg 1644f2886e8Smrg /* There are cases where we go through the 8 bit compositing 1654f2886e8Smrg * path even with 10bpc and higher formats. 1664f2886e8Smrg */ 1674f2886e8Smrg if (PIXMAN_FORMAT_A(s) == PIXMAN_FORMAT_A(d)) 1684f2886e8Smrg return 1.f / 255.f; 1694f2886e8Smrg else if (PIXMAN_FORMAT_A(s) > PIXMAN_FORMAT_A(d)) 1704f2886e8Smrg return 1.f / ((1 << PIXMAN_FORMAT_A(d)) - 1); 1714f2886e8Smrg else 1724f2886e8Smrg return 1.f / ((1 << PIXMAN_FORMAT_A(s)) - 1); 1734f2886e8Smrg} 1744f2886e8Smrg 1751b18d63aSmrgstatic int 1761b18d63aSmrgrun_test (int s, int d, int sa, int da, int soff, int doff) 1771b18d63aSmrg{ 1781b18d63aSmrg pixman_format_code_t sf = formats[s]; 1791b18d63aSmrg pixman_format_code_t df = formats[d]; 1801b18d63aSmrg pixman_format_code_t saf = alpha_formats[sa]; 1811b18d63aSmrg pixman_format_code_t daf = alpha_formats[da]; 1829ad247e8Sjmcneill pixman_image_t *src, *dst, *orig_dst, *alpha, *orig_alpha; 1831b18d63aSmrg pixman_transform_t t1; 1841b18d63aSmrg int j, k; 1854f2886e8Smrg int n_red_bits; 1861b18d63aSmrg 1871b18d63aSmrg soff = origins[soff]; 1881b18d63aSmrg doff = origins[doff]; 1891b18d63aSmrg 1909ad247e8Sjmcneill n_red_bits = PIXMAN_FORMAT_R (df); 1919ad247e8Sjmcneill 1929ad247e8Sjmcneill /* Source */ 1939ad247e8Sjmcneill src = make_image (sf); 1949ad247e8Sjmcneill if (saf != PIXMAN_null) 1959ad247e8Sjmcneill { 1969ad247e8Sjmcneill alpha = make_image (saf); 1979ad247e8Sjmcneill pixman_image_set_alpha_map (src, alpha, soff, soff); 1989ad247e8Sjmcneill pixman_image_unref (alpha); 1999ad247e8Sjmcneill } 2009ad247e8Sjmcneill 2019ad247e8Sjmcneill /* Destination */ 2029ad247e8Sjmcneill orig_dst = make_image (df); 2039ad247e8Sjmcneill dst = make_image (df); 2049ad247e8Sjmcneill pixman_image_composite (PIXMAN_OP_SRC, orig_dst, NULL, dst, 2059ad247e8Sjmcneill 0, 0, 0, 0, 0, 0, WIDTH, HEIGHT); 2069ad247e8Sjmcneill 2079ad247e8Sjmcneill if (daf != PIXMAN_null) 2089ad247e8Sjmcneill { 2099ad247e8Sjmcneill orig_alpha = make_image (daf); 2109ad247e8Sjmcneill alpha = make_image (daf); 2119ad247e8Sjmcneill 2129ad247e8Sjmcneill pixman_image_composite (PIXMAN_OP_SRC, orig_alpha, NULL, alpha, 2139ad247e8Sjmcneill 0, 0, 0, 0, 0, 0, WIDTH, HEIGHT); 2141b18d63aSmrg 2159ad247e8Sjmcneill pixman_image_set_alpha_map (orig_dst, orig_alpha, doff, doff); 2169ad247e8Sjmcneill pixman_image_set_alpha_map (dst, alpha, doff, doff); 2179ad247e8Sjmcneill 2189ad247e8Sjmcneill pixman_image_unref (orig_alpha); 2199ad247e8Sjmcneill pixman_image_unref (alpha); 2209ad247e8Sjmcneill } 221952204abSmrg 222953d7d37Smrg /* Transformations, repeats and filters on destinations should be ignored, 223953d7d37Smrg * so just set some random ones. 2241b18d63aSmrg */ 2251b18d63aSmrg pixman_transform_init_identity (&t1); 2261b18d63aSmrg pixman_transform_scale (&t1, NULL, pixman_int_to_fixed (100), pixman_int_to_fixed (11)); 2271b18d63aSmrg pixman_transform_rotate (&t1, NULL, pixman_double_to_fixed (0.5), pixman_double_to_fixed (0.11)); 2281b18d63aSmrg pixman_transform_translate (&t1, NULL, pixman_int_to_fixed (11), pixman_int_to_fixed (17)); 2291b18d63aSmrg 2301b18d63aSmrg pixman_image_set_transform (dst, &t1); 231953d7d37Smrg pixman_image_set_filter (dst, PIXMAN_FILTER_BILINEAR, NULL, 0); 232953d7d37Smrg pixman_image_set_repeat (dst, PIXMAN_REPEAT_REFLECT); 2331b18d63aSmrg 2341b18d63aSmrg pixman_image_composite (PIXMAN_OP_ADD, src, NULL, dst, 2351b18d63aSmrg 0, 0, 0, 0, 0, 0, WIDTH, HEIGHT); 2361b18d63aSmrg 2371b18d63aSmrg for (j = MAX (doff, 0); j < MIN (HEIGHT, HEIGHT + doff); ++j) 2381b18d63aSmrg { 2391b18d63aSmrg for (k = MAX (doff, 0); k < MIN (WIDTH, WIDTH + doff); ++k) 240952204abSmrg { 2414f2886e8Smrg float sa, da, oda, refa; 2429ad247e8Sjmcneill uint16_t sr, dr, odr, refr; 2434f2886e8Smrg float err; 2444f2886e8Smrg 2454f2886e8Smrg err = get_alpha_err(sf, saf, df, daf); 2461b18d63aSmrg 2471b18d63aSmrg sa = get_alpha (src, k, j, soff, soff); 2481b18d63aSmrg da = get_alpha (dst, k, j, doff, doff); 2491b18d63aSmrg oda = get_alpha (orig_dst, k, j, doff, doff); 2501b18d63aSmrg 2514f2886e8Smrg if (sa + oda > 1.f) 2524f2886e8Smrg refa = 1.f; 2531b18d63aSmrg else 2549ad247e8Sjmcneill refa = sa + oda; 2551b18d63aSmrg 2564f2886e8Smrg if (da - err > refa || 2574f2886e8Smrg da + err < refa) 258952204abSmrg { 2594f2886e8Smrg printf ("\nWrong alpha value at (%d, %d). Should be %g; got %g. Source was %g, original dest was %g\n", 2609ad247e8Sjmcneill k, j, refa, da, sa, oda); 2611b18d63aSmrg 2621b18d63aSmrg printf ("src: %s, alpha: %s, origin %d %d\ndst: %s, alpha: %s, origin: %d %d\n\n", 2631b18d63aSmrg format_name (sf), 2641b18d63aSmrg format_name (saf), 2651b18d63aSmrg soff, soff, 2661b18d63aSmrg format_name (df), 2671b18d63aSmrg format_name (daf), 2681b18d63aSmrg doff, doff); 2691b18d63aSmrg return 1; 2701b18d63aSmrg } 2719ad247e8Sjmcneill 2729ad247e8Sjmcneill /* There are cases where we go through the 8 bit compositing 2739ad247e8Sjmcneill * path even with 10bpc formats. This results in incorrect 2749ad247e8Sjmcneill * results here, so only do the red check for narrow formats 2759ad247e8Sjmcneill */ 2769ad247e8Sjmcneill if (n_red_bits <= 8) 2779ad247e8Sjmcneill { 2789ad247e8Sjmcneill sr = get_red (src, k, j, soff, soff); 2799ad247e8Sjmcneill dr = get_red (dst, k, j, doff, doff); 2809ad247e8Sjmcneill odr = get_red (orig_dst, k, j, doff, doff); 2819ad247e8Sjmcneill 2829ad247e8Sjmcneill if (sr + odr > 0xffff) 2839ad247e8Sjmcneill refr = 0xffff; 2849ad247e8Sjmcneill else 2859ad247e8Sjmcneill refr = sr + odr; 2869ad247e8Sjmcneill 2879ad247e8Sjmcneill if (abs ((dr >> (16 - n_red_bits)) - (refr >> (16 - n_red_bits))) > 1) 2889ad247e8Sjmcneill { 2899ad247e8Sjmcneill printf ("%d red bits\n", n_red_bits); 2909ad247e8Sjmcneill printf ("\nWrong red value at (%d, %d). Should be 0x%x; got 0x%x. Source was 0x%x, original dest was 0x%x\n", 2919ad247e8Sjmcneill k, j, refr, dr, sr, odr); 2929ad247e8Sjmcneill 2939ad247e8Sjmcneill printf ("src: %s, alpha: %s, origin %d %d\ndst: %s, alpha: %s, origin: %d %d\n\n", 2949ad247e8Sjmcneill format_name (sf), 2959ad247e8Sjmcneill format_name (saf), 2969ad247e8Sjmcneill soff, soff, 2979ad247e8Sjmcneill format_name (df), 2989ad247e8Sjmcneill format_name (daf), 2999ad247e8Sjmcneill doff, doff); 3009ad247e8Sjmcneill return 1; 3019ad247e8Sjmcneill } 3029ad247e8Sjmcneill } 3031b18d63aSmrg } 3041b18d63aSmrg } 3051b18d63aSmrg 3061b18d63aSmrg pixman_image_set_alpha_map (src, NULL, 0, 0); 3071b18d63aSmrg pixman_image_set_alpha_map (dst, NULL, 0, 0); 3081b18d63aSmrg pixman_image_set_alpha_map (orig_dst, NULL, 0, 0); 3091b18d63aSmrg 3101b18d63aSmrg pixman_image_unref (src); 3111b18d63aSmrg pixman_image_unref (dst); 3121b18d63aSmrg pixman_image_unref (orig_dst); 3131b18d63aSmrg 3141b18d63aSmrg return 0; 3151b18d63aSmrg} 3161b18d63aSmrg 3171b18d63aSmrgint 3181b18d63aSmrgmain (int argc, char **argv) 3191b18d63aSmrg{ 3201b18d63aSmrg int i, j, a, b, x, y; 321952204abSmrg 322f4f78bb6Smrg prng_srand (0); 323f4f78bb6Smrg 3241b18d63aSmrg for (i = 0; i < ARRAY_LENGTH (formats); ++i) 3251b18d63aSmrg { 3261b18d63aSmrg for (j = 0; j < ARRAY_LENGTH (formats); ++j) 3271b18d63aSmrg { 3281b18d63aSmrg for (a = 0; a < ARRAY_LENGTH (alpha_formats); ++a) 3291b18d63aSmrg { 3301b18d63aSmrg for (b = 0; b < ARRAY_LENGTH (alpha_formats); ++b) 331952204abSmrg { 3321b18d63aSmrg for (x = 0; x < ARRAY_LENGTH (origins); ++x) 3331b18d63aSmrg { 3341b18d63aSmrg for (y = 0; y < ARRAY_LENGTH (origins); ++y) 3351b18d63aSmrg { 3361b18d63aSmrg if (run_test (i, j, a, b, x, y) != 0) 3371b18d63aSmrg return 1; 3381b18d63aSmrg } 3391b18d63aSmrg } 340952204abSmrg } 341952204abSmrg } 342952204abSmrg } 343952204abSmrg } 344952204abSmrg 345952204abSmrg return 0; 346952204abSmrg} 347