Merge "Added screenshot after glDraw* option to GLES2 Debugger"

This commit is contained in:
David Li 2011-03-09 10:05:38 -08:00 committed by Android (Google) Code Review
commit c95e452508
21 changed files with 6139 additions and 5898 deletions

View File

@ -17,7 +17,7 @@ LOCAL_STATIC_LIBRARIES += libGLESv2_dbg libprotobuf-cpp-2.3.0-lite
LOCAL_SHARED_LIBRARIES += libcutils libutils libstlport
LOCAL_LDLIBS := -lpthread -ldl
LOCAL_MODULE:= libEGL
LOCAL_LDFLAGS += -Wl,--exclude-libs=ALL
# needed on sim build because of weird logging issues
ifeq ($(TARGET_SIMULATOR),true)
else

View File

@ -1650,6 +1650,10 @@ __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
{
EGLBoolean Debug_eglSwapBuffers(EGLDisplay dpy, EGLSurface draw);
if (gEGLDebugLevel > 0)
Debug_eglSwapBuffers(dpy, draw);
clearError();
SurfaceRef _s(draw);

View File

@ -3,11 +3,13 @@ LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
src/DebuggerMessage.pb.cpp \
src/api.cpp \
src/debugger_message.pb.cpp \
src/egl.cpp \
src/server.cpp \
src/shader.cpp \
src/texture.cpp
src/texture.cpp \
src/vertex.cpp
LOCAL_C_INCLUDES := \
$(LOCAL_PATH) \
@ -16,9 +18,6 @@ LOCAL_C_INCLUDES := \
external/protobuf/src \
bionic
LOCAL_SHARED_LIBRARIES := libstlport libcutils libutils
LOCAL_LDLIBS := -lpthread
#LOCAL_CFLAGS += -O0 -g -DDEBUG -UNDEBUG
LOCAL_CFLAGS := -DGOOGLE_PROTOBUF_NO_RTTI

View File

@ -1,73 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
import os
def generate_DebuggerMessage(output,lines,i):
for line in lines:
if line.find("API_ENTRY(") >= 0:
line = line[line.find("(") + 1: line.find(")")] #extract GL function name
output.write("\t\t%s = %d;\n" % (line, i))
i += 1
return i
if __name__ == "__main__":
output = open("DebuggerMessage.proto",'w')
output.write( """// do not edit; auto generated by generate_DebuggerMessage_proto.py
package GLESv2Debugger;
option optimize_for = LITE_RUNTIME;
message Message
{
\trequired int32 context_id = 1; // GL context id
\tenum Function
\t{
""")
i = 0;
lines = open("gl2_api.in").readlines()
i = generate_DebuggerMessage(output, lines, i)
output.write("\t\t// end of GL functions\n")
#lines = open("gl2ext_api.in").readlines()
#i = generate_DebuggerMessage(output, lines, i)
#output.write("\t\t// end of GL EXT functions\n")
output.write("\t\tACK = %d;\n" % (i))
i += 1
output.write("\t\tNEG = %d;\n" % (i))
i += 1
output.write("\t\tCONTINUE = %d;\n" % (i))
i += 1
output.write("\t\tSKIP = %d;\n" % (i))
i += 1
output.write("""\t}
\trequired Function function = 2 [default = NEG]; // type/function of message
\trequired bool has_next_message = 3;
\trequired bool expect_response = 4;
\toptional int32 ret = 5; // return value from previous GL call
\toptional int32 arg0 = 6; // args to GL call
\toptional int32 arg1 = 7;
\toptional int32 arg2 = 8;
\toptional int32 arg3 = 9;
\toptional int32 arg4 = 16;
\toptional int32 arg5 = 17;
\toptional int32 arg6 = 18;
\toptional int32 arg7 = 19;
\toptional int32 arg8 = 20;
\toptional bytes data = 10; // variable length data used for GL call
\toptional float time = 11; // timing of previous GL call (seconds)
}
""")
output.close()
os.system("aprotoc --cpp_out=src --java_out=client/src DebuggerMessage.proto")
os.system(' mv -f "src/DebuggerMessage.pb.cc" "src/DebuggerMessage.pb.cpp" ')

View File

@ -1,43 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
import os
if __name__ == "__main__":
externs = []
lines = open("enums.in").readlines()
i = 0
print "// auto generated by generate_GLFunction_java.py"
print """package GLESv2Debugger;
public enum GLEnum
{"""
index = 0
for line in lines:
value = line[line.find("(") + 1: line.find(",")]
name = line[line.find(",") + 1: line.find(")")]
print "\t%s(%s)," % (name, value)
print """\t;
\tpublic final int value;
\tGLEnum(final int value)
\t{
\t\tthis.value = value;
\t}
\tprivate static final java.util.HashMap<Integer, GLEnum> reverseMap = new java.util.HashMap<Integer, GLEnum>();
\tstatic
\t{
\t\tfor (GLEnum e : GLEnum.values())
\t\t\treverseMap.put(e.value, e);
\t}
\tpublic static GLEnum valueOf(final int value)
\t{
\t\treturn reverseMap.get(value);
\t}
}"""

View File

@ -1,34 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
import os
if __name__ == "__main__":
externs = []
lines = open("gl2_api.in").readlines()
i = 0
print "// auto generated by generate_GLFunction_java.py"
print """package GLESv2Debugger;
public enum GLFunction
{"""
index = 0
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
print "\t%s(%d, DebuggerMessage.Message.Function.%s)," % (functionName, index, functionName)
index += 1
print """\t;
\tpublic final int index;
\tpublic final DebuggerMessage.Message.Function function;
\tGLFunction(final int index, final DebuggerMessage.Message.Function function)
\t{
\t\tthis.index = index;
\t\tthis.function = function;
\t}
}"""

View File

@ -1,239 +0,0 @@
#!/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
if __name__ == "__main__":
externs = []
lines = open("gl2_api_annotated.in").readlines()
i = 0
print """// auto generated by generate_MessageFormatter_java.py"
package GLESv2Debugger;
public class MessageFormatter {
\tstatic String FormatFloats(int count, byte [] data)
\t{
\t\tString ret = "[";
\t\tfor (int i = 0; i < count; i++)
\t\t{
\t\t\tint bits = (data[i* 4 + 0] & 0xff) << 24;
\t\t\tbits |= (data[i* 4 + 1] & 0xff) << 16;
\t\t\tbits |= (data[i* 4 + 2] & 0xff) << 8;
\t\t\tbits |= (data[i* 4 + 3] & 0xff) << 0;
\t\t\tret += Float.intBitsToFloat(bits);
\t\t\tif (i < count - 1)
\t\t\t\tret += ", ";
\t\t}
\t\treturn ret + "]";
\t}
\t
\tstatic String FormatInts(int count, byte [] data)
\t{
\t\tString ret = "[";
\t\tfor (int i = 0; i < count; i++)
\t\t{
\t\t\tint bits = (data[i* 4 + 3] & 0xff) << 24;
\t\t\tbits |= (data[i* 4 + 2] & 0xff) << 16;
\t\t\tbits |= (data[i* 4 + 1] & 0xff) << 8;
\t\t\tbits |= (data[i* 4 + 0] & 0xff) << 0;
\t\t\tret += bits;
\t\t\tif (i < count - 1)
\t\t\t\tret += ", ";
\t\t}
\t\treturn ret + "]";
\t}
\t
\tstatic String FormatUints(int count, byte [] data)
\t{
\t\tString ret = "[";
\t\tfor (int i = 0; i < count; i++)
\t\t{
\t\t\tlong bits = (data[i* 4 + 3] & 0xff) << 24;
\t\t\tbits |= (data[i* 4 + 2] & 0xff) << 16;
\t\t\tbits |= (data[i* 4 + 1] & 0xff) << 8;
\t\t\tbits |= (data[i* 4 + 0] & 0xff) << 0;
\t\t\tret += bits;
\t\t\tif (i < count - 1)
\t\t\t\tret += ", ";
\t\t}
\t\treturn ret + "]";
\t}
\t
\tstatic String FormatMatrix(int columns, int count, byte [] data)
\t{
\t\tString ret = "[";
\t\tfor (int i = 0; i < count; i++)
\t\t{
\t\t\tint bits = (data[i* 4 + 0] & 0xff) << 24;
\t\t\tbits |= (data[i* 4 + 1] & 0xff) << 16;
\t\t\tbits |= (data[i* 4 + 2] & 0xff) << 8;
\t\t\tbits |= (data[i* 4 + 3] & 0xff) << 0;
\t\t\tret += Float.intBitsToFloat(bits);
\t\t\tif (i % columns == columns - 1)
\t\t\t\tret += '\\n';
\t\t\telse if (i < count - 1)
\t\t\t\tret += ", ";
\t\t}
\t\treturn ret + "]";
\t}
\tpublic static String Format(final DebuggerMessage.Message msg)
\t{
\t\tString str;
\t\tswitch (msg.getFunction())
\t\t{"""
for line in lines:
if line.find("API_ENTRY(") >= 0: # a function prototype
returnType = line[0: line.find(" API_ENTRY(")].replace("const ", "")
functionName = line[line.find("(") + 1: line.find(")")] #extract GL function name
parameterList = line[line.find(")(") + 2: line.find(") {")]
# print "\t\tcase %s:" % (functionName)
# print "\t\t\t//return MessageFormatterCustom.Format(msg);"
# print "\t\t\tstr = msg.toString(); break;"
# #extern = "%s Format_%s(%s);" % (returnType, functionName, parameterList)
# extern = functionName
# externs.append(extern)
# continue
parameters = parameterList.split(',')
paramIndex = 0
formatString = "%s "
formatArgs = ""
if returnType != "void":
if returnType == "GLenum":
formatArgs += "GLEnum.valueOf(msg.getRet())"
elif returnType.find("*") >= 0:
formatArgs += '"0x" + Integer.toHexString(msg.getRet())'
else:
formatArgs += "msg.getRet()"
else:
formatArgs += '"void"'
#formatString += "%s(" % (functionName)
formatString += "("
if parameterList == "void":
parameters = []
paramTypes = []
paramNames = []
paramAnnotations = []
for parameter in parameters:
parameter = parameter.replace("const","")
parameter = parameter.strip()
paramType = parameter.split(' ')[0]
paramName = parameter.split(' ')[1]
annotation = ""
formatString += paramName + "=%s"
if parameter.find(":") >= 0:
assert paramIndex == len(parameters) - 1 # only last parameter should be annotated
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 = annotation
else:
count = int(annotation)
dataFormatter = ""
if paramType == "GLfloat":
dataFormatter = "FormatFloats"
elif paramType == "GLint":
dataFormatter = "FormatInts"
elif paramType == "GLuint":
dataFormatter = "FormatUints"
elif annotation == "GLstring":
assert paramType == "GLchar"
else:
assert 0
if functionName.find("Matrix") >= 0:
columns = int(functionName[functionName.find("fv") - 1: functionName.find("fv")])
assert columns * columns == count
assert countArg != ""
assert paramType == "GLfloat"
formatArgs += ", FormatMatrix(%d, %d * msg.getArg%d(), msg.getData().toByteArray())" % (columns, count, paramNames.index(countArg))
elif annotation == "GLstring":
formatArgs += ", msg.getData().toStringUtf8()"
elif countArg == "":
formatArgs += ", %s(%d, msg.getData().toByteArray())" % (dataFormatter, count)
else:
formatArgs += ", %s(%d * msg.getArg%d(), msg.getData().toByteArray())" % (dataFormatter, count, paramNames.index(countArg))
else:
#formatArgs += ', "%s"' % (paramName)
if paramType == "GLfloat" or paramType == "GLclampf":
formatArgs += ", Float.intBitsToFloat(msg.getArg%d())" % (paramIndex)
elif paramType == "GLenum":
formatArgs += ", GLEnum.valueOf(msg.getArg%d())" % (paramIndex)
elif paramType.find("*") >= 0:
formatArgs += ', "0x" + Integer.toHexString(msg.getArg%d())' % (paramIndex)
else:
formatArgs += ", msg.getArg%d()" % (paramIndex)
if paramIndex < len(parameters) - 1:
formatString += ", "
paramTypes.append(paramType)
paramNames.append(paramName)
paramAnnotations.append(annotation)
paramIndex += 1
formatString += ")"
print "\t\tcase %s:" % (functionName)
if line.find("*") >= 0 and (line.find("*") < line.find(":") or line.find("*") > line.rfind(":")):
sys.stderr.write(line)
print "\t\t\t// FIXME: this function uses pointers, debugger may send data in msg.data"
print '\t\t\tstr = String.format("%s", %s); break;' % (formatString, formatArgs)
print """\t\tdefault:
\t\t\tstr = msg.toString();
\t\t}
\t\treturn str;
\t}
}"""
print """/*
package GLESv2Debugger;
public class MessageFormatterCustom {
\tpublic static String Format(final DebuggerMessage.Message msg) {
\t\tString str;
\t\tswitch (msg.getFunction()) {"""
for extern in externs:
print "\t\tcase %s" % (extern)
print "\t\t\t// TODO:"
print """\t\tdefault:
\t\t\tstr = msg.toString();
\t\t}
\t\treturn str;
\t}
}
*/"""

View File

@ -1,174 +1,192 @@
#!/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
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
externs = []
i = 0
# these have been hand written
skipFunctions = ["glTexImage2D", "glTexSubImage2D", "glShaderSource", "glReadPixels", "glDrawArrays", "glDrawElements"]
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(":")):
# 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;
const bool expectResponse = false;"""
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 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
print " int * ret = MessageLoop(caller, msg, expectResponse,"
print " 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 "// 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)
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 "src/header.h"
template<typename T> static int ToInt(const T & t) { STATIC_ASSERT(sizeof(T) == sizeof(int), bitcast); return (int &)t; }
template<typename T> static T FromInt(const int & t) { STATIC_ASSERT(sizeof(T) == sizeof(int), bitcast); return (T &)t; }
"""
lines = open("gl2_api_annotated.in").readlines()
generate_api(lines)
#lines = open("gl2ext_api.in").readlines()
#generate_api(lines)

