translate_test: fix segfault on x86-64
[mesa.git] / src / gallium / tests / unit / translate_test.c
1 /**************************************************************************
2 *
3 * Copyright © 2010 Luca Barbieri
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *
24 **************************************************************************/
25
26 #include <stdio.h>
27 #include <translate/translate.h>
28 #include <util/u_memory.h>
29 #include <util/u_format.h>
30 #include <util/u_cpu_detect.h>
31 #include <rtasm/rtasm_cpu.h>
32
33 int main(int argc, char** argv)
34 {
35 struct translate *(*create_fn)(const struct translate_key *key) = 0;
36
37 struct translate_key key;
38 unsigned output_format;
39 unsigned input_format;
40 unsigned char* buffer[5];
41 unsigned count = 4;
42 unsigned i, j, k;
43 unsigned passed = 0;
44 unsigned total = 0;
45 const float error = 0.03125;
46
47 create_fn = 0;
48
49 util_cpu_detect();
50
51 if(argc <= 1)
52 {}
53 else if (!strcmp(argv[1], "generic"))
54 create_fn = translate_generic_create;
55 else if (!strcmp(argv[1], "x86"))
56 create_fn = translate_sse2_create;
57 else if (!strcmp(argv[1], "nosse"))
58 {
59 util_cpu_caps.has_sse = 0;
60 util_cpu_caps.has_sse2 = 0;
61 util_cpu_caps.has_sse3 = 0;
62 util_cpu_caps.has_sse4_1 = 0;
63 create_fn = translate_sse2_create;
64 }
65 else if (!strcmp(argv[1], "sse"))
66 {
67 if(!util_cpu_caps.has_sse || !rtasm_cpu_has_sse())
68 {
69 printf("Error: CPU doesn't support SSE (test with qemu)\n");
70 return 2;
71 }
72 util_cpu_caps.has_sse2 = 0;
73 util_cpu_caps.has_sse3 = 0;
74 util_cpu_caps.has_sse4_1 = 0;
75 create_fn = translate_sse2_create;
76 }
77 else if (!strcmp(argv[1], "sse2"))
78 {
79 if(!util_cpu_caps.has_sse2 || !rtasm_cpu_has_sse())
80 {
81 printf("Error: CPU doesn't support SSE2 (test with qemu)\n");
82 return 2;
83 }
84 util_cpu_caps.has_sse3 = 0;
85 util_cpu_caps.has_sse4_1 = 0;
86 create_fn = translate_sse2_create;
87 }
88 else if (!strcmp(argv[1], "sse3"))
89 {
90 if(!util_cpu_caps.has_sse3 || !rtasm_cpu_has_sse())
91 {
92 printf("Error: CPU doesn't support SSE3 (test with qemu)\n");
93 return 2;
94 }
95 util_cpu_caps.has_sse4_1 = 0;
96 create_fn = translate_sse2_create;
97 }
98 else if (!strcmp(argv[1], "sse4.1"))
99 {
100 if(!util_cpu_caps.has_sse4_1 || !rtasm_cpu_has_sse())
101 {
102 printf("Error: CPU doesn't support SSE4.1 (test with qemu)\n");
103 return 2;
104 }
105 create_fn = translate_sse2_create;
106 }
107
108 if (!create_fn)
109 {
110 printf("Usage: ./translate_test [generic|x86|nosse|sse|sse2|sse3|sse4.1]\n");
111 return 2;
112 }
113
114 for (i = 0; i < Elements(buffer); ++i)
115 buffer[i] = align_malloc(4096, 4096);
116
117 key.nr_elements = 1;
118 key.element[0].input_buffer = 0;
119 key.element[0].input_offset = 0;
120 key.element[0].output_offset = 0;
121 key.element[0].type = TRANSLATE_ELEMENT_NORMAL;
122 key.element[0].instance_divisor = 0;
123
124 srand(4359025);
125 for (i = 0; i < 4096; ++i)
126 buffer[0][i] = rand() & 0x7f; /* avoid negative values that work badly when converted to unsigned format*/
127
128 for (output_format = 1; output_format < PIPE_FORMAT_COUNT; ++output_format)
129 {
130 const struct util_format_description* output_format_desc = util_format_description(output_format);
131 unsigned output_format_size;
132 if (!output_format_desc
133 || !output_format_desc->fetch_rgba_float
134 || !output_format_desc->pack_rgba_float
135 || output_format_desc->colorspace != UTIL_FORMAT_COLORSPACE_RGB
136 || output_format_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN
137 || !translate_is_output_format_supported(output_format))
138 continue;
139
140 output_format_size = util_format_get_stride(output_format, 1);
141
142 for (input_format = 1; input_format < PIPE_FORMAT_COUNT; ++input_format)
143 {
144 const struct util_format_description* input_format_desc = util_format_description(input_format);
145 unsigned input_format_size;
146 struct translate* translate[2];
147 unsigned fail = 0;
148 unsigned used_generic = 0;
149
150 if (!input_format_desc
151 || !input_format_desc->fetch_rgba_float
152 || !input_format_desc->pack_rgba_float
153 || input_format_desc->colorspace != UTIL_FORMAT_COLORSPACE_RGB
154 || input_format_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN
155 || !translate_is_output_format_supported(input_format))
156 continue;
157
158 input_format_size = util_format_get_stride(input_format, 1);
159
160 key.element[0].input_format = input_format;
161 key.element[0].output_format = output_format;
162 key.output_stride = output_format_size;
163 translate[0] = create_fn(&key);
164 if (!translate[0])
165 continue;
166
167 key.element[0].input_format = output_format;
168 key.element[0].output_format = input_format;
169 key.output_stride = input_format_size;
170 translate[1] = create_fn(&key);
171 if(!translate[1])
172 {
173 used_generic = 1;
174 translate[1] = translate_generic_create(&key);
175 if(!translate[1])
176 continue;
177 }
178
179 translate[0]->set_buffer(translate[0], 0, buffer[0], input_format_size, ~0);
180 translate[0]->run(translate[0], 0, count, 0, buffer[1]);
181 translate[1]->set_buffer(translate[1], 0, buffer[1], output_format_size, ~0);
182 translate[1]->run(translate[1], 0, count, 0, buffer[2]);
183 translate[0]->set_buffer(translate[0], 0, buffer[2], input_format_size, ~0);
184 translate[0]->run(translate[0], 0, count, 0, buffer[3]);
185 translate[1]->set_buffer(translate[1], 0, buffer[3], output_format_size, ~0);
186 translate[1]->run(translate[1], 0, count, 0, buffer[4]);
187
188 for (i = 0; i < count; ++i)
189 {
190 float a[4];
191 float b[4];
192 input_format_desc->fetch_rgba_float(a, buffer[2] + i * input_format_size, 0, 0);
193 input_format_desc->fetch_rgba_float(b, buffer[4] + i * input_format_size, 0, 0);
194
195 for (j = 0; j < count; ++j)
196 {
197 float d = a[j] - b[j];
198 if (d > error || d < -error)
199 {
200 fail = 1;
201 break;
202 }
203 }
204 }
205
206 printf("%s%s: %s -> %s -> %s -> %s -> %s\n",
207 fail ? "FAIL" : "PASS",
208 used_generic ? "[GENERIC]" : "",
209 input_format_desc->name, output_format_desc->name, input_format_desc->name, output_format_desc->name, input_format_desc->name);
210
211 if (fail)
212 {
213 for (i = 0; i < Elements(buffer); ++i)
214 {
215 unsigned format_size = (i & 1) ? output_format_size : input_format_size;
216 printf("%c ", (i == 2 || i == 4) ? '*' : ' ');
217 for (j = 0; j < count; ++j)
218 {
219 for (k = 0; k < format_size; ++k)
220 {
221 printf("%02x", buffer[i][j * format_size + k]);
222 }
223 printf(" ");
224 }
225 printf("\n");
226 }
227 }
228
229 if (!fail)
230 ++passed;
231 ++total;
232
233 if(translate[1])
234 translate[1]->release(translate[1]);
235 translate[0]->release(translate[0]);
236 }
237 }
238
239 printf("%u/%u tests passed for translate_%s\n", passed, total, argv[1]);
240 return passed != total;
241 }