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