View File

@ -1,6 +1,22 @@
#!/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
@ -42,11 +58,11 @@ def append_functions(functions, lines):
if __name__ == "__main__":
definedFunctions = []
lines = open("gl2_api.in").readlines()
lines = open("gl2_api_annotated.in").readlines()
definedFunctions = append_functions(definedFunctions, lines)
output = open("debug.in", "w")
lines = open("trace.in").readlines()
output = open("../debug.in", "w")
lines = open("../trace.in").readlines()
output.write("// the following functions are not defined in GLESv2_dbg\n")
for line in lines:
functionName = ""

View File

@ -0,0 +1,139 @@
#!/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
def generate_egl_entries(output, lines, i):
for line in lines:
if line.find("EGL_ENTRY(") >= 0:
line = line.split(",")[1].strip() #extract EGL function name
output.write(" %s = %d;\n" % (line, i))
i += 1
return i
def generate_gl_entries(output,lines,i):
for line in lines:
if line.find("API_ENTRY(") >= 0:
line = line[line.find("(") + 1: line.find(")")] #extract GL function name
output.write(" %s = %d;\n" % (line, i))
i += 1
return i
if __name__ == "__main__":
output = open("debugger_message.proto",'w')
output.write("""
/*
* Copyright (C) 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.
*/
// do not edit; auto generated by generate_debugger_message_proto.py
package com.android.glesv2debugger;
option optimize_for = LITE_RUNTIME;
message Message
{
required int32 context_id = 1; // GL context id
enum Function
{
""")
i = 0;
lines = open("gl2_api_annotated.in").readlines()
i = generate_gl_entries(output, lines, i)
output.write(" // end of GL functions\n")
#lines = open("gl2ext_api.in").readlines()
#i = generate_gl_entries(output, lines, i)
#output.write(" // end of GL EXT functions\n")
lines = open("../EGL/egl_entries.in").readlines()
i = generate_egl_entries(output, lines, i)
output.write(" // end of GL EXT functions\n")
output.write(" ACK = %d;\n" % (i))
i += 1
output.write(" NEG = %d;\n" % (i))
i += 1
output.write(" CONTINUE = %d;\n" % (i))
i += 1
output.write(" SKIP = %d;\n" % (i))
i += 1
output.write(" SETPROP = %d;\n" % (i))
i += 1
output.write(" CAPTURE = %d;\n" % (i))
i += 1
output.write(""" }
required Function function = 2 [default = NEG]; // type/function of message
enum Type
{
BeforeCall = 0;
AfterCall = 1;
Response = 2; // currently used for misc messages
}
required Type type = 3;
required bool expect_response = 4;
optional int32 ret = 5; // return value from previous GL call
optional int32 arg0 = 6; // args to GL call
optional int32 arg1 = 7;
optional int32 arg2 = 8;
optional int32 arg3 = 9;
optional int32 arg4 = 16;
optional int32 arg5 = 17;
optional int32 arg6 = 18;
optional int32 arg7 = 19;
optional int32 arg8 = 20;
optional bytes data = 10; // variable length data used for GL call
optional float time = 11; // duration of previous GL call (ms)
enum Prop
{
Capture = 0; // arg0 = true | false
TimeMode = 1; // arg0 = SYSTEM_TIME_* in utils/Timers.h
};
optional Prop prop = 21; // used with SETPROP, value in arg0
optional float clock = 22; // wall clock in seconds
}
""")
output.close()
os.system("aprotoc --cpp_out=src --java_out=../../../../../development/tools/glesv2debugger/src debugger_message.proto")
os.system('mv -f "src/debugger_message.pb.cc" "src/debugger_message.pb.cpp"')

