summaryrefslogtreecommitdiff
path: root/src/glsl/builtins/tools/generate_builtins.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/glsl/builtins/tools/generate_builtins.py')
-rwxr-xr-xsrc/glsl/builtins/tools/generate_builtins.py207
1 files changed, 207 insertions, 0 deletions
diff --git a/src/glsl/builtins/tools/generate_builtins.py b/src/glsl/builtins/tools/generate_builtins.py
new file mode 100755
index 0000000000..2eb67e398a
--- /dev/null
+++ b/src/glsl/builtins/tools/generate_builtins.py
@@ -0,0 +1,207 @@
+#!/usr/bin/python
+# -*- coding: UTF-8 -*-
+
+import re, glob, sys
+from os import path
+from subprocess import Popen, PIPE
+
+# Local module: generator for texture lookup builtins
+from texture_builtins import generate_texture_functions
+
+builtins_dir = path.join(path.dirname(path.abspath(__file__)), "..")
+
+# Read the files in builtins/ir/*...add them to the supplied dictionary.
+def read_ir_files(fs):
+ for filename in glob.glob(path.join(path.join(builtins_dir, 'ir'), '*')):
+ with open(filename) as f:
+ fs[path.basename(filename)] = f.read()
+
+# Return a dictionary containing all builtin definitions (even generated)
+def get_builtin_definitions():
+ fs = {}
+ generate_texture_functions(fs)
+ read_ir_files(fs)
+ return fs
+
+def stringify(s):
+ t = s.replace('\\', '\\\\').replace('"', '\\"').replace('\n', '\\n"\n "')
+ return ' "' + t + '"\n'
+
+def write_function_definitions():
+ fs = get_builtin_definitions()
+ for k, v in fs.iteritems():
+ print 'static const char *builtin_' + k + ' ='
+ print stringify(v), ';'
+
+def run_compiler(args):
+ compiler_path = path.join(path.join(builtins_dir, '..'), 'glsl_compiler')
+ command = [compiler_path, '--dump-lir'] + args
+ p = Popen(command, 1, stdout=PIPE, shell=False)
+ output = p.communicate()[0]
+ return (output, p.returncode)
+
+def write_profile(filename, profile):
+ (proto_ir, returncode) = run_compiler([filename])
+
+ if returncode != 0:
+ print '#error builtins profile', profile, 'failed to compile'
+ return
+
+ # Kill any global variable declarations. We don't want them.
+ kill_globals = re.compile(r'^\(declare.*\n', re.MULTILINE);
+ proto_ir = kill_globals.sub('', proto_ir)
+
+ print 'static const char *prototypes_for_' + profile + ' ='
+ print stringify(proto_ir), ';'
+
+ # Print a table of all the functions (not signatures) referenced.
+ # This is done so we can avoid bothering with a hash table in the C++ code.
+
+ function_names = set()
+ for func in re.finditer(r'\(function (.+)\n', proto_ir):
+ function_names.add(func.group(1))
+
+ print 'static const char *functions_for_' + profile + ' [] = {'
+ for func in function_names:
+ print ' builtin_' + func + ','
+ print '};'
+
+def write_profiles():
+ profiles = get_profile_list()
+ for (filename, profile) in profiles:
+ write_profile(filename, profile)
+
+def get_profile_list():
+ profiles = []
+ for pfile in glob.glob(path.join(path.join(builtins_dir, 'profiles'), '*')):
+ profiles.append((pfile, path.basename(pfile).replace('.', '_')))
+ return profiles
+
+if __name__ == "__main__":
+ print """/* DO NOT MODIFY - automatically generated by generate_builtins.py */
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include "main/compiler.h"
+#include "glsl_parser_extras.h"
+#include "ir_reader.h"
+#include "program.h"
+#include "ast.h"
+
+extern "C" struct gl_shader *
+_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type);
+
+gl_shader *
+read_builtins(GLenum target, const char *protos, const char **functions, unsigned count)
+{
+ gl_shader *sh = _mesa_new_shader(NULL, 0, target);
+ struct _mesa_glsl_parse_state *st =
+ new(sh) _mesa_glsl_parse_state(NULL, target, sh);
+
+ st->language_version = 130;
+ st->ARB_texture_rectangle_enable = true;
+ st->EXT_texture_array_enable = true;
+ _mesa_glsl_initialize_types(st);
+
+ sh->ir = new(sh) exec_list;
+ sh->symbols = st->symbols;
+
+ /* Read the IR containing the prototypes */
+ _mesa_glsl_read_ir(st, sh->ir, protos, true);
+
+ /* Read ALL the function bodies, telling the IR reader not to scan for
+ * prototypes (we've already created them). The IR reader will skip any
+ * signature that does not already exist as a prototype.
+ */
+ for (unsigned i = 0; i < count; i++) {
+ _mesa_glsl_read_ir(st, sh->ir, functions[i], false);
+
+ if (st->error) {
+ printf("error reading builtin: %.35s ...\\n", functions[i]);
+ talloc_free(sh);
+ return NULL;
+ }
+ }
+
+ reparent_ir(sh->ir, sh);
+ delete st;
+
+ return sh;
+}
+"""
+
+ write_function_definitions()
+ write_profiles()
+
+ print """
+void *builtin_mem_ctx = NULL;
+
+void
+_mesa_glsl_release_functions(void)
+{
+ talloc_free(builtin_mem_ctx);
+}
+
+void
+_mesa_glsl_initialize_functions(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ if (builtin_mem_ctx == NULL)
+ builtin_mem_ctx = talloc_init("GLSL built-in functions");
+
+ state->num_builtins_to_link = 0;
+"""
+
+ profiles = get_profile_list()
+ for (filename, profile) in profiles:
+ if profile.endswith('_vert'):
+ check = 'state->target == vertex_shader && '
+ elif profile.endswith('_frag'):
+ check = 'state->target == fragment_shader && '
+
+ version = re.sub(r'_(vert|frag)$', '', profile)
+ if version.isdigit():
+ check += 'state->language_version == ' + version
+ else: # an extension name
+ check += 'state->' + version + '_enable'
+
+ print ' if (' + check + ') {'
+ print ' static gl_shader *sh = NULL;'
+ print ' if (sh == NULL) {'
+ print ' sh = read_builtins(GL_VERTEX_SHADER,'
+ print ' prototypes_for_' + profile + ','
+ print ' functions_for_' + profile + ','
+ print ' Elements(functions_for_' + profile,
+ print '));'
+ print ' talloc_steal(builtin_mem_ctx, sh);'
+ print ' }'
+ print
+ print ' import_prototypes(sh->ir, instructions, state->symbols,'
+ print ' state);'
+ print ' state->builtins_to_link[state->num_builtins_to_link] = sh;'
+ print ' state->num_builtins_to_link++;'
+ print ' }'
+ print
+ print '}'
+