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