View File

@ -34,10 +34,10 @@ void API_ENTRY(glBlendFunc)(GLenum sfactor, GLenum dfactor) {
void API_ENTRY(glBlendFuncSeparate)(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) {
CALL_GL_API(glBlendFuncSeparate, srcRGB, dstRGB, srcAlpha, dstAlpha);
}
void API_ENTRY(glBufferData)(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) {
void API_ENTRY(glBufferData)(GLenum target, GLsizeiptr size, const GLvoid:size:in data, GLenum usage) {
CALL_GL_API(glBufferData, target, size, data, usage);
}
void API_ENTRY(glBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) {
void API_ENTRY(glBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid:size:in data) {
CALL_GL_API(glBufferSubData, target, offset, size, data);
}
GLenum API_ENTRY(glCheckFramebufferStatus)(GLenum target) {

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,19 @@
/*
** 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.
*/
#include "src/header.h"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,41 @@
/*
** 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.
*/
#include "header.h"
EGLBoolean Debug_eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
{
glesv2debugger::Message msg;
const bool expectResponse = true;
struct : public FunctionCall {
EGLDisplay dpy;
EGLSurface draw;
const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
msg.set_time(-1);
return reinterpret_cast<const int *>(true);
}
} caller;
caller.dpy = dpy;
caller.draw = draw;
msg.set_arg0(reinterpret_cast<int>(dpy));
msg.set_arg1(reinterpret_cast<int>(draw));
int * ret = MessageLoop(caller, msg, expectResponse,
glesv2debugger::Message_Function_eglSwapBuffers);
return static_cast<EGLBoolean>(reinterpret_cast<int>(ret));
}

View File

@ -19,15 +19,11 @@
#include <string.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <sys/socket.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <cutils/log.h>
#include <cutils/properties.h>
#include <utils/Timers.h>
#include <../../../libcore/include/StaticAssert.h>
#define EGL_TRACE 1
@ -36,9 +32,10 @@
#define GL_ENTRY(_r, _api, ...) _r Debug_##_api ( __VA_ARGS__ );
#include "../include/glesv2_dbg.h"
#include "DebuggerMessage.pb.h"
#include "debugger_message.pb.h"
using namespace android;
using namespace com::android;
#define API_ENTRY(_api) Debug_##_api
@ -57,9 +54,21 @@ using namespace android;
namespace android
{
extern int clientSock, serverSock;
#define BUFFSIZE 256
extern char sockBuff [BUFFSIZE];
struct FunctionCall {
virtual const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) = 0;
virtual ~FunctionCall() {}
};
void Send(const GLESv2Debugger::Message & msg, GLESv2Debugger::Message & cmd);
extern bool capture;
extern int timeMode; // SYSTEM_TIME_
extern int clientSock, serverSock;
unsigned GetBytesPerPixel(const GLenum format, const GLenum type);
int * MessageLoop(FunctionCall & functionCall, glesv2debugger::Message & msg,
const bool expectResponse, const glesv2debugger::Message_Function function);
void Receive(glesv2debugger::Message & cmd);
float Send(const glesv2debugger::Message & msg, glesv2debugger::Message & cmd);
void SetProp(const glesv2debugger::Message & cmd);
}; // namespace android {

View File

@ -14,6 +14,9 @@
** limitations under the License.
*/
#include <sys/ioctl.h>
#include <unistd.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
@ -24,10 +27,10 @@
namespace android
{
char sockBuff [BUFFSIZE];
int serverSock = -1, clientSock = -1;
int timeMode = SYSTEM_TIME_THREAD;
void StopDebugServer();
static void Die(const char * msg)
@ -79,11 +82,11 @@ void StartDebugServer()
LOGD("Client connected: %s\n", inet_ntoa(client.sin_addr));
// fcntl(clientSock, F_SETFL, O_NONBLOCK);
GLESv2Debugger::Message msg, cmd;
glesv2debugger::Message msg, cmd;
msg.set_context_id(0);
msg.set_function(GLESv2Debugger::Message_Function_ACK);
msg.set_has_next_message(false);
msg.set_expect_response(true);
msg.set_function(glesv2debugger::Message_Function_ACK);
msg.set_type(glesv2debugger::Message_Type_Response);
msg.set_expect_response(false);
Send(msg, cmd);
}
@ -101,41 +104,18 @@ void StopDebugServer()
}
void Send(const GLESv2Debugger::Message & msg, GLESv2Debugger::Message & cmd)
void Receive(glesv2debugger::Message & cmd)
{
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&mutex); // TODO: this is just temporary
unsigned len = 0;
static std::string str;
const_cast<GLESv2Debugger::Message &>(msg).set_context_id(pthread_self());
msg.SerializeToString(&str);
unsigned len = str.length();
len = htonl(len);
int sent = -1;
sent = send(clientSock, (const char *)&len, sizeof(len), 0);
if (sent != sizeof(len)) {
LOGD("actual sent=%d expected=%d clientSock=%d", sent, sizeof(len), clientSock);
Die("Failed to send message length");
}
sent = send(clientSock, str.c_str(), str.length(), 0);
if (sent != str.length()) {
LOGD("actual sent=%d expected=%d clientSock=%d", sent, str.length(), clientSock);
Die("Failed to send message");
}
if (!msg.expect_response()) {
pthread_mutex_unlock(&mutex);
return;
}
int received = recv(clientSock, sockBuff, 4, MSG_WAITALL);
int received = recv(clientSock, &len, 4, MSG_WAITALL);
if (received < 0)
Die("Failed to receive response");
Die("Failed to receive response length");
else if (4 != received) {
LOGD("received %dB: %.8X", received, *(unsigned *)sockBuff);
LOGD("received %dB: %.8X", received, len);
Die("Received length mismatch, expected 4");
}
len = ntohl(*(unsigned *)sockBuff);
len = ntohl(len);
static void * buffer = NULL;
static unsigned bufferSize = 0;
if (bufferSize < len) {
@ -150,9 +130,100 @@ void Send(const GLESv2Debugger::Message & msg, GLESv2Debugger::Message & cmd)
Die("Received length mismatch");
cmd.Clear();
cmd.ParseFromArray(buffer, len);
}
float Send(const glesv2debugger::Message & msg, glesv2debugger::Message & cmd)
{
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&mutex); // TODO: this is just temporary
static std::string str;
const_cast<glesv2debugger::Message &>(msg).set_context_id(pthread_self());
msg.SerializeToString(&str);
unsigned len = str.length();
len = htonl(len);
int sent = -1;
sent = send(clientSock, (const char *)&len, sizeof(len), 0);
if (sent != sizeof(len)) {
LOGD("actual sent=%d expected=%d clientSock=%d", sent, sizeof(len), clientSock);
Die("Failed to send message length");
}
nsecs_t c0 = systemTime(timeMode);
sent = send(clientSock, str.c_str(), str.length(), 0);
float t = (float)ns2ms(systemTime(timeMode) - c0);
if (sent != str.length()) {
LOGD("actual sent=%d expected=%d clientSock=%d", sent, str.length(), clientSock);
Die("Failed to send message");
}
if (!msg.expect_response()) {
pthread_mutex_unlock(&mutex);
return t;
}
Receive(cmd);
//LOGD("Message sent tid=%lu len=%d", pthread_self(), str.length());
pthread_mutex_unlock(&mutex);
return t;
}
void SetProp(const glesv2debugger::Message & cmd)
{
switch (cmd.prop()) {
case glesv2debugger::Message_Prop_Capture:
LOGD("SetProp Message_Prop_Capture %d", cmd.arg0());
capture = cmd.arg0();
break;
case glesv2debugger::Message_Prop_TimeMode:
LOGD("SetProp Message_Prop_TimeMode %d", cmd.arg0());
timeMode = cmd.arg0();
break;
default:
assert(0);
}
}
int * MessageLoop(FunctionCall & functionCall, glesv2debugger::Message & msg,
const bool expectResponse, const glesv2debugger::Message_Function function)
{
gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl;
const int * ret = 0;
glesv2debugger::Message cmd;
msg.set_context_id(0);
msg.set_type(glesv2debugger::Message_Type_BeforeCall);
msg.set_expect_response(expectResponse);
msg.set_function(function);
Send(msg, cmd);
if (!expectResponse)
cmd.set_function(glesv2debugger::Message_Function_CONTINUE);
while (true) {
msg.Clear();
nsecs_t c0 = systemTime(timeMode);
switch (cmd.function()) {
case glesv2debugger::Message_Function_CONTINUE:
ret = functionCall(_c, msg);
if (!msg.has_time()) // some has output data copy, so time inside call
msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
msg.set_context_id(0);
msg.set_function(function);
msg.set_type(glesv2debugger::Message_Type_AfterCall);
msg.set_expect_response(expectResponse);
Send(msg, cmd);
if (!expectResponse)
cmd.set_function(glesv2debugger::Message_Function_SKIP);
break;
case glesv2debugger::Message_Function_SKIP:
return const_cast<int *>(ret);
case glesv2debugger::Message_Function_SETPROP:
SetProp(cmd);
Receive(cmd);
break;
default:
ASSERT(0); //GenerateCall(msg, cmd);
break;
}
}
return 0;
}
}; // namespace android {

