Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(752)

Side by Side Diff: conformance/ogles/process-ogles2-tests.py

Issue 41993002: Add ToT WebGL conformance tests : part 9 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/webgl/sdk/tests/
Patch Set: Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « conformance/ogles/ogles-utils.js ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
## -0,0 +1 ##
+LF
\ No newline at end of property
OLDNEW
(Empty)
1 #!/usr/bin/python
2
3 """generates tests from OpenGL ES 2.0 .run/.test files."""
4
5 import os
6 import os.path
7 import sys
8 import re
9 import json
10 import shutil
11 from optparse import OptionParser
12 from xml.dom.minidom import parse
13
14 if sys.version < '2.6':
15 print 'Wrong Python Version !!!: Need >= 2.6'
16 sys.exit(1)
17
18 # each shader test generates up to 3 512x512 images.
19 # a 512x512 image takes 1meg of memory so set this
20 # number apporpriate for the platform with
21 # the smallest memory issue. At 8 that means
22 # at least 24 meg is needed to run the test.
23 MAX_TESTS_PER_SET = 8
24
25 VERBOSE = False
26
27 FILTERS = [
28 re.compile("GL/"),
29 ]
30
31 LICENSE = """
32 /*
33 ** Copyright (c) 2012 The Khronos Group Inc.
34 **
35 ** Permission is hereby granted, free of charge, to any person obtaining a
36 ** copy of this software and/or associated documentation files (the
37 ** "Materials"), to deal in the Materials without restriction, including
38 ** without limitation the rights to use, copy, modify, merge, publish,
39 ** distribute, sublicense, and/or sell copies of the Materials, and to
40 ** permit persons to whom the Materials are furnished to do so, subject to
41 ** the following conditions:
42 **
43 ** The above copyright notice and this permission notice shall be included
44 ** in all copies or substantial portions of the Materials.
45 **
46 ** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
47 ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
48 ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
49 ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
50 ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
51 ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
52 ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
53 */
54 """
55
56 COMMENT_RE = re.compile("/\*\n\*\*\s+Copyright.*?\*/",
57 re.IGNORECASE | re.DOTALL)
58 REMOVE_COPYRIGHT_RE = re.compile("\/\/\s+Copyright.*?\n",
59 re.IGNORECASE | re.DOTALL)
60 MATRIX_RE = re.compile("Matrix(\\d)")
61
62 VALID_UNIFORM_TYPES = [
63 "uniform1f",
64 "uniform1fv",
65 "uniform1fv",
66 "uniform1i",
67 "uniform1iv",
68 "uniform1iv",
69 "uniform2f",
70 "uniform2fv",
71 "uniform2fv",
72 "uniform2i",
73 "uniform2iv",
74 "uniform2iv",
75 "uniform3f",
76 "uniform3fv",
77 "uniform3fv",
78 "uniform3i",
79 "uniform3iv",
80 "uniform3iv",
81 "uniform4f",
82 "uniform4fv",
83 "uniform4fv",
84 "uniform4i",
85 "uniform4iv",
86 "uniform4ivy",
87 "uniformMatrix2fv",
88 "uniformMatrix2fv",
89 "uniformMatrix3fv",
90 "uniformMatrix3fv",
91 "uniformMatrix4fv",
92 "uniformMatrix4fv",
93 ]
94
95 SUBSTITUTIONS = [
96 ("uniformmat3fv", "uniformMatrix3fv"),
97 ("uniformmat4fv", "uniformMatrix4fv"),
98 ]
99
100
101 def Log(msg):
102 global VERBOSE
103 if VERBOSE:
104 print msg
105
106
107 def TransposeMatrix(values, dim):
108 size = dim * dim
109 count = len(values) / size
110 for m in range(0, count):
111 offset = m * size
112 for i in range(0, dim):
113 for j in range(i + 1, dim):
114 t = values[offset + i * dim + j]
115 values[offset + i * dim + j] = values[offset + j * dim + i]
116 values[offset + j * dim + i] = t
117
118
119 def GetValidTypeName(type_name):
120 global VALID_UNIFORM_TYPES
121 global SUBSTITUTIONS
122 for subst in SUBSTITUTIONS:
123 type_name = type_name.replace(subst[0], subst[1])
124 if not type_name in VALID_UNIFORM_TYPES:
125 print "unknown type name: ", type_name
126 raise SyntaxError
127 return type_name
128
129
130 def WriteOpen(filename):
131 dirname = os.path.dirname(filename)
132 if len(dirname) > 0 and not os.path.exists(dirname):
133 os.makedirs(dirname)
134 return open(filename, "wb")
135
136
137 class TxtWriter():
138 def __init__(self, filename):
139 self.filename = filename
140 self.lines = []
141
142 def Write(self, line):
143 self.lines.append(line)
144
145 def Close(self):
146 if len(self.lines) > 0:
147 Log("Writing: %s" % self.filename)
148 f = WriteOpen(self.filename)
149 f.write("# this file is auto-generated. DO NOT EDIT.\n")
150 f.write("".join(self.lines))
151 f.close()
152
153
154 def ReadFileAsLines(filename):
155 f = open(filename, "r")
156 lines = f.readlines()
157 f.close()
158 return [line.strip() for line in lines]
159
160
161 def ReadFile(filename):
162 f = open(filename, "r")
163 content = f.read()
164 f.close()
165 return content.replace("\r\n", "\n")
166
167
168 def Chunkify(list, chunk_size):
169 """divides an array into chunks of chunk_size"""
170 return [list[i:i + chunk_size] for i in range(0, len(list), chunk_size)]
171
172
173 def GetText(nodelist):
174 """Gets the text of from a list of nodes"""
175 rc = []
176 for node in nodelist:
177 if node.nodeType == node.TEXT_NODE:
178 rc.append(node.data)
179 return ''.join(rc)
180
181
182 def GetElementText(node, name):
183 """Gets the text of an element"""
184 elements = node.getElementsByTagName(name)
185 if len(elements) > 0:
186 return GetText(elements[0].childNodes)
187 else:
188 return None
189
190
191 def GetBoolElement(node, name):
192 text = GetElementText(node, name)
193 return text.lower() == "true"
194
195
196 def GetModel(node):
197 """Gets the model"""
198 model = GetElementText(node, "model")
199 if model and len(model.strip()) == 0:
200 elements = node.getElementsByTagName("model")
201 if len(elements) > 0:
202 model = GetElementText(elements[0], "filename")
203 return model
204
205
206 def RelativizePaths(base, paths, template):
207 """converts paths to relative paths"""
208 rels = []
209 for p in paths:
210 #print "---"
211 #print "base: ", os.path.abspath(base)
212 #print "path: ", os.path.abspath(p)
213 relpath = os.path.relpath(os.path.abspath(p), os.path.dirname(os.path.abspat h(base))).replace("\\", "/")
214 #print "rel : ", relpath
215 rels.append(template % relpath)
216 return "\n".join(rels)
217
218
219 def CopyFile(filename, src, dst):
220 s = os.path.abspath(os.path.join(os.path.dirname(src), filename))
221 d = os.path.abspath(os.path.join(os.path.dirname(dst), filename))
222 dst_dir = os.path.dirname(d)
223 if not os.path.exists(dst_dir):
224 os.makedirs(dst_dir)
225 shutil.copyfile(s, d)
226
227
228 def CopyShader(filename, src, dst):
229 s = os.path.abspath(os.path.join(os.path.dirname(src), filename))
230 d = os.path.abspath(os.path.join(os.path.dirname(dst), filename))
231 text = ReadFile(s)
232 # By agreement with the Khronos OpenGL working group we are allowed
233 # to open source only the .vert and .frag files from the OpenGL ES 2.0
234 # conformance tests. All other files from the OpenGL ES 2.0 conformance
235 # tests are not included.
236 marker = "insert-copyright-here"
237 new_text = COMMENT_RE.sub(marker, text)
238 if new_text == text:
239 print "no matching license found:", s
240 raise RuntimeError
241 new_text = REMOVE_COPYRIGHT_RE.sub("", new_text)
242 new_text = new_text.replace(marker, LICENSE)
243 f = WriteOpen(d)
244 f.write(new_text)
245 f.close()
246
247
248 def IsOneOf(string, regexs):
249 for regex in regexs:
250 if re.match(regex, string):
251 return True
252 return False
253
254
255 def CheckForUnknownTags(valid_tags, node, depth=1):
256 """do a hacky check to make sure we're not missing something."""
257 for child in node.childNodes:
258 if child.localName and not IsOneOf(child.localName, valid_tags[0]):
259 print "unsupported tag:", child.localName
260 print "depth:", depth
261 raise SyntaxError
262 else:
263 if len(valid_tags) > 1:
264 CheckForUnknownTags(valid_tags[1:], child, depth + 1)
265
266
267 def IsFileWeWant(filename):
268 for f in FILTERS:
269 if f.search(filename):
270 return True
271 return False
272
273
274 class TestReader():
275 """class to read and parse tests"""
276
277 def __init__(self, basepath):
278 self.tests = []
279 self.modes = {}
280 self.patterns = {}
281 self.basepath = basepath
282
283 def Print(self, msg):
284 if self.verbose:
285 print msg
286
287 def MakeOutPath(self, filename):
288 relpath = os.path.relpath(os.path.abspath(filename), os.path.dirname(os.path .abspath(self.basepath)))
289 return relpath
290
291 def ReadTests(self, filename):
292 """reads a .run file and parses."""
293 Log("reading %s" % filename)
294 outname = self.MakeOutPath(filename + ".txt")
295 f = TxtWriter(outname)
296 dirname = os.path.dirname(filename)
297 lines = ReadFileAsLines(filename)
298 count = 0
299 tests_data = []
300 for line in lines:
301 if len(line) > 0 and not line.startswith("#"):
302 fname = os.path.join(dirname, line)
303 if line.endswith(".run"):
304 if self.ReadTests(fname):
305 f.Write(line + ".txt\n")
306 count += 1
307 elif line.endswith(".test"):
308 tests_data.extend(self.ReadTest(fname))
309 else:
310 print "Error in %s:%d:%s" % (filename, count, line)
311 raise SyntaxError()
312 if len(tests_data):
313 global MAX_TESTS_PER_SET
314 sets = Chunkify(tests_data, MAX_TESTS_PER_SET)
315 id = 1
316 for set in sets:
317 suffix = "_%03d_to_%03d" % (id, id + len(set) - 1)
318 test_outname = self.MakeOutPath(filename + suffix + ".html")
319 if os.path.basename(test_outname).startswith("input.run"):
320 dname = os.path.dirname(test_outname)
321 folder_name = os.path.basename(dname)
322 test_outname = os.path.join(dname, folder_name + suffix + ".html")
323 self.WriteTests(filename, test_outname, {"tests":set})
324 f.Write(os.path.basename(test_outname) + "\n")
325 id += len(set)
326 count += 1
327 f.Close()
328 return count
329
330 def ReadTest(self, filename):
331 """reads a .test file and parses."""
332 Log("reading %s" % filename)
333 dom = parse(filename)
334 tests = dom.getElementsByTagName("test")
335 tests_data = []
336 outname = self.MakeOutPath(filename + ".html")
337 for test in tests:
338 if not IsFileWeWant(filename):
339 self.CopyShaders(test, filename, outname)
340 else:
341 test_data = self.ProcessTest(test, filename, outname, len(tests_data))
342 if test_data:
343 tests_data.append(test_data)
344 return tests_data
345
346 def ProcessTest(self, test, filename, outname, id):
347 """Process a test"""
348 mode = test.getAttribute("mode")
349 pattern = test.getAttribute("pattern")
350 self.modes[mode] = 1
351 self.patterns[pattern] = 1
352 Log ("%d: mode: %s pattern: %s" % (id, mode, pattern))
353 method = getattr(self, 'Process_' + pattern)
354 test_data = method(test, filename, outname)
355 if test_data:
356 test_data["pattern"] = pattern
357 return test_data
358
359 def WriteTests(self, filename, outname, tests_data):
360 Log("Writing %s" % outname)
361 template = """<!DOCTYPE html>
362 <!-- this file is auto-generated. DO NOT EDIT.
363 %(license)s
364 -->
365 <html>
366 <head>
367 <meta charset="utf-8">
368 <title>WebGL GLSL conformance test: %(title)s</title>
369 %(css)s
370 %(scripts)s
371 </head>
372 <body>
373 <canvas id="example" width="500" height="500" style="width: 16px; height: 16px;" ></canvas>
374 <div id="description"></div>
375 <div id="console"></div>
376 </body>
377 <script>
378 "use strict";
379 OpenGLESTestRunner.run(%(tests_data)s);
380 var successfullyParsed = true;
381 </script>
382 </html>
383 """
384 css = [
385 "../../resources/js-test-style.css",
386 "../resources/ogles-tests.css",
387 ]
388 scripts = [
389 "../../resources/js-test-pre.js",
390 "../resources/webgl-test.js",
391 "../resources/webgl-test-utils.js",
392 "ogles-utils.js",
393 ]
394 css_html = RelativizePaths(outname, css, '<link rel="stylesheet" href="%s" / >')
395 scripts_html = RelativizePaths(outname, scripts, '<script src="%s"></script> ')
396
397 f = WriteOpen(outname)
398 f.write(template % {
399 "license": LICENSE,
400 "css": css_html,
401 "scripts": scripts_html,
402 "title": os.path.basename(outname),
403 "tests_data": json.dumps(tests_data, indent=2)
404 })
405 f.close()
406
407
408 def CopyShaders(self, test, filename, outname):
409 """For tests we don't actually support yet, at least copy the shaders"""
410 shaders = test.getElementsByTagName("shader")
411 for shader in shaders:
412 for name in ["vertshader", "fragshader"]:
413 s = GetElementText(shader, name)
414 if s and s != "empty":
415 CopyShader(s, filename, outname)
416
417 #
418 # pattern handlers.
419 #
420
421 def Process_compare(self, test, filename, outname):
422 global MATRIX_RE
423
424 valid_tags = [
425 ["shader", "model", "glstate"],
426 ["uniform", "vertshader", "fragshader", "filename", "depthrange"],
427 ["name", "count", "transpose", "uniform*", "near", "far"],
428 ]
429 CheckForUnknownTags(valid_tags, test)
430
431 # parse the test
432 shaders = test.getElementsByTagName("shader")
433 shaderInfos = []
434 for shader in shaders:
435 v = GetElementText(shader, "vertshader")
436 f = GetElementText(shader, "fragshader")
437 CopyShader(v, filename, outname)
438 CopyShader(f, filename, outname)
439 info = {
440 "vertexShader": v,
441 "fragmentShader": f,
442 }
443 shaderInfos.append(info)
444 uniformElems = shader.getElementsByTagName("uniform")
445 if len(uniformElems) > 0:
446 uniforms = {}
447 info["uniforms"] = uniforms
448 for uniformElem in uniformElems:
449 uniform = {"count": 1}
450 for child in uniformElem.childNodes:
451 if child.localName == None:
452 pass
453 elif child.localName == "name":
454 uniforms[GetText(child.childNodes)] = uniform
455 elif child.localName == "count":
456 uniform["count"] = int(GetText(child.childNodes))
457 elif child.localName == "transpose":
458 uniform["transpose"] = (GetText(child.childNodes) == "true")
459 else:
460 if "type" in uniform:
461 print "utype was:", uniform["type"], " found ", child.localName
462 raise SyntaxError
463 type_name = GetValidTypeName(child.localName)
464 uniform["type"] = type_name
465 valueText = GetText(child.childNodes).replace(",", " ")
466 uniform["value"] = [float(t) for t in valueText.split()]
467 m = MATRIX_RE.search(type_name)
468 if m:
469 # Why are these backward from the API?!?!?
470 TransposeMatrix(uniform["value"], int(m.group(1)))
471 data = {
472 "name": os.path.basename(outname),
473 "model": GetModel(test),
474 "referenceProgram": shaderInfos[1],
475 "testProgram": shaderInfos[0],
476 }
477 gl_states = test.getElementsByTagName("glstate")
478 if len(gl_states) > 0:
479 state = {}
480 data["state"] = state
481 for gl_state in gl_states:
482 for state_name in gl_state.childNodes:
483 if state_name.localName:
484 values = {}
485 for field in state_name.childNodes:
486 if field.localName:
487 values[field.localName] = GetText(field.childNodes)
488 state[state_name.localName] = values
489 return data
490
491 def Process_shaderload(self, test, filename, outname):
492 """no need for shaderload tests"""
493 self.CopyShaders(test, filename, outname)
494
495 def Process_extension(self, test, filename, outname):
496 """no need for extension tests"""
497 self.CopyShaders(test, filename, outname)
498
499 def Process_createtests(self, test, filename, outname):
500 Log("createtests Not implemented: %s" % filename)
501 self.CopyShaders(test, filename, outname)
502
503 def Process_GL2Test(self, test, filename, outname):
504 Log("GL2Test Not implemented: %s" % filename)
505 self.CopyShaders(test, filename, outname)
506
507 def Process_uniformquery(self, test, filename, outname):
508 Log("uniformquery Not implemented: %s" % filename)
509 self.CopyShaders(test, filename, outname)
510
511 def Process_egl_image_external(self, test, filename, outname):
512 """no need for egl_image_external tests"""
513 self.CopyShaders(test, filename, outname)
514
515 def Process_dismount(self, test, filename, outname):
516 Log("dismount Not implemented: %s" % filename)
517 self.CopyShaders(test, filename, outname)
518
519 def Process_build(self, test, filename, outname):
520 """don't need build tests"""
521 valid_tags = [
522 ["shader", "compstat", "linkstat"],
523 ["vertshader", "fragshader"],
524 ]
525 CheckForUnknownTags(valid_tags, test)
526
527 shader = test.getElementsByTagName("shader")
528 if not shader:
529 return None
530 vs = GetElementText(shader[0], "vertshader")
531 fs = GetElementText(shader[0], "fragshader")
532 if vs and vs != "empty":
533 CopyShader(vs, filename, outname)
534 if fs and fs != "empty":
535 CopyShader(fs, filename, outname)
536 data = {
537 "name": os.path.basename(outname),
538 "compstat": bool(GetBoolElement(test, "compstat")),
539 "linkstat": bool(GetBoolElement(test, "linkstat")),
540 "testProgram": {
541 "vertexShader": vs,
542 "fragmentShader": fs,
543 },
544 }
545 attach = test.getElementsByTagName("attach")
546 if len(attach) > 0:
547 data["attachError"] = GetElementText(attach[0], "attacherror")
548 return data
549
550 def Process_coverage(self, test, filename, outname):
551 Log("coverage Not implemented: %s" % filename)
552 self.CopyShaders(test, filename, outname)
553
554 def Process_attributes(self, test, filename, outname):
555 Log("attributes Not implemented: %s" % filename)
556 self.CopyShaders(test, filename, outname)
557
558 def Process_fixed(self, test, filename, outname):
559 """no need for fixed function tests"""
560 self.CopyShaders(test, filename, outname)
561
562
563 def main(argv):
564 """This is the main function."""
565 global VERBOSE
566
567 parser = OptionParser()
568 parser.add_option(
569 "-v", "--verbose", action="store_true",
570 help="prints more output.")
571
572 (options, args) = parser.parse_args(args=argv)
573
574 if len(args) < 1:
575 pass # fix me
576
577 os.chdir(os.path.dirname(__file__) or '.')
578
579 VERBOSE = options.verbose
580
581 filename = args[0]
582 test_reader = TestReader(filename)
583 test_reader.ReadTests(filename)
584
585
586 if __name__ == '__main__':
587 sys.exit(main(sys.argv[1:]))
OLDNEW
« no previous file with comments | « conformance/ogles/ogles-utils.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698