st/xvmc: fix tests so that they pass
[mesa.git] / src / gallium / state_trackers / xvmc / tests / test_rendering.c
1 /**************************************************************************
2 *
3 * Copyright 2009 Younes Manton.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #include <assert.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <error.h>
32 #include "testlib.h"
33
34 #define BLOCK_WIDTH 8
35 #define BLOCK_HEIGHT 8
36 #define BLOCK_SIZE (BLOCK_WIDTH * BLOCK_HEIGHT)
37 #define MACROBLOCK_WIDTH 16
38 #define MACROBLOCK_HEIGHT 16
39 #define MACROBLOCK_WIDTH_IN_BLOCKS (MACROBLOCK_WIDTH / BLOCK_WIDTH)
40 #define MACROBLOCK_HEIGHT_IN_BLOCKS (MACROBLOCK_HEIGHT / BLOCK_HEIGHT)
41 #define BLOCKS_PER_MACROBLOCK 6
42
43 #define INPUT_WIDTH 64
44 #define INPUT_HEIGHT 64
45 #define INPUT_WIDTH_IN_MACROBLOCKS (INPUT_WIDTH / MACROBLOCK_WIDTH)
46 #define INPUT_HEIGHT_IN_MACROBLOCKS (INPUT_HEIGHT / MACROBLOCK_HEIGHT)
47 #define NUM_MACROBLOCKS (INPUT_WIDTH_IN_MACROBLOCKS * INPUT_HEIGHT_IN_MACROBLOCKS)
48
49 #define DEFAULT_OUTPUT_WIDTH INPUT_WIDTH
50 #define DEFAULT_OUTPUT_HEIGHT INPUT_HEIGHT
51 #define DEFAULT_ACCEPTABLE_ERR 0.01
52
53 static void ParseArgs(int argc, char **argv, unsigned int *output_width, unsigned int *output_height, double *acceptable_error, int *prompt)
54 {
55 int fail = 0;
56 int i;
57
58 *output_width = DEFAULT_OUTPUT_WIDTH;
59 *output_height = DEFAULT_OUTPUT_HEIGHT;
60 *acceptable_error = DEFAULT_ACCEPTABLE_ERR;
61 *prompt = 0;
62
63 for (i = 1; i < argc && !fail; ++i)
64 {
65 if (!strcmp(argv[i], "-w"))
66 {
67 if (sscanf(argv[++i], "%u", output_width) != 1)
68 fail = 1;
69 }
70 else if (!strcmp(argv[i], "-h"))
71 {
72 if (sscanf(argv[++i], "%u", output_height) != 1)
73 fail = 1;
74 }
75 else if (!strcmp(argv[i], "-e"))
76 {
77 if (sscanf(argv[++i], "%lf", acceptable_error) != 1)
78 fail = 1;
79 }
80 else if (!strcmp(argv[i], "-p"))
81 *prompt = 1;
82 else
83 fail = 1;
84 }
85
86 if (fail)
87 error
88 (
89 1, 0,
90 "Bad argument.\n"
91 "\n"
92 "Usage: %s [options]\n"
93 "\t-w <width>\tOutput width\n"
94 "\t-h <height>\tOutput height\n"
95 "\t-e <error>\tAcceptable margin of error per pixel, from 0 to 1\n"
96 "\t-p\tPrompt for quit\n",
97 argv[0]
98 );
99 }
100
101 static void Gradient(short *block, unsigned int start, unsigned int stop, int horizontal, unsigned int intra_unsigned)
102 {
103 unsigned int x, y;
104 unsigned int range = stop - start;
105
106 if (horizontal)
107 {
108 for (y = 0; y < BLOCK_HEIGHT; ++y)
109 for (x = 0; x < BLOCK_WIDTH; ++x) {
110 *block = (short)(start + range * (x / (float)(BLOCK_WIDTH - 1)));
111 if (intra_unsigned)
112 *block += 1 << 10;
113 block++;
114 }
115 }
116 else
117 {
118 for (y = 0; y < BLOCK_HEIGHT; ++y)
119 for (x = 0; x < BLOCK_WIDTH; ++x) {
120 *block = (short)(start + range * (y / (float)(BLOCK_WIDTH - 1)));
121 if (intra_unsigned)
122 *block += 1 << 10;
123 block++;
124 }
125 }
126 }
127
128 int main(int argc, char **argv)
129 {
130 unsigned int output_width;
131 unsigned int output_height;
132 double acceptable_error;
133 int prompt;
134 Display *display;
135 Window root, window;
136 const unsigned int mc_types[] = {XVMC_MOCOMP | XVMC_MPEG_2};
137 XvPortID port_num;
138 int surface_type_id;
139 unsigned int is_overlay, intra_unsigned;
140 int colorkey;
141 XvMCContext context;
142 XvMCSurface surface;
143 XvMCBlockArray block_array;
144 XvMCMacroBlockArray mb_array;
145 int mbx, mby, bx, by;
146 XvMCMacroBlock *mb;
147 short *blocks;
148 int quit = 0;
149
150 ParseArgs(argc, argv, &output_width, &output_height, &acceptable_error, &prompt);
151
152 display = XOpenDisplay(NULL);
153
154 if (!GetPort
155 (
156 display,
157 INPUT_WIDTH,
158 INPUT_HEIGHT,
159 XVMC_CHROMA_FORMAT_420,
160 mc_types,
161 sizeof(mc_types)/sizeof(*mc_types),
162 &port_num,
163 &surface_type_id,
164 &is_overlay,
165 &intra_unsigned
166 ))
167 {
168 XCloseDisplay(display);
169 error(1, 0, "Error, unable to find a good port.\n");
170 }
171
172 if (is_overlay)
173 {
174 Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0);
175 XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey);
176 }
177
178 root = XDefaultRootWindow(display);
179 window = XCreateSimpleWindow(display, root, 0, 0, output_width, output_height, 0, 0, colorkey);
180
181 assert(XvMCCreateContext(display, port_num, surface_type_id, INPUT_WIDTH, INPUT_HEIGHT, XVMC_DIRECT, &context) == Success);
182 assert(XvMCCreateSurface(display, &context, &surface) == Success);
183 assert(XvMCCreateBlocks(display, &context, NUM_MACROBLOCKS * BLOCKS_PER_MACROBLOCK, &block_array) == Success);
184 assert(XvMCCreateMacroBlocks(display, &context, NUM_MACROBLOCKS, &mb_array) == Success);
185
186 mb = mb_array.macro_blocks;
187 blocks = block_array.blocks;
188
189 for (mby = 0; mby < INPUT_HEIGHT_IN_MACROBLOCKS; ++mby)
190 for (mbx = 0; mbx < INPUT_WIDTH_IN_MACROBLOCKS; ++mbx)
191 {
192 mb->x = mbx;
193 mb->y = mby;
194 mb->macroblock_type = XVMC_MB_TYPE_INTRA;
195 /*mb->motion_type = ;*/
196 /*mb->motion_vertical_field_select = ;*/
197 mb->dct_type = XVMC_DCT_TYPE_FRAME;
198 /*mb->PMV[0][0][0] = ;
199 mb->PMV[0][0][1] = ;
200 mb->PMV[0][1][0] = ;
201 mb->PMV[0][1][1] = ;
202 mb->PMV[1][0][0] = ;
203 mb->PMV[1][0][1] = ;
204 mb->PMV[1][1][0] = ;
205 mb->PMV[1][1][1] = ;*/
206 mb->index = (mby * INPUT_WIDTH_IN_MACROBLOCKS + mbx) * BLOCKS_PER_MACROBLOCK;
207 mb->coded_block_pattern = 0x3F;
208
209 mb++;
210
211 for (by = 0; by < MACROBLOCK_HEIGHT_IN_BLOCKS; ++by)
212 for (bx = 0; bx < MACROBLOCK_WIDTH_IN_BLOCKS; ++bx)
213 {
214 const int start = 16, stop = 235, range = stop - start;
215
216 Gradient
217 (
218 blocks,
219 (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))),
220 (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))),
221 1,
222 intra_unsigned
223 );
224
225 blocks += BLOCK_SIZE;
226 }
227
228 for (by = 0; by < MACROBLOCK_HEIGHT_IN_BLOCKS / 2; ++by)
229 for (bx = 0; bx < MACROBLOCK_WIDTH_IN_BLOCKS / 2; ++bx)
230 {
231 const int start = 16, stop = 240, range = stop - start;
232
233 Gradient
234 (
235 blocks,
236 (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))),
237 (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))),
238 1,
239 intra_unsigned
240 );
241
242 blocks += BLOCK_SIZE;
243
244 Gradient
245 (
246 blocks,
247 (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))),
248 (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))),
249 1,
250 intra_unsigned
251 );
252
253 blocks += BLOCK_SIZE;
254 }
255 }
256
257 XSelectInput(display, window, ExposureMask | KeyPressMask);
258 XMapWindow(display, window);
259 XSync(display, 0);
260
261 /* Test NULL context */
262 assert(XvMCRenderSurface(display, NULL, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == XvMCBadContext);
263 /* Test NULL surface */
264 assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, NULL, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == XvMCBadSurface);
265 /* Test bad picture structure */
266 assert(XvMCRenderSurface(display, &context, 0, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == BadValue);
267 /* Test valid params */
268 assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == Success);
269
270 /* Test NULL surface */
271 assert(XvMCPutSurface(display, NULL, window, 0, 0, INPUT_WIDTH, INPUT_HEIGHT, 0, 0, output_width, output_height, XVMC_FRAME_PICTURE) == XvMCBadSurface);
272 /* Test bad window */
273 /* XXX: X halts with a bad drawable for some reason, doesn't return BadDrawable as expected */
274 /*assert(XvMCPutSurface(display, &surface, 0, 0, 0, width, height, 0, 0, width, height, XVMC_FRAME_PICTURE) == BadDrawable);*/
275
276 if (prompt)
277 {
278 puts("Press any button to quit...");
279
280 while (!quit)
281 {
282 if (XPending(display) > 0)
283 {
284 XEvent event;
285
286 XNextEvent(display, &event);
287
288 switch (event.type)
289 {
290 case Expose:
291 {
292 /* Test valid params */
293 assert
294 (
295 XvMCPutSurface
296 (
297 display, &surface, window,
298 0, 0, INPUT_WIDTH, INPUT_HEIGHT,
299 0, 0, output_width, output_height,
300 XVMC_FRAME_PICTURE
301 ) == Success
302 );
303 break;
304 }
305 case KeyPress:
306 {
307 quit = 1;
308 break;
309 }
310 }
311 }
312 }
313 }
314
315 assert(XvMCDestroyBlocks(display, &block_array) == Success);
316 assert(XvMCDestroyMacroBlocks(display, &mb_array) == Success);
317 assert(XvMCDestroySurface(display, &surface) == Success);
318 assert(XvMCDestroyContext(display, &context) == Success);
319
320 XvUngrabPort(display, port_num, CurrentTime);
321 XDestroyWindow(display, window);
322 XCloseDisplay(display);
323
324 return 0;
325 }