X-Git-Url: https://gerrit.akraino.org/r/gitweb?a=blobdiff_plain;f=src%2Ftype3_AndroidCloud%2Fanbox-master%2Fscripts%2Fgen-emugl-entries.py;fp=src%2Ftype3_AndroidCloud%2Fanbox-master%2Fscripts%2Fgen-emugl-entries.py;h=b88137ec4a2a96f02eabaf366f581a6e7006c5f9;hb=e26c1ec581be598521517829adba8c8dd23a768f;hp=0000000000000000000000000000000000000000;hpb=6699c1aea74eeb0eb400e6299079f0c7576f716f;p=iec.git diff --git a/src/type3_AndroidCloud/anbox-master/scripts/gen-emugl-entries.py b/src/type3_AndroidCloud/anbox-master/scripts/gen-emugl-entries.py new file mode 100644 index 0000000..b88137e --- /dev/null +++ b/src/type3_AndroidCloud/anbox-master/scripts/gen-emugl-entries.py @@ -0,0 +1,482 @@ +#!/usr/bin/env python2 + +# Copyright 2015 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Utility functions used to parse a list of DLL entry points. +# Expected format: +# +# -> ignored +# # -> ignored +# % -> verbatim output for header files. +# ! -> prefix name for header files. +# ; -> entry point declaration. +# +# Anything else is an error. + +from __future__ import print_function +import re +import sys +import argparse + +re_func = re.compile(r"""^(.*[\* ])([A-Za-z_][A-Za-z0-9_]*)\((.*)\);$""") +re_param = re.compile(r"""^(.*[\* ])([A-Za-z_][A-Za-z0-9_]*)$""") + +def eprint(*args, **kwargs): + print(*args, file=sys.stderr, **kwargs) + +class Entry: + """Small class used to model a single DLL entry point.""" + def __init__(self, func_name, return_type, parameters): + """Initialize Entry instance. |func_name| is the function name, + |return_type| its return type, and |parameters| is a list of + (type,name) tuples from the entry's signature. + """ + self.func_name = func_name + self.return_type = return_type + self.parameters = "" + self.vartypes = [] + self.varnames = [] + self.call = "" + comma = "" + for param in parameters: + self.vartypes.append(param[0]) + self.varnames.append(param[1]) + self.parameters += "%s%s %s" % (comma, param[0], param[1]) + self.call += "%s%s" % (comma, param[1]) + comma = ", " + +def banner_command(argv): + """Return sanitized command-line description. + |argv| must be a list of command-line parameters, e.g. sys.argv. + Return a string corresponding to the command, with platform-specific + paths removed.""" + + # Remove path from first parameter + argv = argv[:] + argv[0] = "android/scripts/gen-entries.py" + return ' '.join(argv) + +def parse_entries_file(lines): + """Parse an .entries file and return a tuple of: + entries: list of Entry instances from the file. + prefix_name: prefix name from the file, or None. + verbatim: list of verbatim lines from the file. + errors: list of errors in the file, prefixed by line number. + """ + entries = [] + verbatim = [] + errors = [] + lineno = 0 + prefix_name = None + for line in lines: + lineno += 1 + line = line.strip() + if len(line) == 0: # Ignore empty lines + continue + if line[0] == '#': # Ignore comments + continue + if line[0] == '!': # Prefix name + prefix_name = line[1:] + continue + if line[0] == '%': # Verbatim line copy + verbatim.append(line[1:]) + continue + # Must be a function signature. + m = re_func.match(line) + if not m: + errors.append("%d: '%s'" % (lineno, line)) + continue + + return_type, func_name, parameters = m.groups() + return_type = return_type.strip() + parameters = parameters.strip() + params = [] + failure = False + if parameters != "void": + for parameter in parameters.split(','): + parameter = parameter.strip() + m = re_param.match(parameter) + if not m: + errors.append("%d: parameter '%s'" % (lineno, parameter)) + failure = True + break + else: + param_type, param_name = m.groups() + params.append((param_type.strip(), param_name.strip())) + + if not failure: + entries.append(Entry(func_name, return_type, params)) + + return (entries, prefix_name, verbatim, errors) + + +def gen_functions_header(entries, prefix_name, verbatim, filename, with_args): + """Generate a C header containing a macro listing all entry points. + |entries| is a list of Entry instances. + |prefix_name| is a prefix-name, it will be converted to upper-case. + |verbatim| is a list of verbatim lines that must appear before the + macro declaration. Useful to insert #include <> statements. + |filename| is the name of the original file. + """ + prefix_name = prefix_name.upper() + + print("// Auto-generated with: %s" % banner_command(sys.argv)) + print("// DO NOT EDIT THIS FILE") + print("") + print("#ifndef %s_FUNCTIONS_H" % prefix_name) + print("#define %s_FUNCTIONS_H" % prefix_name) + print("") + for line in verbatim: + print(line) + + print("#define LIST_%s_FUNCTIONS(X) \\" % prefix_name) + for entry in entries: + if with_args: + print(" X(%s, %s, (%s), (%s)) \\" % \ + (entry.return_type, entry.func_name, entry.parameters, + entry.call)) + else: + print(" X(%s, %s, (%s)) \\" % \ + (entry.return_type, entry.func_name, entry.parameters)) + + print("") + print("") + print("#endif // %s_FUNCTIONS_H" % prefix_name) + + + +# The purpose of gen_translator() +# is to quickly generate implementations on the host Translator, +# which processes commands that just got onto the renderthread off goldfish pipe +# and are fed to system OpenGL. + +def gen_translator(entries): + # Definitions for custom implementation bodies go in + # android/scripts/gles3translatorgen/gles30_custom.py + # android/scripts/gles3translatorgen/gles31_custom.py + from gles3translatorgen import gles30_custom + from gles3translatorgen import gles31_custom + + translator_custom_share_processing = { } + for (k, v) in gles30_custom.custom_share_processing.items(): + translator_custom_share_processing[k] = v + for (k, v) in gles31_custom.custom_share_processing.items(): + translator_custom_share_processing[k] = v + + translator_custom_pre = { } + for (k, v) in gles30_custom.custom_preprocesses.items(): + translator_custom_pre[k] = v + for (k, v) in gles31_custom.custom_preprocesses.items(): + translator_custom_pre[k] = v + + translator_custom_post = { } + for (k, v) in gles30_custom.custom_postprocesses.items(): + translator_custom_post[k] = v + for (k, v) in gles31_custom.custom_postprocesses.items(): + translator_custom_post[k] = v + + translator_no_passthrough = {} + for (k, v) in gles30_custom.no_passthrough.items(): + translator_no_passthrough[k] = v + for (k, v) in gles31_custom.no_passthrough.items(): + translator_no_passthrough[k] = v + + translator_needexternc = { + "glGetStringi": 1, + "glUniform4ui": 1, + "glGetUniformIndices": 1, + "glTransformFeedbackVaryings": 1, + "glCreateShaderProgramv": 1, + "glProgramUniform2ui": 1, + "glProgramUniform3ui": 1, + "glProgramUniform4ui": 1, + "glBindVertexBuffer": 1, + } + translator_nocontext_fail_codes = { + "glClientWaitSync" : "GL_WAIT_FAILED", + } + def needExternC(entry): + if translator_needexternc.has_key(entry.func_name): + return "extern \"C\" " + else: + return "" + def get_fail_code(entry): + if translator_nocontext_fail_codes.has_key(entry.func_name): + return translator_nocontext_fail_codes[entry.func_name] + else: + return "0" + def gen_cxt_getter(entry): + if (entry.return_type == "void"): + print(" GET_CTX_V2();") + else: + print(" GET_CTX_V2_RET(%s);" % get_fail_code(entry)) + + def gen_validations_custom_impl(entry): + isGen = entry.func_name.startswith("glGen") + isDelete = entry.func_name.startswith("glDelete") + isBufferOp = "Buffer" in entry.func_name + + hasTargetArg = "target" in entry.varnames + hasProgramArg = "program" in entry.varnames + + def mySetError(condition, glerr): + if entry.return_type == "void": + return "SET_ERROR_IF(%s,%s)" % (condition, glerr); + else: + return "RET_AND_SET_ERROR_IF(%s,%s,%s)" % (condition, glerr, get_fail_code(entry)) + + if (isGen or isDelete) and ("n" in entry.varnames): + print(" %s;" % mySetError("n < 0", "GL_INVALID_VALUE")) + if (isBufferOp and hasTargetArg): + print(" %s;" % mySetError("!GLESv2Validate::bufferTarget(ctx, target)", "GL_INVALID_ENUM")) + if translator_custom_pre.has_key(entry.func_name): + print(translator_custom_pre[entry.func_name],) + + def gen_call_ret(entry): + globalNameTypes = { + ("GLuint", "program") : "NamedObjectType::SHADER_OR_PROGRAM", + ("GLuint", "texture") : "NamedObjectType::TEXTURE", + ("GLuint", "buffer") : "NamedObjectType::VERTEXBUFFER", + ("GLuint", "sampler") : "NamedObjectType::SAMPLER", + ("GLuint", "query") : "NamedObjectType::QUERY", + } + globalNames = { + ("GLuint", "program") : "globalProgramName", + ("GLuint", "texture") : "globalTextureName", + ("GLuint", "buffer") : "globalBufferName", + ("GLuint", "sampler") : "globalSampler", + ("GLuint", "query") : "globalQuery", + } + + needsShareGroup = False + for v in zip(entry.vartypes, entry.varnames): + if v in globalNameTypes.keys(): + needsShareGroup = True + + if needsShareGroup: + print(" if (ctx->shareGroup().get()) {") + for key in zip(entry.vartypes, entry.varnames): + vartype, varname = key + if globalNames.has_key(key): + print(" const GLuint %s = ctx->shareGroup()->getGlobalName(%s, %s);" % (globalNames[key], globalNameTypes[key], varname)) + + globalCall = ", ".join(map(lambda k: globalNames.get(k, k[1]), zip(entry.vartypes, entry.varnames))) + + if needsShareGroup and translator_custom_share_processing.has_key(entry.func_name): + print(translator_custom_share_processing[entry.func_name]) + + if (entry.return_type == "void"): + if (needsShareGroup): + print(" "), + + if not translator_no_passthrough.has_key(entry.func_name): + print(" ctx->dispatcher().%s(%s);" % (entry.func_name, globalCall)) + + if needsShareGroup: + print(" }") + if translator_custom_post.has_key(entry.func_name): + print(translator_custom_post[entry.func_name]) + else: + if (needsShareGroup): + print(" "), + if not translator_no_passthrough.has_key(entry.func_name): + print(" %s %s = ctx->dispatcher().%s(%s);" % (entry.return_type, entry.func_name + "RET", entry.func_name, globalCall)) + else: + print(") %s %s = %s" % (entry.return_type, entry_func_name + "RET", get_fail_code(entry))) + + if translator_custom_post.has_key(entry.func_name): + print(translator_custom_post[entry.func_name]) + + print(" return %s;" % (entry.func_name + "RET")) + if needsShareGroup: + print(" } else return %s;" % (get_fail_code(entry))) + + print("// Auto-generated with: %s" % banner_command(sys.argv)) + print("// This file is best left unedited.") + print("// Try to make changes through gen_translator in gen-entries.py,") + print("// and/or parcel out custom functionality in separate code.") + for entry in entries: + print("%sGL_APICALL %s GL_APIENTRY %s(%s) {" % (needExternC(entry), entry.return_type, entry.func_name, entry.parameters)) + gen_cxt_getter(entry) + gen_validations_custom_impl(entry) + gen_call_ret(entry) + print("}\n") + +def gen_dll_wrapper(entries, prefix_name, verbatim, filename): + """Generate a C source file that contains functions that act as wrappers + for entry points located in another shared library. This allows the + code that calls these functions to perform lazy-linking to system + libraries. + |entries|, |prefix_name|, |verbatim| and |filename| are the same as + for gen_functions_header() above. + """ + upper_name = prefix_name.upper() + + ENTRY_PREFIX = "__dll_" + + print("// Auto-generated with: %s" % banner_command(sys.argv)) + print("// DO NOT EDIT THIS FILE") + print("") + print("#include ") + for line in verbatim: + print(line) + + print("") + print("///") + print("/// W R A P P E R P O I N T E R S") + print("///") + print("") + for entry in entries: + ptr_name = ENTRY_PREFIX + entry.func_name + print("static %s (*%s)(%s) = 0;" % \ + (entry.return_type, ptr_name, entry.parameters)) + + print("") + print("///") + print("/// W R A P P E R F U N C T I O N S") + print("///") + print("") + + for entry in entries: + print ("%s %s(%s) {" % \ + (entry.return_type, entry.func_name, entry.parameters)) + ptr_name = ENTRY_PREFIX + entry.func_name + if entry.return_type != "void": + print(" return %s(%s);" % (ptr_name, entry.call)) + else: + print(" %s(%s);" % (ptr_name, entry.call)) + print("}\n") + + print("") + print("///") + print("/// I N I T I A L I Z A T I O N F U N C T I O N") + print("///") + print("") + + print("int %s_dynlink_init(void* lib) {" % prefix_name) + for entry in entries: + ptr_name = ENTRY_PREFIX + entry.func_name + print(" %s = (%s(*)(%s))dlsym(lib, \"%s\");" % \ + (ptr_name, + entry.return_type, + entry.parameters, + entry.func_name)) + print(" if (!%s) return -1;" % ptr_name) + print(" return 0;") + print("}") + + +def gen_windows_def_file(entries): + """Generate a windows DLL .def file. |entries| is a list of Entry instances. + """ + print("EXPORTS") + for entry in entries: + print(" %s" % entry.func_name) + + +def gen_unix_sym_file(entries): + """Generate an ELF linker version file. |entries| is a list of Entry + instances. + """ + print("VERSION {") + print("\tglobal:") + for entry in entries: + print("\t\t%s;" % entry.func_name) + print("\tlocal:") + print("\t\t*;") + print("};") + +def gen_symbols(entries, underscore): + """Generate a list of symbols from |entries|, a list of Entry instances. + |underscore| is a boolean. If True, then prepend an underscore to each + symbol name. + """ + prefix = "" + if underscore: + prefix = "_" + for entry in entries: + print("%s%s" % (prefix, entry.func_name)) + +def parse_file(filename, lines, mode): + """Generate one of possible outputs from |filename|. |lines| must be a list + of text lines from the file, and |mode| is one of the --mode option + values. + """ + entries, prefix_name, verbatim, errors = parse_entries_file(lines) + if errors: + for error in errors: + eprint("ERROR: %s:%s" % (filename, error), file=sys.stderr) + sys.exit(1) + + if not prefix_name: + prefix_name = "unknown" + + if mode == 'def': + gen_windows_def_file(entries) + elif mode == 'sym': + gen_unix_sym_file(entries) + elif mode == 'translator_passthrough': + gen_translator(entries) + elif mode == 'wrapper': + gen_dll_wrapper(entries, prefix_name, verbatim, filename) + elif mode == 'symbols': + gen_symbols(entries, False) + elif mode == '_symbols': + gen_symbols(entries, True) + elif mode == 'functions': + gen_functions_header(entries, prefix_name, verbatim, filename, False) + elif mode == 'funcargs': + gen_functions_header(entries, prefix_name, verbatim, filename, True) + + +# List of valid --mode option values. +mode_list = [ + 'def', 'sym', 'translator_passthrough', 'wrapper', 'symbols', '_symbols', 'functions', 'funcargs' +] + +# Argument parsing. +parser = argparse.ArgumentParser( + formatter_class=argparse.RawDescriptionHelpFormatter, + description="""\ +A script used to parse an .entries input file containing a list of function +declarations, and generate various output files depending on the value of +the --mode option, which can be: + + def Generate a windows DLL .def file. + sym Generate a Unix .so linker script. + wrapper Generate a C source file containing wrapper functions. + symbols Generate a simple list of symbols, one per line. + _symbols Generate a simple list of symbols, prefixed with _. + functions Generate a C header containing a macro listing all functions. + funcargs Like 'functions', but adds function call arguments to listing. + +""") +parser.add_argument("--mode", help="Output mode", choices=mode_list) +parser.add_argument("--output", help="output file") +parser.add_argument("file", help=".entries file path") + +args = parser.parse_args() + +if not args.mode: + eprint("ERROR: Please use --mode=, see --help.", file=sys.stderr) + sys.exit(1) + +if args.output: + sys.stdout = open(args.output, "w+") + +if args.file == '--': + parse_file("", sys.stdin, args.mode) +else: + parse_file(args.file, open(args.file), args.mode)