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