Home | History | Annotate | Download | only in tools
      1 #!/usr/bin/python
      2 # -*- coding: utf-8 -*-
      3 
      4 import re
      5 from glob import glob
      6 from os import path
      7 from subprocess import Popen, PIPE
      8 
      9 # Local module: generator for texture lookup builtins
     10 from texture_builtins import generate_texture_functions
     11 
     12 builtins_dir = path.join(path.dirname(path.abspath(__file__)), "..")
     13 
     14 # Read the files in builtins/ir/*...add them to the supplied dictionary.
     15 def read_ir_files(fs):
     16     for filename in glob(path.join(path.join(builtins_dir, 'ir'), '*')):
     17         with open(filename) as f:
     18             fs[path.basename(filename)] = f.read()
     19 
     20 # Return a dictionary containing all builtin definitions (even generated)
     21 def get_builtin_definitions():
     22     fs = {}
     23     generate_texture_functions(fs)
     24     read_ir_files(fs)
     25     return fs
     26 
     27 def stringify(s):
     28     # Work around MSVC's 65535 byte limit by outputting an array of characters
     29     # rather than actual string literals.
     30     if len(s) >= 65535:
     31         #t = "/* Warning: length " + repr(len(s)) + " too large */\n"
     32         t = ""
     33         for c in re.sub('\s\s+', ' ', s):
     34             if c == '\n':
     35                 t += '\n'
     36             else:
     37                 t += "'" + c + "',"
     38         return '{' + t[:-1] + '}'
     39 
     40     t = s.replace('\\', '\\\\').replace('"', '\\"').replace('\n', '\\n"\n   "')
     41     return '   "' + t + '"\n'
     42 
     43 def write_function_definitions():
     44     fs = get_builtin_definitions()
     45     for k, v in sorted(fs.iteritems()):
     46         print 'static const char builtin_' + k + '[] ='
     47         print stringify(v), ';'
     48 
     49 def run_compiler(args):
     50     compiler_path = path.join(path.join(builtins_dir, '..'), 'glsl_compiler')
     51     command = [compiler_path, '--dump-lir'] + args
     52     p = Popen(command, 1, stdout=PIPE, shell=False)
     53     output = p.communicate()[0]
     54 
     55     # Clean up output a bit by killing whitespace before a closing paren.
     56     kill_paren_whitespace = re.compile(r'[ \n]*\)', re.MULTILINE);
     57     output = kill_paren_whitespace.sub(')', output);
     58 
     59     # Also toss any duplicate newlines
     60     output = output.replace('\n\n', '\n')
     61 
     62     return (output, p.returncode)
     63 
     64 def write_profile(filename, profile):
     65     (proto_ir, returncode) = run_compiler([filename])
     66 
     67     if returncode != 0:
     68         print '#error builtins profile', profile, 'failed to compile'
     69         return
     70 
     71     # Kill any global variable declarations.  We don't want them.
     72     kill_globals = re.compile(r'^\(declare.*\n', re.MULTILINE);
     73     proto_ir = kill_globals.sub('', proto_ir)
     74 
     75     # Kill pointer addresses.  They're not necessary in prototypes and just
     76     # clutter the diff output.
     77     proto_ir = re.sub(r'@0x[0-9a-f]+', '', proto_ir);
     78 
     79     print 'static const char prototypes_for_' + profile + '[] ='
     80     print stringify(proto_ir), ';'
     81 
     82     # Print a table of all the functions (not signatures) referenced.
     83     # This is done so we can avoid bothering with a hash table in the C++ code.
     84 
     85     function_names = set()
     86     for func in re.finditer(r'\(function (.+)\n', proto_ir):
     87         function_names.add(func.group(1))
     88 
     89     print 'static const char *functions_for_' + profile + ' [] = {'
     90     for func in sorted(function_names):
     91         print '   builtin_' + func + ','
     92     print '};'
     93 
     94 def write_profiles():
     95     profiles = get_profile_list()
     96     for (filename, profile) in profiles:
     97         write_profile(filename, profile)
     98 
     99 def get_profile_list():
    100     profiles = []
    101     for pfile in sorted(glob(path.join(path.join(builtins_dir, 'profiles'), '*'))):
    102         profiles.append((pfile, path.basename(pfile).replace('.', '_')))
    103     return profiles
    104 
    105 if __name__ == "__main__":
    106     print """/* DO NOT MODIFY - automatically generated by generate_builtins.py */
    107 /*
    108  * Copyright  2010 Intel Corporation
    109  *
    110  * Permission is hereby granted, free of charge, to any person obtaining a
    111  * copy of this software and associated documentation files (the "Software"),
    112  * to deal in the Software without restriction, including without limitation
    113  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
    114  * and/or sell copies of the Software, and to permit persons to whom the
    115  * Software is furnished to do so, subject to the following conditions:
    116  *
    117  * The above copyright notice and this permission notice (including the next
    118  * paragraph) shall be included in all copies or substantial portions of the
    119  * Software.
    120  *
    121  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    122  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    123  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
    124  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    125  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    126  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    127  * DEALINGS IN THE SOFTWARE.
    128  */
    129 
    130 #include <stdio.h>
    131 #include "main/shaderobj.h" /* for struct gl_shader */
    132 #include "glsl_parser_extras.h"
    133 #include "ir_reader.h"
    134 #include "program.h"
    135 #include "ast.h"
    136 
    137 gl_shader *
    138 read_builtins(void * mem_ctx, GLenum target, const char *protos, const char **functions, unsigned count)
    139 {
    140    struct gl_context fakeCtx;
    141    fakeCtx.API = API_OPENGL;
    142    gl_shader *sh = _mesa_new_shader(mem_ctx, 0, target);
    143    struct _mesa_glsl_parse_state *st =
    144       new(sh) _mesa_glsl_parse_state(&fakeCtx, target, sh);
    145 
    146    st->language_version = 130;
    147    st->symbols->language_version = 130;
    148    st->ARB_texture_rectangle_enable = true;
    149    st->EXT_texture_array_enable = true;
    150    _mesa_glsl_initialize_types(st);
    151 
    152    sh->ir = new(sh) exec_list;
    153    sh->symbols = st->symbols;
    154 
    155    /* Read the IR containing the prototypes */
    156    _mesa_glsl_read_ir(st, sh->ir, protos, true);
    157 
    158    /* Read ALL the function bodies, telling the IR reader not to scan for
    159     * prototypes (we've already created them).  The IR reader will skip any
    160     * signature that does not already exist as a prototype.
    161     */
    162    for (unsigned i = 0; i < count; i++) {
    163       _mesa_glsl_read_ir(st, sh->ir, functions[i], false);
    164 
    165       if (st->error) {
    166          printf("error reading builtin: %.35s ...\\n", functions[i]);
    167          printf("Info log:\\n%s\\n", st->info_log);
    168          _mesa_delete_shader(NULL, sh);
    169          return NULL;
    170       }
    171    }
    172 
    173    reparent_ir(sh->ir, sh);
    174    delete st;
    175 
    176    return sh;
    177 }
    178 """
    179 
    180     write_function_definitions()
    181     write_profiles()
    182 
    183     profiles = get_profile_list()
    184 
    185     print 'static gl_shader *builtin_profiles[%d];' % len(profiles)
    186 
    187     print """
    188 void *builtin_mem_ctx = NULL;
    189 
    190 void
    191 _mesa_glsl_release_functions(void)
    192 {
    193    hieralloc_free(builtin_mem_ctx);
    194    builtin_mem_ctx = NULL;
    195    memset(builtin_profiles, 0, sizeof(builtin_profiles));
    196 }
    197 
    198 static void
    199 _mesa_read_profile(struct _mesa_glsl_parse_state *state,
    200 		   exec_list *instructions,
    201                    int profile_index,
    202 		   const char *prototypes,
    203 		   const char **functions,
    204                    int count)
    205 {
    206    gl_shader *sh = builtin_profiles[profile_index];
    207 
    208    if (sh == NULL) {
    209       sh = read_builtins(state, GL_VERTEX_SHADER, prototypes, functions, count);
    210       hieralloc_steal(builtin_mem_ctx, sh);
    211       builtin_profiles[profile_index] = sh;
    212    }
    213 
    214    state->builtins_to_link[state->num_builtins_to_link] = sh;
    215    state->num_builtins_to_link++;
    216 }
    217 
    218 void
    219 _mesa_glsl_initialize_functions(exec_list *instructions,
    220                                 struct _mesa_glsl_parse_state *state)
    221 {
    222    if (builtin_mem_ctx == NULL) {
    223       builtin_mem_ctx = hieralloc_init("GLSL built-in functions");
    224       memset(&builtin_profiles, 0, sizeof(builtin_profiles));
    225    }
    226 
    227    state->num_builtins_to_link = 0;
    228 """
    229 
    230     i=0
    231     for (filename, profile) in profiles:
    232         if profile.endswith('_vert'):
    233             check = 'state->target == vertex_shader && '
    234         elif profile.endswith('_frag'):
    235             check = 'state->target == fragment_shader && '
    236 
    237         version = re.sub(r'_(vert|frag)$', '', profile)
    238         if version.isdigit():
    239             check += 'state->language_version == ' + version
    240         else: # an extension name
    241             check += 'state->' + version + '_enable'
    242 
    243         print '   if (' + check + ') {'
    244         print '      _mesa_read_profile(state, instructions, %d,' % i
    245         print '                         prototypes_for_' + profile + ','
    246         print '                         functions_for_' + profile + ','
    247         print '                         Elements(functions_for_' + profile + '));'
    248         print '   }'
    249         print
    250         i = i + 1
    251     print '}'
    252 
    253