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