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