Merge remote branch 'origin/master' into lp-setup-llvm
[mesa.git] / src / glsl / builtins / tools / generate_builtins.py
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 t = s.replace('\\', '\\\\').replace('"', '\\"').replace('\n', '\\n"\n "')
29 return ' "' + t + '"\n'
30
31 def 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
37 def 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
52 def 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
82 def write_profiles():
83 profiles = get_profile_list()
84 for (filename, profile) in profiles:
85 write_profile(filename, profile)
86
87 def 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
93 if __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/core.h" /* for struct gl_shader */
120 #include "glsl_parser_extras.h"
121 #include "ir_reader.h"
122 #include "program.h"
123 #include "ast.h"
124
125 extern "C" struct gl_shader *
126 _mesa_new_shader(struct gl_context *ctx, GLuint name, GLenum type);
127
128 gl_shader *
129 read_builtins(GLenum target, const char *protos, const char **functions, unsigned count)
130 {
131 struct gl_context fakeCtx;
132 fakeCtx.API = API_OPENGL;
133 gl_shader *sh = _mesa_new_shader(NULL, 0, target);
134 struct _mesa_glsl_parse_state *st =
135 new(sh) _mesa_glsl_parse_state(&fakeCtx, target, sh);
136
137 st->language_version = 130;
138 st->symbols->language_version = 130;
139 st->ARB_texture_rectangle_enable = true;
140 st->EXT_texture_array_enable = true;
141 _mesa_glsl_initialize_types(st);
142
143 sh->ir = new(sh) exec_list;
144 sh->symbols = st->symbols;
145
146 /* Read the IR containing the prototypes */
147 _mesa_glsl_read_ir(st, sh->ir, protos, true);
148
149 /* Read ALL the function bodies, telling the IR reader not to scan for
150 * prototypes (we've already created them). The IR reader will skip any
151 * signature that does not already exist as a prototype.
152 */
153 for (unsigned i = 0; i < count; i++) {
154 _mesa_glsl_read_ir(st, sh->ir, functions[i], false);
155
156 if (st->error) {
157 printf("error reading builtin: %.35s ...\\n", functions[i]);
158 printf("Info log:\\n%s\\n", st->info_log);
159 talloc_free(sh);
160 return NULL;
161 }
162 }
163
164 reparent_ir(sh->ir, sh);
165 delete st;
166
167 return sh;
168 }
169 """
170
171 write_function_definitions()
172 write_profiles()
173
174 profiles = get_profile_list()
175
176 print 'static gl_shader *builtin_profiles[%d];' % len(profiles)
177
178 print """
179 void *builtin_mem_ctx = NULL;
180
181 void
182 _mesa_glsl_release_functions(void)
183 {
184 talloc_free(builtin_mem_ctx);
185 builtin_mem_ctx = NULL;
186 memset(builtin_profiles, 0, sizeof(builtin_profiles));
187 }
188
189 static void
190 _mesa_read_profile(struct _mesa_glsl_parse_state *state,
191 exec_list *instructions,
192 int profile_index,
193 const char *prototypes,
194 const char **functions,
195 int count)
196 {
197 gl_shader *sh = builtin_profiles[profile_index];
198
199 if (sh == NULL) {
200 sh = read_builtins(GL_VERTEX_SHADER, prototypes, functions, count);
201 talloc_steal(builtin_mem_ctx, sh);
202 builtin_profiles[profile_index] = sh;
203 }
204
205 import_prototypes(sh->ir, instructions, state->symbols, state);
206 state->builtins_to_link[state->num_builtins_to_link] = sh;
207 state->num_builtins_to_link++;
208 }
209
210 void
211 _mesa_glsl_initialize_functions(exec_list *instructions,
212 struct _mesa_glsl_parse_state *state)
213 {
214 if (builtin_mem_ctx == NULL) {
215 builtin_mem_ctx = talloc_init("GLSL built-in functions");
216 memset(&builtin_profiles, 0, sizeof(builtin_profiles));
217 }
218
219 state->num_builtins_to_link = 0;
220 """
221
222 i=0
223 for (filename, profile) in profiles:
224 if profile.endswith('_vert'):
225 check = 'state->target == vertex_shader && '
226 elif profile.endswith('_frag'):
227 check = 'state->target == fragment_shader && '
228
229 version = re.sub(r'_(vert|frag)$', '', profile)
230 if version.isdigit():
231 check += 'state->language_version == ' + version
232 else: # an extension name
233 check += 'state->' + version + '_enable'
234
235 print ' if (' + check + ') {'
236 print ' _mesa_read_profile(state, instructions, %d,' % i
237 print ' prototypes_for_' + profile + ','
238 print ' functions_for_' + profile + ','
239 print ' Elements(functions_for_' + profile + '));'
240 print ' }'
241 print
242 i = i + 1
243 print '}'
244