View File

@ -16,19 +16,32 @@
#include "header.h"
void API_ENTRY(glShaderSource)(GLuint shader, GLsizei count, const GLchar** string, const GLint* length)
void Debug_glShaderSource(GLuint shader, GLsizei count, const GLchar** string, const GLint* length)
{
gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl;
GLESv2Debugger::Message msg, cmd;
msg.set_context_id(0);
msg.set_has_next_message(true);
glesv2debugger::Message msg;
const bool expectResponse = false;
msg.set_expect_response(expectResponse);
msg.set_function(GLESv2Debugger::Message_Function_glShaderSource);
struct : public FunctionCall {
GLuint shader;
GLsizei count;
const GLchar** string;
const GLint* length;
const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
nsecs_t c0 = systemTime(timeMode);
_c->glShaderSource(shader, count, string, length);
msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
return 0;
}
} caller;
caller.shader = shader;
caller.count = count;
caller.string = string;
caller.length = length;
msg.set_arg0(shader);
msg.set_arg1(count);
msg.set_arg2((int)string);
msg.set_arg3((int)length);
msg.set_arg2(reinterpret_cast<int>(string));
msg.set_arg3(reinterpret_cast<int>(length));
std::string data;
for (unsigned i = 0; i < count; i++)
@ -37,30 +50,7 @@ void API_ENTRY(glShaderSource)(GLuint shader, GLsizei count, const GLchar** stri
else
data.append(string[i], length[i]);
msg.set_data(data);
Send(msg, cmd);
if (!expectResponse)
cmd.set_function(GLESv2Debugger::Message_Function_CONTINUE);
while (true) {
msg.Clear();
clock_t c0 = clock();
switch (cmd.function()) {
case GLESv2Debugger::Message_Function_CONTINUE:
_c->glShaderSource(shader, count, string, length);
msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
msg.set_context_id(0);
msg.set_function(GLESv2Debugger::Message_Function_glShaderSource);
msg.set_has_next_message(false);
msg.set_expect_response(expectResponse);
Send(msg, cmd);
if (!expectResponse)
cmd.set_function(GLESv2Debugger::Message_Function_SKIP);
break;
case GLESv2Debugger::Message_Function_SKIP:
return;
default:
ASSERT(0); //GenerateCall(msg, cmd);
break;
}
}
}
int * ret = MessageLoop(caller, msg, expectResponse,
glesv2debugger::Message_Function_glShaderSource);
}

