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