]> git.cworth.org Git - apitrace-tests/blob - mesademos.py
20f7e10fa6f7f83dcea1adc22dc8c745550815bf
[apitrace-tests] / mesademos.py
1 #!/usr/bin/env python
2 ##########################################################################
3 #
4 # Copyright 2011 Jose Fonseca
5 # All Rights Reserved.
6 #
7 # Permission is hereby granted, free of charge, to any person obtaining a copy
8 # of this software and associated documentation files (the "Software"), to deal
9 # in the Software without restriction, including without limitation the rights
10 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 # copies of the Software, and to permit persons to whom the Software is
12 # furnished to do so, subject to the following conditions:
13 #
14 # The above copyright notice and this permission notice shall be included in
15 # all copies or substantial portions of the Software.
16 #
17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 # THE SOFTWARE.
24 #
25 ##########################################################################/
26
27
28 '''Apitrace test suite based on Mesa demos.'''
29
30
31
32 import os.path
33 import optparse
34 import sys
35 import subprocess
36 import time
37 import re
38 import signal
39
40
41 ansi_re = re.compile('\x1b\[[0-9]{1,2}(;[0-9]{1,2}){0,2}m')
42
43
44 def ansi_strip(s):
45     # http://www.theeggeadventure.com/wikimedia/index.php/Linux_Tips#Use_sed_to_remove_ANSI_colors
46     return ansi_re.sub('', s)
47
48
49 def popen(command, *args, **kwargs):
50     if 'cwd' in kwargs:
51         sys.stdout.write('cd %s && ' % kwargs['cwd'])
52     if 'env' in kwargs:
53         for name, value in kwargs['env'].iteritems():
54             if value != os.environ.get(name, None):
55                 sys.stdout.write('%s=%s ' % (name, value))
56     sys.stdout.write(' '.join(command) + '\n')
57     sys.stdout.flush()
58     return subprocess.Popen(command, *args, **kwargs)
59
60
61 ignored_function_names = set([
62     'glGetString',
63     'glXGetCurrentDisplay',
64     'glXGetClientString',
65     'glXGetProcAddress',
66     'glXGetProcAddressARB',
67     'glXQueryVersion',
68     'glXGetVisualFromFBConfig',
69     'glXChooseFBConfig',
70     'glXCreateNewContext',
71     'glXMakeContextCurrent',
72     'glXQueryExtension',
73     'glXIsDirect',
74 ])
75
76
77 def image_tag(html, image):
78     url = os.path.relpath(image, options.results)
79     html.write('        <td><a href="%s"><img src="%s"/></a></td>\n' % (url, url))
80
81
82 def runtest(html, demo):
83
84     app = os.path.join(options.mesa_demos, 'src', demo)
85
86     dirname, basename = os.path.split(app)
87
88     trace = os.path.abspath(os.path.join(options.results, demo.replace('/', '-') + '.trace'))
89
90     env = os.environ.copy()
91     env['LD_PRELOAD'] = os.path.abspath(os.path.join(options.build, 'glxtrace.so'))
92     env['TRACE_FILE'] = trace
93
94     args = [os.path.join('.', basename)]
95     window_name = args[0]
96
97     p = popen(args, cwd=dirname)
98     for i in range(6):
99         time.sleep(0.5)
100         if p.poll() is not None:
101             break
102         if subprocess.call(['xwininfo', '-name', window_name], stdout=subprocess.PIPE, stderr=subprocess.PIPE) == 0:
103             break
104     if p.returncode is None:
105         p.terminate()
106     elif p.returncode:
107         sys.stdout.write('SKIP (app)\n')
108         return
109
110     ref_image = os.path.join(options.results, demo.replace('/', '-') + '.ref.png')
111     p = popen(args, env=env, cwd=dirname)
112     try:
113         for i in range(10):
114             time.sleep(0.5)
115             if p.poll() is not None:
116                 break
117             if subprocess.call(['xwininfo', '-name', window_name], stdout=subprocess.PIPE, stderr=subprocess.PIPE) == 0:
118                 break
119
120         if p.returncode is None:
121             subprocess.call("xwd -name '%s' | xwdtopnm | pnmtopng > '%s'" % (args[0], ref_image), shell=True)
122     finally:
123         if p.returncode is None:
124             p.terminate()
125             p.wait()
126         elif p.returncode:
127             print p.returncode
128             sys.stdout.write('FAIL (trace)\n')
129             return
130
131     p = popen([os.path.join(options.build, 'tracedump'), trace], stdout=subprocess.PIPE)
132     stdout, _ = p.communicate()
133     if p.returncode != 0:
134         sys.stdout.write('FAIL (tracedump)\n')
135         return
136
137     call_re = re.compile('^([0-9]+) (\w+)\(')
138     swapbuffers = 0
139     flushes = 0
140     for orig_line in stdout.split('\n'):
141         line = ansi_strip(orig_line)
142         mo = call_re.match(line)
143         if mo:
144             call_no = int(mo.group(1))
145             function_name = mo.group(2)
146             if function_name in ignored_function_names:
147                 continue
148             if function_name == 'glXSwapBuffers':
149                 swapbuffers += 1
150             if function_name in ('glFlush', 'glFinish'):
151                 flushes += 1
152         #print orig_line
153
154     args = [os.path.join(options.build, 'glretrace')]
155     if swapbuffers:
156         args += ['-db']
157         frames = swapbuffers
158     else:
159         args += ['-sb']
160         frames = flushes
161     if os.path.exists(ref_image) and frames < 10:
162         snapshot_prefix = os.path.join(options.results, demo.replace('/', '-') + '.')
163         args += ['-s', snapshot_prefix]
164     else:
165         snapshot_prefix = None
166     args += [trace]
167     p = popen(args, stdout=subprocess.PIPE)
168     stdout, _ = p.communicate()
169     if p.returncode != 0:
170         sys.stdout.write('FAIL (glretrace)\n')
171         return
172
173     image_re = re.compile('^Wrote (.*\.png)$')
174     image = None
175     for line in stdout.split('\n'):
176         mo = image_re.match(line)
177         if mo:
178             image = mo.group(1)
179
180     if image:
181         delta_image = os.path.join(options.results, demo.replace('/', '-') + '.diff.png')
182         p = popen([
183             'compare',
184             '-alpha', 'opaque',
185             '-metric', 'AE',
186             '-fuzz', '5%',
187             '-dissimilarity-threshold', '1',
188             ref_image, image, delta_image
189         ], stderr = subprocess.PIPE)
190         _, stderr = p.communicate()
191
192         try:
193             ae = int(stderr)
194         except ValueError:
195             ae = 9999
196
197         if ae:
198             html.write('      <tr>\n')
199             image_tag(html, ref_image)
200             image_tag(html, image)
201             image_tag(html, delta_image)
202             html.write('      </tr>\n')
203             html.flush()
204
205             sys.stdout.write('FAIL (snapshot)\n')
206             return
207
208     sys.stdout.write('PASS\n')
209
210
211 tests = [
212     'trivial/clear-color',
213     'trivial/clear-fbo',
214     'trivial/clear-fbo-scissor',
215     'trivial/clear-fbo-tex',
216     'trivial/clear-random',
217     'trivial/clear-repeat',
218     'trivial/clear-scissor',
219     'trivial/clear-undefined',
220     'trivial/createwin',
221     'trivial/dlist-begin-call-end',
222     'trivial/dlist-dangling',
223     'trivial/dlist-degenerate',
224     'trivial/dlist-edgeflag',
225     'trivial/dlist-edgeflag-dangling',
226     'trivial/dlist-flat-tri',
227     'trivial/dlist-mat-tri',
228     'trivial/dlist-recursive-call',
229     'trivial/dlist-tri-flat-tri',
230     'trivial/dlist-tri-mat-tri',
231     'trivial/draw2arrays',
232     'trivial/drawarrays',
233     'trivial/drawelements',
234     'trivial/drawelements-large',
235     'trivial/drawrange',
236     'trivial/flat-clip',
237     'trivial/fs-tri',
238     'trivial/line',
239     'trivial/line-clip',
240     'trivial/line-cull',
241     'trivial/line-flat',
242     'trivial/line-smooth',
243     'trivial/line-stipple-wide',
244     'trivial/line-userclip',
245     'trivial/line-userclip-clip',
246     'trivial/line-userclip-nop',
247     'trivial/line-userclip-nop-clip',
248     'trivial/line-wide',
249     'trivial/line-xor',
250     'trivial/lineloop',
251     'trivial/lineloop-clip',
252     'trivial/lineloop-elts',
253     'trivial/linestrip',
254     'trivial/linestrip-clip',
255     'trivial/linestrip-flat-stipple',
256     'trivial/linestrip-stipple',
257     'trivial/linestrip-stipple-wide',
258     'trivial/long-fixed-func',
259     'trivial/pgon-mode',
260     'trivial/point',
261     'trivial/point-clip',
262     'trivial/point-param',
263     'trivial/point-sprite',
264     'trivial/point-wide',
265     'trivial/point-wide-smooth',
266     'trivial/poly',
267     'trivial/poly-flat',
268     'trivial/poly-flat-clip',
269     'trivial/poly-flat-unfilled-clip',
270     'trivial/poly-unfilled',
271     'trivial/quad',
272     'trivial/quad-clip',
273     'trivial/quad-clip-all-vertices',
274     'trivial/quad-clip-nearplane',
275     'trivial/quad-degenerate',
276     'trivial/quad-flat',
277     'trivial/quad-offset-factor',
278     'trivial/quad-offset-unfilled',
279     'trivial/quad-offset-units',
280     'trivial/quad-tex-2d',
281     'trivial/quad-tex-3d',
282     'trivial/quad-tex-alpha',
283     'trivial/quad-tex-pbo',
284     'trivial/quad-tex-sub',
285     'trivial/quad-unfilled',
286     'trivial/quad-unfilled-clip',
287     'trivial/quad-unfilled-stipple',
288     'trivial/quads',
289     'trivial/quadstrip',
290     'trivial/quadstrip-clip',
291     'trivial/quadstrip-cont',
292     'trivial/quadstrip-flat',
293     'trivial/readpixels',
294     'trivial/sub-tex',
295     'trivial/tex-quads',
296     'trivial/tri',
297     'trivial/tri-alpha',
298     'trivial/tri-alpha-tex',
299     'trivial/tri-array-interleaved',
300     'trivial/tri-blend',
301     'trivial/tri-blend-color',
302     'trivial/tri-blend-max',
303     'trivial/tri-blend-min',
304     'trivial/tri-blend-revsub',
305     'trivial/tri-blend-sub',
306     'trivial/tri-clear',
307     'trivial/tri-clip',
308     'trivial/tri-cull',
309     'trivial/tri-cull-both',
310     'trivial/tri-dlist',
311     'trivial/tri-edgeflag',
312     'trivial/tri-edgeflag-array',
313     'trivial/tri-fbo',
314     'trivial/tri-fbo-tex',
315     'trivial/tri-fbo-tex-mip',
316     'trivial/tri-flat',
317     'trivial/tri-flat-clip',
318     'trivial/tri-fog',
319     'trivial/tri-fp',
320     'trivial/tri-fp-const-imm',
321     'trivial/tri-lit',
322     'trivial/tri-lit-material',
323     'trivial/tri-logicop-none',
324     'trivial/tri-logicop-xor',
325     'trivial/tri-mask-tri',
326     'trivial/tri-multitex-vbo',
327     'trivial/tri-orig',
328     'trivial/tri-point-line-clipped',
329     'trivial/tri-query',
330     'trivial/tri-repeat',
331     'trivial/tri-scissor-tri',
332     'trivial/tri-square',
333     'trivial/tri-stencil',
334     'trivial/tri-stipple',
335     'trivial/tri-tex',
336     'trivial/tri-tex-1d',
337     'trivial/tri-tex-3d',
338     'trivial/tri-tri',
339     'trivial/tri-unfilled',
340     'trivial/tri-unfilled-clip',
341     'trivial/tri-unfilled-edgeflag',
342     'trivial/tri-unfilled-fog',
343     'trivial/tri-unfilled-point',
344     'trivial/tri-unfilled-smooth',
345     'trivial/tri-unfilled-tri',
346     'trivial/tri-unfilled-tri-lit',
347     'trivial/tri-unfilled-userclip',
348     'trivial/tri-unfilled-userclip-stip',
349     'trivial/tri-userclip',
350     'trivial/tri-viewport',
351     'trivial/tri-z',
352     'trivial/tri-z-9',
353     'trivial/tri-z-eq',
354     'trivial/trifan',
355     'trivial/trifan-flat',
356     'trivial/trifan-flat-clip',
357     'trivial/trifan-flat-unfilled-clip',
358     'trivial/trifan-unfilled',
359     'trivial/tristrip',
360     'trivial/tristrip-clip',
361     'trivial/tristrip-flat',
362     'trivial/vbo-drawarrays',
363     'trivial/vbo-drawelements',
364     'trivial/vbo-drawrange',
365     'trivial/vbo-noninterleaved',
366     'trivial/vbo-tri',
367     'trivial/vp-array',
368     'trivial/vp-array-hf',
369     'trivial/vp-array-int',
370     'trivial/vp-clip',
371     'trivial/vp-line-clip',
372     'trivial/vp-tri',
373     'trivial/vp-tri-cb',
374     'trivial/vp-tri-cb-pos',
375     'trivial/vp-tri-cb-tex',
376     'trivial/vp-tri-imm',
377     'trivial/vp-tri-invariant',
378     'trivial/vp-tri-swap',
379     'trivial/vp-tri-tex',
380     'trivial/vp-unfilled',
381
382     'demos/arbfplight',
383     'demos/arbfslight',
384     'demos/arbocclude',
385     'demos/arbocclude2',
386     'demos/bounce',
387     'demos/clearspd',
388     'demos/copypix',
389     'demos/cubemap',
390     'demos/dinoshade',
391     'demos/dissolve',
392     'demos/drawpix',
393     'demos/engine',
394     'demos/fbo_firecube',
395     'demos/fbotexture',
396     'demos/fire',
397     'demos/fogcoord',
398     'demos/fplight',
399     'demos/fslight',
400     'demos/gamma',
401     'demos/gearbox',
402     'demos/gears',
403     'demos/geartrain',
404     'demos/glinfo',
405     'demos/gloss',
406     'demos/gltestperf',
407     'demos/ipers',
408     'demos/isosurf',
409     'demos/lodbias',
410     'demos/morph3d',
411     'demos/multiarb',
412     'demos/paltex',
413     'demos/pointblast',
414     'demos/projtex',
415     'demos/rain',
416     'demos/ray',
417     'demos/readpix',
418     'demos/reflect',
419     'demos/renormal',
420     'demos/shadowtex',
421     'demos/singlebuffer',
422     'demos/spectex',
423     'demos/spriteblast',
424     'demos/stex3d',
425     'demos/teapot',
426     'demos/terrain',
427     'demos/tessdemo',
428     'demos/texcyl',
429     'demos/texenv',
430     'demos/textures',
431     'demos/trispd',
432     'demos/tunnel',
433     'demos/tunnel2',
434     'demos/vao_demo',
435     'demos/winpos',
436
437     #'fp/fp-tri', # XXX: parameterized
438     'fp/point-position',
439     'fp/tri-depth',
440     'fp/tri-depth2',
441     'fp/tri-depthwrite',
442     'fp/tri-depthwrite2',
443     'fp/tri-param',
444     'fp/tri-tex',
445
446     #'fpglsl/fp-tri',
447
448     'glsl/array',
449     'glsl/bezier',
450     'glsl/bitmap',
451     'glsl/brick',
452     'glsl/bump',
453     'glsl/convolutions',
454     'glsl/deriv',
455     'glsl/fragcoord',
456     'glsl/fsraytrace',
457     'glsl/geom-sprites',
458     'glsl/geom-stipple-lines',
459     'glsl/geom-wide-lines',
460     'glsl/identity',
461     'glsl/linktest',
462     'glsl/mandelbrot',
463     'glsl/multinoise',
464     'glsl/multitex',
465     'glsl/noise',
466     'glsl/noise2',
467     'glsl/pointcoord',
468     'glsl/points',
469     'glsl/samplers',
470     'glsl/shadow_sampler',
471     'glsl/shtest',
472     'glsl/skinning',
473     'glsl/texaaline',
474     'glsl/texdemo1',
475     'glsl/toyball',
476     'glsl/trirast',
477     'glsl/twoside',
478     'glsl/vert-or-frag-only',
479     'glsl/vert-tex',
480     'glsl/vsraytrace',
481
482     #'gs/gs-tri',
483
484     #'perf/copytex',
485     #'perf/drawoverhead',
486     #'perf/fbobind',
487     #'perf/fill',
488     #'perf/genmipmap',
489     #'perf/readpixels',
490     #'perf/swapbuffers',
491     #'perf/teximage',
492     #'perf/vbo',
493     #'perf/vertexrate',
494
495     'redbook/aaindex',
496     'redbook/aapoly',
497     'redbook/aargb',
498     'redbook/accanti',
499     'redbook/accpersp',
500     'redbook/alpha',
501     'redbook/alpha3D',
502     'redbook/anti',
503     'redbook/bezcurve',
504     'redbook/bezmesh',
505     'redbook/checker',
506     'redbook/clip',
507     'redbook/colormat',
508     'redbook/combiner',
509     'redbook/convolution',
510     'redbook/cube',
511     'redbook/cubemap',
512     'redbook/depthcue',
513     'redbook/dof',
514     'redbook/double',
515     'redbook/drawf',
516     'redbook/feedback',
517     'redbook/fog',
518     'redbook/fogcoord',
519     'redbook/fogindex',
520     'redbook/font',
521     'redbook/hello',
522     'redbook/histogram',
523     'redbook/image',
524     'redbook/light',
525     'redbook/lines',
526     'redbook/list',
527     'redbook/material',
528     'redbook/minmax',
529     'redbook/mipmap',
530     'redbook/model',
531     'redbook/movelight',
532     'redbook/multisamp',
533     'redbook/multitex',
534     'redbook/mvarray',
535     'redbook/nurbs',
536     'redbook/pickdepth',
537     'redbook/picksquare',
538     'redbook/plane',
539     'redbook/planet',
540     'redbook/pointp',
541     'redbook/polyoff',
542     'redbook/polys',
543     'redbook/quadric',
544     'redbook/robot',
545     'redbook/sccolorlight',
546     'redbook/scene',
547     'redbook/scenebamb',
548     'redbook/sceneflat',
549     'redbook/select',
550     'redbook/shadowmap',
551     'redbook/smooth',
552     'redbook/stencil',
553     'redbook/stroke',
554     'redbook/surface',
555     'redbook/surfpoints',
556     'redbook/teaambient',
557     'redbook/teapots',
558     'redbook/tess',
559     'redbook/tesswind',
560     'redbook/texbind',
561     'redbook/texgen',
562     'redbook/texprox',
563     'redbook/texsub',
564     'redbook/texture3d',
565     'redbook/texturesurf',
566     'redbook/torus',
567     'redbook/trim',
568     'redbook/unproject',
569     'redbook/varray',
570     'redbook/wrap',
571
572     'samples/accum',
573     'samples/bitmap1',
574     'samples/bitmap2',
575     'samples/blendeq',
576     'samples/blendxor',
577     'samples/copy',
578     'samples/cursor',
579     'samples/depth',
580     'samples/eval',
581     'samples/fog',
582     'samples/font',
583     'samples/line',
584     'samples/logo',
585     'samples/nurb',
586     'samples/oglinfo',
587     'samples/olympic',
588     'samples/overlay',
589     'samples/point',
590     'samples/prim',
591     'samples/quad',
592     'samples/rgbtoppm',
593     'samples/select',
594     'samples/shape',
595     'samples/sphere',
596     'samples/star',
597     'samples/stencil',
598     'samples/stretch',
599     'samples/texture',
600     'samples/tri',
601     'samples/wave',
602
603     #'slang/cltest',
604     #'slang/sotest',
605     #'slang/vstest',
606
607     'tests/afsmultiarb',
608     'tests/antialias',
609     'tests/arbfpspec',
610     'tests/arbfptest1',
611     'tests/arbfptexture',
612     'tests/arbfptrig',
613     'tests/arbgpuprog',
614     'tests/arbnpot',
615     'tests/arbnpot-mipmap',
616     'tests/arbvptest1',
617     'tests/arbvptest3',
618     'tests/arbvptorus',
619     'tests/arbvpwarpmesh',
620     'tests/arraytexture',
621     'tests/auxbuffer',
622     'tests/blendxor',
623     'tests/blitfb',
624     'tests/bufferobj',
625     'tests/bug_3050',
626     'tests/bug_3101',
627     'tests/bug_3195',
628     'tests/bug_texstore_i8',
629     'tests/bumpmap',
630     'tests/calibrate_rast',
631     'tests/condrender',
632     #'tests/copypixrate', # XXX: benchmark
633     'tests/cva',
634     'tests/cva_huge',
635     'tests/cylwrap',
636     'tests/drawbuffers',
637     'tests/drawbuffers2',
638     'tests/drawstencil',
639     'tests/exactrast',
640     'tests/ext422square',
641     'tests/fbotest1',
642     'tests/fbotest2',
643     'tests/fbotest3',
644     #'tests/fillrate', # XXX: benchmark
645     'tests/floattex',
646     'tests/fogcoord',
647     'tests/fptest1',
648     'tests/fptexture',
649     'tests/getteximage',
650     'tests/glutfx',
651     'tests/interleave',
652     'tests/invert',
653     'tests/jkrahntest',
654     'tests/lineclip',
655     'tests/manytex',
656     'tests/mapbufrange',
657     'tests/minmag',
658     'tests/mipgen',
659     'tests/mipmap_comp',
660     'tests/mipmap_comp_tests',
661     'tests/mipmap_limits',
662     'tests/mipmap_tunnel',
663     'tests/mipmap_view',
664     'tests/multipal',
665     'tests/multitexarray',
666     'tests/multiwindow',
667     'tests/no_s3tc',
668     'tests/occlude',
669     'tests/packedpixels',
670     'tests/pbo',
671     'tests/persp_hint',
672     'tests/prim',
673     'tests/prog_parameter',
674     'tests/quads',
675     'tests/random',
676     #'tests/readrate', # XXX: benchmark
677     'tests/rubberband',
678     'tests/scissor',
679     'tests/scissor-viewport',
680     'tests/seccolor',
681     'tests/shader-interp',
682     'tests/shader_api',
683     'tests/shadow-sample',
684     'tests/sharedtex',
685     'tests/stencilreaddraw',
686     'tests/stencilwrap',
687     'tests/step',
688     'tests/streaming_rect',
689     'tests/subtex',
690     #'tests/subtexrate', # XXX: benchmark
691     'tests/tex1d',
692     'tests/texcmp',
693     'tests/texcompress2',
694     'tests/texcompsub',
695     'tests/texdown',
696     'tests/texfilt',
697     'tests/texgenmix',
698     'tests/texleak',
699     'tests/texline',
700     'tests/texobj',
701     'tests/texobjshare',
702     'tests/texrect',
703     'tests/unfilledclip',
704     'tests/vparray',
705     'tests/vpeval',
706     'tests/vptest1',
707     'tests/vptest2',
708     'tests/vptest3',
709     'tests/vptorus',
710     'tests/vpwarpmesh',
711     'tests/yuvrect',
712     'tests/yuvsquare',
713     'tests/zbitmap',
714     'tests/zcomp',
715     'tests/zdrawpix',
716     'tests/zreaddraw',
717
718     #'vp/vp-tris',
719     #'vpglsl/vp-tris',
720
721     'xdemos/corender',
722     'xdemos/glsync',
723     #'xdemos/glthreads', # XXX: multithreaded
724     'xdemos/glxcontexts',
725     'xdemos/glxdemo',
726     'xdemos/glxgears',
727     'xdemos/glxgears_fbconfig',
728     'xdemos/glxgears_pixmap',
729     'xdemos/glxheads',
730     'xdemos/glxinfo',
731     'xdemos/glxpbdemo',
732     'xdemos/glxpixmap',
733     'xdemos/glxsnoop',
734     'xdemos/glxswapcontrol',
735     'xdemos/manywin',
736     'xdemos/msctest',
737     'xdemos/multictx',
738     'xdemos/offset',
739     'xdemos/omlsync',
740     'xdemos/opencloseopen',
741     'xdemos/overlay',
742     'xdemos/pbdemo',
743     'xdemos/pbinfo',
744     'xdemos/shape',
745     'xdemos/sharedtex',
746     #'xdemos/sharedtex_mt', # XXX: multithreaded
747     'xdemos/texture_from_pixmap',
748     'xdemos/wincopy',
749     'xdemos/xfont',
750     'xdemos/xrotfontdemo',
751     'xdemos/yuvrect_client',
752 ]
753
754
755 _tests = [
756     'trivial/tri',
757     'trivial/tri-tex',
758 ]
759
760
761 def main():
762     global options
763
764     # Parse command line options
765     optparser = optparse.OptionParser(
766         usage='\n\t%prog [options] [demo] ...',
767         version='%%prog')
768     optparser.add_option(
769         '--build', metavar='PATH',
770         type='string', dest='build', default='.',
771         help='path to apitrace build [default=%default]')
772     optparser.add_option(
773         '--results', metavar='PATH',
774         type='string', dest='results', default='results',
775         help='results directory [default=%default]')
776     optparser.add_option(
777         '--mesa-demos', metavar='PATH',
778         type='string', dest='mesa_demos', default=os.environ.get('MESA_DEMOS'),
779         help='path to Mesa demos [default=%default]')
780
781     (options, args) = optparser.parse_args(sys.argv[1:])
782
783     if not options.mesa_demos:
784         optparser.error('path to Mesa demos not specified')
785     if not os.path.exists(options.results):
786         os.makedirs(options.results)
787
788     if args:
789         testlist = []
790         for arg in args:
791             if arg.endswith('/'):
792                 for test in tests:
793                     if test.startswith(arg):
794                         testlist.append(test)
795             else:
796                 testlist.append(arg)
797     else:
798         testlist = tests
799
800     html = open(os.path.join(options.results, 'index.html'), 'wt')
801     html.write('<html>\n')
802     html.write('  <body>\n')
803     html.write('    <table border="1">\n')
804     html.write('      <tr><th>Ref</th><th>Src</th><th>&Delta;</th></tr>\n')
805     for test in testlist:
806        runtest(html, test)
807     html.write('    </table>\n')
808     html.write('  </body>\n')
809     html.write('</html>\n')
810
811
812 if __name__ == '__main__':
813     main()