2 # -*- coding: utf-8 -*-
4 from __future__
import with_statement
10 from subprocess
import Popen
, PIPE
13 # Local module: generator for texture lookup builtins
14 from texture_builtins
import generate_texture_functions
16 builtins_dir
= path
.join(path
.dirname(path
.abspath(__file__
)), "..")
18 # Get the path to the standalone GLSL compiler
20 print "Usage:", argv
[0], "<path to compiler>"
25 # Read the files in builtins/ir/*...add them to the supplied dictionary.
26 def read_ir_files(fs
):
27 for filename
in glob(path
.join(path
.join(builtins_dir
, 'ir'), '*.ir')):
28 function_name
= path
.basename(filename
).split('.')[0]
29 with
open(filename
) as f
:
30 fs
[function_name
] = f
.read()
32 def read_glsl_files(fs
):
33 for filename
in glob(path
.join(path
.join(builtins_dir
, 'glsl'), '*.glsl')):
34 function_name
= path
.basename(filename
).split('.')[0]
35 (output
, returncode
) = run_compiler([filename
])
37 sys
.stderr
.write("Failed to compile builtin: " + filename
+ "\n")
38 sys
.stderr
.write("Result:\n")
39 sys
.stderr
.write(output
)
41 fs
[function_name
] = output
;
43 # Return a dictionary containing all builtin definitions (even generated)
44 def get_builtin_definitions():
46 generate_texture_functions(fs
)
52 # Work around MSVC's 65535 byte limit by outputting an array of characters
53 # rather than actual string literals.
55 #t = "/* Warning: length " + repr(len(s)) + " too large */\n"
57 for c
in re
.sub('\s\s+', ' ', s
):
62 return '{' + t
[:-1] + '}'
64 t
= s
.replace('\\', '\\\\').replace('"', '\\"').replace('\n', '\\n"\n "')
65 return ' "' + t
+ '"\n'
67 def write_function_definitions():
68 fs
= get_builtin_definitions()
69 for k
, v
in sorted(fs
.iteritems()):
70 print 'static const char builtin_' + k
+ '[] ='
71 print stringify(v
), ';'
73 def run_compiler(args
):
74 command
= [compiler
, '--dump-hir'] + args
75 p
= Popen(command
, 1, stdout
=PIPE
, shell
=False)
76 output
= p
.communicate()[0]
79 sys
.stderr
.write("Failed to compile builtins with command:\n")
81 sys
.stderr
.write(arg
+ " ")
82 sys
.stderr
.write("\n")
83 sys
.stderr
.write("Result:\n")
84 sys
.stderr
.write(output
)
86 # Clean up output a bit by killing whitespace before a closing paren.
87 kill_paren_whitespace
= re
.compile(r
'[ \n]*\)', re
.MULTILINE
)
88 output
= kill_paren_whitespace
.sub(')', output
)
90 # Also toss any duplicate newlines
91 output
= output
.replace('\n\n', '\n')
93 # Kill any global variable declarations. We don't want them.
94 kill_globals
= re
.compile(r
'^\(declare.*\n', re
.MULTILINE
)
95 output
= kill_globals
.sub('', output
)
97 return (output
, p
.returncode
)
99 def write_profile(filename
, profile
):
100 (proto_ir
, returncode
) = run_compiler([filename
])
103 print '#error builtins profile', profile
, 'failed to compile'
106 print 'static const char prototypes_for_' + profile
+ '[] ='
107 print stringify(proto_ir
), ';'
109 # Print a table of all the functions (not signatures) referenced.
110 # This is done so we can avoid bothering with a hash table in the C++ code.
112 function_names
= set()
113 for func
in re
.finditer(r
'\(function (.+)\n', proto_ir
):
114 function_names
.add(func
.group(1))
116 print 'static const char *functions_for_' + profile
+ ' [] = {'
117 for func
in sorted(function_names
):
118 print ' builtin_' + func
+ ','
121 def write_profiles():
122 profiles
= get_profile_list()
123 for (filename
, profile
) in profiles
:
124 write_profile(filename
, profile
)
126 def get_profile_list():
128 for extension
in ['glsl', 'frag', 'vert']:
129 path_glob
= path
.join(
130 path
.join(builtins_dir
, 'profiles'), '*.' + extension
)
131 profile_files
.extend(glob(path_glob
))
133 for pfile
in sorted(profile_files
):
134 profiles
.append((pfile
, path
.basename(pfile
).replace('.', '_')))
137 if __name__
== "__main__":
138 print """/* DO NOT MODIFY - automatically generated by generate_builtins.py */
140 * Copyright © 2010 Intel Corporation
142 * Permission is hereby granted, free of charge, to any person obtaining a
143 * copy of this software and associated documentation files (the "Software"),
144 * to deal in the Software without restriction, including without limitation
145 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
146 * and/or sell copies of the Software, and to permit persons to whom the
147 * Software is furnished to do so, subject to the following conditions:
149 * The above copyright notice and this permission notice (including the next
150 * paragraph) shall be included in all copies or substantial portions of the
153 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
154 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
155 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
156 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
157 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
158 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
159 * DEALINGS IN THE SOFTWARE.
163 #include "main/core.h" /* for struct gl_shader */
164 #include "glsl_parser_extras.h"
165 #include "ir_reader.h"
169 extern "C" struct gl_shader *
170 _mesa_new_shader(struct gl_context *ctx, GLuint name, GLenum type);
173 read_builtins(GLenum target, const char *protos, const char **functions, unsigned count)
175 struct gl_context fakeCtx;
176 fakeCtx.API = API_OPENGL_COMPAT;
177 fakeCtx.Const.GLSLVersion = 150;
178 fakeCtx.Extensions.ARB_ES2_compatibility = true;
179 fakeCtx.Extensions.ARB_ES3_compatibility = true;
180 fakeCtx.Const.ForceGLSLExtensionsWarn = false;
181 gl_shader *sh = _mesa_new_shader(NULL, 0, target);
182 struct _mesa_glsl_parse_state *st =
183 new(sh) _mesa_glsl_parse_state(&fakeCtx, target, sh);
185 st->language_version = 150;
186 st->symbols->separate_function_namespace = false;
187 st->ARB_texture_rectangle_enable = true;
188 st->EXT_texture_array_enable = true;
189 st->OES_EGL_image_external_enable = true;
190 st->ARB_shader_bit_encoding_enable = true;
191 st->ARB_texture_cube_map_array_enable = true;
192 st->ARB_shading_language_packing_enable = true;
193 st->ARB_texture_multisample_enable = true;
194 st->ARB_texture_query_lod_enable = true;
195 _mesa_glsl_initialize_types(st);
197 sh->ir = new(sh) exec_list;
198 sh->symbols = st->symbols;
200 /* Read the IR containing the prototypes */
201 _mesa_glsl_read_ir(st, sh->ir, protos, true);
203 /* Read ALL the function bodies, telling the IR reader not to scan for
204 * prototypes (we've already created them). The IR reader will skip any
205 * signature that does not already exist as a prototype.
207 for (unsigned i = 0; i < count; i++) {
208 _mesa_glsl_read_ir(st, sh->ir, functions[i], false);
211 printf("error reading builtin: %.35s ...\\n", functions[i]);
212 printf("Info log:\\n%s\\n", st->info_log);
218 reparent_ir(sh->ir, sh);
225 write_function_definitions()
228 profiles
= get_profile_list()
230 print 'static gl_shader *builtin_profiles[%d];' % len(profiles
)
233 static void *builtin_mem_ctx = NULL;
236 _mesa_glsl_release_functions(void)
238 ralloc_free(builtin_mem_ctx);
239 builtin_mem_ctx = NULL;
240 memset(builtin_profiles, 0, sizeof(builtin_profiles));
244 _mesa_read_profile(struct _mesa_glsl_parse_state *state,
246 const char *prototypes,
247 const char **functions,
250 gl_shader *sh = builtin_profiles[profile_index];
253 sh = read_builtins(GL_VERTEX_SHADER, prototypes, functions, count);
254 ralloc_steal(builtin_mem_ctx, sh);
255 builtin_profiles[profile_index] = sh;
258 state->builtins_to_link[state->num_builtins_to_link] = sh;
259 state->num_builtins_to_link++;
263 _mesa_glsl_initialize_functions(struct _mesa_glsl_parse_state *state)
265 /* If we've already initialized the built-ins, bail early. */
266 if (state->num_builtins_to_link > 0)
269 if (builtin_mem_ctx == NULL) {
270 builtin_mem_ctx = ralloc_context(NULL); // "GLSL built-in functions"
271 memset(&builtin_profiles, 0, sizeof(builtin_profiles));
276 for (filename
, profile
) in profiles
:
277 if profile
.endswith('_vert'):
278 check
= 'state->target == vertex_shader && '
279 elif profile
.endswith('_frag'):
280 check
= 'state->target == fragment_shader && '
284 version
= re
.sub(r
'_(glsl|vert|frag)$', '', profile
)
285 if version
[0].isdigit():
286 is_es
= version
.endswith('es')
288 version
= version
[:-2]
289 check
+= 'state->language_version == ' + version
290 check
+= ' && {0}state->es_shader'.format('' if is_es
else '!')
291 else: # an extension name
292 check
+= 'state->' + version
+ '_enable'
294 print ' if (' + check
+ ') {'
295 print ' _mesa_read_profile(state, %d,' % i
296 print ' prototypes_for_' + profile
+ ','
297 print ' functions_for_' + profile
+ ','
298 print ' Elements(functions_for_' + profile
+ '));'