1 #include <assert.h> 2 #include <stdlib.h> 3 #include <stdio.h> 4 #include <string.h> 5 #include "utils.h" 6 7 /* 8 * We have a source image filled with solid color, set NORMAL or PAD repeat, 9 * and some transform which results in nearest neighbour scaling. 10 * 11 * The expected result is either that the destination image filled with this solid 12 * color or, if the transformation is such that we can't composite anything at 13 * all, that nothing has changed in the destination. 14 * 15 * The surrounding memory of the source image is a different solid color so that 16 * we are sure to get failures if we access it. 17 */ 18 static int 19 run_test (int32_t dst_width, 20 int32_t dst_height, 21 int32_t src_width, 22 int32_t src_height, 23 int32_t src_x, 24 int32_t src_y, 25 int32_t scale_x, 26 int32_t scale_y, 27 pixman_filter_t filter, 28 pixman_repeat_t repeat) 29 { 30 pixman_image_t * src_img; 31 pixman_image_t * dst_img; 32 pixman_transform_t transform; 33 uint32_t * srcbuf; 34 uint32_t * dstbuf; 35 pixman_color_t color_cc = { 0xcccc, 0xcccc, 0xcccc, 0xcccc }; 36 pixman_image_t * solid; 37 int result; 38 int i; 39 40 static const pixman_fixed_t kernel[] = 41 { 42 #define D(f) (pixman_double_to_fixed (f) + 0x0001) 43 44 pixman_int_to_fixed (5), 45 pixman_int_to_fixed (5), 46 D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), 47 D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), 48 D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), 49 D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), 50 D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0) 51 }; 52 53 result = 0; 54 55 srcbuf = (uint32_t *)malloc ((src_width + 10) * (src_height + 10) * 4); 56 dstbuf = (uint32_t *)malloc (dst_width * dst_height * 4); 57 58 memset (srcbuf, 0x88, src_width * src_height * 4); 59 memset (dstbuf, 0x33, dst_width * dst_height * 4); 60 61 src_img = pixman_image_create_bits ( 62 PIXMAN_a8r8g8b8, src_width, src_height, 63 srcbuf + (src_width + 10) * 5 + 5, (src_width + 10) * 4); 64 65 solid = pixman_image_create_solid_fill (&color_cc); 66 pixman_image_composite32 (PIXMAN_OP_SRC, solid, NULL, src_img, 67 0, 0, 0, 0, 0, 0, src_width, src_height); 68 pixman_image_unref (solid); 69 70 dst_img = pixman_image_create_bits ( 71 PIXMAN_a8r8g8b8, dst_width, dst_height, dstbuf, dst_width * 4); 72 73 pixman_transform_init_scale (&transform, scale_x, scale_y); 74 pixman_image_set_transform (src_img, &transform); 75 pixman_image_set_repeat (src_img, repeat); 76 if (filter == PIXMAN_FILTER_CONVOLUTION) 77 pixman_image_set_filter (src_img, filter, kernel, 27); 78 else 79 pixman_image_set_filter (src_img, filter, NULL, 0); 80 81 pixman_image_composite (PIXMAN_OP_SRC, src_img, NULL, dst_img, 82 src_x, src_y, 0, 0, 0, 0, dst_width, dst_height); 83 84 pixman_image_unref (src_img); 85 pixman_image_unref (dst_img); 86 87 for (i = 0; i < dst_width * dst_height; i++) 88 { 89 if (dstbuf[i] != 0xCCCCCCCC && dstbuf[i] != 0x33333333) 90 { 91 result = 1; 92 break; 93 } 94 } 95 96 free (srcbuf); 97 free (dstbuf); 98 return result; 99 } 100 101 typedef struct filter_info_t filter_info_t; 102 struct filter_info_t 103 { 104 pixman_filter_t value; 105 char name[28]; 106 }; 107 108 static const filter_info_t filters[] = 109 { 110 { PIXMAN_FILTER_NEAREST, "NEAREST" }, 111 { PIXMAN_FILTER_BILINEAR, "BILINEAR" }, 112 { PIXMAN_FILTER_CONVOLUTION, "CONVOLUTION" }, 113 }; 114 115 typedef struct repeat_info_t repeat_info_t; 116 struct repeat_info_t 117 { 118 pixman_repeat_t value; 119 char name[28]; 120 }; 121 122 123 static const repeat_info_t repeats[] = 124 { 125 { PIXMAN_REPEAT_PAD, "PAD" }, 126 { PIXMAN_REPEAT_REFLECT, "REFLECT" }, 127 { PIXMAN_REPEAT_NORMAL, "NORMAL" } 128 }; 129 130 static int 131 do_test (int32_t dst_size, 132 int32_t src_size, 133 int32_t src_offs, 134 int32_t scale_factor) 135 { 136 int i, j; 137 138 for (i = 0; i < ARRAY_LENGTH (filters); ++i) 139 { 140 for (j = 0; j < ARRAY_LENGTH (repeats); ++j) 141 { 142 /* horizontal test */ 143 if (run_test (dst_size, 1, 144 src_size, 1, 145 src_offs, 0, 146 scale_factor, 65536, 147 filters[i].value, 148 repeats[j].value) != 0) 149 { 150 printf ("Vertical test failed with %s filter and repeat mode %s\n", 151 filters[i].name, repeats[j].name); 152 153 return 1; 154 } 155 156 /* vertical test */ 157 if (run_test (1, dst_size, 158 1, src_size, 159 0, src_offs, 160 65536, scale_factor, 161 filters[i].value, 162 repeats[j].value) != 0) 163 { 164 printf ("Vertical test failed with %s filter and repeat mode %s\n", 165 filters[i].name, repeats[j].name); 166 167 return 1; 168 } 169 } 170 } 171 172 return 0; 173 } 174 175 int 176 main (int argc, char *argv[]) 177 { 178 int i; 179 180 pixman_disable_out_of_bounds_workaround (); 181 182 /* can potentially crash */ 183 assert (do_test ( 184 48000, 32767, 1, 65536 * 128) == 0); 185 186 /* can potentially get into a deadloop */ 187 assert (do_test ( 188 16384, 65536, 32, 32768) == 0); 189 190 /* can potentially access memory outside source image buffer */ 191 assert (do_test ( 192 10, 10, 0, 1) == 0); 193 assert (do_test ( 194 10, 10, 0, 0) == 0); 195 196 for (i = 0; i < 100; ++i) 197 { 198 pixman_fixed_t one_seventh = 199 (((pixman_fixed_48_16_t)pixman_fixed_1) << 16) / (7 << 16); 200 201 assert (do_test ( 202 1, 7, 3, one_seventh + i - 50) == 0); 203 } 204 205 for (i = 0; i < 100; ++i) 206 { 207 pixman_fixed_t scale = 208 (((pixman_fixed_48_16_t)pixman_fixed_1) << 16) / (32767 << 16); 209 210 assert (do_test ( 211 1, 32767, 16383, scale + i - 50) == 0); 212 } 213 214 /* can potentially provide invalid results (out of range matrix stuff) */ 215 assert (do_test ( 216 48000, 32767, 16384, 65536 * 128) == 0); 217 218 return 0; 219 } 220