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