Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

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