1# coding=utf-8 2# -*- Mode: Python; py-indent-offset: 4 -*- 3# 4# Copyright © 2012 Intel Corporation 5# 6# Based on code by Kristian Høgsberg <krh@bitplanet.net>, 7# extracted from mesa/main/get.c 8# 9# Permission is hereby granted, free of charge, to any person obtaining a 10# copy of this software and associated documentation files (the "Software"), 11# to deal in the Software without restriction, including without limitation 12# on the rights to use, copy, modify, merge, publish, distribute, sub 13# license, and/or sell copies of the Software, and to permit persons to whom 14# the Software is furnished to do so, subject to the following conditions: 15# 16# The above copyright notice and this permission notice (including the next 17# paragraph) shall be included in all copies or substantial portions of the 18# Software. 19# 20# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 23# IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 26# IN THE SOFTWARE. 27 28# Generate a C header file containing hash tables of glGet parameter 29# names for each GL API. The generated file is to be included by glGet.c 30 31import os, sys, imp, getopt 32from collections import defaultdict 33import get_hash_params 34 35cur_dir = os.path.dirname(sys.argv[0]) 36param_desc_file = "%s/get_hash_params.py" % cur_dir 37 38GLAPI = "%s/../../mapi/glapi/gen" % cur_dir 39sys.path.append(GLAPI) 40import gl_XML 41 42prime_factor = 89 43prime_step = 281 44hash_table_size = 1024 45 46gl_apis=set(["GL", "GL_CORE", "GLES", "GLES2", "GLES3", "GLES31", "GLES32"]) 47 48def print_header(): 49 print "typedef const unsigned short table_t[%d];\n" % (hash_table_size) 50 print "static const int prime_factor = %d, prime_step = %d;\n" % \ 51 (prime_factor, prime_step) 52 53def print_params(params): 54 print "static const struct value_desc values[] = {" 55 for p in params: 56 print " { %s, %s }," % (p[0], p[1]) 57 58 print "};\n" 59 60def api_name(api): 61 return "API_OPEN%s" % api 62 63# This must match gl_api enum in src/mesa/main/mtypes.h 64api_enum = [ 65 'GL', 66 'GLES', 67 'GLES2', 68 'GL_CORE', 69 'GLES3', # Not in gl_api enum in mtypes.h 70 'GLES31', # Not in gl_api enum in mtypes.h 71 'GLES32', # Not in gl_api enum in mtypes.h 72] 73 74def api_index(api): 75 return api_enum.index(api) 76 77def table_name(api): 78 return "table_" + api_name(api) 79 80def print_table(api, table): 81 print "static table_t %s = {" % (table_name(api)) 82 83 # convert sparse (index, value) table into a dense table 84 dense_table = [0] * hash_table_size 85 for i, v in table: 86 dense_table[i] = v 87 88 row_size = 4 89 for i in range(0, hash_table_size, row_size): 90 row = dense_table[i : i + row_size] 91 idx_val = ["%4d" % v for v in row] 92 print " " * 4 + ", ".join(idx_val) + "," 93 94 print "};\n" 95 96def print_tables(tables): 97 for table in tables: 98 print_table(table["apis"][0], table["indices"]) 99 100 dense_tables = ['NULL'] * len(api_enum) 101 for table in tables: 102 tname = table_name(table["apis"][0]) 103 for api in table["apis"]: 104 i = api_index(api) 105 dense_tables[i] = "&%s" % (tname) 106 107 print "static table_t *table_set[] = {" 108 for expr in dense_tables: 109 print " %s," % expr 110 print "};\n" 111 112 print "#define table(api) (*table_set[api])" 113 114# Merge tables with matching parameter lists (i.e. GL and GL_CORE) 115def merge_tables(tables): 116 merged_tables = [] 117 for api, indices in sorted(tables.items()): 118 matching_table = filter(lambda mt:mt["indices"] == indices, 119 merged_tables) 120 if matching_table: 121 matching_table[0]["apis"].append(api) 122 else: 123 merged_tables.append({"apis": [api], "indices": indices}) 124 125 return merged_tables 126 127def add_to_hash_table(table, hash_val, value): 128 while True: 129 index = hash_val & (hash_table_size - 1) 130 if index not in table: 131 table[index] = value 132 break 133 hash_val += prime_step 134 135def die(msg): 136 sys.stderr.write("%s: %s\n" % (program, msg)) 137 exit(1) 138 139program = os.path.basename(sys.argv[0]) 140 141def generate_hash_tables(enum_list, enabled_apis, param_descriptors): 142 tables = defaultdict(lambda:{}) 143 144 # the first entry should be invalid, so that get.c:find_value can use 145 # its index for the 'enum not found' condition. 146 params = [[0, ""]] 147 148 for param_block in param_descriptors: 149 if set(["apis", "params"]) != set(param_block): 150 die("missing fields (%s) in param descriptor file (%s)" % 151 (", ".join(set(["apis", "params"]) - set(param_block)), 152 param_desc_file)) 153 154 valid_apis = set(param_block["apis"]) 155 if valid_apis - gl_apis: 156 die("unknown API(s) in param descriptor file (%s): %s\n" % 157 (param_desc_file, ",".join(valid_apis - gl_apis))) 158 159 if not (valid_apis & enabled_apis): 160 continue 161 162 valid_apis &= enabled_apis 163 164 for param in param_block["params"]: 165 enum_name = param[0] 166 enum_val = enum_list[enum_name].value 167 hash_val = enum_val * prime_factor 168 169 for api in valid_apis: 170 add_to_hash_table(tables[api], hash_val, len(params)) 171 # Also add GLES2 items to the GLES3+ hash tables 172 if api == "GLES2": 173 add_to_hash_table(tables["GLES3"], hash_val, len(params)) 174 add_to_hash_table(tables["GLES31"], hash_val, len(params)) 175 add_to_hash_table(tables["GLES32"], hash_val, len(params)) 176 # Also add GLES3 items to the GLES31+ hash tables 177 if api == "GLES3": 178 add_to_hash_table(tables["GLES31"], hash_val, len(params)) 179 add_to_hash_table(tables["GLES32"], hash_val, len(params)) 180 # Also add GLES31 items to the GLES32+ hash tables 181 if api == "GLES31": 182 add_to_hash_table(tables["GLES32"], hash_val, len(params)) 183 params.append(["GL_" + enum_name, param[1]]) 184 185 sorted_tables={} 186 for api, indices in tables.items(): 187 sorted_tables[api] = sorted(indices.items()) 188 189 return params, merge_tables(sorted_tables) 190 191 192def show_usage(): 193 sys.stderr.write( 194"""Usage: %s [OPTIONS] 195 -f <file> specify GL API XML file 196""" % (program)) 197 exit(1) 198 199if __name__ == '__main__': 200 try: 201 (opts, args) = getopt.getopt(sys.argv[1:], "f:") 202 except Exception,e: 203 show_usage() 204 205 if len(args) != 0: 206 show_usage() 207 208 api_desc_file = "" 209 210 for opt_name, opt_val in opts: 211 if opt_name == "-f": 212 api_desc_file = opt_val 213 214 if not api_desc_file: 215 die("missing descriptor file (-f)\n") 216 217 # generate the code for all APIs 218 enabled_apis = set(["GLES", "GLES2", "GLES3", "GLES31", "GLES32", 219 "GL", "GL_CORE"]) 220 221 try: 222 api_desc = gl_XML.parse_GL_API(api_desc_file) 223 except Exception: 224 die("couldn't parse API specification file %s\n" % api_desc_file) 225 226 (params, hash_tables) = generate_hash_tables(api_desc.enums_by_name, 227 enabled_apis, get_hash_params.descriptor) 228 229 print_header() 230 print_params(params) 231 print_tables(hash_tables) 232