DRI2: report swap events correctly in direct rendered case
[mesa.git] / progs / gallium / python / tests / base.py
1 #!/usr/bin/env python
2 ##########################################################################
3 #
4 # Copyright 2009 VMware, Inc.
5 # Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
6 # All Rights Reserved.
7 #
8 # Permission is hereby granted, free of charge, to any person obtaining a
9 # copy of this software and associated documentation files (the
10 # "Software"), to deal in the Software without restriction, including
11 # without limitation the rights to use, copy, modify, merge, publish,
12 # distribute, sub license, and/or sell copies of the Software, and to
13 # permit persons to whom the Software is furnished to do so, subject to
14 # the following conditions:
15 #
16 # The above copyright notice and this permission notice (including the
17 # next paragraph) shall be included in all copies or substantial portions
18 # of the Software.
19 #
20 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
23 # IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
24 # ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 #
28 ##########################################################################
29
30
31 """Base classes for tests.
32
33 Loosely inspired on Python's unittest module.
34 """
35
36
37 import os.path
38 import sys
39
40 from gallium import *
41
42
43 # Enumerate all pixel formats
44 formats = {}
45 for name, value in globals().items():
46 if name.startswith("PIPE_FORMAT_") and isinstance(value, int):
47 formats[value] = name
48
49 def is_depth_stencil_format(format):
50 # FIXME: make and use binding to util_format_is_depth_or_stencil
51 return format in (
52 PIPE_FORMAT_Z32_UNORM,
53 PIPE_FORMAT_S8Z24_UNORM,
54 PIPE_FORMAT_X8Z24_UNORM,
55 PIPE_FORMAT_Z16_UNORM,
56 )
57
58 def make_image(width, height, rgba):
59 import Image
60 outimage = Image.new(
61 mode='RGB',
62 size=(width, height),
63 color=(0,0,0))
64 outpixels = outimage.load()
65 for y in range(0, height):
66 for x in range(0, width):
67 offset = (y*width + x)*4
68 r, g, b, a = [int(min(max(rgba[offset + ch], 0.0), 1.0)*255) for ch in range(4)]
69 outpixels[x, y] = r, g, b
70 return outimage
71
72 def save_image(width, height, rgba, filename):
73 outimage = make_image(width, height, rgba)
74 outimage.save(filename, "PNG")
75
76 def show_image(width, height, **rgbas):
77 import Tkinter as tk
78 from PIL import Image, ImageTk
79
80 root = tk.Tk()
81
82 x = 64
83 y = 64
84
85 labels = rgbas.keys()
86 labels.sort()
87 for i in range(len(labels)):
88 label = labels[i]
89 outimage = make_image(width, height, rgbas[label])
90
91 if i:
92 window = tk.Toplevel(root)
93 else:
94 window = root
95 window.title(label)
96 image1 = ImageTk.PhotoImage(outimage)
97 w = image1.width()
98 h = image1.height()
99 window.geometry("%dx%d+%d+%d" % (w, h, x, y))
100 panel1 = tk.Label(window, image=image1)
101 panel1.pack(side='top', fill='both', expand='yes')
102 panel1.image = image1
103 x += w + 2
104
105 root.mainloop()
106
107
108 class TestFailure(Exception):
109
110 pass
111
112 class TestSkip(Exception):
113
114 pass
115
116
117 class Test:
118
119 def __init__(self):
120 pass
121
122 def _run(self, result):
123 raise NotImplementedError
124
125 def run(self):
126 result = TestResult()
127 self._run(result)
128 result.summary()
129
130 def assert_rgba(self, surface, x, y, w, h, expected_rgba, pixel_tol=4.0/256, surface_tol=0.85):
131 total = h*w
132 different = surface.compare_tile_rgba(x, y, w, h, expected_rgba, tol=pixel_tol)
133 if different:
134 sys.stderr.write("%u out of %u pixels differ\n" % (different, total))
135
136 if float(total - different)/float(total) < surface_tol:
137 if 0:
138 rgba = FloatArray(h*w*4)
139 surface.get_tile_rgba(x, y, w, h, rgba)
140 show_image(w, h, Result=rgba, Expected=expected_rgba)
141 save_image(w, h, rgba, "result.png")
142 save_image(w, h, expected_rgba, "expected.png")
143 #sys.exit(0)
144
145 raise TestFailure
146
147
148 class TestCase(Test):
149
150 tags = ()
151
152 def __init__(self, dev, **kargs):
153 Test.__init__(self)
154 self.dev = dev
155 self.__dict__.update(kargs)
156
157 def description(self):
158 descriptions = []
159 for tag in self.tags:
160 value = self.get(tag)
161 if value is not None and value != '':
162 descriptions.append(tag + '=' + str(value))
163 return ' '.join(descriptions)
164
165 def get(self, tag):
166 try:
167 method = getattr(self, '_get_' + tag)
168 except AttributeError:
169 return getattr(self, tag, None)
170 else:
171 return method()
172
173 def _get_target(self):
174 return {
175 PIPE_TEXTURE_1D: "1d",
176 PIPE_TEXTURE_2D: "2d",
177 PIPE_TEXTURE_3D: "3d",
178 PIPE_TEXTURE_CUBE: "cube",
179 }[self.target]
180
181 def _get_format(self):
182 name = formats[self.format]
183 if name.startswith('PIPE_FORMAT_'):
184 name = name[12:]
185 name = name.lower()
186 return name
187
188 def _get_face(self):
189 if self.target == PIPE_TEXTURE_CUBE:
190 return {
191 PIPE_TEX_FACE_POS_X: "+x",
192 PIPE_TEX_FACE_NEG_X: "-x",
193 PIPE_TEX_FACE_POS_Y: "+y",
194 PIPE_TEX_FACE_NEG_Y: "-y",
195 PIPE_TEX_FACE_POS_Z: "+z",
196 PIPE_TEX_FACE_NEG_Z: "-z",
197 }[self.face]
198 else:
199 return ''
200
201 def test(self):
202 raise NotImplementedError
203
204 def _run(self, result):
205 result.test_start(self)
206 try:
207 self.test()
208 except KeyboardInterrupt:
209 raise
210 except TestSkip:
211 result.test_skipped(self)
212 except TestFailure:
213 result.test_failed(self)
214 else:
215 result.test_passed(self)
216
217
218 class TestSuite(Test):
219
220 def __init__(self, tests = None):
221 Test.__init__(self)
222 if tests is None:
223 self.tests = []
224 else:
225 self.tests = tests
226
227 def add_test(self, test):
228 self.tests.append(test)
229
230 def _run(self, result):
231 for test in self.tests:
232 test._run(result)
233
234
235 class TestResult:
236
237 def __init__(self):
238 self.tests = 0
239 self.passed = 0
240 self.skipped = 0
241 self.failed = 0
242
243 self.names = ['result']
244 self.types = ['pass skip fail']
245 self.rows = []
246
247 def test_start(self, test):
248 sys.stdout.write("Running %s...\n" % test.description())
249 sys.stdout.flush()
250 self.tests += 1
251
252 def test_passed(self, test):
253 sys.stdout.write("PASS\n")
254 sys.stdout.flush()
255 self.passed += 1
256 self.log_result(test, 'pass')
257
258 def test_skipped(self, test):
259 sys.stdout.write("SKIP\n")
260 sys.stdout.flush()
261 self.skipped += 1
262 #self.log_result(test, 'skip')
263
264 def test_failed(self, test):
265 sys.stdout.write("FAIL\n")
266 sys.stdout.flush()
267 self.failed += 1
268 self.log_result(test, 'fail')
269
270 def log_result(self, test, result):
271 row = ['']*len(self.names)
272
273 # add result
274 assert self.names[0] == 'result'
275 assert result in ('pass', 'skip', 'fail')
276 row[0] = result
277
278 # add tags
279 for tag in test.tags:
280 value = test.get(tag)
281
282 # infer type
283 if value is None:
284 continue
285 elif isinstance(value, (int, float)):
286 value = str(value)
287 type = 'c' # continous
288 elif isinstance(value, basestring):
289 type = 'd' # discrete
290 else:
291 assert False
292 value = str(value)
293 type = 'd' # discrete
294
295 # insert value
296 try:
297 col = self.names.index(tag, 1)
298 except ValueError:
299 self.names.append(tag)
300 self.types.append(type)
301 row.append(value)
302 else:
303 row[col] = value
304 assert self.types[col] == type
305
306 self.rows.append(row)
307
308 def summary(self):
309 sys.stdout.write("%u tests, %u passed, %u skipped, %u failed\n\n" % (self.tests, self.passed, self.skipped, self.failed))
310 sys.stdout.flush()
311
312 name, ext = os.path.splitext(os.path.basename(sys.argv[0]))
313 filename = name + '.tsv'
314 stream = file(filename, 'wt')
315
316 # header
317 stream.write('\t'.join(self.names) + '\n')
318 stream.write('\t'.join(self.types) + '\n')
319 stream.write('class\n')
320
321 # rows
322 for row in self.rows:
323 row += ['']*(len(self.names) - len(row))
324 stream.write('\t'.join(row) + '\n')
325
326 stream.close()
327
328 # See http://www.ailab.si/orange/doc/ofb/c_otherclass.htm
329 try:
330 import orange
331 import orngTree
332 except ImportError:
333 sys.stderr.write('Install Orange from http://www.ailab.si/orange/ for a classification tree.\n')
334 return
335
336 data = orange.ExampleTable(filename)
337
338 tree = orngTree.TreeLearner(data, sameMajorityPruning=1, mForPruning=2)
339
340 orngTree.printTxt(tree, maxDepth=4)
341
342 file(name+'.txt', 'wt').write(orngTree.dumpTree(tree))
343
344 orngTree.printDot(tree, fileName=name+'.dot', nodeShape='ellipse', leafShape='box')