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