View File

@ -16,44 +16,44 @@
#include "header.h"
static inline void GetFormatAndBytesPerPixel(const GLenum format, unsigned & bytesPerPixel)
namespace android
{
switch (format) {
case GL_ALPHA:
bytesPerPixel = 1;
break;
case GL_LUMINANCE:
bytesPerPixel = 1;
break;
case GL_LUMINANCE_ALPHA:
bytesPerPixel = 2;
break;
case GL_RGB:
bytesPerPixel = 3;
break;
case GL_RGBA:
bytesPerPixel = 4;
break;
// internal formats to avoid conversion
unsigned GetBytesPerPixel(const GLenum format, const GLenum type)
{
switch (type) {
case GL_UNSIGNED_SHORT_5_6_5:
bytesPerPixel = 2;
break;
return 2;
case GL_UNSIGNED_SHORT_4_4_4_4:
bytesPerPixel = 2;
break;
return 2;
case GL_UNSIGNED_SHORT_5_5_5_1:
bytesPerPixel = 2;
return 2;
case GL_UNSIGNED_BYTE:
break;
default:
assert(0);
return;
}
switch (format) {
case GL_ALPHA:
return 1;
case GL_LUMINANCE:
return 1;
break;
case GL_LUMINANCE_ALPHA:
return 2;
case GL_RGB:
return 3;
case GL_RGBA:
return 4;
default:
assert(0);
return 0;
}
}
#define USE_RLE 0
#if USE_RLE
template<typename T>
export template<typename T>
void * RLEEncode(const void * pixels, unsigned count, unsigned * encodedSize)
{
// first is a byte indicating data size [1,2,4] bytes
@ -75,14 +75,14 @@ void * RLEEncode(const void * pixels, unsigned count, unsigned * encodedSize)
if (data[0] != data[run]) {
repeat = false;
break;
} else if (run > 127)
} else if (run > 126)
break;
if (!repeat) {
// find literal length
for (run = 1; run < count; run++)
if (data[run - 1] == data[run])
break;
else if (run > 127)
else if (run > 126)
break;
unsigned bytesToWrite = 1 + sizeof(T) * run;
if (bufferWritten + bytesToWrite > bufferSize) {
@ -129,19 +129,39 @@ void * RLEEncode(const void * pixels, const unsigned bytesPerPixel, const unsign
}
}
#endif
}; // namespace android
void API_ENTRY(glTexImage2D)(GLenum target, GLint level, GLint internalformat, GLsizei width,
GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid * pixels)
void Debug_glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels)
{
// LOGD("\n*\n* GLESv2_dbg: %s \n*", "glTexImage2D");
gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl;
GLESv2Debugger::Message msg, cmd;
msg.set_context_id(0);
msg.set_has_next_message(true);
glesv2debugger::Message msg;
const bool expectResponse = false;
msg.set_expect_response(expectResponse);
msg.set_function(GLESv2Debugger::Message_Function_glTexImage2D);
struct : public FunctionCall {
GLenum target;
GLint level;
GLint internalformat;
GLsizei width;
GLsizei height;
GLint border;
GLenum format;
GLenum type;
const GLvoid* pixels;
const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
nsecs_t c0 = systemTime(timeMode);
_c->glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels);
msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
return 0;
}
} caller;
caller.target = target;
caller.level = level;
caller.internalformat = internalformat;
caller.width = width;
caller.height = height;
caller.border = border;
caller.format = format;
caller.type = type;
caller.pixels = pixels;
msg.set_arg0(target);
msg.set_arg1(level);
@ -151,26 +171,13 @@ void API_ENTRY(glTexImage2D)(GLenum target, GLint level, GLint internalformat, G
msg.set_arg5(border);
msg.set_arg6(format);
msg.set_arg7(type);
msg.set_arg8(reinterpret_cast<int>(pixels));
if (pixels) {
assert(internalformat == format);
assert(0 == border);
GLenum newFormat = internalformat;
switch (type) {
case GL_UNSIGNED_BYTE:
break;
case GL_UNSIGNED_SHORT_5_6_5:
case GL_UNSIGNED_SHORT_4_4_4_4:
case GL_UNSIGNED_SHORT_5_5_5_1:
newFormat = type;
break;
default:
LOGD("GLESv2_dbg: glTexImage2D type=0x%.4X", type);
assert(0);
}
unsigned bytesPerPixel = 0;
GetFormatAndBytesPerPixel(newFormat, bytesPerPixel);
unsigned bytesPerPixel = GetBytesPerPixel(format, type);
assert(0 < bytesPerPixel);
// LOGD("GLESv2_dbg: glTexImage2D width=%d height=%d level=%d bytesPerPixel=%d",
@ -186,48 +193,42 @@ void API_ENTRY(glTexImage2D)(GLenum target, GLint level, GLint internalformat, G
msg.set_data(pixels, bytesPerPixel * width * height);
#endif
}
assert(msg.has_arg3());
Send(msg, cmd);
if (!expectResponse)
cmd.set_function(GLESv2Debugger::Message_Function_CONTINUE);
while (true) {
msg.Clear();
clock_t c0 = clock();
switch (cmd.function()) {
case GLESv2Debugger::Message_Function_CONTINUE:
_c->glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels);
msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
msg.set_context_id(0);
msg.set_function(GLESv2Debugger::Message_Function_glTexImage2D);
msg.set_has_next_message(false);
msg.set_expect_response(expectResponse);
assert(!msg.has_arg3());
Send(msg, cmd);
if (!expectResponse)
cmd.set_function(GLESv2Debugger::Message_Function_SKIP);
break;
case GLESv2Debugger::Message_Function_SKIP:
return;
default:
ASSERT(0); //GenerateCall(msg, cmd);
break;
}
}
int * ret = MessageLoop(caller, msg, expectResponse,
glesv2debugger::Message_Function_glTexImage2D);
}
void API_ENTRY(glTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset,
GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels)
void Debug_glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels)
{
// LOGD("\n*\n* GLESv2_dbg: %s \n*", "glTexSubImage2D");
gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl;
GLESv2Debugger::Message msg, cmd;
msg.set_context_id(0);
msg.set_has_next_message(true);
glesv2debugger::Message msg;
const bool expectResponse = false;
msg.set_expect_response(expectResponse);
msg.set_function(GLESv2Debugger::Message_Function_glTexSubImage2D);
struct : public FunctionCall {
GLenum target;
GLint level;
GLint xoffset;
GLint yoffset;
GLsizei width;
GLsizei height;
GLenum format;
GLenum type;
const GLvoid* pixels;
const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
nsecs_t c0 = systemTime(timeMode);
_c->glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
return 0;
}
} caller;
caller.target = target;
caller.level = level;
caller.xoffset = xoffset;
caller.yoffset = yoffset;
caller.width = width;
caller.height = height;
caller.format = format;
caller.type = type;
caller.pixels = pixels;
msg.set_arg0(target);
msg.set_arg1(level);
@ -237,23 +238,11 @@ void API_ENTRY(glTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint
msg.set_arg5(height);
msg.set_arg6(format);
msg.set_arg7(type);
msg.set_arg8(reinterpret_cast<int>(pixels));
assert(pixels);
if (pixels) {
GLenum newFormat = format;
switch (type) {
case GL_UNSIGNED_BYTE:
break;
case GL_UNSIGNED_SHORT_5_6_5:
case GL_UNSIGNED_SHORT_4_4_4_4:
case GL_UNSIGNED_SHORT_5_5_5_1:
newFormat = type;
break;
default:
assert(0);
}
unsigned bytesPerPixel = 0;
GetFormatAndBytesPerPixel(newFormat, bytesPerPixel);
unsigned bytesPerPixel = GetBytesPerPixel(format, type);
assert(0 < bytesPerPixel);
// LOGD("GLESv2_dbg: glTexSubImage2D width=%d height=%d level=%d bytesPerPixel=%d",
@ -270,31 +259,7 @@ void API_ENTRY(glTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint
msg.set_data(pixels, bytesPerPixel * width * height);
#endif
}
Send(msg, cmd);
if (!expectResponse)
cmd.set_function(GLESv2Debugger::Message_Function_CONTINUE);
while (true) {
msg.Clear();
clock_t c0 = clock();
switch (cmd.function()) {
case GLESv2Debugger::Message_Function_CONTINUE:
_c->glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
msg.set_function(GLESv2Debugger::Message_Function_glTexImage2D);
msg.set_context_id(0);
msg.set_has_next_message(false);
msg.set_expect_response(expectResponse);
Send(msg, cmd);
if (!expectResponse)
cmd.set_function(GLESv2Debugger::Message_Function_SKIP);
break;
case GLESv2Debugger::Message_Function_SKIP:
return;
default:
ASSERT(0); //GenerateCall(msg, cmd);
break;
}
}
}
int * ret = MessageLoop(caller, msg, expectResponse,
glesv2debugger::Message_Function_glTexSubImage2D);
}

