1bf215546Sopenharmony_ci 2bf215546Sopenharmony_ci# (C) Copyright Zack Rusin 2005. All Rights Reserved. 3bf215546Sopenharmony_ci# Copyright (C) 2015 Intel Corporation 4bf215546Sopenharmony_ci# Copyright (C) 2015 Broadcom Corporation 5bf215546Sopenharmony_ci# 6bf215546Sopenharmony_ci# Permission is hereby granted, free of charge, to any person obtaining a 7bf215546Sopenharmony_ci# copy of this software and associated documentation files (the "Software"), 8bf215546Sopenharmony_ci# to deal in the Software without restriction, including without limitation 9bf215546Sopenharmony_ci# on the rights to use, copy, modify, merge, publish, distribute, sub 10bf215546Sopenharmony_ci# license, and/or sell copies of the Software, and to permit persons to whom 11bf215546Sopenharmony_ci# the Software is furnished to do so, subject to the following conditions: 12bf215546Sopenharmony_ci# 13bf215546Sopenharmony_ci# The above copyright notice and this permission notice (including the next 14bf215546Sopenharmony_ci# paragraph) shall be included in all copies or substantial portions of the 15bf215546Sopenharmony_ci# Software. 16bf215546Sopenharmony_ci# 17bf215546Sopenharmony_ci# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18bf215546Sopenharmony_ci# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19bf215546Sopenharmony_ci# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 20bf215546Sopenharmony_ci# IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21bf215546Sopenharmony_ci# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22bf215546Sopenharmony_ci# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23bf215546Sopenharmony_ci# IN THE SOFTWARE. 24bf215546Sopenharmony_ci# 25bf215546Sopenharmony_ci# Authors: 26bf215546Sopenharmony_ci# Zack Rusin <zack@kde.org> 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ciimport argparse 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ciimport license 31bf215546Sopenharmony_ciimport gl_XML 32bf215546Sopenharmony_ciimport xml.etree.ElementTree as ET 33bf215546Sopenharmony_ciimport sys, getopt 34bf215546Sopenharmony_ciimport re 35bf215546Sopenharmony_ci 36bf215546Sopenharmony_ciclass PrintGlEnums(gl_XML.gl_print_base): 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_ci def __init__(self): 39bf215546Sopenharmony_ci gl_XML.gl_print_base.__init__(self) 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_ci self.name = "gl_enums.py (from Mesa)" 42bf215546Sopenharmony_ci self.license = license.bsd_license_template % ( \ 43bf215546Sopenharmony_ci"""Copyright (C) 1999-2005 Brian Paul All Rights Reserved.""", "BRIAN PAUL") 44bf215546Sopenharmony_ci # Mapping from enum value to (name, priority) tuples. 45bf215546Sopenharmony_ci self.enum_table = {} 46bf215546Sopenharmony_ci # Mapping from enum name to value 47bf215546Sopenharmony_ci self.string_to_int = {} 48bf215546Sopenharmony_ci 49bf215546Sopenharmony_ci 50bf215546Sopenharmony_ci def printRealHeader(self): 51bf215546Sopenharmony_ci print('#include <stdio.h>') 52bf215546Sopenharmony_ci print('#include "main/glheader.h"') 53bf215546Sopenharmony_ci print('#include "main/enums.h"') 54bf215546Sopenharmony_ci print('#include "main/mtypes.h"') 55bf215546Sopenharmony_ci print('') 56bf215546Sopenharmony_ci print('typedef struct PACKED {') 57bf215546Sopenharmony_ci print(' uint32_t offset;') 58bf215546Sopenharmony_ci print(' int n;') 59bf215546Sopenharmony_ci print('} enum_elt;') 60bf215546Sopenharmony_ci print('') 61bf215546Sopenharmony_ci return 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_ci def print_code(self): 64bf215546Sopenharmony_ci print(""" 65bf215546Sopenharmony_citypedef int (*cfunc)(const void *, const void *); 66bf215546Sopenharmony_ci 67bf215546Sopenharmony_ci/** 68bf215546Sopenharmony_ci * Compare a key enum value to an element in the \c enum_string_table_offsets array. 69bf215546Sopenharmony_ci * 70bf215546Sopenharmony_ci * \c bsearch always passes the key as the first parameter and the pointer 71bf215546Sopenharmony_ci * to the array element as the second parameter. We can elimiate some 72bf215546Sopenharmony_ci * extra work by taking advantage of that fact. 73bf215546Sopenharmony_ci * 74bf215546Sopenharmony_ci * \param a Pointer to the desired enum name. 75bf215546Sopenharmony_ci * \param b Pointer into the \c enum_string_table_offsets array. 76bf215546Sopenharmony_ci */ 77bf215546Sopenharmony_cistatic int compar_nr( const int *a, enum_elt *b ) 78bf215546Sopenharmony_ci{ 79bf215546Sopenharmony_ci return a[0] - b->n; 80bf215546Sopenharmony_ci} 81bf215546Sopenharmony_ci 82bf215546Sopenharmony_ci 83bf215546Sopenharmony_cistatic char token_tmp[20]; 84bf215546Sopenharmony_ci 85bf215546Sopenharmony_ci/** 86bf215546Sopenharmony_ci * This function always returns a string. If the number is a valid enum, it 87bf215546Sopenharmony_ci * returns the enum name. Otherwise, it returns a numeric string. 88bf215546Sopenharmony_ci */ 89bf215546Sopenharmony_ciconst char * 90bf215546Sopenharmony_ci_mesa_enum_to_string(int nr) 91bf215546Sopenharmony_ci{ 92bf215546Sopenharmony_ci enum_elt *elt; 93bf215546Sopenharmony_ci 94bf215546Sopenharmony_ci elt = bsearch(& nr, enum_string_table_offsets, 95bf215546Sopenharmony_ci ARRAY_SIZE(enum_string_table_offsets), 96bf215546Sopenharmony_ci sizeof(enum_string_table_offsets[0]), 97bf215546Sopenharmony_ci (cfunc) compar_nr); 98bf215546Sopenharmony_ci 99bf215546Sopenharmony_ci if (elt != NULL) { 100bf215546Sopenharmony_ci return &enum_string_table[elt->offset]; 101bf215546Sopenharmony_ci } 102bf215546Sopenharmony_ci else { 103bf215546Sopenharmony_ci /* this is not re-entrant safe, no big deal here */ 104bf215546Sopenharmony_ci snprintf(token_tmp, sizeof(token_tmp) - 1, "0x%x", nr); 105bf215546Sopenharmony_ci token_tmp[sizeof(token_tmp) - 1] = '\\0'; 106bf215546Sopenharmony_ci return token_tmp; 107bf215546Sopenharmony_ci } 108bf215546Sopenharmony_ci} 109bf215546Sopenharmony_ci 110bf215546Sopenharmony_ci/** 111bf215546Sopenharmony_ci * Primitive names 112bf215546Sopenharmony_ci */ 113bf215546Sopenharmony_cistatic const char *prim_names[PRIM_MAX+3] = { 114bf215546Sopenharmony_ci "GL_POINTS", 115bf215546Sopenharmony_ci "GL_LINES", 116bf215546Sopenharmony_ci "GL_LINE_LOOP", 117bf215546Sopenharmony_ci "GL_LINE_STRIP", 118bf215546Sopenharmony_ci "GL_TRIANGLES", 119bf215546Sopenharmony_ci "GL_TRIANGLE_STRIP", 120bf215546Sopenharmony_ci "GL_TRIANGLE_FAN", 121bf215546Sopenharmony_ci "GL_QUADS", 122bf215546Sopenharmony_ci "GL_QUAD_STRIP", 123bf215546Sopenharmony_ci "GL_POLYGON", 124bf215546Sopenharmony_ci "GL_LINES_ADJACENCY", 125bf215546Sopenharmony_ci "GL_LINE_STRIP_ADJACENCY", 126bf215546Sopenharmony_ci "GL_TRIANGLES_ADJACENCY", 127bf215546Sopenharmony_ci "GL_TRIANGLE_STRIP_ADJACENCY", 128bf215546Sopenharmony_ci "GL_PATCHES", 129bf215546Sopenharmony_ci "outside begin/end", 130bf215546Sopenharmony_ci "unknown state" 131bf215546Sopenharmony_ci}; 132bf215546Sopenharmony_ci 133bf215546Sopenharmony_ci 134bf215546Sopenharmony_ci/* Get the name of an enum given that it is a primitive type. Avoids 135bf215546Sopenharmony_ci * GL_FALSE/GL_POINTS ambiguity and others. 136bf215546Sopenharmony_ci */ 137bf215546Sopenharmony_ciconst char * 138bf215546Sopenharmony_ci_mesa_lookup_prim_by_nr(GLuint nr) 139bf215546Sopenharmony_ci{ 140bf215546Sopenharmony_ci if (nr < ARRAY_SIZE(prim_names)) 141bf215546Sopenharmony_ci return prim_names[nr]; 142bf215546Sopenharmony_ci else 143bf215546Sopenharmony_ci return "invalid mode"; 144bf215546Sopenharmony_ci} 145bf215546Sopenharmony_ci 146bf215546Sopenharmony_ci 147bf215546Sopenharmony_ci""") 148bf215546Sopenharmony_ci return 149bf215546Sopenharmony_ci 150bf215546Sopenharmony_ci 151bf215546Sopenharmony_ci def printBody(self, xml): 152bf215546Sopenharmony_ci self.process_enums(xml) 153bf215546Sopenharmony_ci 154bf215546Sopenharmony_ci sorted_enum_values = sorted(self.enum_table.keys()) 155bf215546Sopenharmony_ci string_offsets = {} 156bf215546Sopenharmony_ci i = 0; 157bf215546Sopenharmony_ci print('#if defined(__GNUC__)') 158bf215546Sopenharmony_ci print('# define LONGSTRING __extension__') 159bf215546Sopenharmony_ci print('#else') 160bf215546Sopenharmony_ci print('# define LONGSTRING') 161bf215546Sopenharmony_ci print('#endif') 162bf215546Sopenharmony_ci print('') 163bf215546Sopenharmony_ci print('LONGSTRING static const char enum_string_table[] = {') 164bf215546Sopenharmony_ci # We express the very long concatenation of enum strings as an array 165bf215546Sopenharmony_ci # of characters rather than as a string literal to work-around MSVC's 166bf215546Sopenharmony_ci # 65535 character limit. 167bf215546Sopenharmony_ci for enum in sorted_enum_values: 168bf215546Sopenharmony_ci (name, pri) = self.enum_table[enum] 169bf215546Sopenharmony_ci print(" ", end=' ') 170bf215546Sopenharmony_ci for ch in name: 171bf215546Sopenharmony_ci print("'%c'," % ch, end=' ') 172bf215546Sopenharmony_ci print("'\\0',") 173bf215546Sopenharmony_ci 174bf215546Sopenharmony_ci string_offsets[ enum ] = i 175bf215546Sopenharmony_ci i += len(name) + 1 176bf215546Sopenharmony_ci 177bf215546Sopenharmony_ci print('};') 178bf215546Sopenharmony_ci print('') 179bf215546Sopenharmony_ci 180bf215546Sopenharmony_ci 181bf215546Sopenharmony_ci print('static const enum_elt enum_string_table_offsets[%u] =' % (len(self.enum_table))) 182bf215546Sopenharmony_ci print('{') 183bf215546Sopenharmony_ci for enum in sorted_enum_values: 184bf215546Sopenharmony_ci (name, pri) = self.enum_table[enum] 185bf215546Sopenharmony_ci print(' { %5u, 0x%08X }, /* %s */' % (string_offsets[enum], enum, name)) 186bf215546Sopenharmony_ci print('};') 187bf215546Sopenharmony_ci print('') 188bf215546Sopenharmony_ci 189bf215546Sopenharmony_ci self.print_code() 190bf215546Sopenharmony_ci return 191bf215546Sopenharmony_ci 192bf215546Sopenharmony_ci def add_enum_provider(self, name, priority): 193bf215546Sopenharmony_ci value = self.string_to_int[name] 194bf215546Sopenharmony_ci 195bf215546Sopenharmony_ci # We don't want the weird GL_SKIP_COMPONENTS1_NV enums. 196bf215546Sopenharmony_ci if value < 0: 197bf215546Sopenharmony_ci return 198bf215546Sopenharmony_ci # We don't want the 64-bit GL_TIMEOUT_IGNORED "enums" 199bf215546Sopenharmony_ci if value > 0xffffffff: 200bf215546Sopenharmony_ci return 201bf215546Sopenharmony_ci 202bf215546Sopenharmony_ci # We don't want bitfields in the enum-to-string table -- 203bf215546Sopenharmony_ci # individual bits have so many names, it's pointless. Note 204bf215546Sopenharmony_ci # that we check for power-of-two, since some getters have 205bf215546Sopenharmony_ci # "_BITS" in their name, but none have a power-of-two enum 206bf215546Sopenharmony_ci # number. 207bf215546Sopenharmony_ci if not (value & (value - 1)) and '_BIT' in name: 208bf215546Sopenharmony_ci return 209bf215546Sopenharmony_ci 210bf215546Sopenharmony_ci # Also drop the GL_*_ATTRIB_BITS bitmasks. 211bf215546Sopenharmony_ci if value == 0xffffffff: 212bf215546Sopenharmony_ci return 213bf215546Sopenharmony_ci 214bf215546Sopenharmony_ci if value in self.enum_table: 215bf215546Sopenharmony_ci (n, p) = self.enum_table[value] 216bf215546Sopenharmony_ci if priority < p: 217bf215546Sopenharmony_ci self.enum_table[value] = (name, priority) 218bf215546Sopenharmony_ci else: 219bf215546Sopenharmony_ci self.enum_table[value] = (name, priority) 220bf215546Sopenharmony_ci 221bf215546Sopenharmony_ci def process_extension(self, extension): 222bf215546Sopenharmony_ci if extension.get('name').startswith('GL_ARB_'): 223bf215546Sopenharmony_ci extension_prio = 400 224bf215546Sopenharmony_ci elif extension.get('name').startswith('GL_EXT_'): 225bf215546Sopenharmony_ci extension_prio = 600 226bf215546Sopenharmony_ci else: 227bf215546Sopenharmony_ci extension_prio = 800 228bf215546Sopenharmony_ci 229bf215546Sopenharmony_ci for enum in extension.findall('require/enum'): 230bf215546Sopenharmony_ci self.add_enum_provider(enum.get('name'), extension_prio) 231bf215546Sopenharmony_ci 232bf215546Sopenharmony_ci def process_enums(self, xml): 233bf215546Sopenharmony_ci # First, process the XML entries that define the hex values 234bf215546Sopenharmony_ci # for all of the enum names. 235bf215546Sopenharmony_ci for enum in xml.findall('enums/enum'): 236bf215546Sopenharmony_ci name = enum.get('name') 237bf215546Sopenharmony_ci value = int(enum.get('value'), base=16) 238bf215546Sopenharmony_ci 239bf215546Sopenharmony_ci # If the same name ever maps to multiple values, that can 240bf215546Sopenharmony_ci # confuse us. GL_ACTIVE_PROGRAM_EXT is OK to lose because 241bf215546Sopenharmony_ci # we choose GL_ACTIVE PROGRAM instead. 242bf215546Sopenharmony_ci if name in self.string_to_int and name != "GL_ACTIVE_PROGRAM_EXT": 243bf215546Sopenharmony_ci print("#error Renumbering {0} from {1} to {2}".format(name, self.string_to_int[name], value)) 244bf215546Sopenharmony_ci 245bf215546Sopenharmony_ci self.string_to_int[name] = value 246bf215546Sopenharmony_ci 247bf215546Sopenharmony_ci # Now, process all of the API versions and extensions that 248bf215546Sopenharmony_ci # provide enums, so we can decide what name to call any hex 249bf215546Sopenharmony_ci # value. 250bf215546Sopenharmony_ci for feature in xml.findall('feature'): 251bf215546Sopenharmony_ci feature_name = feature.get('name') 252bf215546Sopenharmony_ci 253bf215546Sopenharmony_ci # When an enum gets renamed in a newer version (generally 254bf215546Sopenharmony_ci # because of some generalization of the functionality), 255bf215546Sopenharmony_ci # prefer the newer name. Also, prefer desktop GL names to 256bf215546Sopenharmony_ci # ES. 257bf215546Sopenharmony_ci m = re.match('GL_VERSION_([0-9])_([0-9])', feature_name) 258bf215546Sopenharmony_ci if m: 259bf215546Sopenharmony_ci feature_prio = 100 - int(m.group(1) + m.group(2)) 260bf215546Sopenharmony_ci else: 261bf215546Sopenharmony_ci m = re.match('GL_ES_VERSION_([0-9])_([0-9])', feature_name) 262bf215546Sopenharmony_ci if m: 263bf215546Sopenharmony_ci feature_prio = 200 - int(m.group(1) + m.group(2)) 264bf215546Sopenharmony_ci else: 265bf215546Sopenharmony_ci feature_prio = 200 266bf215546Sopenharmony_ci 267bf215546Sopenharmony_ci for enum in feature.findall('require/enum'): 268bf215546Sopenharmony_ci self.add_enum_provider(enum.get('name'), feature_prio) 269bf215546Sopenharmony_ci 270bf215546Sopenharmony_ci for extension in xml.findall('extensions/extension'): 271bf215546Sopenharmony_ci self.process_extension(extension) 272bf215546Sopenharmony_ci 273bf215546Sopenharmony_ci 274bf215546Sopenharmony_cidef _parser(): 275bf215546Sopenharmony_ci parser = argparse.ArgumentParser() 276bf215546Sopenharmony_ci parser.add_argument('-f', '--input_file', 277bf215546Sopenharmony_ci required=True, 278bf215546Sopenharmony_ci help="Choose an xml file to parse.") 279bf215546Sopenharmony_ci return parser.parse_args() 280bf215546Sopenharmony_ci 281bf215546Sopenharmony_ci 282bf215546Sopenharmony_cidef main(): 283bf215546Sopenharmony_ci args = _parser() 284bf215546Sopenharmony_ci xml = ET.parse(args.input_file) 285bf215546Sopenharmony_ci 286bf215546Sopenharmony_ci printer = PrintGlEnums() 287bf215546Sopenharmony_ci printer.Print(xml) 288bf215546Sopenharmony_ci 289bf215546Sopenharmony_ci 290bf215546Sopenharmony_ciif __name__ == '__main__': 291bf215546Sopenharmony_ci main() 292