diff options
Diffstat (limited to 'mesalib/src/mesa/main/get_hash_generator.py')
-rw-r--r-- | mesalib/src/mesa/main/get_hash_generator.py | 235 |
1 files changed, 235 insertions, 0 deletions
diff --git a/mesalib/src/mesa/main/get_hash_generator.py b/mesalib/src/mesa/main/get_hash_generator.py new file mode 100644 index 000000000..4b3f5f490 --- /dev/null +++ b/mesalib/src/mesa/main/get_hash_generator.py @@ -0,0 +1,235 @@ +#!/usr/bin/python2 +# coding=utf-8 +# -*- Mode: Python; py-indent-offset: 4 -*- +# +# Copyright © 2012 Intel Corporation +# +# Based on code by Kristian Høgsberg <krh@bitplanet.net>, +# extracted from mesa/main/get.c +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# on the rights to use, copy, modify, merge, publish, distribute, sub +# license, and/or sell copies of the Software, and to permit persons to whom +# the Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice (including the next +# paragraph) shall be included in all copies or substantial portions of the +# Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +# IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + +# Generate a C header file containing hash tables of glGet parameter +# names for each GL API. The generated file is to be included by glGet.c + +import os, sys, imp, getopt +from collections import defaultdict +import get_hash_params + +cur_dir = os.path.dirname(sys.argv[0]) +param_desc_file = "%s/get_hash_params.py" % cur_dir + +GLAPI = "%s/../../mapi/glapi/gen" % cur_dir +sys.path.append(GLAPI) +import gl_XML + +prime_factor = 89 +prime_step = 281 +hash_table_size = 1024 + +gl_apis=set(["GL", "GL_CORE", "GLES", "GLES2"]) + +def print_header(): + print "typedef const unsigned short table_t[%d];\n" % (hash_table_size) + print "static const int prime_factor = %d, prime_step = %d;\n" % \ + (prime_factor, prime_step) + +def print_params(params): + print "static struct value_desc values[] = {" + for p in params: + print " { %s, %s }," % (p[0], p[1]) + + print "};\n" + +def api_name(api): + return "API_OPEN%s" % api + +# This must match gl_api enum in src/mesa/main/mtypes.h +api_enum = [ + 'GL', + 'GLES', + 'GLES2', + 'GL_CORE', +] + +def api_index(api): + return api_enum.index(api) + +def table_name(api): + return "table_" + api_name(api) + +def print_table(api, table): + print "static table_t %s = {" % (table_name(api)) + + # convert sparse (index, value) table into a dense table + dense_table = [0] * hash_table_size + for i, v in table: + dense_table[i] = v + + row_size = 4 + for i in range(0, hash_table_size, row_size): + row = dense_table[i : i + row_size] + idx_val = ["%4d" % v for v in row] + print " " * 4 + ", ".join(idx_val) + "," + + print "};\n" + +def print_tables(tables): + for table in tables: + print_table(table["apis"][0], table["indices"]) + + dense_tables = ['NULL'] * len(api_enum) + for table in tables: + tname = table_name(table["apis"][0]) + for api in table["apis"]: + i = api_index(api) + dense_tables[i] = "&%s" % (tname) + + print "static table_t *table_set[] = {" + for expr in dense_tables: + print " %s," % expr + print "};\n" + + print "#define table(api) (*table_set[api])" + +# Merge tables with matching parameter lists (i.e. GL and GL_CORE) +def merge_tables(tables): + merged_tables = [] + for api, indices in sorted(tables.items()): + matching_table = filter(lambda mt:mt["indices"] == indices, + merged_tables) + if matching_table: + matching_table[0]["apis"].append(api) + else: + merged_tables.append({"apis": [api], "indices": indices}) + + return merged_tables + +def add_to_hash_table(table, hash_val, value): + while True: + index = hash_val & (hash_table_size - 1) + if index not in table: + table[index] = value + break + hash_val += prime_step + +def die(msg): + sys.stderr.write("%s: %s\n" % (program, msg)) + exit(1) + +program = os.path.basename(sys.argv[0]) + +def generate_hash_tables(enum_list, enabled_apis, param_descriptors): + tables = defaultdict(lambda:{}) + + # the first entry should be invalid, so that get.c:find_value can use + # its index for the 'enum not found' condition. + params = [[0, ""]] + + for param_block in param_descriptors: + if set(["apis", "params"]) != set(param_block): + die("missing fields (%s) in param descriptor file (%s)" % + (", ".join(set(["apis", "params"]) - set(param_block)), + param_desc_file)) + + valid_apis = set(param_block["apis"]) + if valid_apis - gl_apis: + die("unknown API(s) in param descriptor file (%s): %s\n" % + (param_desc_file, ",".join(valid_apis - gl_apis))) + + if not (valid_apis & enabled_apis): + continue + + valid_apis &= enabled_apis + + for param in param_block["params"]: + enum_name = param[0] + enum_val = enum_list[enum_name].value + hash_val = enum_val * prime_factor + + for api in valid_apis: + add_to_hash_table(tables[api], hash_val, len(params)) + + params.append(["GL_" + enum_name, param[1]]) + + sorted_tables={} + for api, indices in tables.items(): + sorted_tables[api] = sorted(indices.items()) + + return params, merge_tables(sorted_tables) + +def opt_to_apis(feature): + _map = {"ES1": "GLES", "ES2": "GLES2", "GL": "GL"} + if feature not in _map: + return None + + apis = set([_map[feature]]) + if "GL" in apis: + apis.add("GL_CORE") + + return apis + +def show_usage(): + sys.stderr.write( +"""Usage: %s [OPTIONS] + -f <file> specify GL API XML file + -a [GL|ES1|ES2] specify APIs to generate hash tables for +""" % (program)) + exit(1) + +if __name__ == '__main__': + try: + (opts, args) = getopt.getopt(sys.argv[1:], "f:a:") + except Exception,e: + show_usage() + + if len(args) != 0: + show_usage() + + enabled_apis = set([]) + api_desc_file = "" + + for opt_name, opt_val in opts: + if opt_name == "-f": + api_desc_file = opt_val + if opt_name == "-a": + apis = opt_to_apis(opt_val.upper()) + if not apis: + die("invalid API %s\n" % opt_val) + + enabled_apis |= apis + + if not api_desc_file: + die("missing descriptor file (-f)\n") + + if len(enabled_apis) == 0: + die("need at least a single enabled API\n") + + try: + api_desc = gl_XML.parse_GL_API(api_desc_file) + except Exception: + die("couldn't parse API specification file %s\n" % api_desc_file) + + (params, hash_tables) = generate_hash_tables(api_desc.enums_by_name, + enabled_apis, get_hash_params.descriptor) + + print_header() + print_params(params) + print_tables(hash_tables) |