View File

@ -0,0 +1,189 @@
/*
** 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.
*/
#include "header.h"
namespace android
{
bool capture; // capture after each glDraw*
void * RLEEncode(const void * pixels, const unsigned bytesPerPixel, const unsigned count, unsigned * encodedSize);
}
void Debug_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
{
gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl;
glesv2debugger::Message msg, cmd;
msg.set_context_id(0);
msg.set_type(glesv2debugger::Message_Type_BeforeCall);
const bool expectResponse = false;
msg.set_expect_response(expectResponse);
msg.set_function(glesv2debugger::Message_Function_glReadPixels);
msg.set_arg0(x);
msg.set_arg1(y);
msg.set_arg2(width);
msg.set_arg3(height);
msg.set_arg4(format);
msg.set_arg5(type);
msg.set_arg6(reinterpret_cast<int>(pixels));
//void * data = NULL;
//unsigned encodedSize = 0;
Send(msg, cmd);
float t = 0;
if (!expectResponse)
cmd.set_function(glesv2debugger::Message_Function_CONTINUE);
while (true) {
msg.Clear();
nsecs_t c0 = systemTime(timeMode);
switch (cmd.function()) {
case glesv2debugger::Message_Function_CONTINUE:
_c->glReadPixels(x, y, width, height, format, type, pixels);
msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
msg.set_context_id(0);
msg.set_function(glesv2debugger::Message_Function_glReadPixels);
msg.set_type(glesv2debugger::Message_Type_AfterCall);
msg.set_expect_response(expectResponse);
//data = RLEEncode(pixels, GetBytesPerPixel(format, type), width * height, &encodedSize);
msg.set_data(pixels, width * height * GetBytesPerPixel(format, type));
//msg.set_data(data, encodedSize);
//free(data);
c0 = systemTime(timeMode);
t = Send(msg, cmd);
msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
msg.set_clock(t);
// time is total send time in seconds, clock is msg serialization time in seconds
msg.clear_data();
msg.set_expect_response(false);
msg.set_type(glesv2debugger::Message_Type_AfterCall);
Send(msg, cmd);
if (!expectResponse)
cmd.set_function(glesv2debugger::Message_Function_SKIP);
break;
case glesv2debugger::Message_Function_SKIP:
return;
default:
ASSERT(0); //GenerateCall(msg, cmd);
break;
}
}
}
void Debug_glDrawArrays(GLenum mode, GLint first, GLsizei count)
{
gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl;
glesv2debugger::Message msg, cmd;
msg.set_context_id(0);
msg.set_type(glesv2debugger::Message_Type_BeforeCall);
const bool expectResponse = false;
msg.set_expect_response(expectResponse);
msg.set_function(glesv2debugger::Message_Function_glDrawArrays);
msg.set_arg0(mode);
msg.set_arg1(first);
msg.set_arg2(count);
void * data = NULL;
int viewport[4] = {};
Send(msg, cmd);
if (!expectResponse)
cmd.set_function(glesv2debugger::Message_Function_CONTINUE);
while (true) {
msg.Clear();
nsecs_t c0 = systemTime(timeMode);
switch (cmd.function()) {
case glesv2debugger::Message_Function_CONTINUE:
_c->glDrawArrays(mode, first, count);
msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
msg.set_context_id(0);
msg.set_function(glesv2debugger::Message_Function_glDrawArrays);
msg.set_type(glesv2debugger::Message_Type_AfterCall);
msg.set_expect_response(expectResponse);
Send(msg, cmd);
if (capture)
cmd.set_function(glesv2debugger::Message_Function_CAPTURE);
else if (!expectResponse)
cmd.set_function(glesv2debugger::Message_Function_SKIP);
break;
case glesv2debugger::Message_Function_SKIP:
return;
case glesv2debugger::Message_Function_CAPTURE:
_c->glGetIntegerv(GL_VIEWPORT, viewport);
LOGD("glDrawArrays CAPTURE: glGetIntegerv GL_VIEWPORT x=%d y=%d width=%d height=%d",
viewport[0], viewport[1], viewport[2], viewport[3]);
data = malloc(viewport[2] * viewport[3] * 4);
Debug_glReadPixels(viewport[0], viewport[1], viewport[2], viewport[3],
GL_RGBA, GL_UNSIGNED_BYTE, data);
free(data);
cmd.set_function(glesv2debugger::Message_Function_SKIP);
break;
default:
ASSERT(0); //GenerateCall(msg, cmd);
break;
}
}
}
void Debug_glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
{
gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl;
glesv2debugger::Message msg, cmd;
msg.set_context_id(0);
msg.set_type(glesv2debugger::Message_Type_BeforeCall);
const bool expectResponse = false;
msg.set_expect_response(expectResponse);
msg.set_function(glesv2debugger::Message_Function_glDrawElements);
msg.set_arg0(mode);
msg.set_arg1(count);
msg.set_arg2(type);
msg.set_arg3(reinterpret_cast<int>(indices));
void * data = NULL;
int viewport[4] = {};
Send(msg, cmd);
if (!expectResponse)
cmd.set_function(glesv2debugger::Message_Function_CONTINUE);
while (true) {
msg.Clear();
nsecs_t c0 = systemTime(timeMode);
switch (cmd.function()) {
case glesv2debugger::Message_Function_CONTINUE:
_c->glDrawElements(mode, count, type, indices);
msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
msg.set_context_id(0);
msg.set_function(glesv2debugger::Message_Function_glDrawElements);
msg.set_type(glesv2debugger::Message_Type_AfterCall);
msg.set_expect_response(expectResponse);
Send(msg, cmd);
if (capture)
cmd.set_function(glesv2debugger::Message_Function_CAPTURE);
else if (!expectResponse)
cmd.set_function(glesv2debugger::Message_Function_SKIP);
break;
case glesv2debugger::Message_Function_SKIP:
return;
case glesv2debugger::Message_Function_CAPTURE:
_c->glGetIntegerv(GL_VIEWPORT, viewport);
LOGD("glDrawElements CAPTURE: glGetIntegerv GL_VIEWPORT x=%d y=%d width=%d height=%d",
viewport[0], viewport[1], viewport[2], viewport[3]);
data = malloc(viewport[2] * viewport[3] * 4);
Debug_glReadPixels(viewport[0], viewport[1], viewport[2], viewport[3],
GL_RGBA, GL_UNSIGNED_BYTE, data);
free(data);
cmd.set_function(glesv2debugger::Message_Function_SKIP);
break;
default:
ASSERT(0); //GenerateCall(msg, cmd);
break;
}
}
}