g3dvl: Implement XvMC using pipe_video_context.
[mesa.git] / src / xvmc / tests / test_rendering.c
1 #include <assert.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <error.h>
5 #include "testlib.h"
6
7 #define BLOCK_WIDTH 8
8 #define BLOCK_HEIGHT 8
9 #define BLOCK_SIZE (BLOCK_WIDTH * BLOCK_HEIGHT)
10 #define MACROBLOCK_WIDTH 16
11 #define MACROBLOCK_HEIGHT 16
12 #define MACROBLOCK_WIDTH_IN_BLOCKS (MACROBLOCK_WIDTH / BLOCK_WIDTH)
13 #define MACROBLOCK_HEIGHT_IN_BLOCKS (MACROBLOCK_HEIGHT / BLOCK_HEIGHT)
14 #define BLOCKS_PER_MACROBLOCK 6
15
16 #define INPUT_WIDTH 16
17 #define INPUT_HEIGHT 16
18 #define INPUT_WIDTH_IN_MACROBLOCKS (INPUT_WIDTH / MACROBLOCK_WIDTH)
19 #define INPUT_HEIGHT_IN_MACROBLOCKS (INPUT_HEIGHT / MACROBLOCK_HEIGHT)
20 #define NUM_MACROBLOCKS (INPUT_WIDTH_IN_MACROBLOCKS * INPUT_HEIGHT_IN_MACROBLOCKS)
21
22 #define DEFAULT_OUTPUT_WIDTH INPUT_WIDTH
23 #define DEFAULT_OUTPUT_HEIGHT INPUT_HEIGHT
24 #define DEFAULT_ACCEPTABLE_ERR 0.01
25
26 void ParseArgs(int argc, char **argv, unsigned int *output_width, unsigned int *output_height, double *acceptable_error, int *prompt);
27 void Gradient(short *block, unsigned int start, unsigned int stop, int horizontal);
28
29 void ParseArgs(int argc, char **argv, unsigned int *output_width, unsigned int *output_height, double *acceptable_error, int *prompt)
30 {
31 int fail = 0;
32 int i;
33
34 *output_width = DEFAULT_OUTPUT_WIDTH;
35 *output_height = DEFAULT_OUTPUT_WIDTH;
36 *acceptable_error = DEFAULT_ACCEPTABLE_ERR;
37 *prompt = 1;
38
39 for (i = 1; i < argc && !fail; ++i)
40 {
41 if (!strcmp(argv[i], "-w"))
42 {
43 if (sscanf(argv[++i], "%u", output_width) != 1)
44 fail = 1;
45 }
46 else if (!strcmp(argv[i], "-h"))
47 {
48 if (sscanf(argv[++i], "%u", output_height) != 1)
49 fail = 1;
50 }
51 else if (!strcmp(argv[i], "-e"))
52 {
53 if (sscanf(argv[++i], "%lf", acceptable_error) != 1)
54 fail = 1;
55 }
56 else if (strcmp(argv[i], "-n"))
57 *prompt = 0;
58 else
59 fail = 1;
60 }
61
62 if (fail)
63 error
64 (
65 1, 0,
66 "Bad argument.\n"
67 "\n"
68 "Usage: %s [options]\n"
69 "\t-w <width>\tOutput width\n"
70 "\t-h <height>\tOutput height\n"
71 "\t-e <error>\tAcceptable margin of error per pixel, from 0 to 1\n"
72 "\t-n\tDon't prompt for quit\n",
73 argv[0]
74 );
75 }
76
77 void Gradient(short *block, unsigned int start, unsigned int stop, int horizontal)
78 {
79 unsigned int x, y;
80 unsigned int range = stop - start;
81
82 if (horizontal)
83 {
84 for (y = 0; y < BLOCK_HEIGHT; ++y)
85 for (x = 0; x < BLOCK_WIDTH; ++x)
86 block[y * BLOCK_WIDTH + x] = (short)(start + range * (x / (float)(BLOCK_WIDTH - 1)));
87 }
88 else
89 {
90 for (y = 0; y < BLOCK_HEIGHT; ++y)
91 for (x = 0; x < BLOCK_WIDTH; ++x)
92 block[y * BLOCK_WIDTH + x] = (short)(start + range * (y / (float)(BLOCK_HEIGHT - 1)));
93 }
94 }
95
96 int main(int argc, char **argv)
97 {
98 unsigned int output_width;
99 unsigned int output_height;
100 double acceptable_error;
101 int prompt;
102 Display *display;
103 Window root, window;
104 const unsigned int mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2};
105 XvPortID port_num;
106 int surface_type_id;
107 unsigned int is_overlay, intra_unsigned;
108 int colorkey;
109 XvMCContext context;
110 XvMCSurface surface;
111 XvMCBlockArray block_array;
112 XvMCMacroBlockArray mb_array;
113 int mbx, mby, bx, by;
114 XvMCMacroBlock *mb;
115 short *blocks;
116 int quit = 0;
117
118 ParseArgs(argc, argv, &output_width, &output_height, &acceptable_error, &prompt);
119
120 display = XOpenDisplay(NULL);
121
122 if (!GetPort
123 (
124 display,
125 INPUT_WIDTH,
126 INPUT_HEIGHT,
127 XVMC_CHROMA_FORMAT_420,
128 mc_types,
129 2,
130 &port_num,
131 &surface_type_id,
132 &is_overlay,
133 &intra_unsigned
134 ))
135 {
136 XCloseDisplay(display);
137 error(1, 0, "Error, unable to find a good port.\n");
138 }
139
140 if (is_overlay)
141 {
142 Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0);
143 XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey);
144 }
145
146 root = XDefaultRootWindow(display);
147 window = XCreateSimpleWindow(display, root, 0, 0, output_width, output_height, 0, 0, colorkey);
148
149 assert(XvMCCreateContext(display, port_num, surface_type_id, INPUT_WIDTH, INPUT_HEIGHT, XVMC_DIRECT, &context) == Success);
150 assert(XvMCCreateSurface(display, &context, &surface) == Success);
151 assert(XvMCCreateBlocks(display, &context, NUM_MACROBLOCKS * BLOCKS_PER_MACROBLOCK, &block_array) == Success);
152 assert(XvMCCreateMacroBlocks(display, &context, NUM_MACROBLOCKS, &mb_array) == Success);
153
154 mb = mb_array.macro_blocks;
155 blocks = block_array.blocks;
156
157 for (mby = 0; mby < INPUT_HEIGHT_IN_MACROBLOCKS; ++mby)
158 for (mbx = 0; mbx < INPUT_WIDTH_IN_MACROBLOCKS; ++mbx)
159 {
160 mb->x = mbx;
161 mb->y = mby;
162 mb->macroblock_type = XVMC_MB_TYPE_INTRA;
163 /*mb->motion_type = ;*/
164 /*mb->motion_vertical_field_select = ;*/
165 mb->dct_type = XVMC_DCT_TYPE_FRAME;
166 /*mb->PMV[0][0][0] = ;
167 mb->PMV[0][0][1] = ;
168 mb->PMV[0][1][0] = ;
169 mb->PMV[0][1][1] = ;
170 mb->PMV[1][0][0] = ;
171 mb->PMV[1][0][1] = ;
172 mb->PMV[1][1][0] = ;
173 mb->PMV[1][1][1] = ;*/
174 mb->index = (mby * INPUT_WIDTH_IN_MACROBLOCKS + mbx) * BLOCKS_PER_MACROBLOCK;
175 mb->coded_block_pattern = 0x3F;
176
177 mb++;
178
179 for (by = 0; by < MACROBLOCK_HEIGHT_IN_BLOCKS; ++by)
180 for (bx = 0; bx < MACROBLOCK_WIDTH_IN_BLOCKS; ++bx)
181 {
182 const int start = 16, stop = 235, range = stop - start;
183
184 Gradient
185 (
186 blocks,
187 (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))),
188 (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))),
189 1
190 );
191
192 blocks += BLOCK_SIZE;
193 }
194
195 for (by = 0; by < MACROBLOCK_HEIGHT_IN_BLOCKS / 2; ++by)
196 for (bx = 0; bx < MACROBLOCK_WIDTH_IN_BLOCKS / 2; ++bx)
197 {
198 const int start = 16, stop = 240, range = stop - start;
199
200 Gradient
201 (
202 blocks,
203 (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))),
204 (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))),
205 1
206 );
207
208 blocks += BLOCK_SIZE;
209
210 Gradient
211 (
212 blocks,
213 (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))),
214 (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))),
215 1
216 );
217
218 blocks += BLOCK_SIZE;
219 }
220 }
221
222 XSelectInput(display, window, ExposureMask | KeyPressMask);
223 XMapWindow(display, window);
224 XSync(display, 0);
225
226 /* Test NULL context */
227 assert(XvMCRenderSurface(display, NULL, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == XvMCBadContext);
228 /* Test NULL surface */
229 assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, NULL, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == XvMCBadSurface);
230 /* Test bad picture structure */
231 assert(XvMCRenderSurface(display, &context, 0, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == BadValue);
232 /* Test valid params */
233 assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == Success);
234
235 /* Test NULL surface */
236 assert(XvMCPutSurface(display, NULL, window, 0, 0, INPUT_WIDTH, INPUT_HEIGHT, 0, 0, output_width, output_height, XVMC_FRAME_PICTURE) == XvMCBadSurface);
237 /* Test bad window */
238 /* XXX: X halts with a bad drawable for some reason, doesn't return BadDrawable as expected */
239 /*assert(XvMCPutSurface(display, &surface, 0, 0, 0, width, height, 0, 0, width, height, XVMC_FRAME_PICTURE) == BadDrawable);*/
240
241 if (prompt)
242 {
243 puts("Press any button to quit...");
244
245 while (!quit)
246 {
247 if (XPending(display) > 0)
248 {
249 XEvent event;
250
251 XNextEvent(display, &event);
252
253 switch (event.type)
254 {
255 case Expose:
256 {
257 /* Test valid params */
258 assert
259 (
260 XvMCPutSurface
261 (
262 display, &surface, window,
263 0, 0, INPUT_WIDTH, INPUT_HEIGHT,
264 0, 0, output_width, output_height,
265 XVMC_FRAME_PICTURE
266 ) == Success
267 );
268 break;
269 }
270 case KeyPress:
271 {
272 quit = 1;
273 break;
274 }
275 }
276 }
277 }
278 }
279
280 assert(XvMCDestroyBlocks(display, &block_array) == Success);
281 assert(XvMCDestroyMacroBlocks(display, &mb_array) == Success);
282 assert(XvMCDestroySurface(display, &surface) == Success);
283 assert(XvMCDestroyContext(display, &context) == Success);
284
285 XvUngrabPort(display, port_num, CurrentTime);
286 XDestroyWindow(display, window);
287 XCloseDisplay(display);
288
289 return 0;
290 }