| #!/usr/bin/python |
| # -*- coding: utf-8 -*- |
| |
| # |
| # Copyright 2011, 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. |
| # |
| |
| import os |
| import sys |
| |
| def RemoveAnnotation(line): |
| if line.find(":") >= 0: |
| annotation = line[line.find(":"): line.find(" ", line.find(":"))] |
| return line.replace(annotation, "*") |
| else: |
| return line |
| |
| def generate_api(lines): |
| externs = [] |
| i = 0 |
| # these have been hand written |
| skipFunctions = ["glDrawArrays", "glDrawElements"] |
| |
| # these have an EXTEND_Debug_* macro for getting data |
| extendFunctions = ["glCopyTexImage2D", "glCopyTexSubImage2D", "glReadPixels", |
| "glShaderSource", "glTexImage2D", "glTexSubImage2D"] |
| |
| # these also needs to be forwarded to DbgContext |
| contextFunctions = ["glUseProgram", "glEnableVertexAttribArray", "glDisableVertexAttribArray", |
| "glVertexAttribPointer", "glBindBuffer", "glBufferData", "glBufferSubData", "glDeleteBuffers",] |
| |
| for line in lines: |
| if line.find("API_ENTRY(") >= 0: # a function prototype |
| returnType = line[0: line.find(" API_ENTRY(")] |
| functionName = line[line.find("(") + 1: line.find(")")] #extract GL function name |
| parameterList = line[line.find(")(") + 2: line.find(") {")] |
| |
| #if line.find("*") >= 0: |
| # extern = "%s Debug_%s(%s);" % (returnType, functionName, parameterList) |
| # externs.append(extern) |
| # continue |
| |
| if functionName in skipFunctions: |
| sys.stderr.write("!\n! skipping function '%s'\n!\n" % (functionName)) |
| continue |
| |
| parameters = parameterList.split(',') |
| paramIndex = 0 |
| if line.find("*") >= 0 and (line.find("*") < line.find(":") or line.find("*") > line.rfind(":")): # unannotated pointer |
| if not functionName in extendFunctions: |
| # add function to list of functions that should be hand written, but generate code anyways |
| extern = "%s Debug_%s(%s);" % (returnType, functionName, RemoveAnnotation(parameterList)) |
| sys.stderr.write("%s should be hand written\n" % (extern)) |
| print "// FIXME: this function has pointers, it should be hand written" |
| externs.append(extern) |
| |
| print "%s Debug_%s(%s)\n{" % (returnType, functionName, RemoveAnnotation(parameterList)) |
| print " glesv2debugger::Message msg;" |
| |
| if parameterList == "void": |
| parameters = [] |
| arguments = "" |
| paramNames = [] |
| inout = "" |
| getData = "" |
| |
| callerMembers = "" |
| setCallerMembers = "" |
| setMsgParameters = "" |
| |
| for parameter in parameters: |
| const = parameter.find("const") |
| parameter = parameter.replace("const", "") |
| parameter = parameter.strip() |
| paramType = parameter.split(' ')[0] |
| paramName = parameter.split(' ')[1] |
| annotation = "" |
| arguments += paramName |
| if parameter.find(":") >= 0: # has annotation |
| assert inout == "" # only one parameter should be annotated |
| sys.stderr.write("%s is annotated: %s \n" % (functionName, paramType)) |
| inout = paramType.split(":")[2] |
| annotation = paramType.split(":")[1] |
| paramType = paramType.split(":")[0] |
| count = 1 |
| countArg = "" |
| if annotation.find("*") >= 0: # [1,n] * param |
| count = int(annotation.split("*")[0]) |
| countArg = annotation.split("*")[1] |
| assert countArg in paramNames |
| elif annotation in paramNames: |
| count = 1 |
| countArg = annotation |
| elif annotation == "GLstring": |
| annotation = "strlen(%s)" % (paramName) |
| else: |
| count = int(annotation) |
| |
| setMsgParameters += " msg.set_arg%d(ToInt(%s));\n" % (paramIndex, paramName) |
| if paramType.find("void") >= 0: |
| getData += " msg.mutable_data()->assign(reinterpret_cast<const char *>(%s), %s * sizeof(char));" % (paramName, annotation) |
| else: |
| getData += " msg.mutable_data()->assign(reinterpret_cast<const char *>(%s), %s * sizeof(%s));" % (paramName, annotation, paramType) |
| paramType += "*" |
| else: |
| if paramType == "GLfloat" or paramType == "GLclampf" or paramType.find("*") >= 0: |
| setMsgParameters += " msg.set_arg%d(ToInt(%s));\n" % (paramIndex, paramName) |
| else: |
| setMsgParameters += " msg.set_arg%d(%s);\n" % (paramIndex, paramName) |
| if paramIndex < len(parameters) - 1: |
| arguments += ', ' |
| if const >= 0: |
| paramType = "const " + paramType |
| paramNames.append(paramName) |
| paramIndex += 1 |
| callerMembers += " %s %s;\n" % (paramType, paramName) |
| setCallerMembers += " caller.%s = %s;\n" % (paramName, paramName) |
| |
| print " struct : public FunctionCall {" |
| print callerMembers |
| print " const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {" |
| if inout in ["out", "inout"]: # get timing excluding output data copy |
| print " nsecs_t c0 = systemTime(timeMode);" |
| if returnType == "void": |
| print " _c->%s(%s);" % (functionName, arguments) |
| else: |
| print " const int * ret = reinterpret_cast<const int *>(_c->%s(%s));" % (functionName, arguments) |
| print " msg.set_ret(ToInt(ret));" |
| if inout in ["out", "inout"]: |
| print " msg.set_time((systemTime(timeMode) - c0) * 1e-6f);" |
| print " " + getData |
| if functionName in extendFunctions: |
| print "\ |
| #ifdef EXTEND_AFTER_CALL_Debug_%s\n\ |
| EXTEND_AFTER_CALL_Debug_%s;\n\ |
| #endif" % (functionName, functionName) |
| if functionName in contextFunctions: |
| print " getDbgContextThreadSpecific()->%s(%s);" % (functionName, arguments) |
| if returnType == "void": |
| print " return 0;" |
| else: |
| print " return ret;" |
| print """ } |
| } caller;""" |
| print setCallerMembers |
| print setMsgParameters |
| |
| if line.find("*") >= 0 or line.find(":") >= 0: |
| print " // FIXME: check for pointer usage" |
| if inout in ["in", "inout"]: |
| print getData |
| if functionName in extendFunctions: |
| print "\ |
| #ifdef EXTEND_Debug_%s\n\ |
| EXTEND_Debug_%s;\n\ |
| #endif" % (functionName, functionName) |
| print " int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_%s);"\ |
| % (functionName) |
| if returnType != "void": |
| if returnType == "GLboolean": |
| print " return static_cast<GLboolean>(reinterpret_cast<int>(ret));" |
| else: |
| print " return reinterpret_cast<%s>(ret);" % (returnType) |
| print "}\n" |
| |
| |
| print "// FIXME: the following functions should be written by hand" |
| for extern in externs: |
| print extern |
| |
| if __name__ == "__main__": |
| print """\ |
| /* |
| ** Copyright 2011, 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. |
| */ |
| |
| // auto generated by generate_api_cpp.py |
| |
| #include <utils/Debug.h> |
| |
| #include "src/header.h" |
| #include "src/api.h" |
| |
| template<typename T> static int ToInt(const T & t) |
| { |
| COMPILE_TIME_ASSERT_FUNCTION_SCOPE(sizeof(T) == sizeof(int)); |
| return (int &)t; |
| } |
| """ |
| lines = open("gl2_api_annotated.in").readlines() |
| generate_api(lines) |
| #lines = open("gl2ext_api.in").readlines() |
| #generate_api(lines) |
| |
| |