• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/python
2# -*- coding: utf-8 -*-
3
4#
5# Copyright 2011, The Android Open Source Project
6#
7# Licensed under the Apache License, Version 2.0 (the "License");
8# you may not use this file except in compliance with the License.
9# You may obtain a copy of the License at
10#
11#     http://www.apache.org/licenses/LICENSE-2.0
12#
13# Unless required by applicable law or agreed to in writing, software
14# distributed under the License is distributed on an "AS IS" BASIS,
15# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16# See the License for the specific language governing permissions and
17# limitations under the License.
18#
19
20import os
21import sys
22
23def RemoveAnnotation(line):
24    if line.find(":") >= 0:
25        annotation = line[line.find(":"): line.find(" ", line.find(":"))]
26        return line.replace(annotation, "*")
27    else:
28        return line
29
30def generate_api(lines):
31    externs = []
32    i = 0
33    # these have been hand written
34    skipFunctions = ["glDrawArrays", "glDrawElements"]
35
36    # these have an EXTEND_Debug_* macro for getting data
37    extendFunctions = ["glCopyTexImage2D", "glCopyTexSubImage2D", "glReadPixels",
38"glShaderSource", "glTexImage2D", "glTexSubImage2D"]
39
40    # these also needs to be forwarded to DbgContext
41    contextFunctions = ["glUseProgram", "glEnableVertexAttribArray", "glDisableVertexAttribArray",
42"glVertexAttribPointer", "glBindBuffer", "glBufferData", "glBufferSubData", "glDeleteBuffers",]
43
44    for line in lines:
45        if line.find("API_ENTRY(") >= 0: # a function prototype
46            returnType = line[0: line.find(" API_ENTRY(")]
47            functionName = line[line.find("(") + 1: line.find(")")] #extract GL function name
48            parameterList = line[line.find(")(") + 2: line.find(") {")]
49
50            #if line.find("*") >= 0:
51            #    extern = "%s Debug_%s(%s);" % (returnType, functionName, parameterList)
52            #    externs.append(extern)
53            #    continue
54
55            if functionName in skipFunctions:
56                sys.stderr.write("!\n! skipping function '%s'\n!\n" % (functionName))
57                continue
58
59            parameters = parameterList.split(',')
60            paramIndex = 0
61            if line.find("*") >= 0 and (line.find("*") < line.find(":") or line.find("*") > line.rfind(":")): # unannotated pointer
62                if not functionName in extendFunctions:
63                    # add function to list of functions that should be hand written, but generate code anyways
64                    extern = "%s Debug_%s(%s);" % (returnType, functionName, RemoveAnnotation(parameterList))
65                    sys.stderr.write("%s should be hand written\n" % (extern))
66                    print "// FIXME: this function has pointers, it should be hand written"
67                    externs.append(extern)
68
69            print "%s Debug_%s(%s)\n{" % (returnType, functionName, RemoveAnnotation(parameterList))
70            print "    glesv2debugger::Message msg;"
71
72            if parameterList == "void":
73                parameters = []
74            arguments = ""
75            paramNames = []
76            inout = ""
77            getData = ""
78
79            callerMembers = ""
80            setCallerMembers = ""
81            setMsgParameters = ""
82
83            for parameter in parameters:
84                const = parameter.find("const")
85                parameter = parameter.replace("const", "")
86                parameter = parameter.strip()
87                paramType = parameter.split(' ')[0]
88                paramName = parameter.split(' ')[1]
89                annotation = ""
90                arguments += paramName
91                if parameter.find(":") >= 0: # has annotation
92                    assert inout == "" # only one parameter should be annotated
93                    sys.stderr.write("%s is annotated: %s \n" % (functionName, paramType))
94                    inout = paramType.split(":")[2]
95                    annotation = paramType.split(":")[1]
96                    paramType = paramType.split(":")[0]
97                    count = 1
98                    countArg = ""
99                    if annotation.find("*") >= 0: # [1,n] * param
100                        count = int(annotation.split("*")[0])
101                        countArg = annotation.split("*")[1]
102                        assert countArg in paramNames
103                    elif annotation in paramNames:
104                        count = 1
105                        countArg = annotation
106                    elif annotation == "GLstring":
107                        annotation = "strlen(%s)" % (paramName)
108                    else:
109                        count = int(annotation)
110
111                    setMsgParameters += "    msg.set_arg%d(ToInt(%s));\n" % (paramIndex, paramName)
112                    if paramType.find("void") >= 0:
113                        getData += "    msg.mutable_data()->assign(reinterpret_cast<const char *>(%s), %s * sizeof(char));" % (paramName, annotation)
114                    else:
115                        getData += "    msg.mutable_data()->assign(reinterpret_cast<const char *>(%s), %s * sizeof(%s));" % (paramName, annotation, paramType)
116                    paramType += "*"
117                else:
118                    if paramType == "GLfloat" or paramType == "GLclampf" or paramType.find("*") >= 0:
119                        setMsgParameters += "    msg.set_arg%d(ToInt(%s));\n" % (paramIndex, paramName)
120                    else:
121                        setMsgParameters += "    msg.set_arg%d(%s);\n" % (paramIndex, paramName)
122                if paramIndex < len(parameters) - 1:
123                        arguments += ', '
124                if const >= 0:
125                    paramType = "const " + paramType
126                paramNames.append(paramName)
127                paramIndex += 1
128                callerMembers += "        %s %s;\n" % (paramType, paramName)
129                setCallerMembers += "    caller.%s = %s;\n" % (paramName, paramName)
130
131            print "    struct : public FunctionCall {"
132            print callerMembers
133            print "        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {"
134            if inout in ["out", "inout"]: # get timing excluding output data copy
135                print "            nsecs_t c0 = systemTime(timeMode);"
136            if returnType == "void":
137                print "            _c->%s(%s);" % (functionName, arguments)
138            else:
139                print "            const int * ret = reinterpret_cast<const int *>(_c->%s(%s));" % (functionName, arguments)
140                print "            msg.set_ret(ToInt(ret));"
141            if inout in ["out", "inout"]:
142                print "            msg.set_time((systemTime(timeMode) - c0) * 1e-6f);"
143                print "        " + getData
144            if functionName in extendFunctions:
145                print "\
146#ifdef EXTEND_AFTER_CALL_Debug_%s\n\
147            EXTEND_AFTER_CALL_Debug_%s;\n\
148#endif" % (functionName, functionName)
149            if functionName in contextFunctions:
150                print "            getDbgContextThreadSpecific()->%s(%s);" % (functionName, arguments)
151            if returnType == "void":
152                print "            return 0;"
153            else:
154                print "            return ret;"
155            print """        }
156    } caller;"""
157            print setCallerMembers
158            print setMsgParameters
159
160            if line.find("*") >= 0 or line.find(":") >= 0:
161                print "    // FIXME: check for pointer usage"
162            if inout in ["in", "inout"]:
163                print getData
164            if functionName in extendFunctions:
165                print "\
166#ifdef EXTEND_Debug_%s\n\
167    EXTEND_Debug_%s;\n\
168#endif" % (functionName, functionName)
169            print "    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_%s);"\
170                % (functionName)
171            if returnType != "void":
172                if returnType == "GLboolean":
173                    print "    return static_cast<GLboolean>(reinterpret_cast<int>(ret));"
174                else:
175                    print "    return reinterpret_cast<%s>(ret);" % (returnType)
176            print "}\n"
177
178
179    print "// FIXME: the following functions should be written by hand"
180    for extern in externs:
181        print extern
182
183if __name__ == "__main__":
184    print """\
185/*
186 ** Copyright 2011, The Android Open Source Project
187 **
188 ** Licensed under the Apache License, Version 2.0 (the "License");
189 ** you may not use this file except in compliance with the License.
190 ** You may obtain a copy of the License at
191 **
192 **     http://www.apache.org/licenses/LICENSE-2.0
193 **
194 ** Unless required by applicable law or agreed to in writing, software
195 ** distributed under the License is distributed on an "AS IS" BASIS,
196 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
197 ** See the License for the specific language governing permissions and
198 ** limitations under the License.
199 */
200
201// auto generated by generate_api_cpp.py
202
203#include <utils/Debug.h>
204
205#include "src/header.h"
206#include "src/api.h"
207
208template<typename T> static int ToInt(const T & t)
209{
210    COMPILE_TIME_ASSERT_FUNCTION_SCOPE(sizeof(T) == sizeof(int));
211    return (int &)t;
212}
213"""
214    lines = open("gl2_api_annotated.in").readlines()
215    generate_api(lines)
216    #lines = open("gl2ext_api.in").readlines()
217    #generate_api(lines)
218
219
220