175 lines
6.0 KiB
Python
175 lines
6.0 KiB
Python
|
#!/usr/bin/python
|
||
|
# -*- coding: utf-8 -*-
|
||
|
|
||
|
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
|
||
|
skipFunctions = ["glTexImage2D", "glTexSubImage2D", "glShaderSource"]
|
||
|
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(":")):
|
||
|
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))
|
||
|
|
||
|
if returnType != "void":
|
||
|
print "\t%s ret = 0;" % (returnType)
|
||
|
print """\tgl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl;
|
||
|
\tGLESv2Debugger::Message msg, cmd;
|
||
|
\tmsg.set_context_id(0);
|
||
|
\tmsg.set_has_next_message(true);
|
||
|
\tconst bool expectResponse = false;
|
||
|
\tmsg.set_expect_response(expectResponse);"""
|
||
|
print "\tmsg.set_function(GLESv2Debugger::Message_Function_%s);" % (functionName)
|
||
|
|
||
|
if parameterList == "void":
|
||
|
parameters = []
|
||
|
|
||
|
arguments = ""
|
||
|
|
||
|
paramTypes = []
|
||
|
paramNames = []
|
||
|
paramAnnotations = []
|
||
|
inout = ""
|
||
|
getData = ""
|
||
|
|
||
|
for parameter in parameters:
|
||
|
parameter = parameter.replace("const", "")
|
||
|
parameter = parameter.strip()
|
||
|
paramType = parameter.split(' ')[0]
|
||
|
paramName = parameter.split(' ')[1]
|
||
|
annotation = ""
|
||
|
arguments += paramName
|
||
|
if parameter.find(":") >= 0:
|
||
|
assert paramIndex == len(parameters) - 1 # only last 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]
|
||
|
assert paramType.find("void") < 0
|
||
|
count = 1
|
||
|
countArg = ""
|
||
|
if annotation.find("*") >= 0:
|
||
|
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)
|
||
|
|
||
|
print "\tmsg.set_arg%d(ToInt(%s));" % (paramIndex, paramName)
|
||
|
print "\tstd::string data;"
|
||
|
getData += "\t\t\tdata.reserve(%s * sizeof(%s));\n" % (annotation, paramType)
|
||
|
getData += "\t\t\tfor (unsigned i = 0; i < (%s); i++)\n" % (annotation)
|
||
|
getData += "\t\t\t\tdata.append((const char *)(%s + i), sizeof(*%s));\n" % (paramName, paramName)
|
||
|
getData += "\t\t\tmsg.set_data(data);"
|
||
|
else:
|
||
|
if paramIndex < len(parameters) - 1:
|
||
|
arguments += ', '
|
||
|
if paramType == "GLfloat" or paramType == "GLclampf" or paramType.find("*") >= 0:
|
||
|
print "\tmsg.set_arg%d(ToInt(%s));" % (paramIndex, paramName)
|
||
|
else:
|
||
|
print "\tmsg.set_arg%d(%s);" % (paramIndex, paramName)
|
||
|
paramTypes.append(paramType)
|
||
|
paramNames.append(paramName)
|
||
|
paramAnnotations.append(annotation)
|
||
|
paramIndex += 1
|
||
|
if line.find("*") >= 0 or line.find(":") >= 0:
|
||
|
print "\t// FIXME: check for pointer usage"
|
||
|
if inout in ["in", "inout"]:
|
||
|
print getData
|
||
|
print """\tSend(msg, cmd);
|
||
|
\tif (!expectResponse)
|
||
|
\t\tcmd.set_function(GLESv2Debugger::Message_Function_CONTINUE);
|
||
|
\twhile (true) {
|
||
|
\t\tmsg.Clear();
|
||
|
\t\tclock_t c0 = clock();
|
||
|
\t\tswitch (cmd.function()) {
|
||
|
\t\tcase GLESv2Debugger::Message_Function_CONTINUE:"""
|
||
|
if returnType == "void":
|
||
|
print "\t\t\t_c->%s(%s);" % (functionName, arguments)
|
||
|
|
||
|
else:
|
||
|
print "\t\t\tret = _c->%s(%s);" % (functionName, arguments)
|
||
|
if returnType == "GLboolean":
|
||
|
print "\t\t\tmsg.set_ret(ret);"
|
||
|
else:
|
||
|
print "\t\t\tmsg.set_ret(ToInt(ret));"
|
||
|
print "\t\t\tmsg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);"
|
||
|
print "\t\t\tmsg.set_context_id(0);"
|
||
|
print "\t\t\tmsg.set_function(GLESv2Debugger::Message_Function_%s);" % (functionName)
|
||
|
print """\t\t\tmsg.set_has_next_message(false);
|
||
|
\t\t\tmsg.set_expect_response(expectResponse);"""
|
||
|
if inout in ["out", "inout"]:
|
||
|
print getData
|
||
|
print """\t\t\tSend(msg, cmd);
|
||
|
\t\t\tif (!expectResponse)
|
||
|
\t\t\t\tcmd.set_function(GLESv2Debugger::Message_Function_SKIP);
|
||
|
\t\t\tbreak;
|
||
|
\t\tcase GLESv2Debugger::Message_Function_SKIP:"""
|
||
|
if returnType == "void":
|
||
|
print "\t\t\treturn;"
|
||
|
else:
|
||
|
print "\t\t\tif (cmd.has_ret())"
|
||
|
if returnType == "GLboolean":
|
||
|
print "\t\t\t\tret = cmd.ret();"
|
||
|
else:
|
||
|
print "\t\t\t\tret = FromInt<%s>(cmd.ret());" % (returnType)
|
||
|
print "\t\t\treturn ret;"
|
||
|
print """\t\tdefault:
|
||
|
\t\t\tASSERT(0); //GenerateCall(msg, cmd);
|
||
|
\t\t\tbreak;
|
||
|
\t\t}
|
||
|
\t}
|
||
|
}
|
||
|
"""
|
||
|
#break
|
||
|
|
||
|
print "// FIXME: the following functions should be written by hand"
|
||
|
for extern in externs:
|
||
|
print extern
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
print "// auto generated by generate_api_cpp.py\n"
|
||
|
print '''#include "src/header.h"\n'''
|
||
|
print "template<typename T> static int ToInt(const T & t) { STATIC_ASSERT(sizeof(T) == sizeof(int), bitcast); return (int &)t; }\n"
|
||
|
print "template<typename T> static T FromInt(const int & t) { STATIC_ASSERT(sizeof(T) == sizeof(int), bitcast); return (T &)t; }\n"
|
||
|
|
||
|
lines = open("gl2_api_annotated.in").readlines()
|
||
|
generate_api(lines)
|
||
|
#lines = open("gl2ext_api.in").readlines()
|
||
|
#generate_api(lines)
|
||
|
|
||
|
|