bf94d8562347011132e5e5da450b23a412833f37
[profile/ivi/mesa.git] / src / gallium / state_trackers / xorg / xvmc / tests / xvmc_bench.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 <sys/time.h>
33 #include "testlib.h"
34
35 #define MACROBLOCK_WIDTH                16
36 #define MACROBLOCK_HEIGHT               16
37 #define BLOCKS_PER_MACROBLOCK           6
38
39 #define DEFAULT_INPUT_WIDTH             720
40 #define DEFAULT_INPUT_HEIGHT            480
41 #define DEFAULT_REPS                    100
42
43 #define PIPELINE_STEP_MC                1
44 #define PIPELINE_STEP_CSC               2
45 #define PIPELINE_STEP_SWAP              4
46
47 #define MB_TYPE_I                       1
48 #define MB_TYPE_P                       2
49 #define MB_TYPE_B                       4
50
51 struct Config
52 {
53         unsigned int input_width;
54         unsigned int input_height;
55         unsigned int output_width;
56         unsigned int output_height;
57         unsigned int pipeline;
58         unsigned int mb_types;
59         unsigned int reps;
60 };
61
62 void ParseArgs(int argc, char **argv, struct Config *config);
63
64 void ParseArgs(int argc, char **argv, struct Config *config)
65 {
66         int fail = 0;
67         int i;
68
69         config->input_width = DEFAULT_INPUT_WIDTH;
70         config->input_height = DEFAULT_INPUT_HEIGHT;
71         config->output_width = 0;
72         config->output_height = 0;
73         config->pipeline = 0;
74         config->mb_types = 0;
75         config->reps = DEFAULT_REPS;
76
77         for (i = 1; i < argc && !fail; ++i)
78         {
79                 if (!strcmp(argv[i], "-iw"))
80                 {
81                         if (sscanf(argv[++i], "%u", &config->input_width) != 1)
82                                 fail = 1;
83                 }
84                 else if (!strcmp(argv[i], "-ih"))
85                 {
86                         if (sscanf(argv[++i], "%u", &config->input_height) != 1)
87                                 fail = 1;
88                 }
89                 else if (!strcmp(argv[i], "-ow"))
90                 {
91                         if (sscanf(argv[++i], "%u", &config->output_width) != 1)
92                                 fail = 1;
93                 }
94                 else if (!strcmp(argv[i], "-oh"))
95                 {
96                         if (sscanf(argv[++i], "%u", &config->output_height) != 1)
97                                 fail = 1;
98                 }
99                 else if (!strcmp(argv[i], "-p"))
100                 {
101                         char *token = strtok(argv[++i], ",");
102
103                         while (token && !fail)
104                         {
105                                 if (!strcmp(token, "mc"))
106                                         config->pipeline |= PIPELINE_STEP_MC;
107                                 else if (!strcmp(token, "csc"))
108                                         config->pipeline |= PIPELINE_STEP_CSC;
109                                 else if (!strcmp(token, "swp"))
110                                         config->pipeline |= PIPELINE_STEP_SWAP;
111                                 else
112                                         fail = 1;
113
114                                 if (!fail)
115                                         token = strtok(NULL, ",");
116                         }
117                 }
118                 else if (!strcmp(argv[i], "-mb"))
119                 {
120                         char *token = strtok(argv[++i], ",");
121
122                         while (token && !fail)
123                         {
124                                 if (strcmp(token, "i"))
125                                         config->mb_types |= MB_TYPE_I;
126                                 else if (strcmp(token, "p"))
127                                         config->mb_types |= MB_TYPE_P;
128                                 else if (strcmp(token, "b"))
129                                         config->mb_types |= MB_TYPE_B;
130                                 else
131                                         fail = 1;
132
133                                 if (!fail)
134                                         token = strtok(NULL, ",");
135                         }
136                 }
137                 else if (!strcmp(argv[i], "-r"))
138                 {
139                         if (sscanf(argv[++i], "%u", &config->reps) != 1)
140                                 fail = 1;
141                 }
142                 else
143                         fail = 1;
144         }
145
146         if (fail)
147                 error
148                 (
149                         1, 0,
150                         "Bad argument.\n"
151                         "\n"
152                         "Usage: %s [options]\n"
153                         "\t-iw <width>\tInput width\n"
154                         "\t-ih <height>\tInput height\n"
155                         "\t-ow <width>\tOutput width\n"
156                         "\t-oh <height>\tOutput height\n"
157                         "\t-p <pipeline>\tPipeline to test\n"
158                         "\t-mb <mb type>\tMacroBlock types to use\n"
159                         "\t-r <reps>\tRepetitions\n\n"
160                         "\tPipeline steps: mc,csc,swap\n"
161                         "\tMB types: i,p,b\n",
162                         argv[0]
163                 );
164
165         if (config->output_width == 0)
166                 config->output_width = config->input_width;
167         if (config->output_height == 0)
168                 config->output_height = config->input_height;
169         if (!config->pipeline)
170                 config->pipeline = PIPELINE_STEP_MC | PIPELINE_STEP_CSC | PIPELINE_STEP_SWAP;
171         if (!config->mb_types)
172                 config->mb_types = MB_TYPE_I | MB_TYPE_P | MB_TYPE_B;
173 }
174
175 int main(int argc, char **argv)
176 {
177         struct Config           config;
178         Display                 *display;
179         Window                  root, window;
180         const unsigned int      mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2};
181         XvPortID                port_num;
182         int                     surface_type_id;
183         unsigned int            is_overlay, intra_unsigned;
184         int                     colorkey;
185         XvMCContext             context;
186         XvMCSurface             surface;
187         XvMCBlockArray          block_array;
188         XvMCMacroBlockArray     mb_array;
189         unsigned int            mbw, mbh;
190         unsigned int            mbx, mby;
191         unsigned int            reps;
192         struct timeval          start, stop, diff;
193         double                  diff_secs;
194
195         ParseArgs(argc, argv, &config);
196
197         mbw = align(config.input_width, MACROBLOCK_WIDTH) / MACROBLOCK_WIDTH;
198         mbh = align(config.input_height, MACROBLOCK_HEIGHT) / MACROBLOCK_HEIGHT;
199
200         display = XOpenDisplay(NULL);
201
202         if (!GetPort
203         (
204                 display,
205                 config.input_width,
206                 config.input_height,
207                 XVMC_CHROMA_FORMAT_420,
208                 mc_types,
209                 2,
210                 &port_num,
211                 &surface_type_id,
212                 &is_overlay,
213                 &intra_unsigned
214         ))
215         {
216                 XCloseDisplay(display);
217                 error(1, 0, "Error, unable to find a good port.\n");
218         }
219
220         if (is_overlay)
221         {
222                 Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0);
223                 XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey);
224         }
225
226         root = XDefaultRootWindow(display);
227         window = XCreateSimpleWindow(display, root, 0, 0, config.output_width, config.output_height, 0, 0, colorkey);
228
229         assert(XvMCCreateContext(display, port_num, surface_type_id, config.input_width, config.input_height, XVMC_DIRECT, &context) == Success);
230         assert(XvMCCreateSurface(display, &context, &surface) == Success);
231         assert(XvMCCreateBlocks(display, &context, mbw * mbh * BLOCKS_PER_MACROBLOCK, &block_array) == Success);
232         assert(XvMCCreateMacroBlocks(display, &context, mbw * mbh, &mb_array) == Success);
233
234         for (mby = 0; mby < mbh; ++mby)
235                 for (mbx = 0; mbx < mbw; ++mbx)
236                 {
237                         mb_array.macro_blocks[mby * mbw + mbx].x = mbx;
238                         mb_array.macro_blocks[mby * mbw + mbx].y = mby;
239                         mb_array.macro_blocks[mby * mbw + mbx].macroblock_type = XVMC_MB_TYPE_INTRA;
240                         /*mb->motion_type = ;*/
241                         /*mb->motion_vertical_field_select = ;*/
242                         mb_array.macro_blocks[mby * mbw + mbx].dct_type = XVMC_DCT_TYPE_FRAME;
243                         /*mb->PMV[0][0][0] = ;
244                         mb->PMV[0][0][1] = ;
245                         mb->PMV[0][1][0] = ;
246                         mb->PMV[0][1][1] = ;
247                         mb->PMV[1][0][0] = ;
248                         mb->PMV[1][0][1] = ;
249                         mb->PMV[1][1][0] = ;
250                         mb->PMV[1][1][1] = ;*/
251                         mb_array.macro_blocks[mby * mbw + mbx].index = (mby * mbw + mbx) * BLOCKS_PER_MACROBLOCK;
252                         mb_array.macro_blocks[mby * mbw + mbx].coded_block_pattern = 0x3F;
253                 }
254
255         XSelectInput(display, window, ExposureMask | KeyPressMask);
256         XMapWindow(display, window);
257         XSync(display, 0);
258
259         gettimeofday(&start, NULL);
260
261         for (reps = 0; reps < config.reps; ++reps)
262         {
263                 if (config.pipeline & PIPELINE_STEP_MC)
264                 {
265                         assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, mbw * mbh, 0, &mb_array, &block_array) == Success);
266                         assert(XvMCFlushSurface(display, &surface) == Success);
267                 }
268                 if (config.pipeline & PIPELINE_STEP_CSC)
269                         assert(XvMCPutSurface(display, &surface, window, 0, 0, config.input_width, config.input_height, 0, 0, config.output_width, config.output_height, XVMC_FRAME_PICTURE) == Success);
270         }
271
272         gettimeofday(&stop, NULL);
273
274         timeval_subtract(&diff, &stop, &start);
275         diff_secs = (double)diff.tv_sec + (double)diff.tv_usec / 1000000.0;
276
277         printf("XvMC Benchmark\n");
278         printf("Input: %u,%u\nOutput: %u,%u\n", config.input_width, config.input_height, config.output_width, config.output_height);
279         printf("Pipeline: ");
280         if (config.pipeline & PIPELINE_STEP_MC)
281                 printf("|mc|");
282         if (config.pipeline & PIPELINE_STEP_CSC)
283                 printf("|csc|");
284         if (config.pipeline & PIPELINE_STEP_SWAP)
285                 printf("|swap|");
286         printf("\n");
287         printf("Reps: %u\n", config.reps);
288         printf("Total time: %.2lf (%.2lf reps / sec)\n", diff_secs, config.reps / diff_secs);
289
290         assert(XvMCDestroyBlocks(display, &block_array) == Success);
291         assert(XvMCDestroyMacroBlocks(display, &mb_array) == Success);
292         assert(XvMCDestroySurface(display, &surface) == Success);
293         assert(XvMCDestroyContext(display, &context) == Success);
294
295         XvUngrabPort(display, port_num, CurrentTime);
296         XDestroyWindow(display, window);
297         XCloseDisplay(display);
298
299         return 0;
300 }