Added screenshot after glDraw* option to GLES2 Debugger

Also added timing mode option using utils/Timers.h.
Factored out common code to reduce size.
Improved Protobuf message.
Uploads data from glBufferData and glBufferSubData.

Change-Id: Iaae5e706235d942df81c7eada7223fb0b0583911
Signed-off-by: David Li <davidxli@google.com>
diff --git a/opengl/libs/Android.mk b/opengl/libs/Android.mk
index f1afbb6..123306b6 100644
--- a/opengl/libs/Android.mk
+++ b/opengl/libs/Android.mk
@@ -17,7 +17,7 @@
 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
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index e427504..8e4b0ee 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -1650,6 +1650,10 @@
 
 EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
 {
+    EGLBoolean Debug_eglSwapBuffers(EGLDisplay dpy, EGLSurface draw);
+    if (gEGLDebugLevel > 0)
+        Debug_eglSwapBuffers(dpy, draw);
+
     clearError();
 
     SurfaceRef _s(draw);
diff --git a/opengl/libs/GLES2_dbg/Android.mk b/opengl/libs/GLES2_dbg/Android.mk
index c919886..0d35faf 100644
--- a/opengl/libs/GLES2_dbg/Android.mk
+++ b/opengl/libs/GLES2_dbg/Android.mk
@@ -3,11 +3,13 @@
 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 @@
     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
 
diff --git a/opengl/libs/GLES2_dbg/generate_DebuggerMessage_proto.py b/opengl/libs/GLES2_dbg/generate_DebuggerMessage_proto.py
deleted file mode 100755
index a803fae..0000000
--- a/opengl/libs/GLES2_dbg/generate_DebuggerMessage_proto.py
+++ /dev/null
@@ -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" ')
diff --git a/opengl/libs/GLES2_dbg/generate_GLEnum_java.py b/opengl/libs/GLES2_dbg/generate_GLEnum_java.py
deleted file mode 100755
index f927422..0000000
--- a/opengl/libs/GLES2_dbg/generate_GLEnum_java.py
+++ /dev/null
@@ -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}
-}"""
-
-
diff --git a/opengl/libs/GLES2_dbg/generate_GLFunction_java.py b/opengl/libs/GLES2_dbg/generate_GLFunction_java.py
deleted file mode 100755
index 07bbf14..0000000
--- a/opengl/libs/GLES2_dbg/generate_GLFunction_java.py
+++ /dev/null
@@ -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}
-}"""
-			
-
diff --git a/opengl/libs/GLES2_dbg/generate_MessageFormatter_java.py b/opengl/libs/GLES2_dbg/generate_MessageFormatter_java.py
deleted file mode 100755
index 81272e6..0000000
--- a/opengl/libs/GLES2_dbg/generate_MessageFormatter_java.py
+++ /dev/null
@@ -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}
-}
-*/"""	
-		
-		
diff --git a/opengl/libs/GLES2_dbg/generate_api_cpp.py b/opengl/libs/GLES2_dbg/generate_api_cpp.py
index 7c0b39e..93d6f7d 100755
--- a/opengl/libs/GLES2_dbg/generate_api_cpp.py
+++ b/opengl/libs/GLES2_dbg/generate_api_cpp.py
@@ -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)
+            
 
diff --git a/opengl/libs/GLES2_dbg/generate_debug_in.py b/opengl/libs/GLES2_dbg/generate_debug_in.py
index 830bcb9..1280c6f 100755
--- a/opengl/libs/GLES2_dbg/generate_debug_in.py
+++ b/opengl/libs/GLES2_dbg/generate_debug_in.py
@@ -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 @@
 
 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 = ""
diff --git a/opengl/libs/GLES2_dbg/generate_debugger_message_proto.py b/opengl/libs/GLES2_dbg/generate_debugger_message_proto.py
new file mode 100755
index 0000000..dcffdd0
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/generate_debugger_message_proto.py
@@ -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"')
diff --git a/opengl/libs/GLES2_dbg/gl2_api_annotated.in b/opengl/libs/GLES2_dbg/gl2_api_annotated.in
index 2296570..227e2eb 100644
--- a/opengl/libs/GLES2_dbg/gl2_api_annotated.in
+++ b/opengl/libs/GLES2_dbg/gl2_api_annotated.in
@@ -34,10 +34,10 @@
 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) {
diff --git a/opengl/libs/GLES2_dbg/src/api.cpp b/opengl/libs/GLES2_dbg/src/api.cpp
index b2b8ec0..a1de440 100644
--- a/opengl/libs/GLES2_dbg/src/api.cpp
+++ b/opengl/libs/GLES2_dbg/src/api.cpp
@@ -1,5707 +1,3590 @@
+
+/*
+ ** 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; }
 
 void Debug_glActiveTexture(GLenum texture)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glActiveTexture);
-	msg.set_arg0(texture);
-	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->glActiveTexture(texture);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glActiveTexture);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum texture;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glActiveTexture(texture);
+            return 0;
+        }
+    } caller;
+    caller.texture = texture;
+
+    msg.set_arg0(texture);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glActiveTexture);
 }
 
 void Debug_glAttachShader(GLuint program, GLuint shader)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glAttachShader);
-	msg.set_arg0(program);
-	msg.set_arg1(shader);
-	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->glAttachShader(program, shader);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glAttachShader);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint program;
+        GLuint shader;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glAttachShader(program, shader);
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+    caller.shader = shader;
+
+    msg.set_arg0(program);
+    msg.set_arg1(shader);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glAttachShader);
 }
 
 void Debug_glBindAttribLocation(GLuint program, GLuint index, const GLchar* name)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glBindAttribLocation);
-	msg.set_arg0(program);
-	msg.set_arg1(index);
-	msg.set_arg2(ToInt(name));
-	std::string data;
-	// FIXME: check for pointer usage
-			data.reserve(strlen(name) * sizeof(GLchar));
-			for (unsigned i = 0; i < (strlen(name)); i++)
-				data.append((const char *)(name + i), sizeof(*name));
-			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->glBindAttribLocation(program, index, name);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glBindAttribLocation);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint program;
+        GLuint index;
+        const GLchar* name;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glBindAttribLocation(program, index, name);
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+    caller.index = index;
+    caller.name = name;
+
+    msg.set_arg0(program);
+    msg.set_arg1(index);
+    msg.set_arg2(ToInt(name));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(name), strlen(name) * sizeof(GLchar));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glBindAttribLocation);
 }
 
 void Debug_glBindBuffer(GLenum target, GLuint buffer)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glBindBuffer);
-	msg.set_arg0(target);
-	msg.set_arg1(buffer);
-	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->glBindBuffer(target, buffer);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glBindBuffer);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLuint buffer;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glBindBuffer(target, buffer);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.buffer = buffer;
+
+    msg.set_arg0(target);
+    msg.set_arg1(buffer);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glBindBuffer);
 }
 
 void Debug_glBindFramebuffer(GLenum target, GLuint framebuffer)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glBindFramebuffer);
-	msg.set_arg0(target);
-	msg.set_arg1(framebuffer);
-	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->glBindFramebuffer(target, framebuffer);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glBindFramebuffer);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLuint framebuffer;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glBindFramebuffer(target, framebuffer);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.framebuffer = framebuffer;
+
+    msg.set_arg0(target);
+    msg.set_arg1(framebuffer);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glBindFramebuffer);
 }
 
 void Debug_glBindRenderbuffer(GLenum target, GLuint renderbuffer)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glBindRenderbuffer);
-	msg.set_arg0(target);
-	msg.set_arg1(renderbuffer);
-	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->glBindRenderbuffer(target, renderbuffer);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glBindRenderbuffer);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLuint renderbuffer;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glBindRenderbuffer(target, renderbuffer);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.renderbuffer = renderbuffer;
+
+    msg.set_arg0(target);
+    msg.set_arg1(renderbuffer);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glBindRenderbuffer);
 }
 
 void Debug_glBindTexture(GLenum target, GLuint texture)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glBindTexture);
-	msg.set_arg0(target);
-	msg.set_arg1(texture);
-	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->glBindTexture(target, texture);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glBindTexture);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLuint texture;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glBindTexture(target, texture);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.texture = texture;
+
+    msg.set_arg0(target);
+    msg.set_arg1(texture);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glBindTexture);
 }
 
 void Debug_glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glBlendColor);
-	msg.set_arg0(ToInt(red));
-	msg.set_arg1(ToInt(green));
-	msg.set_arg2(ToInt(blue));
-	msg.set_arg3(ToInt(alpha));
-	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->glBlendColor(red, green, blue, alpha);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glBlendColor);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLclampf red;
+        GLclampf green;
+        GLclampf blue;
+        GLclampf alpha;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glBlendColor(red, green, blue, alpha);
+            return 0;
+        }
+    } caller;
+    caller.red = red;
+    caller.green = green;
+    caller.blue = blue;
+    caller.alpha = alpha;
+
+    msg.set_arg0(ToInt(red));
+    msg.set_arg1(ToInt(green));
+    msg.set_arg2(ToInt(blue));
+    msg.set_arg3(ToInt(alpha));
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glBlendColor);
 }
 
 void Debug_glBlendEquation( GLenum mode )
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glBlendEquation);
-	msg.set_arg0(mode);
-	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->glBlendEquation(mode);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glBlendEquation);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum mode;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glBlendEquation(mode);
+            return 0;
+        }
+    } caller;
+    caller.mode = mode;
+
+    msg.set_arg0(mode);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glBlendEquation);
 }
 
 void Debug_glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glBlendEquationSeparate);
-	msg.set_arg0(modeRGB);
-	msg.set_arg1(modeAlpha);
-	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->glBlendEquationSeparate(modeRGB, modeAlpha);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glBlendEquationSeparate);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum modeRGB;
+        GLenum modeAlpha;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glBlendEquationSeparate(modeRGB, modeAlpha);
+            return 0;
+        }
+    } caller;
+    caller.modeRGB = modeRGB;
+    caller.modeAlpha = modeAlpha;
+
+    msg.set_arg0(modeRGB);
+    msg.set_arg1(modeAlpha);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glBlendEquationSeparate);
 }
 
 void Debug_glBlendFunc(GLenum sfactor, GLenum dfactor)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glBlendFunc);
-	msg.set_arg0(sfactor);
-	msg.set_arg1(dfactor);
-	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->glBlendFunc(sfactor, dfactor);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glBlendFunc);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum sfactor;
+        GLenum dfactor;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glBlendFunc(sfactor, dfactor);
+            return 0;
+        }
+    } caller;
+    caller.sfactor = sfactor;
+    caller.dfactor = dfactor;
+
+    msg.set_arg0(sfactor);
+    msg.set_arg1(dfactor);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glBlendFunc);
 }
 
 void Debug_glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glBlendFuncSeparate);
-	msg.set_arg0(srcRGB);
-	msg.set_arg1(dstRGB);
-	msg.set_arg2(srcAlpha);
-	msg.set_arg3(dstAlpha);
-	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->glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glBlendFuncSeparate);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum srcRGB;
+        GLenum dstRGB;
+        GLenum srcAlpha;
+        GLenum dstAlpha;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
+            return 0;
+        }
+    } caller;
+    caller.srcRGB = srcRGB;
+    caller.dstRGB = dstRGB;
+    caller.srcAlpha = srcAlpha;
+    caller.dstAlpha = dstAlpha;
+
+    msg.set_arg0(srcRGB);
+    msg.set_arg1(dstRGB);
+    msg.set_arg2(srcAlpha);
+    msg.set_arg3(dstAlpha);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glBlendFuncSeparate);
 }
 
-// FIXME: this function has pointers, it should be hand written
 void Debug_glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glBufferData);
-	msg.set_arg0(target);
-	msg.set_arg1(size);
-	msg.set_arg2(ToInt(data));
-	msg.set_arg3(usage);
-	// FIXME: check for pointer usage
-	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->glBufferData(target, size, data, usage);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glBufferData);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLsizeiptr size;
+        const GLvoid* data;
+        GLenum usage;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glBufferData(target, size, data, usage);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.size = size;
+    caller.data = data;
+    caller.usage = usage;
+
+    msg.set_arg0(target);
+    msg.set_arg1(size);
+    msg.set_arg2(ToInt(data));
+    msg.set_arg3(usage);
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(data), size * sizeof(char));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glBufferData);
 }
 
-// FIXME: this function has pointers, it should be hand written
 void Debug_glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glBufferSubData);
-	msg.set_arg0(target);
-	msg.set_arg1(offset);
-	msg.set_arg2(size);
-	msg.set_arg3(ToInt(data));
-	// FIXME: check for pointer usage
-	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->glBufferSubData(target, offset, size, data);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glBufferSubData);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLintptr offset;
+        GLsizeiptr size;
+        const GLvoid* data;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glBufferSubData(target, offset, size, data);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.offset = offset;
+    caller.size = size;
+    caller.data = data;
+
+    msg.set_arg0(target);
+    msg.set_arg1(offset);
+    msg.set_arg2(size);
+    msg.set_arg3(ToInt(data));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(data), size * sizeof(char));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glBufferSubData);
 }
 
 GLenum Debug_glCheckFramebufferStatus(GLenum target)
 {
-	GLenum ret = 0;
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glCheckFramebufferStatus);
-	msg.set_arg0(target);
-	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:
-			ret = _c->glCheckFramebufferStatus(target);
-			msg.set_ret(ToInt(ret));
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glCheckFramebufferStatus);
-			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:
-			if (cmd.has_ret())
-				ret = FromInt<GLenum>(cmd.ret());
-			return ret;
-		default:
-			ASSERT(0); //GenerateCall(msg, cmd); 
-			break;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glCheckFramebufferStatus(target));
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+    caller.target = target;
+
+    msg.set_arg0(target);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glCheckFramebufferStatus);
+    return reinterpret_cast<GLenum>(ret);
 }
 
 void Debug_glClear(GLbitfield mask)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glClear);
-	msg.set_arg0(mask);
-	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->glClear(mask);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glClear);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLbitfield mask;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glClear(mask);
+            return 0;
+        }
+    } caller;
+    caller.mask = mask;
+
+    msg.set_arg0(mask);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glClear);
 }
 
 void Debug_glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glClearColor);
-	msg.set_arg0(ToInt(red));
-	msg.set_arg1(ToInt(green));
-	msg.set_arg2(ToInt(blue));
-	msg.set_arg3(ToInt(alpha));
-	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->glClearColor(red, green, blue, alpha);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glClearColor);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLclampf red;
+        GLclampf green;
+        GLclampf blue;
+        GLclampf alpha;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glClearColor(red, green, blue, alpha);
+            return 0;
+        }
+    } caller;
+    caller.red = red;
+    caller.green = green;
+    caller.blue = blue;
+    caller.alpha = alpha;
+
+    msg.set_arg0(ToInt(red));
+    msg.set_arg1(ToInt(green));
+    msg.set_arg2(ToInt(blue));
+    msg.set_arg3(ToInt(alpha));
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glClearColor);
 }
 
 void Debug_glClearDepthf(GLclampf depth)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glClearDepthf);
-	msg.set_arg0(ToInt(depth));
-	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->glClearDepthf(depth);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glClearDepthf);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLclampf depth;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glClearDepthf(depth);
+            return 0;
+        }
+    } caller;
+    caller.depth = depth;
+
+    msg.set_arg0(ToInt(depth));
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glClearDepthf);
 }
 
 void Debug_glClearStencil(GLint s)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glClearStencil);
-	msg.set_arg0(s);
-	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->glClearStencil(s);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glClearStencil);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint s;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glClearStencil(s);
+            return 0;
+        }
+    } caller;
+    caller.s = s;
+
+    msg.set_arg0(s);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glClearStencil);
 }
 
 void Debug_glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glColorMask);
-	msg.set_arg0(red);
-	msg.set_arg1(green);
-	msg.set_arg2(blue);
-	msg.set_arg3(alpha);
-	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->glColorMask(red, green, blue, alpha);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glColorMask);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLboolean red;
+        GLboolean green;
+        GLboolean blue;
+        GLboolean alpha;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glColorMask(red, green, blue, alpha);
+            return 0;
+        }
+    } caller;
+    caller.red = red;
+    caller.green = green;
+    caller.blue = blue;
+    caller.alpha = alpha;
+
+    msg.set_arg0(red);
+    msg.set_arg1(green);
+    msg.set_arg2(blue);
+    msg.set_arg3(alpha);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glColorMask);
 }
 
 void Debug_glCompileShader(GLuint shader)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glCompileShader);
-	msg.set_arg0(shader);
-	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->glCompileShader(shader);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glCompileShader);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint shader;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glCompileShader(shader);
+            return 0;
+        }
+    } caller;
+    caller.shader = shader;
+
+    msg.set_arg0(shader);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glCompileShader);
 }
 
 // FIXME: this function has pointers, it should be hand written
 void Debug_glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glCompressedTexImage2D);
-	msg.set_arg0(target);
-	msg.set_arg1(level);
-	msg.set_arg2(internalformat);
-	msg.set_arg3(width);
-	msg.set_arg4(height);
-	msg.set_arg5(border);
-	msg.set_arg6(imageSize);
-	msg.set_arg7(ToInt(data));
-	// FIXME: check for pointer usage
-	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->glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glCompressedTexImage2D);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLint level;
+        GLenum internalformat;
+        GLsizei width;
+        GLsizei height;
+        GLint border;
+        GLsizei imageSize;
+        const GLvoid* data;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.level = level;
+    caller.internalformat = internalformat;
+    caller.width = width;
+    caller.height = height;
+    caller.border = border;
+    caller.imageSize = imageSize;
+    caller.data = data;
+
+    msg.set_arg0(target);
+    msg.set_arg1(level);
+    msg.set_arg2(internalformat);
+    msg.set_arg3(width);
+    msg.set_arg4(height);
+    msg.set_arg5(border);
+    msg.set_arg6(imageSize);
+    msg.set_arg7(ToInt(data));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glCompressedTexImage2D);
 }
 
 // FIXME: this function has pointers, it should be hand written
 void Debug_glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glCompressedTexSubImage2D);
-	msg.set_arg0(target);
-	msg.set_arg1(level);
-	msg.set_arg2(xoffset);
-	msg.set_arg3(yoffset);
-	msg.set_arg4(width);
-	msg.set_arg5(height);
-	msg.set_arg6(format);
-	msg.set_arg7(imageSize);
-	msg.set_arg8(ToInt(data));
-	// FIXME: check for pointer usage
-	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->glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glCompressedTexSubImage2D);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLint level;
+        GLint xoffset;
+        GLint yoffset;
+        GLsizei width;
+        GLsizei height;
+        GLenum format;
+        GLsizei imageSize;
+        const GLvoid* data;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data);
+            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.imageSize = imageSize;
+    caller.data = data;
+
+    msg.set_arg0(target);
+    msg.set_arg1(level);
+    msg.set_arg2(xoffset);
+    msg.set_arg3(yoffset);
+    msg.set_arg4(width);
+    msg.set_arg5(height);
+    msg.set_arg6(format);
+    msg.set_arg7(imageSize);
+    msg.set_arg8(ToInt(data));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glCompressedTexSubImage2D);
 }
 
 void Debug_glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glCopyTexImage2D);
-	msg.set_arg0(target);
-	msg.set_arg1(level);
-	msg.set_arg2(internalformat);
-	msg.set_arg3(x);
-	msg.set_arg4(y);
-	msg.set_arg5(width);
-	msg.set_arg6(height);
-	msg.set_arg7(border);
-	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->glCopyTexImage2D(target, level, internalformat, x, y, width, height, border);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glCopyTexImage2D);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLint level;
+        GLenum internalformat;
+        GLint x;
+        GLint y;
+        GLsizei width;
+        GLsizei height;
+        GLint border;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glCopyTexImage2D(target, level, internalformat, x, y, width, height, border);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.level = level;
+    caller.internalformat = internalformat;
+    caller.x = x;
+    caller.y = y;
+    caller.width = width;
+    caller.height = height;
+    caller.border = border;
+
+    msg.set_arg0(target);
+    msg.set_arg1(level);
+    msg.set_arg2(internalformat);
+    msg.set_arg3(x);
+    msg.set_arg4(y);
+    msg.set_arg5(width);
+    msg.set_arg6(height);
+    msg.set_arg7(border);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glCopyTexImage2D);
 }
 
 void Debug_glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glCopyTexSubImage2D);
-	msg.set_arg0(target);
-	msg.set_arg1(level);
-	msg.set_arg2(xoffset);
-	msg.set_arg3(yoffset);
-	msg.set_arg4(x);
-	msg.set_arg5(y);
-	msg.set_arg6(width);
-	msg.set_arg7(height);
-	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->glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glCopyTexSubImage2D);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLint level;
+        GLint xoffset;
+        GLint yoffset;
+        GLint x;
+        GLint y;
+        GLsizei width;
+        GLsizei height;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.level = level;
+    caller.xoffset = xoffset;
+    caller.yoffset = yoffset;
+    caller.x = x;
+    caller.y = y;
+    caller.width = width;
+    caller.height = height;
+
+    msg.set_arg0(target);
+    msg.set_arg1(level);
+    msg.set_arg2(xoffset);
+    msg.set_arg3(yoffset);
+    msg.set_arg4(x);
+    msg.set_arg5(y);
+    msg.set_arg6(width);
+    msg.set_arg7(height);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glCopyTexSubImage2D);
 }
 
 GLuint Debug_glCreateProgram(void)
 {
-	GLuint ret = 0;
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glCreateProgram);
-	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:
-			ret = _c->glCreateProgram();
-			msg.set_ret(ToInt(ret));
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glCreateProgram);
-			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:
-			if (cmd.has_ret())
-				ret = FromInt<GLuint>(cmd.ret());
-			return ret;
-		default:
-			ASSERT(0); //GenerateCall(msg, cmd); 
-			break;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glCreateProgram());
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glCreateProgram);
+    return reinterpret_cast<GLuint>(ret);
 }
 
 GLuint Debug_glCreateShader(GLenum type)
 {
-	GLuint ret = 0;
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glCreateShader);
-	msg.set_arg0(type);
-	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:
-			ret = _c->glCreateShader(type);
-			msg.set_ret(ToInt(ret));
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glCreateShader);
-			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:
-			if (cmd.has_ret())
-				ret = FromInt<GLuint>(cmd.ret());
-			return ret;
-		default:
-			ASSERT(0); //GenerateCall(msg, cmd); 
-			break;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum type;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glCreateShader(type));
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+    caller.type = type;
+
+    msg.set_arg0(type);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glCreateShader);
+    return reinterpret_cast<GLuint>(ret);
 }
 
 void Debug_glCullFace(GLenum mode)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glCullFace);
-	msg.set_arg0(mode);
-	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->glCullFace(mode);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glCullFace);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum mode;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glCullFace(mode);
+            return 0;
+        }
+    } caller;
+    caller.mode = mode;
+
+    msg.set_arg0(mode);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glCullFace);
 }
 
 void Debug_glDeleteBuffers(GLsizei n, const GLuint* buffers)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glDeleteBuffers);
-	msg.set_arg0(n);
-	msg.set_arg1(ToInt(buffers));
-	std::string data;
-	// FIXME: check for pointer usage
-			data.reserve(n * sizeof(GLuint));
-			for (unsigned i = 0; i < (n); i++)
-				data.append((const char *)(buffers + i), sizeof(*buffers));
-			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->glDeleteBuffers(n, buffers);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glDeleteBuffers);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLsizei n;
+        const GLuint* buffers;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glDeleteBuffers(n, buffers);
+            return 0;
+        }
+    } caller;
+    caller.n = n;
+    caller.buffers = buffers;
+
+    msg.set_arg0(n);
+    msg.set_arg1(ToInt(buffers));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(buffers), n * sizeof(GLuint));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glDeleteBuffers);
 }
 
 void Debug_glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glDeleteFramebuffers);
-	msg.set_arg0(n);
-	msg.set_arg1(ToInt(framebuffers));
-	std::string data;
-	// FIXME: check for pointer usage
-			data.reserve(n * sizeof(GLuint));
-			for (unsigned i = 0; i < (n); i++)
-				data.append((const char *)(framebuffers + i), sizeof(*framebuffers));
-			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->glDeleteFramebuffers(n, framebuffers);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glDeleteFramebuffers);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLsizei n;
+        const GLuint* framebuffers;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glDeleteFramebuffers(n, framebuffers);
+            return 0;
+        }
+    } caller;
+    caller.n = n;
+    caller.framebuffers = framebuffers;
+
+    msg.set_arg0(n);
+    msg.set_arg1(ToInt(framebuffers));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(framebuffers), n * sizeof(GLuint));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glDeleteFramebuffers);
 }
 
 void Debug_glDeleteProgram(GLuint program)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glDeleteProgram);
-	msg.set_arg0(program);
-	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->glDeleteProgram(program);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glDeleteProgram);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint program;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glDeleteProgram(program);
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+
+    msg.set_arg0(program);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glDeleteProgram);
 }
 
 void Debug_glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glDeleteRenderbuffers);
-	msg.set_arg0(n);
-	msg.set_arg1(ToInt(renderbuffers));
-	std::string data;
-	// FIXME: check for pointer usage
-			data.reserve(n * sizeof(GLuint));
-			for (unsigned i = 0; i < (n); i++)
-				data.append((const char *)(renderbuffers + i), sizeof(*renderbuffers));
-			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->glDeleteRenderbuffers(n, renderbuffers);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glDeleteRenderbuffers);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLsizei n;
+        const GLuint* renderbuffers;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glDeleteRenderbuffers(n, renderbuffers);
+            return 0;
+        }
+    } caller;
+    caller.n = n;
+    caller.renderbuffers = renderbuffers;
+
+    msg.set_arg0(n);
+    msg.set_arg1(ToInt(renderbuffers));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(renderbuffers), n * sizeof(GLuint));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glDeleteRenderbuffers);
 }
 
 void Debug_glDeleteShader(GLuint shader)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glDeleteShader);
-	msg.set_arg0(shader);
-	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->glDeleteShader(shader);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glDeleteShader);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint shader;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glDeleteShader(shader);
+            return 0;
+        }
+    } caller;
+    caller.shader = shader;
+
+    msg.set_arg0(shader);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glDeleteShader);
 }
 
 void Debug_glDeleteTextures(GLsizei n, const GLuint* textures)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glDeleteTextures);
-	msg.set_arg0(n);
-	msg.set_arg1(ToInt(textures));
-	std::string data;
-	// FIXME: check for pointer usage
-			data.reserve(n * sizeof(GLuint));
-			for (unsigned i = 0; i < (n); i++)
-				data.append((const char *)(textures + i), sizeof(*textures));
-			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->glDeleteTextures(n, textures);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glDeleteTextures);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLsizei n;
+        const GLuint* textures;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glDeleteTextures(n, textures);
+            return 0;
+        }
+    } caller;
+    caller.n = n;
+    caller.textures = textures;
+
+    msg.set_arg0(n);
+    msg.set_arg1(ToInt(textures));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(textures), n * sizeof(GLuint));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glDeleteTextures);
 }
 
 void Debug_glDepthFunc(GLenum func)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glDepthFunc);
-	msg.set_arg0(func);
-	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->glDepthFunc(func);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glDepthFunc);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum func;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glDepthFunc(func);
+            return 0;
+        }
+    } caller;
+    caller.func = func;
+
+    msg.set_arg0(func);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glDepthFunc);
 }
 
 void Debug_glDepthMask(GLboolean flag)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glDepthMask);
-	msg.set_arg0(flag);
-	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->glDepthMask(flag);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glDepthMask);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLboolean flag;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glDepthMask(flag);
+            return 0;
+        }
+    } caller;
+    caller.flag = flag;
+
+    msg.set_arg0(flag);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glDepthMask);
 }
 
 void Debug_glDepthRangef(GLclampf zNear, GLclampf zFar)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glDepthRangef);
-	msg.set_arg0(ToInt(zNear));
-	msg.set_arg1(ToInt(zFar));
-	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->glDepthRangef(zNear, zFar);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glDepthRangef);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLclampf zNear;
+        GLclampf zFar;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glDepthRangef(zNear, zFar);
+            return 0;
+        }
+    } caller;
+    caller.zNear = zNear;
+    caller.zFar = zFar;
+
+    msg.set_arg0(ToInt(zNear));
+    msg.set_arg1(ToInt(zFar));
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glDepthRangef);
 }
 
 void Debug_glDetachShader(GLuint program, GLuint shader)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glDetachShader);
-	msg.set_arg0(program);
-	msg.set_arg1(shader);
-	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->glDetachShader(program, shader);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glDetachShader);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint program;
+        GLuint shader;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glDetachShader(program, shader);
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+    caller.shader = shader;
+
+    msg.set_arg0(program);
+    msg.set_arg1(shader);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glDetachShader);
 }
 
 void Debug_glDisable(GLenum cap)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glDisable);
-	msg.set_arg0(cap);
-	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->glDisable(cap);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glDisable);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum cap;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glDisable(cap);
+            return 0;
+        }
+    } caller;
+    caller.cap = cap;
+
+    msg.set_arg0(cap);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glDisable);
 }
 
 void Debug_glDisableVertexAttribArray(GLuint index)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glDisableVertexAttribArray);
-	msg.set_arg0(index);
-	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->glDisableVertexAttribArray(index);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glDisableVertexAttribArray);
-			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;
-		}
-	}
-}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint index;
 
-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_has_next_message(true);
-	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);
-	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->glDrawArrays(mode, first, count);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glDrawArrays);
-			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;
-		}
-	}
-}
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glDisableVertexAttribArray(index);
+            return 0;
+        }
+    } caller;
+    caller.index = index;
 
-// FIXME: this function has pointers, it should be hand written
-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_has_next_message(true);
-	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(ToInt(indices));
-	// FIXME: check for pointer usage
-	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->glDrawElements(mode, count, type, indices);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glDrawElements);
-			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;
-		}
-	}
+    msg.set_arg0(index);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glDisableVertexAttribArray);
 }
 
 void Debug_glEnable(GLenum cap)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glEnable);
-	msg.set_arg0(cap);
-	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->glEnable(cap);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glEnable);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum cap;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glEnable(cap);
+            return 0;
+        }
+    } caller;
+    caller.cap = cap;
+
+    msg.set_arg0(cap);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glEnable);
 }
 
 void Debug_glEnableVertexAttribArray(GLuint index)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glEnableVertexAttribArray);
-	msg.set_arg0(index);
-	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->glEnableVertexAttribArray(index);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glEnableVertexAttribArray);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint index;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glEnableVertexAttribArray(index);
+            return 0;
+        }
+    } caller;
+    caller.index = index;
+
+    msg.set_arg0(index);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glEnableVertexAttribArray);
 }
 
 void Debug_glFinish(void)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glFinish);
-	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->glFinish();
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glFinish);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glFinish();
+            return 0;
+        }
+    } caller;
+
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glFinish);
 }
 
 void Debug_glFlush(void)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glFlush);
-	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->glFlush();
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glFlush);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glFlush();
+            return 0;
+        }
+    } caller;
+
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glFlush);
 }
 
 void Debug_glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glFramebufferRenderbuffer);
-	msg.set_arg0(target);
-	msg.set_arg1(attachment);
-	msg.set_arg2(renderbuffertarget);
-	msg.set_arg3(renderbuffer);
-	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->glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glFramebufferRenderbuffer);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLenum attachment;
+        GLenum renderbuffertarget;
+        GLuint renderbuffer;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.attachment = attachment;
+    caller.renderbuffertarget = renderbuffertarget;
+    caller.renderbuffer = renderbuffer;
+
+    msg.set_arg0(target);
+    msg.set_arg1(attachment);
+    msg.set_arg2(renderbuffertarget);
+    msg.set_arg3(renderbuffer);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glFramebufferRenderbuffer);
 }
 
 void Debug_glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glFramebufferTexture2D);
-	msg.set_arg0(target);
-	msg.set_arg1(attachment);
-	msg.set_arg2(textarget);
-	msg.set_arg3(texture);
-	msg.set_arg4(level);
-	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->glFramebufferTexture2D(target, attachment, textarget, texture, level);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glFramebufferTexture2D);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLenum attachment;
+        GLenum textarget;
+        GLuint texture;
+        GLint level;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glFramebufferTexture2D(target, attachment, textarget, texture, level);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.attachment = attachment;
+    caller.textarget = textarget;
+    caller.texture = texture;
+    caller.level = level;
+
+    msg.set_arg0(target);
+    msg.set_arg1(attachment);
+    msg.set_arg2(textarget);
+    msg.set_arg3(texture);
+    msg.set_arg4(level);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glFramebufferTexture2D);
 }
 
 void Debug_glFrontFace(GLenum mode)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glFrontFace);
-	msg.set_arg0(mode);
-	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->glFrontFace(mode);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glFrontFace);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum mode;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glFrontFace(mode);
+            return 0;
+        }
+    } caller;
+    caller.mode = mode;
+
+    msg.set_arg0(mode);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glFrontFace);
 }
 
 void Debug_glGenBuffers(GLsizei n, GLuint* buffers)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glGenBuffers);
-	msg.set_arg0(n);
-	msg.set_arg1(ToInt(buffers));
-	std::string data;
-	// FIXME: check for pointer usage
-	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->glGenBuffers(n, buffers);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glGenBuffers);
-			msg.set_has_next_message(false);
-			msg.set_expect_response(expectResponse);
-			data.reserve(n * sizeof(GLuint));
-			for (unsigned i = 0; i < (n); i++)
-				data.append((const char *)(buffers + i), sizeof(*buffers));
-			msg.set_data(data);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLsizei n;
+        GLuint* buffers;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            nsecs_t c0 = systemTime(timeMode);
+            _c->glGenBuffers(n, buffers);
+            msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
+            msg.mutable_data()->assign(reinterpret_cast<const char *>(buffers), n * sizeof(GLuint));
+            return 0;
+        }
+    } caller;
+    caller.n = n;
+    caller.buffers = buffers;
+
+    msg.set_arg0(n);
+    msg.set_arg1(ToInt(buffers));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGenBuffers);
 }
 
 void Debug_glGenerateMipmap(GLenum target)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glGenerateMipmap);
-	msg.set_arg0(target);
-	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->glGenerateMipmap(target);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glGenerateMipmap);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGenerateMipmap(target);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+
+    msg.set_arg0(target);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGenerateMipmap);
 }
 
 void Debug_glGenFramebuffers(GLsizei n, GLuint* framebuffers)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glGenFramebuffers);
-	msg.set_arg0(n);
-	msg.set_arg1(ToInt(framebuffers));
-	std::string data;
-	// FIXME: check for pointer usage
-	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->glGenFramebuffers(n, framebuffers);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glGenFramebuffers);
-			msg.set_has_next_message(false);
-			msg.set_expect_response(expectResponse);
-			data.reserve(n * sizeof(GLuint));
-			for (unsigned i = 0; i < (n); i++)
-				data.append((const char *)(framebuffers + i), sizeof(*framebuffers));
-			msg.set_data(data);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLsizei n;
+        GLuint* framebuffers;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            nsecs_t c0 = systemTime(timeMode);
+            _c->glGenFramebuffers(n, framebuffers);
+            msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
+            msg.mutable_data()->assign(reinterpret_cast<const char *>(framebuffers), n * sizeof(GLuint));
+            return 0;
+        }
+    } caller;
+    caller.n = n;
+    caller.framebuffers = framebuffers;
+
+    msg.set_arg0(n);
+    msg.set_arg1(ToInt(framebuffers));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGenFramebuffers);
 }
 
 void Debug_glGenRenderbuffers(GLsizei n, GLuint* renderbuffers)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glGenRenderbuffers);
-	msg.set_arg0(n);
-	msg.set_arg1(ToInt(renderbuffers));
-	std::string data;
-	// FIXME: check for pointer usage
-	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->glGenRenderbuffers(n, renderbuffers);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glGenRenderbuffers);
-			msg.set_has_next_message(false);
-			msg.set_expect_response(expectResponse);
-			data.reserve(n * sizeof(GLuint));
-			for (unsigned i = 0; i < (n); i++)
-				data.append((const char *)(renderbuffers + i), sizeof(*renderbuffers));
-			msg.set_data(data);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLsizei n;
+        GLuint* renderbuffers;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            nsecs_t c0 = systemTime(timeMode);
+            _c->glGenRenderbuffers(n, renderbuffers);
+            msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
+            msg.mutable_data()->assign(reinterpret_cast<const char *>(renderbuffers), n * sizeof(GLuint));
+            return 0;
+        }
+    } caller;
+    caller.n = n;
+    caller.renderbuffers = renderbuffers;
+
+    msg.set_arg0(n);
+    msg.set_arg1(ToInt(renderbuffers));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGenRenderbuffers);
 }
 
 void Debug_glGenTextures(GLsizei n, GLuint* textures)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glGenTextures);
-	msg.set_arg0(n);
-	msg.set_arg1(ToInt(textures));
-	std::string data;
-	// FIXME: check for pointer usage
-	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->glGenTextures(n, textures);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glGenTextures);
-			msg.set_has_next_message(false);
-			msg.set_expect_response(expectResponse);
-			data.reserve(n * sizeof(GLuint));
-			for (unsigned i = 0; i < (n); i++)
-				data.append((const char *)(textures + i), sizeof(*textures));
-			msg.set_data(data);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLsizei n;
+        GLuint* textures;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            nsecs_t c0 = systemTime(timeMode);
+            _c->glGenTextures(n, textures);
+            msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
+            msg.mutable_data()->assign(reinterpret_cast<const char *>(textures), n * sizeof(GLuint));
+            return 0;
+        }
+    } caller;
+    caller.n = n;
+    caller.textures = textures;
+
+    msg.set_arg0(n);
+    msg.set_arg1(ToInt(textures));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGenTextures);
 }
 
 // FIXME: this function has pointers, it should be hand written
 void Debug_glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glGetActiveAttrib);
-	msg.set_arg0(program);
-	msg.set_arg1(index);
-	msg.set_arg2(bufsize);
-	msg.set_arg3(ToInt(length));
-	msg.set_arg4(ToInt(size));
-	msg.set_arg5(ToInt(type));
-	msg.set_arg6(ToInt(name));
-	std::string data;
-	// FIXME: check for pointer usage
-			data.reserve(strlen(name) * sizeof(GLchar));
-			for (unsigned i = 0; i < (strlen(name)); i++)
-				data.append((const char *)(name + i), sizeof(*name));
-			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->glGetActiveAttrib(program, index, bufsize, length, size, type, name);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glGetActiveAttrib);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint program;
+        GLuint index;
+        GLsizei bufsize;
+        GLsizei* length;
+        GLint* size;
+        GLenum* type;
+        GLchar* name;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetActiveAttrib(program, index, bufsize, length, size, type, name);
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+    caller.index = index;
+    caller.bufsize = bufsize;
+    caller.length = length;
+    caller.size = size;
+    caller.type = type;
+    caller.name = name;
+
+    msg.set_arg0(program);
+    msg.set_arg1(index);
+    msg.set_arg2(bufsize);
+    msg.set_arg3(ToInt(length));
+    msg.set_arg4(ToInt(size));
+    msg.set_arg5(ToInt(type));
+    msg.set_arg6(ToInt(name));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(name), strlen(name) * sizeof(GLchar));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetActiveAttrib);
 }
 
 // FIXME: this function has pointers, it should be hand written
 void Debug_glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glGetActiveUniform);
-	msg.set_arg0(program);
-	msg.set_arg1(index);
-	msg.set_arg2(bufsize);
-	msg.set_arg3(ToInt(length));
-	msg.set_arg4(ToInt(size));
-	msg.set_arg5(ToInt(type));
-	msg.set_arg6(ToInt(name));
-	std::string data;
-	// FIXME: check for pointer usage
-			data.reserve(strlen(name) * sizeof(GLchar));
-			for (unsigned i = 0; i < (strlen(name)); i++)
-				data.append((const char *)(name + i), sizeof(*name));
-			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->glGetActiveUniform(program, index, bufsize, length, size, type, name);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glGetActiveUniform);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint program;
+        GLuint index;
+        GLsizei bufsize;
+        GLsizei* length;
+        GLint* size;
+        GLenum* type;
+        GLchar* name;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetActiveUniform(program, index, bufsize, length, size, type, name);
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+    caller.index = index;
+    caller.bufsize = bufsize;
+    caller.length = length;
+    caller.size = size;
+    caller.type = type;
+    caller.name = name;
+
+    msg.set_arg0(program);
+    msg.set_arg1(index);
+    msg.set_arg2(bufsize);
+    msg.set_arg3(ToInt(length));
+    msg.set_arg4(ToInt(size));
+    msg.set_arg5(ToInt(type));
+    msg.set_arg6(ToInt(name));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(name), strlen(name) * sizeof(GLchar));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetActiveUniform);
 }
 
 // FIXME: this function has pointers, it should be hand written
 void Debug_glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glGetAttachedShaders);
-	msg.set_arg0(program);
-	msg.set_arg1(maxcount);
-	msg.set_arg2(ToInt(count));
-	msg.set_arg3(ToInt(shaders));
-	// FIXME: check for pointer usage
-	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->glGetAttachedShaders(program, maxcount, count, shaders);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glGetAttachedShaders);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint program;
+        GLsizei maxcount;
+        GLsizei* count;
+        GLuint* shaders;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetAttachedShaders(program, maxcount, count, shaders);
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+    caller.maxcount = maxcount;
+    caller.count = count;
+    caller.shaders = shaders;
+
+    msg.set_arg0(program);
+    msg.set_arg1(maxcount);
+    msg.set_arg2(ToInt(count));
+    msg.set_arg3(ToInt(shaders));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetAttachedShaders);
 }
 
 int Debug_glGetAttribLocation(GLuint program, const GLchar* name)
 {
-	int ret = 0;
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glGetAttribLocation);
-	msg.set_arg0(program);
-	msg.set_arg1(ToInt(name));
-	std::string data;
-	// FIXME: check for pointer usage
-			data.reserve(strlen(name) * sizeof(GLchar));
-			for (unsigned i = 0; i < (strlen(name)); i++)
-				data.append((const char *)(name + i), sizeof(*name));
-			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:
-			ret = _c->glGetAttribLocation(program, name);
-			msg.set_ret(ToInt(ret));
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glGetAttribLocation);
-			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:
-			if (cmd.has_ret())
-				ret = FromInt<int>(cmd.ret());
-			return ret;
-		default:
-			ASSERT(0); //GenerateCall(msg, cmd); 
-			break;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint program;
+        const GLchar* name;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glGetAttribLocation(program, name));
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+    caller.program = program;
+    caller.name = name;
+
+    msg.set_arg0(program);
+    msg.set_arg1(ToInt(name));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(name), strlen(name) * sizeof(GLchar));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetAttribLocation);
+    return reinterpret_cast<int>(ret);
 }
 
 // FIXME: this function has pointers, it should be hand written
 void Debug_glGetBooleanv(GLenum pname, GLboolean* params)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glGetBooleanv);
-	msg.set_arg0(pname);
-	msg.set_arg1(ToInt(params));
-	// FIXME: check for pointer usage
-	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->glGetBooleanv(pname, params);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glGetBooleanv);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum pname;
+        GLboolean* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetBooleanv(pname, params);
+            return 0;
+        }
+    } caller;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(pname);
+    msg.set_arg1(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetBooleanv);
 }
 
 // FIXME: this function has pointers, it should be hand written
 void Debug_glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glGetBufferParameteriv);
-	msg.set_arg0(target);
-	msg.set_arg1(pname);
-	msg.set_arg2(ToInt(params));
-	// FIXME: check for pointer usage
-	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->glGetBufferParameteriv(target, pname, params);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glGetBufferParameteriv);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLenum pname;
+        GLint* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetBufferParameteriv(target, pname, params);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(target);
+    msg.set_arg1(pname);
+    msg.set_arg2(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetBufferParameteriv);
 }
 
 GLenum Debug_glGetError(void)
 {
-	GLenum ret = 0;
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glGetError);
-	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:
-			ret = _c->glGetError();
-			msg.set_ret(ToInt(ret));
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glGetError);
-			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:
-			if (cmd.has_ret())
-				ret = FromInt<GLenum>(cmd.ret());
-			return ret;
-		default:
-			ASSERT(0); //GenerateCall(msg, cmd); 
-			break;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glGetError());
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetError);
+    return reinterpret_cast<GLenum>(ret);
 }
 
 // FIXME: this function has pointers, it should be hand written
 void Debug_glGetFloatv(GLenum pname, GLfloat* params)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glGetFloatv);
-	msg.set_arg0(pname);
-	msg.set_arg1(ToInt(params));
-	// FIXME: check for pointer usage
-	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->glGetFloatv(pname, params);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glGetFloatv);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum pname;
+        GLfloat* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetFloatv(pname, params);
+            return 0;
+        }
+    } caller;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(pname);
+    msg.set_arg1(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetFloatv);
 }
 
 // FIXME: this function has pointers, it should be hand written
 void Debug_glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glGetFramebufferAttachmentParameteriv);
-	msg.set_arg0(target);
-	msg.set_arg1(attachment);
-	msg.set_arg2(pname);
-	msg.set_arg3(ToInt(params));
-	// FIXME: check for pointer usage
-	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->glGetFramebufferAttachmentParameteriv(target, attachment, pname, params);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glGetFramebufferAttachmentParameteriv);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLenum attachment;
+        GLenum pname;
+        GLint* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetFramebufferAttachmentParameteriv(target, attachment, pname, params);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.attachment = attachment;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(target);
+    msg.set_arg1(attachment);
+    msg.set_arg2(pname);
+    msg.set_arg3(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetFramebufferAttachmentParameteriv);
 }
 
 // FIXME: this function has pointers, it should be hand written
 void Debug_glGetIntegerv(GLenum pname, GLint* params)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glGetIntegerv);
-	msg.set_arg0(pname);
-	msg.set_arg1(ToInt(params));
-	// FIXME: check for pointer usage
-	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->glGetIntegerv(pname, params);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glGetIntegerv);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum pname;
+        GLint* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetIntegerv(pname, params);
+            return 0;
+        }
+    } caller;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(pname);
+    msg.set_arg1(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetIntegerv);
 }
 
 void Debug_glGetProgramiv(GLuint program, GLenum pname, GLint* params)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glGetProgramiv);
-	msg.set_arg0(program);
-	msg.set_arg1(pname);
-	msg.set_arg2(ToInt(params));
-	std::string data;
-	// FIXME: check for pointer usage
-	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->glGetProgramiv(program, pname, params);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glGetProgramiv);
-			msg.set_has_next_message(false);
-			msg.set_expect_response(expectResponse);
-			data.reserve(1 * sizeof(GLint));
-			for (unsigned i = 0; i < (1); i++)
-				data.append((const char *)(params + i), sizeof(*params));
-			msg.set_data(data);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint program;
+        GLenum pname;
+        GLint* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            nsecs_t c0 = systemTime(timeMode);
+            _c->glGetProgramiv(program, pname, params);
+            msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
+            msg.mutable_data()->assign(reinterpret_cast<const char *>(params), 1 * sizeof(GLint));
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(program);
+    msg.set_arg1(pname);
+    msg.set_arg2(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetProgramiv);
 }
 
 // FIXME: this function has pointers, it should be hand written
 void Debug_glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glGetProgramInfoLog);
-	msg.set_arg0(program);
-	msg.set_arg1(bufsize);
-	msg.set_arg2(ToInt(length));
-	msg.set_arg3(ToInt(infolog));
-	std::string data;
-	// FIXME: check for pointer usage
-	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->glGetProgramInfoLog(program, bufsize, length, infolog);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glGetProgramInfoLog);
-			msg.set_has_next_message(false);
-			msg.set_expect_response(expectResponse);
-			data.reserve(strlen(infolog) * sizeof(GLchar));
-			for (unsigned i = 0; i < (strlen(infolog)); i++)
-				data.append((const char *)(infolog + i), sizeof(*infolog));
-			msg.set_data(data);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint program;
+        GLsizei bufsize;
+        GLsizei* length;
+        GLchar* infolog;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            nsecs_t c0 = systemTime(timeMode);
+            _c->glGetProgramInfoLog(program, bufsize, length, infolog);
+            msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
+            msg.mutable_data()->assign(reinterpret_cast<const char *>(infolog), strlen(infolog) * sizeof(GLchar));
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+    caller.bufsize = bufsize;
+    caller.length = length;
+    caller.infolog = infolog;
+
+    msg.set_arg0(program);
+    msg.set_arg1(bufsize);
+    msg.set_arg2(ToInt(length));
+    msg.set_arg3(ToInt(infolog));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetProgramInfoLog);
 }
 
 // FIXME: this function has pointers, it should be hand written
 void Debug_glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glGetRenderbufferParameteriv);
-	msg.set_arg0(target);
-	msg.set_arg1(pname);
-	msg.set_arg2(ToInt(params));
-	// FIXME: check for pointer usage
-	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->glGetRenderbufferParameteriv(target, pname, params);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glGetRenderbufferParameteriv);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLenum pname;
+        GLint* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetRenderbufferParameteriv(target, pname, params);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(target);
+    msg.set_arg1(pname);
+    msg.set_arg2(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetRenderbufferParameteriv);
 }
 
 void Debug_glGetShaderiv(GLuint shader, GLenum pname, GLint* params)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glGetShaderiv);
-	msg.set_arg0(shader);
-	msg.set_arg1(pname);
-	msg.set_arg2(ToInt(params));
-	std::string data;
-	// FIXME: check for pointer usage
-	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->glGetShaderiv(shader, pname, params);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glGetShaderiv);
-			msg.set_has_next_message(false);
-			msg.set_expect_response(expectResponse);
-			data.reserve(1 * sizeof(GLint));
-			for (unsigned i = 0; i < (1); i++)
-				data.append((const char *)(params + i), sizeof(*params));
-			msg.set_data(data);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint shader;
+        GLenum pname;
+        GLint* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            nsecs_t c0 = systemTime(timeMode);
+            _c->glGetShaderiv(shader, pname, params);
+            msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
+            msg.mutable_data()->assign(reinterpret_cast<const char *>(params), 1 * sizeof(GLint));
+            return 0;
+        }
+    } caller;
+    caller.shader = shader;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(shader);
+    msg.set_arg1(pname);
+    msg.set_arg2(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetShaderiv);
 }
 
 // FIXME: this function has pointers, it should be hand written
 void Debug_glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glGetShaderInfoLog);
-	msg.set_arg0(shader);
-	msg.set_arg1(bufsize);
-	msg.set_arg2(ToInt(length));
-	msg.set_arg3(ToInt(infolog));
-	std::string data;
-	// FIXME: check for pointer usage
-	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->glGetShaderInfoLog(shader, bufsize, length, infolog);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glGetShaderInfoLog);
-			msg.set_has_next_message(false);
-			msg.set_expect_response(expectResponse);
-			data.reserve(strlen(infolog) * sizeof(GLchar));
-			for (unsigned i = 0; i < (strlen(infolog)); i++)
-				data.append((const char *)(infolog + i), sizeof(*infolog));
-			msg.set_data(data);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint shader;
+        GLsizei bufsize;
+        GLsizei* length;
+        GLchar* infolog;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            nsecs_t c0 = systemTime(timeMode);
+            _c->glGetShaderInfoLog(shader, bufsize, length, infolog);
+            msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
+            msg.mutable_data()->assign(reinterpret_cast<const char *>(infolog), strlen(infolog) * sizeof(GLchar));
+            return 0;
+        }
+    } caller;
+    caller.shader = shader;
+    caller.bufsize = bufsize;
+    caller.length = length;
+    caller.infolog = infolog;
+
+    msg.set_arg0(shader);
+    msg.set_arg1(bufsize);
+    msg.set_arg2(ToInt(length));
+    msg.set_arg3(ToInt(infolog));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetShaderInfoLog);
 }
 
 // FIXME: this function has pointers, it should be hand written
 void Debug_glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glGetShaderPrecisionFormat);
-	msg.set_arg0(shadertype);
-	msg.set_arg1(precisiontype);
-	msg.set_arg2(ToInt(range));
-	msg.set_arg3(ToInt(precision));
-	// FIXME: check for pointer usage
-	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->glGetShaderPrecisionFormat(shadertype, precisiontype, range, precision);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glGetShaderPrecisionFormat);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum shadertype;
+        GLenum precisiontype;
+        GLint* range;
+        GLint* precision;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetShaderPrecisionFormat(shadertype, precisiontype, range, precision);
+            return 0;
+        }
+    } caller;
+    caller.shadertype = shadertype;
+    caller.precisiontype = precisiontype;
+    caller.range = range;
+    caller.precision = precision;
+
+    msg.set_arg0(shadertype);
+    msg.set_arg1(precisiontype);
+    msg.set_arg2(ToInt(range));
+    msg.set_arg3(ToInt(precision));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetShaderPrecisionFormat);
 }
 
 // FIXME: this function has pointers, it should be hand written
 void Debug_glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glGetShaderSource);
-	msg.set_arg0(shader);
-	msg.set_arg1(bufsize);
-	msg.set_arg2(ToInt(length));
-	msg.set_arg3(ToInt(source));
-	std::string data;
-	// FIXME: check for pointer usage
-	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->glGetShaderSource(shader, bufsize, length, source);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glGetShaderSource);
-			msg.set_has_next_message(false);
-			msg.set_expect_response(expectResponse);
-			data.reserve(strlen(source) * sizeof(GLchar));
-			for (unsigned i = 0; i < (strlen(source)); i++)
-				data.append((const char *)(source + i), sizeof(*source));
-			msg.set_data(data);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint shader;
+        GLsizei bufsize;
+        GLsizei* length;
+        GLchar* source;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            nsecs_t c0 = systemTime(timeMode);
+            _c->glGetShaderSource(shader, bufsize, length, source);
+            msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
+            msg.mutable_data()->assign(reinterpret_cast<const char *>(source), strlen(source) * sizeof(GLchar));
+            return 0;
+        }
+    } caller;
+    caller.shader = shader;
+    caller.bufsize = bufsize;
+    caller.length = length;
+    caller.source = source;
+
+    msg.set_arg0(shader);
+    msg.set_arg1(bufsize);
+    msg.set_arg2(ToInt(length));
+    msg.set_arg3(ToInt(source));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetShaderSource);
 }
 
 // FIXME: this function has pointers, it should be hand written
 const GLubyte* Debug_glGetString(GLenum name)
 {
-	const GLubyte* ret = 0;
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glGetString);
-	msg.set_arg0(name);
-	// FIXME: check for pointer usage
-	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:
-			ret = _c->glGetString(name);
-			msg.set_ret(ToInt(ret));
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glGetString);
-			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:
-			if (cmd.has_ret())
-				ret = FromInt<const GLubyte*>(cmd.ret());
-			return ret;
-		default:
-			ASSERT(0); //GenerateCall(msg, cmd); 
-			break;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum name;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glGetString(name));
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+    caller.name = name;
+
+    msg.set_arg0(name);
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetString);
+    return reinterpret_cast<const GLubyte*>(ret);
 }
 
 // FIXME: this function has pointers, it should be hand written
 void Debug_glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glGetTexParameterfv);
-	msg.set_arg0(target);
-	msg.set_arg1(pname);
-	msg.set_arg2(ToInt(params));
-	// FIXME: check for pointer usage
-	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->glGetTexParameterfv(target, pname, params);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glGetTexParameterfv);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLenum pname;
+        GLfloat* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetTexParameterfv(target, pname, params);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(target);
+    msg.set_arg1(pname);
+    msg.set_arg2(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetTexParameterfv);
 }
 
 // FIXME: this function has pointers, it should be hand written
 void Debug_glGetTexParameteriv(GLenum target, GLenum pname, GLint* params)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glGetTexParameteriv);
-	msg.set_arg0(target);
-	msg.set_arg1(pname);
-	msg.set_arg2(ToInt(params));
-	// FIXME: check for pointer usage
-	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->glGetTexParameteriv(target, pname, params);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glGetTexParameteriv);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLenum pname;
+        GLint* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetTexParameteriv(target, pname, params);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(target);
+    msg.set_arg1(pname);
+    msg.set_arg2(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetTexParameteriv);
 }
 
 // FIXME: this function has pointers, it should be hand written
 void Debug_glGetUniformfv(GLuint program, GLint location, GLfloat* params)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glGetUniformfv);
-	msg.set_arg0(program);
-	msg.set_arg1(location);
-	msg.set_arg2(ToInt(params));
-	// FIXME: check for pointer usage
-	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->glGetUniformfv(program, location, params);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glGetUniformfv);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint program;
+        GLint location;
+        GLfloat* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetUniformfv(program, location, params);
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+    caller.location = location;
+    caller.params = params;
+
+    msg.set_arg0(program);
+    msg.set_arg1(location);
+    msg.set_arg2(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetUniformfv);
 }
 
 // FIXME: this function has pointers, it should be hand written
 void Debug_glGetUniformiv(GLuint program, GLint location, GLint* params)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glGetUniformiv);
-	msg.set_arg0(program);
-	msg.set_arg1(location);
-	msg.set_arg2(ToInt(params));
-	// FIXME: check for pointer usage
-	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->glGetUniformiv(program, location, params);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glGetUniformiv);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint program;
+        GLint location;
+        GLint* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetUniformiv(program, location, params);
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+    caller.location = location;
+    caller.params = params;
+
+    msg.set_arg0(program);
+    msg.set_arg1(location);
+    msg.set_arg2(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetUniformiv);
 }
 
 int Debug_glGetUniformLocation(GLuint program, const GLchar* name)
 {
-	int ret = 0;
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glGetUniformLocation);
-	msg.set_arg0(program);
-	msg.set_arg1(ToInt(name));
-	std::string data;
-	// FIXME: check for pointer usage
-			data.reserve(strlen(name) * sizeof(GLchar));
-			for (unsigned i = 0; i < (strlen(name)); i++)
-				data.append((const char *)(name + i), sizeof(*name));
-			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:
-			ret = _c->glGetUniformLocation(program, name);
-			msg.set_ret(ToInt(ret));
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glGetUniformLocation);
-			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:
-			if (cmd.has_ret())
-				ret = FromInt<int>(cmd.ret());
-			return ret;
-		default:
-			ASSERT(0); //GenerateCall(msg, cmd); 
-			break;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint program;
+        const GLchar* name;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glGetUniformLocation(program, name));
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+    caller.program = program;
+    caller.name = name;
+
+    msg.set_arg0(program);
+    msg.set_arg1(ToInt(name));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(name), strlen(name) * sizeof(GLchar));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetUniformLocation);
+    return reinterpret_cast<int>(ret);
 }
 
 // FIXME: this function has pointers, it should be hand written
 void Debug_glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glGetVertexAttribfv);
-	msg.set_arg0(index);
-	msg.set_arg1(pname);
-	msg.set_arg2(ToInt(params));
-	// FIXME: check for pointer usage
-	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->glGetVertexAttribfv(index, pname, params);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glGetVertexAttribfv);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint index;
+        GLenum pname;
+        GLfloat* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetVertexAttribfv(index, pname, params);
+            return 0;
+        }
+    } caller;
+    caller.index = index;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(index);
+    msg.set_arg1(pname);
+    msg.set_arg2(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetVertexAttribfv);
 }
 
 // FIXME: this function has pointers, it should be hand written
 void Debug_glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glGetVertexAttribiv);
-	msg.set_arg0(index);
-	msg.set_arg1(pname);
-	msg.set_arg2(ToInt(params));
-	// FIXME: check for pointer usage
-	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->glGetVertexAttribiv(index, pname, params);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glGetVertexAttribiv);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint index;
+        GLenum pname;
+        GLint* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetVertexAttribiv(index, pname, params);
+            return 0;
+        }
+    } caller;
+    caller.index = index;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(index);
+    msg.set_arg1(pname);
+    msg.set_arg2(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetVertexAttribiv);
 }
 
 // FIXME: this function has pointers, it should be hand written
 void Debug_glGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glGetVertexAttribPointerv);
-	msg.set_arg0(index);
-	msg.set_arg1(pname);
-	msg.set_arg2(ToInt(pointer));
-	// FIXME: check for pointer usage
-	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->glGetVertexAttribPointerv(index, pname, pointer);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glGetVertexAttribPointerv);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint index;
+        GLenum pname;
+        GLvoid** pointer;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetVertexAttribPointerv(index, pname, pointer);
+            return 0;
+        }
+    } caller;
+    caller.index = index;
+    caller.pname = pname;
+    caller.pointer = pointer;
+
+    msg.set_arg0(index);
+    msg.set_arg1(pname);
+    msg.set_arg2(ToInt(pointer));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetVertexAttribPointerv);
 }
 
 void Debug_glHint(GLenum target, GLenum mode)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glHint);
-	msg.set_arg0(target);
-	msg.set_arg1(mode);
-	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->glHint(target, mode);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glHint);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLenum mode;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glHint(target, mode);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.mode = mode;
+
+    msg.set_arg0(target);
+    msg.set_arg1(mode);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glHint);
 }
 
 GLboolean Debug_glIsBuffer(GLuint buffer)
 {
-	GLboolean ret = 0;
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glIsBuffer);
-	msg.set_arg0(buffer);
-	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:
-			ret = _c->glIsBuffer(buffer);
-			msg.set_ret(ret);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glIsBuffer);
-			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:
-			if (cmd.has_ret())
-				ret = cmd.ret();
-			return ret;
-		default:
-			ASSERT(0); //GenerateCall(msg, cmd); 
-			break;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint buffer;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glIsBuffer(buffer));
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+    caller.buffer = buffer;
+
+    msg.set_arg0(buffer);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glIsBuffer);
+    return static_cast<GLboolean>(reinterpret_cast<int>(ret));
 }
 
 GLboolean Debug_glIsEnabled(GLenum cap)
 {
-	GLboolean ret = 0;
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glIsEnabled);
-	msg.set_arg0(cap);
-	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:
-			ret = _c->glIsEnabled(cap);
-			msg.set_ret(ret);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glIsEnabled);
-			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:
-			if (cmd.has_ret())
-				ret = cmd.ret();
-			return ret;
-		default:
-			ASSERT(0); //GenerateCall(msg, cmd); 
-			break;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum cap;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glIsEnabled(cap));
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+    caller.cap = cap;
+
+    msg.set_arg0(cap);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glIsEnabled);
+    return static_cast<GLboolean>(reinterpret_cast<int>(ret));
 }
 
 GLboolean Debug_glIsFramebuffer(GLuint framebuffer)
 {
-	GLboolean ret = 0;
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glIsFramebuffer);
-	msg.set_arg0(framebuffer);
-	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:
-			ret = _c->glIsFramebuffer(framebuffer);
-			msg.set_ret(ret);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glIsFramebuffer);
-			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:
-			if (cmd.has_ret())
-				ret = cmd.ret();
-			return ret;
-		default:
-			ASSERT(0); //GenerateCall(msg, cmd); 
-			break;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint framebuffer;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glIsFramebuffer(framebuffer));
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+    caller.framebuffer = framebuffer;
+
+    msg.set_arg0(framebuffer);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glIsFramebuffer);
+    return static_cast<GLboolean>(reinterpret_cast<int>(ret));
 }
 
 GLboolean Debug_glIsProgram(GLuint program)
 {
-	GLboolean ret = 0;
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glIsProgram);
-	msg.set_arg0(program);
-	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:
-			ret = _c->glIsProgram(program);
-			msg.set_ret(ret);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glIsProgram);
-			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:
-			if (cmd.has_ret())
-				ret = cmd.ret();
-			return ret;
-		default:
-			ASSERT(0); //GenerateCall(msg, cmd); 
-			break;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint program;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glIsProgram(program));
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+    caller.program = program;
+
+    msg.set_arg0(program);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glIsProgram);
+    return static_cast<GLboolean>(reinterpret_cast<int>(ret));
 }
 
 GLboolean Debug_glIsRenderbuffer(GLuint renderbuffer)
 {
-	GLboolean ret = 0;
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glIsRenderbuffer);
-	msg.set_arg0(renderbuffer);
-	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:
-			ret = _c->glIsRenderbuffer(renderbuffer);
-			msg.set_ret(ret);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glIsRenderbuffer);
-			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:
-			if (cmd.has_ret())
-				ret = cmd.ret();
-			return ret;
-		default:
-			ASSERT(0); //GenerateCall(msg, cmd); 
-			break;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint renderbuffer;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glIsRenderbuffer(renderbuffer));
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+    caller.renderbuffer = renderbuffer;
+
+    msg.set_arg0(renderbuffer);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glIsRenderbuffer);
+    return static_cast<GLboolean>(reinterpret_cast<int>(ret));
 }
 
 GLboolean Debug_glIsShader(GLuint shader)
 {
-	GLboolean ret = 0;
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glIsShader);
-	msg.set_arg0(shader);
-	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:
-			ret = _c->glIsShader(shader);
-			msg.set_ret(ret);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glIsShader);
-			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:
-			if (cmd.has_ret())
-				ret = cmd.ret();
-			return ret;
-		default:
-			ASSERT(0); //GenerateCall(msg, cmd); 
-			break;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint shader;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glIsShader(shader));
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+    caller.shader = shader;
+
+    msg.set_arg0(shader);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glIsShader);
+    return static_cast<GLboolean>(reinterpret_cast<int>(ret));
 }
 
 GLboolean Debug_glIsTexture(GLuint texture)
 {
-	GLboolean ret = 0;
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glIsTexture);
-	msg.set_arg0(texture);
-	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:
-			ret = _c->glIsTexture(texture);
-			msg.set_ret(ret);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glIsTexture);
-			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:
-			if (cmd.has_ret())
-				ret = cmd.ret();
-			return ret;
-		default:
-			ASSERT(0); //GenerateCall(msg, cmd); 
-			break;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint texture;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glIsTexture(texture));
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+    caller.texture = texture;
+
+    msg.set_arg0(texture);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glIsTexture);
+    return static_cast<GLboolean>(reinterpret_cast<int>(ret));
 }
 
 void Debug_glLineWidth(GLfloat width)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glLineWidth);
-	msg.set_arg0(ToInt(width));
-	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->glLineWidth(width);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glLineWidth);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLfloat width;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glLineWidth(width);
+            return 0;
+        }
+    } caller;
+    caller.width = width;
+
+    msg.set_arg0(ToInt(width));
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glLineWidth);
 }
 
 void Debug_glLinkProgram(GLuint program)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glLinkProgram);
-	msg.set_arg0(program);
-	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->glLinkProgram(program);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glLinkProgram);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint program;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glLinkProgram(program);
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+
+    msg.set_arg0(program);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glLinkProgram);
 }
 
 void Debug_glPixelStorei(GLenum pname, GLint param)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glPixelStorei);
-	msg.set_arg0(pname);
-	msg.set_arg1(param);
-	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->glPixelStorei(pname, param);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glPixelStorei);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum pname;
+        GLint param;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glPixelStorei(pname, param);
+            return 0;
+        }
+    } caller;
+    caller.pname = pname;
+    caller.param = param;
+
+    msg.set_arg0(pname);
+    msg.set_arg1(param);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glPixelStorei);
 }
 
 void Debug_glPolygonOffset(GLfloat factor, GLfloat units)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glPolygonOffset);
-	msg.set_arg0(ToInt(factor));
-	msg.set_arg1(ToInt(units));
-	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->glPolygonOffset(factor, units);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glPolygonOffset);
-			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;
-		}
-	}
-}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLfloat factor;
+        GLfloat units;
 
-// FIXME: this function has pointers, it should be hand written
-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_has_next_message(true);
-	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(ToInt(pixels));
-	// FIXME: check for pointer usage
-	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->glReadPixels(x, y, width, height, format, type, pixels);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glReadPixels);
-			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;
-		}
-	}
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glPolygonOffset(factor, units);
+            return 0;
+        }
+    } caller;
+    caller.factor = factor;
+    caller.units = units;
+
+    msg.set_arg0(ToInt(factor));
+    msg.set_arg1(ToInt(units));
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glPolygonOffset);
 }
 
 void Debug_glReleaseShaderCompiler(void)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glReleaseShaderCompiler);
-	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->glReleaseShaderCompiler();
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glReleaseShaderCompiler);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glReleaseShaderCompiler();
+            return 0;
+        }
+    } caller;
+
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glReleaseShaderCompiler);
 }
 
 void Debug_glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glRenderbufferStorage);
-	msg.set_arg0(target);
-	msg.set_arg1(internalformat);
-	msg.set_arg2(width);
-	msg.set_arg3(height);
-	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->glRenderbufferStorage(target, internalformat, width, height);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glRenderbufferStorage);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLenum internalformat;
+        GLsizei width;
+        GLsizei height;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glRenderbufferStorage(target, internalformat, width, height);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.internalformat = internalformat;
+    caller.width = width;
+    caller.height = height;
+
+    msg.set_arg0(target);
+    msg.set_arg1(internalformat);
+    msg.set_arg2(width);
+    msg.set_arg3(height);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glRenderbufferStorage);
 }
 
 void Debug_glSampleCoverage(GLclampf value, GLboolean invert)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glSampleCoverage);
-	msg.set_arg0(ToInt(value));
-	msg.set_arg1(invert);
-	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->glSampleCoverage(value, invert);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glSampleCoverage);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLclampf value;
+        GLboolean invert;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glSampleCoverage(value, invert);
+            return 0;
+        }
+    } caller;
+    caller.value = value;
+    caller.invert = invert;
+
+    msg.set_arg0(ToInt(value));
+    msg.set_arg1(invert);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glSampleCoverage);
 }
 
 void Debug_glScissor(GLint x, GLint y, GLsizei width, GLsizei height)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glScissor);
-	msg.set_arg0(x);
-	msg.set_arg1(y);
-	msg.set_arg2(width);
-	msg.set_arg3(height);
-	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->glScissor(x, y, width, height);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glScissor);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint x;
+        GLint y;
+        GLsizei width;
+        GLsizei height;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glScissor(x, y, width, height);
+            return 0;
+        }
+    } caller;
+    caller.x = x;
+    caller.y = y;
+    caller.width = width;
+    caller.height = height;
+
+    msg.set_arg0(x);
+    msg.set_arg1(y);
+    msg.set_arg2(width);
+    msg.set_arg3(height);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glScissor);
 }
 
 // FIXME: this function has pointers, it should be hand written
 void Debug_glShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei 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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glShaderBinary);
-	msg.set_arg0(n);
-	msg.set_arg1(ToInt(shaders));
-	msg.set_arg2(binaryformat);
-	msg.set_arg3(ToInt(binary));
-	msg.set_arg4(length);
-	// FIXME: check for pointer usage
-	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->glShaderBinary(n, shaders, binaryformat, binary, length);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glShaderBinary);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLsizei n;
+        const GLuint* shaders;
+        GLenum binaryformat;
+        const GLvoid* binary;
+        GLsizei length;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glShaderBinary(n, shaders, binaryformat, binary, length);
+            return 0;
+        }
+    } caller;
+    caller.n = n;
+    caller.shaders = shaders;
+    caller.binaryformat = binaryformat;
+    caller.binary = binary;
+    caller.length = length;
+
+    msg.set_arg0(n);
+    msg.set_arg1(ToInt(shaders));
+    msg.set_arg2(binaryformat);
+    msg.set_arg3(ToInt(binary));
+    msg.set_arg4(length);
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glShaderBinary);
 }
 
 void Debug_glStencilFunc(GLenum func, GLint ref, GLuint mask)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glStencilFunc);
-	msg.set_arg0(func);
-	msg.set_arg1(ref);
-	msg.set_arg2(mask);
-	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->glStencilFunc(func, ref, mask);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glStencilFunc);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum func;
+        GLint ref;
+        GLuint mask;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glStencilFunc(func, ref, mask);
+            return 0;
+        }
+    } caller;
+    caller.func = func;
+    caller.ref = ref;
+    caller.mask = mask;
+
+    msg.set_arg0(func);
+    msg.set_arg1(ref);
+    msg.set_arg2(mask);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glStencilFunc);
 }
 
 void Debug_glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glStencilFuncSeparate);
-	msg.set_arg0(face);
-	msg.set_arg1(func);
-	msg.set_arg2(ref);
-	msg.set_arg3(mask);
-	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->glStencilFuncSeparate(face, func, ref, mask);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glStencilFuncSeparate);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum face;
+        GLenum func;
+        GLint ref;
+        GLuint mask;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glStencilFuncSeparate(face, func, ref, mask);
+            return 0;
+        }
+    } caller;
+    caller.face = face;
+    caller.func = func;
+    caller.ref = ref;
+    caller.mask = mask;
+
+    msg.set_arg0(face);
+    msg.set_arg1(func);
+    msg.set_arg2(ref);
+    msg.set_arg3(mask);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glStencilFuncSeparate);
 }
 
 void Debug_glStencilMask(GLuint mask)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glStencilMask);
-	msg.set_arg0(mask);
-	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->glStencilMask(mask);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glStencilMask);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint mask;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glStencilMask(mask);
+            return 0;
+        }
+    } caller;
+    caller.mask = mask;
+
+    msg.set_arg0(mask);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glStencilMask);
 }
 
 void Debug_glStencilMaskSeparate(GLenum face, GLuint mask)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glStencilMaskSeparate);
-	msg.set_arg0(face);
-	msg.set_arg1(mask);
-	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->glStencilMaskSeparate(face, mask);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glStencilMaskSeparate);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum face;
+        GLuint mask;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glStencilMaskSeparate(face, mask);
+            return 0;
+        }
+    } caller;
+    caller.face = face;
+    caller.mask = mask;
+
+    msg.set_arg0(face);
+    msg.set_arg1(mask);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glStencilMaskSeparate);
 }
 
 void Debug_glStencilOp(GLenum fail, GLenum zfail, GLenum zpass)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glStencilOp);
-	msg.set_arg0(fail);
-	msg.set_arg1(zfail);
-	msg.set_arg2(zpass);
-	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->glStencilOp(fail, zfail, zpass);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glStencilOp);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum fail;
+        GLenum zfail;
+        GLenum zpass;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glStencilOp(fail, zfail, zpass);
+            return 0;
+        }
+    } caller;
+    caller.fail = fail;
+    caller.zfail = zfail;
+    caller.zpass = zpass;
+
+    msg.set_arg0(fail);
+    msg.set_arg1(zfail);
+    msg.set_arg2(zpass);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glStencilOp);
 }
 
 void Debug_glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glStencilOpSeparate);
-	msg.set_arg0(face);
-	msg.set_arg1(fail);
-	msg.set_arg2(zfail);
-	msg.set_arg3(zpass);
-	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->glStencilOpSeparate(face, fail, zfail, zpass);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glStencilOpSeparate);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum face;
+        GLenum fail;
+        GLenum zfail;
+        GLenum zpass;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glStencilOpSeparate(face, fail, zfail, zpass);
+            return 0;
+        }
+    } caller;
+    caller.face = face;
+    caller.fail = fail;
+    caller.zfail = zfail;
+    caller.zpass = zpass;
+
+    msg.set_arg0(face);
+    msg.set_arg1(fail);
+    msg.set_arg2(zfail);
+    msg.set_arg3(zpass);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glStencilOpSeparate);
 }
 
 void Debug_glTexParameterf(GLenum target, GLenum pname, GLfloat param)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glTexParameterf);
-	msg.set_arg0(target);
-	msg.set_arg1(pname);
-	msg.set_arg2(ToInt(param));
-	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->glTexParameterf(target, pname, param);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glTexParameterf);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLenum pname;
+        GLfloat param;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glTexParameterf(target, pname, param);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.pname = pname;
+    caller.param = param;
+
+    msg.set_arg0(target);
+    msg.set_arg1(pname);
+    msg.set_arg2(ToInt(param));
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glTexParameterf);
 }
 
 // FIXME: this function has pointers, it should be hand written
 void Debug_glTexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glTexParameterfv);
-	msg.set_arg0(target);
-	msg.set_arg1(pname);
-	msg.set_arg2(ToInt(params));
-	// FIXME: check for pointer usage
-	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->glTexParameterfv(target, pname, params);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glTexParameterfv);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLenum pname;
+        const GLfloat* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glTexParameterfv(target, pname, params);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(target);
+    msg.set_arg1(pname);
+    msg.set_arg2(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glTexParameterfv);
 }
 
 void Debug_glTexParameteri(GLenum target, GLenum pname, GLint param)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glTexParameteri);
-	msg.set_arg0(target);
-	msg.set_arg1(pname);
-	msg.set_arg2(param);
-	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->glTexParameteri(target, pname, param);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glTexParameteri);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLenum pname;
+        GLint param;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glTexParameteri(target, pname, param);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.pname = pname;
+    caller.param = param;
+
+    msg.set_arg0(target);
+    msg.set_arg1(pname);
+    msg.set_arg2(param);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glTexParameteri);
 }
 
 // FIXME: this function has pointers, it should be hand written
 void Debug_glTexParameteriv(GLenum target, GLenum pname, const GLint* params)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glTexParameteriv);
-	msg.set_arg0(target);
-	msg.set_arg1(pname);
-	msg.set_arg2(ToInt(params));
-	// FIXME: check for pointer usage
-	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->glTexParameteriv(target, pname, params);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glTexParameteriv);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLenum pname;
+        const GLint* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glTexParameteriv(target, pname, params);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(target);
+    msg.set_arg1(pname);
+    msg.set_arg2(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glTexParameteriv);
 }
 
 void Debug_glUniform1f(GLint location, GLfloat x)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glUniform1f);
-	msg.set_arg0(location);
-	msg.set_arg1(ToInt(x));
-	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->glUniform1f(location, x);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glUniform1f);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint location;
+        GLfloat x;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform1f(location, x);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.x = x;
+
+    msg.set_arg0(location);
+    msg.set_arg1(ToInt(x));
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glUniform1f);
 }
 
 void Debug_glUniform1fv(GLint location, GLsizei count, const GLfloat* v)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glUniform1fv);
-	msg.set_arg0(location);
-	msg.set_arg1(count);
-	msg.set_arg2(ToInt(v));
-	std::string data;
-	// FIXME: check for pointer usage
-			data.reserve(1*count * sizeof(GLfloat));
-			for (unsigned i = 0; i < (1*count); i++)
-				data.append((const char *)(v + i), sizeof(*v));
-			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->glUniform1fv(location, count, v);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glUniform1fv);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint location;
+        GLsizei count;
+        const GLfloat* v;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform1fv(location, count, v);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.count = count;
+    caller.v = v;
+
+    msg.set_arg0(location);
+    msg.set_arg1(count);
+    msg.set_arg2(ToInt(v));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(v), 1*count * sizeof(GLfloat));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glUniform1fv);
 }
 
 void Debug_glUniform1i(GLint location, GLint x)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glUniform1i);
-	msg.set_arg0(location);
-	msg.set_arg1(x);
-	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->glUniform1i(location, x);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glUniform1i);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint location;
+        GLint x;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform1i(location, x);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.x = x;
+
+    msg.set_arg0(location);
+    msg.set_arg1(x);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glUniform1i);
 }
 
 void Debug_glUniform1iv(GLint location, GLsizei count, const GLint* v)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glUniform1iv);
-	msg.set_arg0(location);
-	msg.set_arg1(count);
-	msg.set_arg2(ToInt(v));
-	std::string data;
-	// FIXME: check for pointer usage
-			data.reserve(1*count * sizeof(GLint));
-			for (unsigned i = 0; i < (1*count); i++)
-				data.append((const char *)(v + i), sizeof(*v));
-			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->glUniform1iv(location, count, v);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glUniform1iv);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint location;
+        GLsizei count;
+        const GLint* v;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform1iv(location, count, v);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.count = count;
+    caller.v = v;
+
+    msg.set_arg0(location);
+    msg.set_arg1(count);
+    msg.set_arg2(ToInt(v));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(v), 1*count * sizeof(GLint));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glUniform1iv);
 }
 
 void Debug_glUniform2f(GLint location, GLfloat x, GLfloat y)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glUniform2f);
-	msg.set_arg0(location);
-	msg.set_arg1(ToInt(x));
-	msg.set_arg2(ToInt(y));
-	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->glUniform2f(location, x, y);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glUniform2f);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint location;
+        GLfloat x;
+        GLfloat y;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform2f(location, x, y);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.x = x;
+    caller.y = y;
+
+    msg.set_arg0(location);
+    msg.set_arg1(ToInt(x));
+    msg.set_arg2(ToInt(y));
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glUniform2f);
 }
 
 void Debug_glUniform2fv(GLint location, GLsizei count, const GLfloat* v)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glUniform2fv);
-	msg.set_arg0(location);
-	msg.set_arg1(count);
-	msg.set_arg2(ToInt(v));
-	std::string data;
-	// FIXME: check for pointer usage
-			data.reserve(2*count * sizeof(GLfloat));
-			for (unsigned i = 0; i < (2*count); i++)
-				data.append((const char *)(v + i), sizeof(*v));
-			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->glUniform2fv(location, count, v);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glUniform2fv);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint location;
+        GLsizei count;
+        const GLfloat* v;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform2fv(location, count, v);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.count = count;
+    caller.v = v;
+
+    msg.set_arg0(location);
+    msg.set_arg1(count);
+    msg.set_arg2(ToInt(v));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(v), 2*count * sizeof(GLfloat));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glUniform2fv);
 }
 
 void Debug_glUniform2i(GLint location, GLint x, GLint y)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glUniform2i);
-	msg.set_arg0(location);
-	msg.set_arg1(x);
-	msg.set_arg2(y);
-	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->glUniform2i(location, x, y);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glUniform2i);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint location;
+        GLint x;
+        GLint y;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform2i(location, x, y);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.x = x;
+    caller.y = y;
+
+    msg.set_arg0(location);
+    msg.set_arg1(x);
+    msg.set_arg2(y);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glUniform2i);
 }
 
 void Debug_glUniform2iv(GLint location, GLsizei count, const GLint* v)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glUniform2iv);
-	msg.set_arg0(location);
-	msg.set_arg1(count);
-	msg.set_arg2(ToInt(v));
-	std::string data;
-	// FIXME: check for pointer usage
-			data.reserve(2*count * sizeof(GLint));
-			for (unsigned i = 0; i < (2*count); i++)
-				data.append((const char *)(v + i), sizeof(*v));
-			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->glUniform2iv(location, count, v);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glUniform2iv);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint location;
+        GLsizei count;
+        const GLint* v;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform2iv(location, count, v);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.count = count;
+    caller.v = v;
+
+    msg.set_arg0(location);
+    msg.set_arg1(count);
+    msg.set_arg2(ToInt(v));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(v), 2*count * sizeof(GLint));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glUniform2iv);
 }
 
 void Debug_glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glUniform3f);
-	msg.set_arg0(location);
-	msg.set_arg1(ToInt(x));
-	msg.set_arg2(ToInt(y));
-	msg.set_arg3(ToInt(z));
-	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->glUniform3f(location, x, y, z);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glUniform3f);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint location;
+        GLfloat x;
+        GLfloat y;
+        GLfloat z;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform3f(location, x, y, z);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.x = x;
+    caller.y = y;
+    caller.z = z;
+
+    msg.set_arg0(location);
+    msg.set_arg1(ToInt(x));
+    msg.set_arg2(ToInt(y));
+    msg.set_arg3(ToInt(z));
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glUniform3f);
 }
 
 void Debug_glUniform3fv(GLint location, GLsizei count, const GLfloat* v)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glUniform3fv);
-	msg.set_arg0(location);
-	msg.set_arg1(count);
-	msg.set_arg2(ToInt(v));
-	std::string data;
-	// FIXME: check for pointer usage
-			data.reserve(3*count * sizeof(GLfloat));
-			for (unsigned i = 0; i < (3*count); i++)
-				data.append((const char *)(v + i), sizeof(*v));
-			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->glUniform3fv(location, count, v);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glUniform3fv);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint location;
+        GLsizei count;
+        const GLfloat* v;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform3fv(location, count, v);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.count = count;
+    caller.v = v;
+
+    msg.set_arg0(location);
+    msg.set_arg1(count);
+    msg.set_arg2(ToInt(v));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(v), 3*count * sizeof(GLfloat));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glUniform3fv);
 }
 
 void Debug_glUniform3i(GLint location, GLint x, GLint y, GLint z)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glUniform3i);
-	msg.set_arg0(location);
-	msg.set_arg1(x);
-	msg.set_arg2(y);
-	msg.set_arg3(z);
-	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->glUniform3i(location, x, y, z);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glUniform3i);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint location;
+        GLint x;
+        GLint y;
+        GLint z;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform3i(location, x, y, z);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.x = x;
+    caller.y = y;
+    caller.z = z;
+
+    msg.set_arg0(location);
+    msg.set_arg1(x);
+    msg.set_arg2(y);
+    msg.set_arg3(z);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glUniform3i);
 }
 
 void Debug_glUniform3iv(GLint location, GLsizei count, const GLint* v)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glUniform3iv);
-	msg.set_arg0(location);
-	msg.set_arg1(count);
-	msg.set_arg2(ToInt(v));
-	std::string data;
-	// FIXME: check for pointer usage
-			data.reserve(3*count * sizeof(GLint));
-			for (unsigned i = 0; i < (3*count); i++)
-				data.append((const char *)(v + i), sizeof(*v));
-			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->glUniform3iv(location, count, v);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glUniform3iv);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint location;
+        GLsizei count;
+        const GLint* v;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform3iv(location, count, v);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.count = count;
+    caller.v = v;
+
+    msg.set_arg0(location);
+    msg.set_arg1(count);
+    msg.set_arg2(ToInt(v));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(v), 3*count * sizeof(GLint));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glUniform3iv);
 }
 
 void Debug_glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glUniform4f);
-	msg.set_arg0(location);
-	msg.set_arg1(ToInt(x));
-	msg.set_arg2(ToInt(y));
-	msg.set_arg3(ToInt(z));
-	msg.set_arg4(ToInt(w));
-	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->glUniform4f(location, x, y, z, w);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glUniform4f);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint location;
+        GLfloat x;
+        GLfloat y;
+        GLfloat z;
+        GLfloat w;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform4f(location, x, y, z, w);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.x = x;
+    caller.y = y;
+    caller.z = z;
+    caller.w = w;
+
+    msg.set_arg0(location);
+    msg.set_arg1(ToInt(x));
+    msg.set_arg2(ToInt(y));
+    msg.set_arg3(ToInt(z));
+    msg.set_arg4(ToInt(w));
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glUniform4f);
 }
 
 void Debug_glUniform4fv(GLint location, GLsizei count, const GLfloat* v)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glUniform4fv);
-	msg.set_arg0(location);
-	msg.set_arg1(count);
-	msg.set_arg2(ToInt(v));
-	std::string data;
-	// FIXME: check for pointer usage
-			data.reserve(4*count * sizeof(GLfloat));
-			for (unsigned i = 0; i < (4*count); i++)
-				data.append((const char *)(v + i), sizeof(*v));
-			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->glUniform4fv(location, count, v);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glUniform4fv);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint location;
+        GLsizei count;
+        const GLfloat* v;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform4fv(location, count, v);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.count = count;
+    caller.v = v;
+
+    msg.set_arg0(location);
+    msg.set_arg1(count);
+    msg.set_arg2(ToInt(v));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(v), 4*count * sizeof(GLfloat));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glUniform4fv);
 }
 
 void Debug_glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glUniform4i);
-	msg.set_arg0(location);
-	msg.set_arg1(x);
-	msg.set_arg2(y);
-	msg.set_arg3(z);
-	msg.set_arg4(w);
-	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->glUniform4i(location, x, y, z, w);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glUniform4i);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint location;
+        GLint x;
+        GLint y;
+        GLint z;
+        GLint w;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform4i(location, x, y, z, w);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.x = x;
+    caller.y = y;
+    caller.z = z;
+    caller.w = w;
+
+    msg.set_arg0(location);
+    msg.set_arg1(x);
+    msg.set_arg2(y);
+    msg.set_arg3(z);
+    msg.set_arg4(w);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glUniform4i);
 }
 
 void Debug_glUniform4iv(GLint location, GLsizei count, const GLint* v)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glUniform4iv);
-	msg.set_arg0(location);
-	msg.set_arg1(count);
-	msg.set_arg2(ToInt(v));
-	std::string data;
-	// FIXME: check for pointer usage
-			data.reserve(4*count * sizeof(GLint));
-			for (unsigned i = 0; i < (4*count); i++)
-				data.append((const char *)(v + i), sizeof(*v));
-			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->glUniform4iv(location, count, v);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glUniform4iv);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint location;
+        GLsizei count;
+        const GLint* v;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform4iv(location, count, v);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.count = count;
+    caller.v = v;
+
+    msg.set_arg0(location);
+    msg.set_arg1(count);
+    msg.set_arg2(ToInt(v));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(v), 4*count * sizeof(GLint));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glUniform4iv);
 }
 
 void Debug_glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glUniformMatrix2fv);
-	msg.set_arg0(location);
-	msg.set_arg1(count);
-	msg.set_arg2(transpose);
-	msg.set_arg3(ToInt(value));
-	std::string data;
-	// FIXME: check for pointer usage
-			data.reserve(4*count * sizeof(GLfloat));
-			for (unsigned i = 0; i < (4*count); i++)
-				data.append((const char *)(value + i), sizeof(*value));
-			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->glUniformMatrix2fv(location, count, transpose, value);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glUniformMatrix2fv);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint location;
+        GLsizei count;
+        GLboolean transpose;
+        const GLfloat* value;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniformMatrix2fv(location, count, transpose, value);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.count = count;
+    caller.transpose = transpose;
+    caller.value = value;
+
+    msg.set_arg0(location);
+    msg.set_arg1(count);
+    msg.set_arg2(transpose);
+    msg.set_arg3(ToInt(value));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(value), 4*count * sizeof(GLfloat));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glUniformMatrix2fv);
 }
 
 void Debug_glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glUniformMatrix3fv);
-	msg.set_arg0(location);
-	msg.set_arg1(count);
-	msg.set_arg2(transpose);
-	msg.set_arg3(ToInt(value));
-	std::string data;
-	// FIXME: check for pointer usage
-			data.reserve(9*count * sizeof(GLfloat));
-			for (unsigned i = 0; i < (9*count); i++)
-				data.append((const char *)(value + i), sizeof(*value));
-			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->glUniformMatrix3fv(location, count, transpose, value);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glUniformMatrix3fv);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint location;
+        GLsizei count;
+        GLboolean transpose;
+        const GLfloat* value;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniformMatrix3fv(location, count, transpose, value);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.count = count;
+    caller.transpose = transpose;
+    caller.value = value;
+
+    msg.set_arg0(location);
+    msg.set_arg1(count);
+    msg.set_arg2(transpose);
+    msg.set_arg3(ToInt(value));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(value), 9*count * sizeof(GLfloat));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glUniformMatrix3fv);
 }
 
 void Debug_glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glUniformMatrix4fv);
-	msg.set_arg0(location);
-	msg.set_arg1(count);
-	msg.set_arg2(transpose);
-	msg.set_arg3(ToInt(value));
-	std::string data;
-	// FIXME: check for pointer usage
-			data.reserve(16*count * sizeof(GLfloat));
-			for (unsigned i = 0; i < (16*count); i++)
-				data.append((const char *)(value + i), sizeof(*value));
-			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->glUniformMatrix4fv(location, count, transpose, value);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glUniformMatrix4fv);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint location;
+        GLsizei count;
+        GLboolean transpose;
+        const GLfloat* value;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniformMatrix4fv(location, count, transpose, value);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.count = count;
+    caller.transpose = transpose;
+    caller.value = value;
+
+    msg.set_arg0(location);
+    msg.set_arg1(count);
+    msg.set_arg2(transpose);
+    msg.set_arg3(ToInt(value));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(value), 16*count * sizeof(GLfloat));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glUniformMatrix4fv);
 }
 
 void Debug_glUseProgram(GLuint program)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glUseProgram);
-	msg.set_arg0(program);
-	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->glUseProgram(program);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glUseProgram);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint program;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUseProgram(program);
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+
+    msg.set_arg0(program);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glUseProgram);
 }
 
 void Debug_glValidateProgram(GLuint program)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glValidateProgram);
-	msg.set_arg0(program);
-	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->glValidateProgram(program);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glValidateProgram);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint program;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glValidateProgram(program);
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+
+    msg.set_arg0(program);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glValidateProgram);
 }
 
 void Debug_glVertexAttrib1f(GLuint indx, GLfloat x)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glVertexAttrib1f);
-	msg.set_arg0(indx);
-	msg.set_arg1(ToInt(x));
-	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->glVertexAttrib1f(indx, x);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glVertexAttrib1f);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint indx;
+        GLfloat x;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glVertexAttrib1f(indx, x);
+            return 0;
+        }
+    } caller;
+    caller.indx = indx;
+    caller.x = x;
+
+    msg.set_arg0(indx);
+    msg.set_arg1(ToInt(x));
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glVertexAttrib1f);
 }
 
 void Debug_glVertexAttrib1fv(GLuint indx, const GLfloat* values)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glVertexAttrib1fv);
-	msg.set_arg0(indx);
-	msg.set_arg1(ToInt(values));
-	std::string data;
-	// FIXME: check for pointer usage
-			data.reserve(1 * sizeof(GLfloat));
-			for (unsigned i = 0; i < (1); i++)
-				data.append((const char *)(values + i), sizeof(*values));
-			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->glVertexAttrib1fv(indx, values);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glVertexAttrib1fv);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint indx;
+        const GLfloat* values;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glVertexAttrib1fv(indx, values);
+            return 0;
+        }
+    } caller;
+    caller.indx = indx;
+    caller.values = values;
+
+    msg.set_arg0(indx);
+    msg.set_arg1(ToInt(values));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(values), 1 * sizeof(GLfloat));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glVertexAttrib1fv);
 }
 
 void Debug_glVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glVertexAttrib2f);
-	msg.set_arg0(indx);
-	msg.set_arg1(ToInt(x));
-	msg.set_arg2(ToInt(y));
-	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->glVertexAttrib2f(indx, x, y);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glVertexAttrib2f);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint indx;
+        GLfloat x;
+        GLfloat y;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glVertexAttrib2f(indx, x, y);
+            return 0;
+        }
+    } caller;
+    caller.indx = indx;
+    caller.x = x;
+    caller.y = y;
+
+    msg.set_arg0(indx);
+    msg.set_arg1(ToInt(x));
+    msg.set_arg2(ToInt(y));
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glVertexAttrib2f);
 }
 
 void Debug_glVertexAttrib2fv(GLuint indx, const GLfloat* values)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glVertexAttrib2fv);
-	msg.set_arg0(indx);
-	msg.set_arg1(ToInt(values));
-	std::string data;
-	// FIXME: check for pointer usage
-			data.reserve(2 * sizeof(GLfloat));
-			for (unsigned i = 0; i < (2); i++)
-				data.append((const char *)(values + i), sizeof(*values));
-			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->glVertexAttrib2fv(indx, values);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glVertexAttrib2fv);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint indx;
+        const GLfloat* values;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glVertexAttrib2fv(indx, values);
+            return 0;
+        }
+    } caller;
+    caller.indx = indx;
+    caller.values = values;
+
+    msg.set_arg0(indx);
+    msg.set_arg1(ToInt(values));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(values), 2 * sizeof(GLfloat));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glVertexAttrib2fv);
 }
 
 void Debug_glVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glVertexAttrib3f);
-	msg.set_arg0(indx);
-	msg.set_arg1(ToInt(x));
-	msg.set_arg2(ToInt(y));
-	msg.set_arg3(ToInt(z));
-	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->glVertexAttrib3f(indx, x, y, z);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glVertexAttrib3f);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint indx;
+        GLfloat x;
+        GLfloat y;
+        GLfloat z;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glVertexAttrib3f(indx, x, y, z);
+            return 0;
+        }
+    } caller;
+    caller.indx = indx;
+    caller.x = x;
+    caller.y = y;
+    caller.z = z;
+
+    msg.set_arg0(indx);
+    msg.set_arg1(ToInt(x));
+    msg.set_arg2(ToInt(y));
+    msg.set_arg3(ToInt(z));
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glVertexAttrib3f);
 }
 
 void Debug_glVertexAttrib3fv(GLuint indx, const GLfloat* values)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glVertexAttrib3fv);
-	msg.set_arg0(indx);
-	msg.set_arg1(ToInt(values));
-	std::string data;
-	// FIXME: check for pointer usage
-			data.reserve(3 * sizeof(GLfloat));
-			for (unsigned i = 0; i < (3); i++)
-				data.append((const char *)(values + i), sizeof(*values));
-			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->glVertexAttrib3fv(indx, values);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glVertexAttrib3fv);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint indx;
+        const GLfloat* values;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glVertexAttrib3fv(indx, values);
+            return 0;
+        }
+    } caller;
+    caller.indx = indx;
+    caller.values = values;
+
+    msg.set_arg0(indx);
+    msg.set_arg1(ToInt(values));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(values), 3 * sizeof(GLfloat));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glVertexAttrib3fv);
 }
 
 void Debug_glVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glVertexAttrib4f);
-	msg.set_arg0(indx);
-	msg.set_arg1(ToInt(x));
-	msg.set_arg2(ToInt(y));
-	msg.set_arg3(ToInt(z));
-	msg.set_arg4(ToInt(w));
-	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->glVertexAttrib4f(indx, x, y, z, w);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glVertexAttrib4f);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint indx;
+        GLfloat x;
+        GLfloat y;
+        GLfloat z;
+        GLfloat w;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glVertexAttrib4f(indx, x, y, z, w);
+            return 0;
+        }
+    } caller;
+    caller.indx = indx;
+    caller.x = x;
+    caller.y = y;
+    caller.z = z;
+    caller.w = w;
+
+    msg.set_arg0(indx);
+    msg.set_arg1(ToInt(x));
+    msg.set_arg2(ToInt(y));
+    msg.set_arg3(ToInt(z));
+    msg.set_arg4(ToInt(w));
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glVertexAttrib4f);
 }
 
 void Debug_glVertexAttrib4fv(GLuint indx, const GLfloat* values)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glVertexAttrib4fv);
-	msg.set_arg0(indx);
-	msg.set_arg1(ToInt(values));
-	std::string data;
-	// FIXME: check for pointer usage
-			data.reserve(4 * sizeof(GLfloat));
-			for (unsigned i = 0; i < (4); i++)
-				data.append((const char *)(values + i), sizeof(*values));
-			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->glVertexAttrib4fv(indx, values);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glVertexAttrib4fv);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint indx;
+        const GLfloat* values;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glVertexAttrib4fv(indx, values);
+            return 0;
+        }
+    } caller;
+    caller.indx = indx;
+    caller.values = values;
+
+    msg.set_arg0(indx);
+    msg.set_arg1(ToInt(values));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(values), 4 * sizeof(GLfloat));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glVertexAttrib4fv);
 }
 
 // FIXME: this function has pointers, it should be hand written
 void Debug_glVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glVertexAttribPointer);
-	msg.set_arg0(indx);
-	msg.set_arg1(size);
-	msg.set_arg2(type);
-	msg.set_arg3(normalized);
-	msg.set_arg4(stride);
-	msg.set_arg5(ToInt(ptr));
-	// FIXME: check for pointer usage
-	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->glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glVertexAttribPointer);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint indx;
+        GLint size;
+        GLenum type;
+        GLboolean normalized;
+        GLsizei stride;
+        const GLvoid* ptr;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
+            return 0;
+        }
+    } caller;
+    caller.indx = indx;
+    caller.size = size;
+    caller.type = type;
+    caller.normalized = normalized;
+    caller.stride = stride;
+    caller.ptr = ptr;
+
+    msg.set_arg0(indx);
+    msg.set_arg1(size);
+    msg.set_arg2(type);
+    msg.set_arg3(normalized);
+    msg.set_arg4(stride);
+    msg.set_arg5(ToInt(ptr));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glVertexAttribPointer);
 }
 
 void Debug_glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
 {
-	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);
-	const bool expectResponse = false;
-	msg.set_expect_response(expectResponse);
-	msg.set_function(GLESv2Debugger::Message_Function_glViewport);
-	msg.set_arg0(x);
-	msg.set_arg1(y);
-	msg.set_arg2(width);
-	msg.set_arg3(height);
-	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->glViewport(x, y, width, height);
-			msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC);
-			msg.set_context_id(0);
-			msg.set_function(GLESv2Debugger::Message_Function_glViewport);
-			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;
-		}
-	}
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint x;
+        GLint y;
+        GLsizei width;
+        GLsizei height;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glViewport(x, y, width, height);
+            return 0;
+        }
+    } caller;
+    caller.x = x;
+    caller.y = y;
+    caller.width = width;
+    caller.height = height;
+
+    msg.set_arg0(x);
+    msg.set_arg1(y);
+    msg.set_arg2(width);
+    msg.set_arg3(height);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glViewport);
 }
 
 // FIXME: the following functions should be written by hand
-void Debug_glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);
-void Debug_glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data);
 void Debug_glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data);
 void Debug_glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data);
-void Debug_glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices);
 void Debug_glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
 void Debug_glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
 void Debug_glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders);
@@ -5723,7 +3606,6 @@
 void Debug_glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params);
 void Debug_glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params);
 void Debug_glGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer);
-void Debug_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels);
 void Debug_glShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length);
 void Debug_glTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
 void Debug_glTexParameteriv(GLenum target, GLenum pname, const GLint* params);
diff --git a/opengl/libs/GLES2_dbg/src/caller.h b/opengl/libs/GLES2_dbg/src/caller.h
new file mode 100644
index 0000000..01bc4ea
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/src/caller.h
@@ -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"
+
+
diff --git a/opengl/libs/GLES2_dbg/src/debugger_message.pb.cpp b/opengl/libs/GLES2_dbg/src/debugger_message.pb.cpp
new file mode 100644
index 0000000..4083c44
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/src/debugger_message.pb.cpp
@@ -0,0 +1,1252 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+
+#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
+#include "debugger_message.pb.h"
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+// @@protoc_insertion_point(includes)
+
+namespace com {
+namespace android {
+namespace glesv2debugger {
+
+void protobuf_ShutdownFile_debugger_5fmessage_2eproto() {
+  delete Message::default_instance_;
+}
+
+void protobuf_AddDesc_debugger_5fmessage_2eproto() {
+  static bool already_here = false;
+  if (already_here) return;
+  already_here = true;
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  Message::default_instance_ = new Message();
+  Message::default_instance_->InitAsDefaultInstance();
+  ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_debugger_5fmessage_2eproto);
+}
+
+// Force AddDescriptors() to be called at static initialization time.
+struct StaticDescriptorInitializer_debugger_5fmessage_2eproto {
+  StaticDescriptorInitializer_debugger_5fmessage_2eproto() {
+    protobuf_AddDesc_debugger_5fmessage_2eproto();
+  }
+} static_descriptor_initializer_debugger_5fmessage_2eproto_;
+
+
+// ===================================================================
+
+bool Message_Function_IsValid(int value) {
+  switch(value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+    case 5:
+    case 6:
+    case 7:
+    case 8:
+    case 9:
+    case 10:
+    case 11:
+    case 12:
+    case 13:
+    case 14:
+    case 15:
+    case 16:
+    case 17:
+    case 18:
+    case 19:
+    case 20:
+    case 21:
+    case 22:
+    case 23:
+    case 24:
+    case 25:
+    case 26:
+    case 27:
+    case 28:
+    case 29:
+    case 30:
+    case 31:
+    case 32:
+    case 33:
+    case 34:
+    case 35:
+    case 36:
+    case 37:
+    case 38:
+    case 39:
+    case 40:
+    case 41:
+    case 42:
+    case 43:
+    case 44:
+    case 45:
+    case 46:
+    case 47:
+    case 48:
+    case 49:
+    case 50:
+    case 51:
+    case 52:
+    case 53:
+    case 54:
+    case 55:
+    case 56:
+    case 57:
+    case 58:
+    case 59:
+    case 60:
+    case 61:
+    case 62:
+    case 63:
+    case 64:
+    case 65:
+    case 66:
+    case 67:
+    case 68:
+    case 69:
+    case 70:
+    case 71:
+    case 72:
+    case 73:
+    case 74:
+    case 75:
+    case 76:
+    case 77:
+    case 78:
+    case 79:
+    case 80:
+    case 81:
+    case 82:
+    case 83:
+    case 84:
+    case 85:
+    case 86:
+    case 87:
+    case 88:
+    case 89:
+    case 90:
+    case 91:
+    case 92:
+    case 93:
+    case 94:
+    case 95:
+    case 96:
+    case 97:
+    case 98:
+    case 99:
+    case 100:
+    case 101:
+    case 102:
+    case 103:
+    case 104:
+    case 105:
+    case 106:
+    case 107:
+    case 108:
+    case 109:
+    case 110:
+    case 111:
+    case 112:
+    case 113:
+    case 114:
+    case 115:
+    case 116:
+    case 117:
+    case 118:
+    case 119:
+    case 120:
+    case 121:
+    case 122:
+    case 123:
+    case 124:
+    case 125:
+    case 126:
+    case 127:
+    case 128:
+    case 129:
+    case 130:
+    case 131:
+    case 132:
+    case 133:
+    case 134:
+    case 135:
+    case 136:
+    case 137:
+    case 138:
+    case 139:
+    case 140:
+    case 141:
+    case 142:
+    case 143:
+    case 144:
+    case 145:
+    case 146:
+    case 147:
+    case 148:
+    case 149:
+    case 150:
+    case 151:
+    case 152:
+    case 153:
+    case 154:
+    case 155:
+    case 156:
+    case 157:
+    case 158:
+    case 159:
+    case 160:
+    case 161:
+    case 162:
+    case 163:
+    case 164:
+    case 165:
+    case 166:
+    case 167:
+    case 168:
+    case 169:
+    case 170:
+    case 171:
+    case 172:
+    case 173:
+    case 174:
+    case 175:
+    case 176:
+    case 177:
+    case 178:
+    case 179:
+    case 180:
+    case 181:
+    case 182:
+    case 183:
+    case 184:
+    case 185:
+    case 186:
+    case 187:
+    case 188:
+    case 189:
+    case 190:
+    case 191:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#ifndef _MSC_VER
+const Message_Function Message::glActiveTexture;
+const Message_Function Message::glAttachShader;
+const Message_Function Message::glBindAttribLocation;
+const Message_Function Message::glBindBuffer;
+const Message_Function Message::glBindFramebuffer;
+const Message_Function Message::glBindRenderbuffer;
+const Message_Function Message::glBindTexture;
+const Message_Function Message::glBlendColor;
+const Message_Function Message::glBlendEquation;
+const Message_Function Message::glBlendEquationSeparate;
+const Message_Function Message::glBlendFunc;
+const Message_Function Message::glBlendFuncSeparate;
+const Message_Function Message::glBufferData;
+const Message_Function Message::glBufferSubData;
+const Message_Function Message::glCheckFramebufferStatus;
+const Message_Function Message::glClear;
+const Message_Function Message::glClearColor;
+const Message_Function Message::glClearDepthf;
+const Message_Function Message::glClearStencil;
+const Message_Function Message::glColorMask;
+const Message_Function Message::glCompileShader;
+const Message_Function Message::glCompressedTexImage2D;
+const Message_Function Message::glCompressedTexSubImage2D;
+const Message_Function Message::glCopyTexImage2D;
+const Message_Function Message::glCopyTexSubImage2D;
+const Message_Function Message::glCreateProgram;
+const Message_Function Message::glCreateShader;
+const Message_Function Message::glCullFace;
+const Message_Function Message::glDeleteBuffers;
+const Message_Function Message::glDeleteFramebuffers;
+const Message_Function Message::glDeleteProgram;
+const Message_Function Message::glDeleteRenderbuffers;
+const Message_Function Message::glDeleteShader;
+const Message_Function Message::glDeleteTextures;
+const Message_Function Message::glDepthFunc;
+const Message_Function Message::glDepthMask;
+const Message_Function Message::glDepthRangef;
+const Message_Function Message::glDetachShader;
+const Message_Function Message::glDisable;
+const Message_Function Message::glDisableVertexAttribArray;
+const Message_Function Message::glDrawArrays;
+const Message_Function Message::glDrawElements;
+const Message_Function Message::glEnable;
+const Message_Function Message::glEnableVertexAttribArray;
+const Message_Function Message::glFinish;
+const Message_Function Message::glFlush;
+const Message_Function Message::glFramebufferRenderbuffer;
+const Message_Function Message::glFramebufferTexture2D;
+const Message_Function Message::glFrontFace;
+const Message_Function Message::glGenBuffers;
+const Message_Function Message::glGenerateMipmap;
+const Message_Function Message::glGenFramebuffers;
+const Message_Function Message::glGenRenderbuffers;
+const Message_Function Message::glGenTextures;
+const Message_Function Message::glGetActiveAttrib;
+const Message_Function Message::glGetActiveUniform;
+const Message_Function Message::glGetAttachedShaders;
+const Message_Function Message::glGetAttribLocation;
+const Message_Function Message::glGetBooleanv;
+const Message_Function Message::glGetBufferParameteriv;
+const Message_Function Message::glGetError;
+const Message_Function Message::glGetFloatv;
+const Message_Function Message::glGetFramebufferAttachmentParameteriv;
+const Message_Function Message::glGetIntegerv;
+const Message_Function Message::glGetProgramiv;
+const Message_Function Message::glGetProgramInfoLog;
+const Message_Function Message::glGetRenderbufferParameteriv;
+const Message_Function Message::glGetShaderiv;
+const Message_Function Message::glGetShaderInfoLog;
+const Message_Function Message::glGetShaderPrecisionFormat;
+const Message_Function Message::glGetShaderSource;
+const Message_Function Message::glGetString;
+const Message_Function Message::glGetTexParameterfv;
+const Message_Function Message::glGetTexParameteriv;
+const Message_Function Message::glGetUniformfv;
+const Message_Function Message::glGetUniformiv;
+const Message_Function Message::glGetUniformLocation;
+const Message_Function Message::glGetVertexAttribfv;
+const Message_Function Message::glGetVertexAttribiv;
+const Message_Function Message::glGetVertexAttribPointerv;
+const Message_Function Message::glHint;
+const Message_Function Message::glIsBuffer;
+const Message_Function Message::glIsEnabled;
+const Message_Function Message::glIsFramebuffer;
+const Message_Function Message::glIsProgram;
+const Message_Function Message::glIsRenderbuffer;
+const Message_Function Message::glIsShader;
+const Message_Function Message::glIsTexture;
+const Message_Function Message::glLineWidth;
+const Message_Function Message::glLinkProgram;
+const Message_Function Message::glPixelStorei;
+const Message_Function Message::glPolygonOffset;
+const Message_Function Message::glReadPixels;
+const Message_Function Message::glReleaseShaderCompiler;
+const Message_Function Message::glRenderbufferStorage;
+const Message_Function Message::glSampleCoverage;
+const Message_Function Message::glScissor;
+const Message_Function Message::glShaderBinary;
+const Message_Function Message::glShaderSource;
+const Message_Function Message::glStencilFunc;
+const Message_Function Message::glStencilFuncSeparate;
+const Message_Function Message::glStencilMask;
+const Message_Function Message::glStencilMaskSeparate;
+const Message_Function Message::glStencilOp;
+const Message_Function Message::glStencilOpSeparate;
+const Message_Function Message::glTexImage2D;
+const Message_Function Message::glTexParameterf;
+const Message_Function Message::glTexParameterfv;
+const Message_Function Message::glTexParameteri;
+const Message_Function Message::glTexParameteriv;
+const Message_Function Message::glTexSubImage2D;
+const Message_Function Message::glUniform1f;
+const Message_Function Message::glUniform1fv;
+const Message_Function Message::glUniform1i;
+const Message_Function Message::glUniform1iv;
+const Message_Function Message::glUniform2f;
+const Message_Function Message::glUniform2fv;
+const Message_Function Message::glUniform2i;
+const Message_Function Message::glUniform2iv;
+const Message_Function Message::glUniform3f;
+const Message_Function Message::glUniform3fv;
+const Message_Function Message::glUniform3i;
+const Message_Function Message::glUniform3iv;
+const Message_Function Message::glUniform4f;
+const Message_Function Message::glUniform4fv;
+const Message_Function Message::glUniform4i;
+const Message_Function Message::glUniform4iv;
+const Message_Function Message::glUniformMatrix2fv;
+const Message_Function Message::glUniformMatrix3fv;
+const Message_Function Message::glUniformMatrix4fv;
+const Message_Function Message::glUseProgram;
+const Message_Function Message::glValidateProgram;
+const Message_Function Message::glVertexAttrib1f;
+const Message_Function Message::glVertexAttrib1fv;
+const Message_Function Message::glVertexAttrib2f;
+const Message_Function Message::glVertexAttrib2fv;
+const Message_Function Message::glVertexAttrib3f;
+const Message_Function Message::glVertexAttrib3fv;
+const Message_Function Message::glVertexAttrib4f;
+const Message_Function Message::glVertexAttrib4fv;
+const Message_Function Message::glVertexAttribPointer;
+const Message_Function Message::glViewport;
+const Message_Function Message::eglGetDisplay;
+const Message_Function Message::eglInitialize;
+const Message_Function Message::eglTerminate;
+const Message_Function Message::eglGetConfigs;
+const Message_Function Message::eglChooseConfig;
+const Message_Function Message::eglGetConfigAttrib;
+const Message_Function Message::eglCreateWindowSurface;
+const Message_Function Message::eglCreatePixmapSurface;
+const Message_Function Message::eglCreatePbufferSurface;
+const Message_Function Message::eglDestroySurface;
+const Message_Function Message::eglQuerySurface;
+const Message_Function Message::eglCreateContext;
+const Message_Function Message::eglDestroyContext;
+const Message_Function Message::eglMakeCurrent;
+const Message_Function Message::eglGetCurrentContext;
+const Message_Function Message::eglGetCurrentSurface;
+const Message_Function Message::eglGetCurrentDisplay;
+const Message_Function Message::eglQueryContext;
+const Message_Function Message::eglWaitGL;
+const Message_Function Message::eglWaitNative;
+const Message_Function Message::eglSwapBuffers;
+const Message_Function Message::eglCopyBuffers;
+const Message_Function Message::eglGetError;
+const Message_Function Message::eglQueryString;
+const Message_Function Message::eglGetProcAddress;
+const Message_Function Message::eglSurfaceAttrib;
+const Message_Function Message::eglBindTexImage;
+const Message_Function Message::eglReleaseTexImage;
+const Message_Function Message::eglSwapInterval;
+const Message_Function Message::eglBindAPI;
+const Message_Function Message::eglQueryAPI;
+const Message_Function Message::eglWaitClient;
+const Message_Function Message::eglReleaseThread;
+const Message_Function Message::eglCreatePbufferFromClientBuffer;
+const Message_Function Message::eglLockSurfaceKHR;
+const Message_Function Message::eglUnlockSurfaceKHR;
+const Message_Function Message::eglCreateImageKHR;
+const Message_Function Message::eglDestroyImageKHR;
+const Message_Function Message::eglCreateSyncKHR;
+const Message_Function Message::eglDestroySyncKHR;
+const Message_Function Message::eglClientWaitSyncKHR;
+const Message_Function Message::eglGetSyncAttribKHR;
+const Message_Function Message::eglSetSwapRectangleANDROID;
+const Message_Function Message::eglGetRenderBufferANDROID;
+const Message_Function Message::ACK;
+const Message_Function Message::NEG;
+const Message_Function Message::CONTINUE;
+const Message_Function Message::SKIP;
+const Message_Function Message::SETPROP;
+const Message_Function Message::CAPTURE;
+const Message_Function Message::Function_MIN;
+const Message_Function Message::Function_MAX;
+const int Message::Function_ARRAYSIZE;
+#endif  // _MSC_VER
+bool Message_Type_IsValid(int value) {
+  switch(value) {
+    case 0:
+    case 1:
+    case 2:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#ifndef _MSC_VER
+const Message_Type Message::BeforeCall;
+const Message_Type Message::AfterCall;
+const Message_Type Message::Response;
+const Message_Type Message::Type_MIN;
+const Message_Type Message::Type_MAX;
+const int Message::Type_ARRAYSIZE;
+#endif  // _MSC_VER
+bool Message_Prop_IsValid(int value) {
+  switch(value) {
+    case 0:
+    case 1:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#ifndef _MSC_VER
+const Message_Prop Message::Capture;
+const Message_Prop Message::TimeMode;
+const Message_Prop Message::Prop_MIN;
+const Message_Prop Message::Prop_MAX;
+const int Message::Prop_ARRAYSIZE;
+#endif  // _MSC_VER
+const ::std::string Message::_default_data_;
+#ifndef _MSC_VER
+const int Message::kContextIdFieldNumber;
+const int Message::kFunctionFieldNumber;
+const int Message::kTypeFieldNumber;
+const int Message::kExpectResponseFieldNumber;
+const int Message::kRetFieldNumber;
+const int Message::kArg0FieldNumber;
+const int Message::kArg1FieldNumber;
+const int Message::kArg2FieldNumber;
+const int Message::kArg3FieldNumber;
+const int Message::kArg4FieldNumber;
+const int Message::kArg5FieldNumber;
+const int Message::kArg6FieldNumber;
+const int Message::kArg7FieldNumber;
+const int Message::kArg8FieldNumber;
+const int Message::kDataFieldNumber;
+const int Message::kTimeFieldNumber;
+const int Message::kPropFieldNumber;
+const int Message::kClockFieldNumber;
+#endif  // !_MSC_VER
+
+Message::Message()
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+}
+
+void Message::InitAsDefaultInstance() {
+}
+
+Message::Message(const Message& from)
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  MergeFrom(from);
+}
+
+void Message::SharedCtor() {
+  _cached_size_ = 0;
+  context_id_ = 0;
+  function_ = 187;
+  type_ = 0;
+  expect_response_ = false;
+  ret_ = 0;
+  arg0_ = 0;
+  arg1_ = 0;
+  arg2_ = 0;
+  arg3_ = 0;
+  arg4_ = 0;
+  arg5_ = 0;
+  arg6_ = 0;
+  arg7_ = 0;
+  arg8_ = 0;
+  data_ = const_cast< ::std::string*>(&_default_data_);
+  time_ = 0;
+  prop_ = 0;
+  clock_ = 0;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+Message::~Message() {
+  SharedDtor();
+}
+
+void Message::SharedDtor() {
+  if (data_ != &_default_data_) {
+    delete data_;
+  }
+  if (this != default_instance_) {
+  }
+}
+
+void Message::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const Message& Message::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_debugger_5fmessage_2eproto();  return *default_instance_;
+}
+
+Message* Message::default_instance_ = NULL;
+
+Message* Message::New() const {
+  return new Message;
+}
+
+void Message::Clear() {
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    context_id_ = 0;
+    function_ = 187;
+    type_ = 0;
+    expect_response_ = false;
+    ret_ = 0;
+    arg0_ = 0;
+    arg1_ = 0;
+    arg2_ = 0;
+  }
+  if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) {
+    arg3_ = 0;
+    arg4_ = 0;
+    arg5_ = 0;
+    arg6_ = 0;
+    arg7_ = 0;
+    arg8_ = 0;
+    if (_has_bit(14)) {
+      if (data_ != &_default_data_) {
+        data_->clear();
+      }
+    }
+    time_ = 0;
+  }
+  if (_has_bits_[16 / 32] & (0xffu << (16 % 32))) {
+    prop_ = 0;
+    clock_ = 0;
+  }
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+bool Message::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
+  ::google::protobuf::uint32 tag;
+  while ((tag = input->ReadTag()) != 0) {
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // required int32 context_id = 1;
+      case 1: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &context_id_)));
+          _set_bit(0);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(16)) goto parse_function;
+        break;
+      }
+      
+      // required .com.android.glesv2debugger.Message.Function function = 2 [default = NEG];
+      case 2: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_function:
+          int value;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          if (::com::android::glesv2debugger::Message_Function_IsValid(value)) {
+            set_function(static_cast< ::com::android::glesv2debugger::Message_Function >(value));
+          }
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(24)) goto parse_type;
+        break;
+      }
+      
+      // required .com.android.glesv2debugger.Message.Type type = 3;
+      case 3: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_type:
+          int value;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          if (::com::android::glesv2debugger::Message_Type_IsValid(value)) {
+            set_type(static_cast< ::com::android::glesv2debugger::Message_Type >(value));
+          }
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(32)) goto parse_expect_response;
+        break;
+      }
+      
+      // required bool expect_response = 4;
+      case 4: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_expect_response:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &expect_response_)));
+          _set_bit(3);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(40)) goto parse_ret;
+        break;
+      }
+      
+      // optional int32 ret = 5;
+      case 5: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_ret:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &ret_)));
+          _set_bit(4);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(48)) goto parse_arg0;
+        break;
+      }
+      
+      // optional int32 arg0 = 6;
+      case 6: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_arg0:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &arg0_)));
+          _set_bit(5);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(56)) goto parse_arg1;
+        break;
+      }
+      
+      // optional int32 arg1 = 7;
+      case 7: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_arg1:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &arg1_)));
+          _set_bit(6);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(64)) goto parse_arg2;
+        break;
+      }
+      
+      // optional int32 arg2 = 8;
+      case 8: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_arg2:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &arg2_)));
+          _set_bit(7);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(72)) goto parse_arg3;
+        break;
+      }
+      
+      // optional int32 arg3 = 9;
+      case 9: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_arg3:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &arg3_)));
+          _set_bit(8);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(82)) goto parse_data;
+        break;
+      }
+      
+      // optional bytes data = 10;
+      case 10: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+         parse_data:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadBytes(
+                input, this->mutable_data()));
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(93)) goto parse_time;
+        break;
+      }
+      
+      // optional float time = 11;
+      case 11: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) {
+         parse_time:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>(
+                 input, &time_)));
+          _set_bit(15);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(128)) goto parse_arg4;
+        break;
+      }
+      
+      // optional int32 arg4 = 16;
+      case 16: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_arg4:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &arg4_)));
+          _set_bit(9);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(136)) goto parse_arg5;
+        break;
+      }
+      
+      // optional int32 arg5 = 17;
+      case 17: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_arg5:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &arg5_)));
+          _set_bit(10);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(144)) goto parse_arg6;
+        break;
+      }
+      
+      // optional int32 arg6 = 18;
+      case 18: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_arg6:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &arg6_)));
+          _set_bit(11);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(152)) goto parse_arg7;
+        break;
+      }
+      
+      // optional int32 arg7 = 19;
+      case 19: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_arg7:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &arg7_)));
+          _set_bit(12);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(160)) goto parse_arg8;
+        break;
+      }
+      
+      // optional int32 arg8 = 20;
+      case 20: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_arg8:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &arg8_)));
+          _set_bit(13);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(168)) goto parse_prop;
+        break;
+      }
+      
+      // optional .com.android.glesv2debugger.Message.Prop prop = 21;
+      case 21: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_prop:
+          int value;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          if (::com::android::glesv2debugger::Message_Prop_IsValid(value)) {
+            set_prop(static_cast< ::com::android::glesv2debugger::Message_Prop >(value));
+          }
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(181)) goto parse_clock;
+        break;
+      }
+      
+      // optional float clock = 22;
+      case 22: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) {
+         parse_clock:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>(
+                 input, &clock_)));
+          _set_bit(17);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectAtEnd()) return true;
+        break;
+      }
+      
+      default: {
+      handle_uninterpreted:
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          return true;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        break;
+      }
+    }
+  }
+  return true;
+#undef DO_
+}
+
+void Message::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // required int32 context_id = 1;
+  if (_has_bit(0)) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->context_id(), output);
+  }
+  
+  // required .com.android.glesv2debugger.Message.Function function = 2 [default = NEG];
+  if (_has_bit(1)) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      2, this->function(), output);
+  }
+  
+  // required .com.android.glesv2debugger.Message.Type type = 3;
+  if (_has_bit(2)) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      3, this->type(), output);
+  }
+  
+  // required bool expect_response = 4;
+  if (_has_bit(3)) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(4, this->expect_response(), output);
+  }
+  
+  // optional int32 ret = 5;
+  if (_has_bit(4)) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(5, this->ret(), output);
+  }
+  
+  // optional int32 arg0 = 6;
+  if (_has_bit(5)) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(6, this->arg0(), output);
+  }
+  
+  // optional int32 arg1 = 7;
+  if (_has_bit(6)) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(7, this->arg1(), output);
+  }
+  
+  // optional int32 arg2 = 8;
+  if (_has_bit(7)) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(8, this->arg2(), output);
+  }
+  
+  // optional int32 arg3 = 9;
+  if (_has_bit(8)) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(9, this->arg3(), output);
+  }
+  
+  // optional bytes data = 10;
+  if (_has_bit(14)) {
+    ::google::protobuf::internal::WireFormatLite::WriteBytes(
+      10, this->data(), output);
+  }
+  
+  // optional float time = 11;
+  if (_has_bit(15)) {
+    ::google::protobuf::internal::WireFormatLite::WriteFloat(11, this->time(), output);
+  }
+  
+  // optional int32 arg4 = 16;
+  if (_has_bit(9)) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(16, this->arg4(), output);
+  }
+  
+  // optional int32 arg5 = 17;
+  if (_has_bit(10)) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(17, this->arg5(), output);
+  }
+  
+  // optional int32 arg6 = 18;
+  if (_has_bit(11)) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(18, this->arg6(), output);
+  }
+  
+  // optional int32 arg7 = 19;
+  if (_has_bit(12)) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(19, this->arg7(), output);
+  }
+  
+  // optional int32 arg8 = 20;
+  if (_has_bit(13)) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(20, this->arg8(), output);
+  }
+  
+  // optional .com.android.glesv2debugger.Message.Prop prop = 21;
+  if (_has_bit(16)) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      21, this->prop(), output);
+  }
+  
+  // optional float clock = 22;
+  if (_has_bit(17)) {
+    ::google::protobuf::internal::WireFormatLite::WriteFloat(22, this->clock(), output);
+  }
+  
+}
+
+int Message::ByteSize() const {
+  int total_size = 0;
+  
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    // required int32 context_id = 1;
+    if (has_context_id()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->context_id());
+    }
+    
+    // required .com.android.glesv2debugger.Message.Function function = 2 [default = NEG];
+    if (has_function()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::EnumSize(this->function());
+    }
+    
+    // required .com.android.glesv2debugger.Message.Type type = 3;
+    if (has_type()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::EnumSize(this->type());
+    }
+    
+    // required bool expect_response = 4;
+    if (has_expect_response()) {
+      total_size += 1 + 1;
+    }
+    
+    // optional int32 ret = 5;
+    if (has_ret()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->ret());
+    }
+    
+    // optional int32 arg0 = 6;
+    if (has_arg0()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->arg0());
+    }
+    
+    // optional int32 arg1 = 7;
+    if (has_arg1()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->arg1());
+    }
+    
+    // optional int32 arg2 = 8;
+    if (has_arg2()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->arg2());
+    }
+    
+  }
+  if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) {
+    // optional int32 arg3 = 9;
+    if (has_arg3()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->arg3());
+    }
+    
+    // optional int32 arg4 = 16;
+    if (has_arg4()) {
+      total_size += 2 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->arg4());
+    }
+    
+    // optional int32 arg5 = 17;
+    if (has_arg5()) {
+      total_size += 2 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->arg5());
+    }
+    
+    // optional int32 arg6 = 18;
+    if (has_arg6()) {
+      total_size += 2 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->arg6());
+    }
+    
+    // optional int32 arg7 = 19;
+    if (has_arg7()) {
+      total_size += 2 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->arg7());
+    }
+    
+    // optional int32 arg8 = 20;
+    if (has_arg8()) {
+      total_size += 2 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->arg8());
+    }
+    
+    // optional bytes data = 10;
+    if (has_data()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::BytesSize(
+          this->data());
+    }
+    
+    // optional float time = 11;
+    if (has_time()) {
+      total_size += 1 + 4;
+    }
+    
+  }
+  if (_has_bits_[16 / 32] & (0xffu << (16 % 32))) {
+    // optional .com.android.glesv2debugger.Message.Prop prop = 21;
+    if (has_prop()) {
+      total_size += 2 +
+        ::google::protobuf::internal::WireFormatLite::EnumSize(this->prop());
+    }
+    
+    // optional float clock = 22;
+    if (has_clock()) {
+      total_size += 2 + 4;
+    }
+    
+  }
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void Message::CheckTypeAndMergeFrom(
+    const ::google::protobuf::MessageLite& from) {
+  MergeFrom(*::google::protobuf::down_cast<const Message*>(&from));
+}
+
+void Message::MergeFrom(const Message& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from._has_bit(0)) {
+      set_context_id(from.context_id());
+    }
+    if (from._has_bit(1)) {
+      set_function(from.function());
+    }
+    if (from._has_bit(2)) {
+      set_type(from.type());
+    }
+    if (from._has_bit(3)) {
+      set_expect_response(from.expect_response());
+    }
+    if (from._has_bit(4)) {
+      set_ret(from.ret());
+    }
+    if (from._has_bit(5)) {
+      set_arg0(from.arg0());
+    }
+    if (from._has_bit(6)) {
+      set_arg1(from.arg1());
+    }
+    if (from._has_bit(7)) {
+      set_arg2(from.arg2());
+    }
+  }
+  if (from._has_bits_[8 / 32] & (0xffu << (8 % 32))) {
+    if (from._has_bit(8)) {
+      set_arg3(from.arg3());
+    }
+    if (from._has_bit(9)) {
+      set_arg4(from.arg4());
+    }
+    if (from._has_bit(10)) {
+      set_arg5(from.arg5());
+    }
+    if (from._has_bit(11)) {
+      set_arg6(from.arg6());
+    }
+    if (from._has_bit(12)) {
+      set_arg7(from.arg7());
+    }
+    if (from._has_bit(13)) {
+      set_arg8(from.arg8());
+    }
+    if (from._has_bit(14)) {
+      set_data(from.data());
+    }
+    if (from._has_bit(15)) {
+      set_time(from.time());
+    }
+  }
+  if (from._has_bits_[16 / 32] & (0xffu << (16 % 32))) {
+    if (from._has_bit(16)) {
+      set_prop(from.prop());
+    }
+    if (from._has_bit(17)) {
+      set_clock(from.clock());
+    }
+  }
+}
+
+void Message::CopyFrom(const Message& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool Message::IsInitialized() const {
+  if ((_has_bits_[0] & 0x0000000f) != 0x0000000f) return false;
+  
+  return true;
+}
+
+void Message::Swap(Message* other) {
+  if (other != this) {
+    std::swap(context_id_, other->context_id_);
+    std::swap(function_, other->function_);
+    std::swap(type_, other->type_);
+    std::swap(expect_response_, other->expect_response_);
+    std::swap(ret_, other->ret_);
+    std::swap(arg0_, other->arg0_);
+    std::swap(arg1_, other->arg1_);
+    std::swap(arg2_, other->arg2_);
+    std::swap(arg3_, other->arg3_);
+    std::swap(arg4_, other->arg4_);
+    std::swap(arg5_, other->arg5_);
+    std::swap(arg6_, other->arg6_);
+    std::swap(arg7_, other->arg7_);
+    std::swap(arg8_, other->arg8_);
+    std::swap(data_, other->data_);
+    std::swap(time_, other->time_);
+    std::swap(prop_, other->prop_);
+    std::swap(clock_, other->clock_);
+    std::swap(_has_bits_[0], other->_has_bits_[0]);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::std::string Message::GetTypeName() const {
+  return "com.android.glesv2debugger.Message";
+}
+
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace glesv2debugger
+}  // namespace android
+}  // namespace com
+
+// @@protoc_insertion_point(global_scope)
diff --git a/opengl/libs/GLES2_dbg/src/debugger_message.pb.h b/opengl/libs/GLES2_dbg/src/debugger_message.pb.h
new file mode 100644
index 0000000..3f2b842
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/src/debugger_message.pb.h
@@ -0,0 +1,1036 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: debugger_message.proto
+
+#ifndef PROTOBUF_debugger_5fmessage_2eproto__INCLUDED
+#define PROTOBUF_debugger_5fmessage_2eproto__INCLUDED
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+#if GOOGLE_PROTOBUF_VERSION < 2003000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please update
+#error your headers.
+#endif
+#if 2003000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/extension_set.h>
+// @@protoc_insertion_point(includes)
+
+namespace com {
+namespace android {
+namespace glesv2debugger {
+
+// Internal implementation detail -- do not call these.
+void  protobuf_AddDesc_debugger_5fmessage_2eproto();
+void protobuf_AssignDesc_debugger_5fmessage_2eproto();
+void protobuf_ShutdownFile_debugger_5fmessage_2eproto();
+
+class Message;
+
+enum Message_Function {
+  Message_Function_glActiveTexture = 0,
+  Message_Function_glAttachShader = 1,
+  Message_Function_glBindAttribLocation = 2,
+  Message_Function_glBindBuffer = 3,
+  Message_Function_glBindFramebuffer = 4,
+  Message_Function_glBindRenderbuffer = 5,
+  Message_Function_glBindTexture = 6,
+  Message_Function_glBlendColor = 7,
+  Message_Function_glBlendEquation = 8,
+  Message_Function_glBlendEquationSeparate = 9,
+  Message_Function_glBlendFunc = 10,
+  Message_Function_glBlendFuncSeparate = 11,
+  Message_Function_glBufferData = 12,
+  Message_Function_glBufferSubData = 13,
+  Message_Function_glCheckFramebufferStatus = 14,
+  Message_Function_glClear = 15,
+  Message_Function_glClearColor = 16,
+  Message_Function_glClearDepthf = 17,
+  Message_Function_glClearStencil = 18,
+  Message_Function_glColorMask = 19,
+  Message_Function_glCompileShader = 20,
+  Message_Function_glCompressedTexImage2D = 21,
+  Message_Function_glCompressedTexSubImage2D = 22,
+  Message_Function_glCopyTexImage2D = 23,
+  Message_Function_glCopyTexSubImage2D = 24,
+  Message_Function_glCreateProgram = 25,
+  Message_Function_glCreateShader = 26,
+  Message_Function_glCullFace = 27,
+  Message_Function_glDeleteBuffers = 28,
+  Message_Function_glDeleteFramebuffers = 29,
+  Message_Function_glDeleteProgram = 30,
+  Message_Function_glDeleteRenderbuffers = 31,
+  Message_Function_glDeleteShader = 32,
+  Message_Function_glDeleteTextures = 33,
+  Message_Function_glDepthFunc = 34,
+  Message_Function_glDepthMask = 35,
+  Message_Function_glDepthRangef = 36,
+  Message_Function_glDetachShader = 37,
+  Message_Function_glDisable = 38,
+  Message_Function_glDisableVertexAttribArray = 39,
+  Message_Function_glDrawArrays = 40,
+  Message_Function_glDrawElements = 41,
+  Message_Function_glEnable = 42,
+  Message_Function_glEnableVertexAttribArray = 43,
+  Message_Function_glFinish = 44,
+  Message_Function_glFlush = 45,
+  Message_Function_glFramebufferRenderbuffer = 46,
+  Message_Function_glFramebufferTexture2D = 47,
+  Message_Function_glFrontFace = 48,
+  Message_Function_glGenBuffers = 49,
+  Message_Function_glGenerateMipmap = 50,
+  Message_Function_glGenFramebuffers = 51,
+  Message_Function_glGenRenderbuffers = 52,
+  Message_Function_glGenTextures = 53,
+  Message_Function_glGetActiveAttrib = 54,
+  Message_Function_glGetActiveUniform = 55,
+  Message_Function_glGetAttachedShaders = 56,
+  Message_Function_glGetAttribLocation = 57,
+  Message_Function_glGetBooleanv = 58,
+  Message_Function_glGetBufferParameteriv = 59,
+  Message_Function_glGetError = 60,
+  Message_Function_glGetFloatv = 61,
+  Message_Function_glGetFramebufferAttachmentParameteriv = 62,
+  Message_Function_glGetIntegerv = 63,
+  Message_Function_glGetProgramiv = 64,
+  Message_Function_glGetProgramInfoLog = 65,
+  Message_Function_glGetRenderbufferParameteriv = 66,
+  Message_Function_glGetShaderiv = 67,
+  Message_Function_glGetShaderInfoLog = 68,
+  Message_Function_glGetShaderPrecisionFormat = 69,
+  Message_Function_glGetShaderSource = 70,
+  Message_Function_glGetString = 71,
+  Message_Function_glGetTexParameterfv = 72,
+  Message_Function_glGetTexParameteriv = 73,
+  Message_Function_glGetUniformfv = 74,
+  Message_Function_glGetUniformiv = 75,
+  Message_Function_glGetUniformLocation = 76,
+  Message_Function_glGetVertexAttribfv = 77,
+  Message_Function_glGetVertexAttribiv = 78,
+  Message_Function_glGetVertexAttribPointerv = 79,
+  Message_Function_glHint = 80,
+  Message_Function_glIsBuffer = 81,
+  Message_Function_glIsEnabled = 82,
+  Message_Function_glIsFramebuffer = 83,
+  Message_Function_glIsProgram = 84,
+  Message_Function_glIsRenderbuffer = 85,
+  Message_Function_glIsShader = 86,
+  Message_Function_glIsTexture = 87,
+  Message_Function_glLineWidth = 88,
+  Message_Function_glLinkProgram = 89,
+  Message_Function_glPixelStorei = 90,
+  Message_Function_glPolygonOffset = 91,
+  Message_Function_glReadPixels = 92,
+  Message_Function_glReleaseShaderCompiler = 93,
+  Message_Function_glRenderbufferStorage = 94,
+  Message_Function_glSampleCoverage = 95,
+  Message_Function_glScissor = 96,
+  Message_Function_glShaderBinary = 97,
+  Message_Function_glShaderSource = 98,
+  Message_Function_glStencilFunc = 99,
+  Message_Function_glStencilFuncSeparate = 100,
+  Message_Function_glStencilMask = 101,
+  Message_Function_glStencilMaskSeparate = 102,
+  Message_Function_glStencilOp = 103,
+  Message_Function_glStencilOpSeparate = 104,
+  Message_Function_glTexImage2D = 105,
+  Message_Function_glTexParameterf = 106,
+  Message_Function_glTexParameterfv = 107,
+  Message_Function_glTexParameteri = 108,
+  Message_Function_glTexParameteriv = 109,
+  Message_Function_glTexSubImage2D = 110,
+  Message_Function_glUniform1f = 111,
+  Message_Function_glUniform1fv = 112,
+  Message_Function_glUniform1i = 113,
+  Message_Function_glUniform1iv = 114,
+  Message_Function_glUniform2f = 115,
+  Message_Function_glUniform2fv = 116,
+  Message_Function_glUniform2i = 117,
+  Message_Function_glUniform2iv = 118,
+  Message_Function_glUniform3f = 119,
+  Message_Function_glUniform3fv = 120,
+  Message_Function_glUniform3i = 121,
+  Message_Function_glUniform3iv = 122,
+  Message_Function_glUniform4f = 123,
+  Message_Function_glUniform4fv = 124,
+  Message_Function_glUniform4i = 125,
+  Message_Function_glUniform4iv = 126,
+  Message_Function_glUniformMatrix2fv = 127,
+  Message_Function_glUniformMatrix3fv = 128,
+  Message_Function_glUniformMatrix4fv = 129,
+  Message_Function_glUseProgram = 130,
+  Message_Function_glValidateProgram = 131,
+  Message_Function_glVertexAttrib1f = 132,
+  Message_Function_glVertexAttrib1fv = 133,
+  Message_Function_glVertexAttrib2f = 134,
+  Message_Function_glVertexAttrib2fv = 135,
+  Message_Function_glVertexAttrib3f = 136,
+  Message_Function_glVertexAttrib3fv = 137,
+  Message_Function_glVertexAttrib4f = 138,
+  Message_Function_glVertexAttrib4fv = 139,
+  Message_Function_glVertexAttribPointer = 140,
+  Message_Function_glViewport = 141,
+  Message_Function_eglGetDisplay = 142,
+  Message_Function_eglInitialize = 143,
+  Message_Function_eglTerminate = 144,
+  Message_Function_eglGetConfigs = 145,
+  Message_Function_eglChooseConfig = 146,
+  Message_Function_eglGetConfigAttrib = 147,
+  Message_Function_eglCreateWindowSurface = 148,
+  Message_Function_eglCreatePixmapSurface = 149,
+  Message_Function_eglCreatePbufferSurface = 150,
+  Message_Function_eglDestroySurface = 151,
+  Message_Function_eglQuerySurface = 152,
+  Message_Function_eglCreateContext = 153,
+  Message_Function_eglDestroyContext = 154,
+  Message_Function_eglMakeCurrent = 155,
+  Message_Function_eglGetCurrentContext = 156,
+  Message_Function_eglGetCurrentSurface = 157,
+  Message_Function_eglGetCurrentDisplay = 158,
+  Message_Function_eglQueryContext = 159,
+  Message_Function_eglWaitGL = 160,
+  Message_Function_eglWaitNative = 161,
+  Message_Function_eglSwapBuffers = 162,
+  Message_Function_eglCopyBuffers = 163,
+  Message_Function_eglGetError = 164,
+  Message_Function_eglQueryString = 165,
+  Message_Function_eglGetProcAddress = 166,
+  Message_Function_eglSurfaceAttrib = 167,
+  Message_Function_eglBindTexImage = 168,
+  Message_Function_eglReleaseTexImage = 169,
+  Message_Function_eglSwapInterval = 170,
+  Message_Function_eglBindAPI = 171,
+  Message_Function_eglQueryAPI = 172,
+  Message_Function_eglWaitClient = 173,
+  Message_Function_eglReleaseThread = 174,
+  Message_Function_eglCreatePbufferFromClientBuffer = 175,
+  Message_Function_eglLockSurfaceKHR = 176,
+  Message_Function_eglUnlockSurfaceKHR = 177,
+  Message_Function_eglCreateImageKHR = 178,
+  Message_Function_eglDestroyImageKHR = 179,
+  Message_Function_eglCreateSyncKHR = 180,
+  Message_Function_eglDestroySyncKHR = 181,
+  Message_Function_eglClientWaitSyncKHR = 182,
+  Message_Function_eglGetSyncAttribKHR = 183,
+  Message_Function_eglSetSwapRectangleANDROID = 184,
+  Message_Function_eglGetRenderBufferANDROID = 185,
+  Message_Function_ACK = 186,
+  Message_Function_NEG = 187,
+  Message_Function_CONTINUE = 188,
+  Message_Function_SKIP = 189,
+  Message_Function_SETPROP = 190,
+  Message_Function_CAPTURE = 191
+};
+bool Message_Function_IsValid(int value);
+const Message_Function Message_Function_Function_MIN = Message_Function_glActiveTexture;
+const Message_Function Message_Function_Function_MAX = Message_Function_CAPTURE;
+const int Message_Function_Function_ARRAYSIZE = Message_Function_Function_MAX + 1;
+
+enum Message_Type {
+  Message_Type_BeforeCall = 0,
+  Message_Type_AfterCall = 1,
+  Message_Type_Response = 2
+};
+bool Message_Type_IsValid(int value);
+const Message_Type Message_Type_Type_MIN = Message_Type_BeforeCall;
+const Message_Type Message_Type_Type_MAX = Message_Type_Response;
+const int Message_Type_Type_ARRAYSIZE = Message_Type_Type_MAX + 1;
+
+enum Message_Prop {
+  Message_Prop_Capture = 0,
+  Message_Prop_TimeMode = 1
+};
+bool Message_Prop_IsValid(int value);
+const Message_Prop Message_Prop_Prop_MIN = Message_Prop_Capture;
+const Message_Prop Message_Prop_Prop_MAX = Message_Prop_TimeMode;
+const int Message_Prop_Prop_ARRAYSIZE = Message_Prop_Prop_MAX + 1;
+
+// ===================================================================
+
+class Message : public ::google::protobuf::MessageLite {
+ public:
+  Message();
+  virtual ~Message();
+  
+  Message(const Message& from);
+  
+  inline Message& operator=(const Message& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  
+  static const Message& default_instance();
+  
+  void Swap(Message* other);
+  
+  // implements Message ----------------------------------------------
+  
+  Message* New() const;
+  void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
+  void CopyFrom(const Message& from);
+  void MergeFrom(const Message& from);
+  void Clear();
+  bool IsInitialized() const;
+  
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  
+  ::std::string GetTypeName() const;
+  
+  // nested types ----------------------------------------------------
+  
+  typedef Message_Function Function;
+  static const Function glActiveTexture = Message_Function_glActiveTexture;
+  static const Function glAttachShader = Message_Function_glAttachShader;
+  static const Function glBindAttribLocation = Message_Function_glBindAttribLocation;
+  static const Function glBindBuffer = Message_Function_glBindBuffer;
+  static const Function glBindFramebuffer = Message_Function_glBindFramebuffer;
+  static const Function glBindRenderbuffer = Message_Function_glBindRenderbuffer;
+  static const Function glBindTexture = Message_Function_glBindTexture;
+  static const Function glBlendColor = Message_Function_glBlendColor;
+  static const Function glBlendEquation = Message_Function_glBlendEquation;
+  static const Function glBlendEquationSeparate = Message_Function_glBlendEquationSeparate;
+  static const Function glBlendFunc = Message_Function_glBlendFunc;
+  static const Function glBlendFuncSeparate = Message_Function_glBlendFuncSeparate;
+  static const Function glBufferData = Message_Function_glBufferData;
+  static const Function glBufferSubData = Message_Function_glBufferSubData;
+  static const Function glCheckFramebufferStatus = Message_Function_glCheckFramebufferStatus;
+  static const Function glClear = Message_Function_glClear;
+  static const Function glClearColor = Message_Function_glClearColor;
+  static const Function glClearDepthf = Message_Function_glClearDepthf;
+  static const Function glClearStencil = Message_Function_glClearStencil;
+  static const Function glColorMask = Message_Function_glColorMask;
+  static const Function glCompileShader = Message_Function_glCompileShader;
+  static const Function glCompressedTexImage2D = Message_Function_glCompressedTexImage2D;
+  static const Function glCompressedTexSubImage2D = Message_Function_glCompressedTexSubImage2D;
+  static const Function glCopyTexImage2D = Message_Function_glCopyTexImage2D;
+  static const Function glCopyTexSubImage2D = Message_Function_glCopyTexSubImage2D;
+  static const Function glCreateProgram = Message_Function_glCreateProgram;
+  static const Function glCreateShader = Message_Function_glCreateShader;
+  static const Function glCullFace = Message_Function_glCullFace;
+  static const Function glDeleteBuffers = Message_Function_glDeleteBuffers;
+  static const Function glDeleteFramebuffers = Message_Function_glDeleteFramebuffers;
+  static const Function glDeleteProgram = Message_Function_glDeleteProgram;
+  static const Function glDeleteRenderbuffers = Message_Function_glDeleteRenderbuffers;
+  static const Function glDeleteShader = Message_Function_glDeleteShader;
+  static const Function glDeleteTextures = Message_Function_glDeleteTextures;
+  static const Function glDepthFunc = Message_Function_glDepthFunc;
+  static const Function glDepthMask = Message_Function_glDepthMask;
+  static const Function glDepthRangef = Message_Function_glDepthRangef;
+  static const Function glDetachShader = Message_Function_glDetachShader;
+  static const Function glDisable = Message_Function_glDisable;
+  static const Function glDisableVertexAttribArray = Message_Function_glDisableVertexAttribArray;
+  static const Function glDrawArrays = Message_Function_glDrawArrays;
+  static const Function glDrawElements = Message_Function_glDrawElements;
+  static const Function glEnable = Message_Function_glEnable;
+  static const Function glEnableVertexAttribArray = Message_Function_glEnableVertexAttribArray;
+  static const Function glFinish = Message_Function_glFinish;
+  static const Function glFlush = Message_Function_glFlush;
+  static const Function glFramebufferRenderbuffer = Message_Function_glFramebufferRenderbuffer;
+  static const Function glFramebufferTexture2D = Message_Function_glFramebufferTexture2D;
+  static const Function glFrontFace = Message_Function_glFrontFace;
+  static const Function glGenBuffers = Message_Function_glGenBuffers;
+  static const Function glGenerateMipmap = Message_Function_glGenerateMipmap;
+  static const Function glGenFramebuffers = Message_Function_glGenFramebuffers;
+  static const Function glGenRenderbuffers = Message_Function_glGenRenderbuffers;
+  static const Function glGenTextures = Message_Function_glGenTextures;
+  static const Function glGetActiveAttrib = Message_Function_glGetActiveAttrib;
+  static const Function glGetActiveUniform = Message_Function_glGetActiveUniform;
+  static const Function glGetAttachedShaders = Message_Function_glGetAttachedShaders;
+  static const Function glGetAttribLocation = Message_Function_glGetAttribLocation;
+  static const Function glGetBooleanv = Message_Function_glGetBooleanv;
+  static const Function glGetBufferParameteriv = Message_Function_glGetBufferParameteriv;
+  static const Function glGetError = Message_Function_glGetError;
+  static const Function glGetFloatv = Message_Function_glGetFloatv;
+  static const Function glGetFramebufferAttachmentParameteriv = Message_Function_glGetFramebufferAttachmentParameteriv;
+  static const Function glGetIntegerv = Message_Function_glGetIntegerv;
+  static const Function glGetProgramiv = Message_Function_glGetProgramiv;
+  static const Function glGetProgramInfoLog = Message_Function_glGetProgramInfoLog;
+  static const Function glGetRenderbufferParameteriv = Message_Function_glGetRenderbufferParameteriv;
+  static const Function glGetShaderiv = Message_Function_glGetShaderiv;
+  static const Function glGetShaderInfoLog = Message_Function_glGetShaderInfoLog;
+  static const Function glGetShaderPrecisionFormat = Message_Function_glGetShaderPrecisionFormat;
+  static const Function glGetShaderSource = Message_Function_glGetShaderSource;
+  static const Function glGetString = Message_Function_glGetString;
+  static const Function glGetTexParameterfv = Message_Function_glGetTexParameterfv;
+  static const Function glGetTexParameteriv = Message_Function_glGetTexParameteriv;
+  static const Function glGetUniformfv = Message_Function_glGetUniformfv;
+  static const Function glGetUniformiv = Message_Function_glGetUniformiv;
+  static const Function glGetUniformLocation = Message_Function_glGetUniformLocation;
+  static const Function glGetVertexAttribfv = Message_Function_glGetVertexAttribfv;
+  static const Function glGetVertexAttribiv = Message_Function_glGetVertexAttribiv;
+  static const Function glGetVertexAttribPointerv = Message_Function_glGetVertexAttribPointerv;
+  static const Function glHint = Message_Function_glHint;
+  static const Function glIsBuffer = Message_Function_glIsBuffer;
+  static const Function glIsEnabled = Message_Function_glIsEnabled;
+  static const Function glIsFramebuffer = Message_Function_glIsFramebuffer;
+  static const Function glIsProgram = Message_Function_glIsProgram;
+  static const Function glIsRenderbuffer = Message_Function_glIsRenderbuffer;
+  static const Function glIsShader = Message_Function_glIsShader;
+  static const Function glIsTexture = Message_Function_glIsTexture;
+  static const Function glLineWidth = Message_Function_glLineWidth;
+  static const Function glLinkProgram = Message_Function_glLinkProgram;
+  static const Function glPixelStorei = Message_Function_glPixelStorei;
+  static const Function glPolygonOffset = Message_Function_glPolygonOffset;
+  static const Function glReadPixels = Message_Function_glReadPixels;
+  static const Function glReleaseShaderCompiler = Message_Function_glReleaseShaderCompiler;
+  static const Function glRenderbufferStorage = Message_Function_glRenderbufferStorage;
+  static const Function glSampleCoverage = Message_Function_glSampleCoverage;
+  static const Function glScissor = Message_Function_glScissor;
+  static const Function glShaderBinary = Message_Function_glShaderBinary;
+  static const Function glShaderSource = Message_Function_glShaderSource;
+  static const Function glStencilFunc = Message_Function_glStencilFunc;
+  static const Function glStencilFuncSeparate = Message_Function_glStencilFuncSeparate;
+  static const Function glStencilMask = Message_Function_glStencilMask;
+  static const Function glStencilMaskSeparate = Message_Function_glStencilMaskSeparate;
+  static const Function glStencilOp = Message_Function_glStencilOp;
+  static const Function glStencilOpSeparate = Message_Function_glStencilOpSeparate;
+  static const Function glTexImage2D = Message_Function_glTexImage2D;
+  static const Function glTexParameterf = Message_Function_glTexParameterf;
+  static const Function glTexParameterfv = Message_Function_glTexParameterfv;
+  static const Function glTexParameteri = Message_Function_glTexParameteri;
+  static const Function glTexParameteriv = Message_Function_glTexParameteriv;
+  static const Function glTexSubImage2D = Message_Function_glTexSubImage2D;
+  static const Function glUniform1f = Message_Function_glUniform1f;
+  static const Function glUniform1fv = Message_Function_glUniform1fv;
+  static const Function glUniform1i = Message_Function_glUniform1i;
+  static const Function glUniform1iv = Message_Function_glUniform1iv;
+  static const Function glUniform2f = Message_Function_glUniform2f;
+  static const Function glUniform2fv = Message_Function_glUniform2fv;
+  static const Function glUniform2i = Message_Function_glUniform2i;
+  static const Function glUniform2iv = Message_Function_glUniform2iv;
+  static const Function glUniform3f = Message_Function_glUniform3f;
+  static const Function glUniform3fv = Message_Function_glUniform3fv;
+  static const Function glUniform3i = Message_Function_glUniform3i;
+  static const Function glUniform3iv = Message_Function_glUniform3iv;
+  static const Function glUniform4f = Message_Function_glUniform4f;
+  static const Function glUniform4fv = Message_Function_glUniform4fv;
+  static const Function glUniform4i = Message_Function_glUniform4i;
+  static const Function glUniform4iv = Message_Function_glUniform4iv;
+  static const Function glUniformMatrix2fv = Message_Function_glUniformMatrix2fv;
+  static const Function glUniformMatrix3fv = Message_Function_glUniformMatrix3fv;
+  static const Function glUniformMatrix4fv = Message_Function_glUniformMatrix4fv;
+  static const Function glUseProgram = Message_Function_glUseProgram;
+  static const Function glValidateProgram = Message_Function_glValidateProgram;
+  static const Function glVertexAttrib1f = Message_Function_glVertexAttrib1f;
+  static const Function glVertexAttrib1fv = Message_Function_glVertexAttrib1fv;
+  static const Function glVertexAttrib2f = Message_Function_glVertexAttrib2f;
+  static const Function glVertexAttrib2fv = Message_Function_glVertexAttrib2fv;
+  static const Function glVertexAttrib3f = Message_Function_glVertexAttrib3f;
+  static const Function glVertexAttrib3fv = Message_Function_glVertexAttrib3fv;
+  static const Function glVertexAttrib4f = Message_Function_glVertexAttrib4f;
+  static const Function glVertexAttrib4fv = Message_Function_glVertexAttrib4fv;
+  static const Function glVertexAttribPointer = Message_Function_glVertexAttribPointer;
+  static const Function glViewport = Message_Function_glViewport;
+  static const Function eglGetDisplay = Message_Function_eglGetDisplay;
+  static const Function eglInitialize = Message_Function_eglInitialize;
+  static const Function eglTerminate = Message_Function_eglTerminate;
+  static const Function eglGetConfigs = Message_Function_eglGetConfigs;
+  static const Function eglChooseConfig = Message_Function_eglChooseConfig;
+  static const Function eglGetConfigAttrib = Message_Function_eglGetConfigAttrib;
+  static const Function eglCreateWindowSurface = Message_Function_eglCreateWindowSurface;
+  static const Function eglCreatePixmapSurface = Message_Function_eglCreatePixmapSurface;
+  static const Function eglCreatePbufferSurface = Message_Function_eglCreatePbufferSurface;
+  static const Function eglDestroySurface = Message_Function_eglDestroySurface;
+  static const Function eglQuerySurface = Message_Function_eglQuerySurface;
+  static const Function eglCreateContext = Message_Function_eglCreateContext;
+  static const Function eglDestroyContext = Message_Function_eglDestroyContext;
+  static const Function eglMakeCurrent = Message_Function_eglMakeCurrent;
+  static const Function eglGetCurrentContext = Message_Function_eglGetCurrentContext;
+  static const Function eglGetCurrentSurface = Message_Function_eglGetCurrentSurface;
+  static const Function eglGetCurrentDisplay = Message_Function_eglGetCurrentDisplay;
+  static const Function eglQueryContext = Message_Function_eglQueryContext;
+  static const Function eglWaitGL = Message_Function_eglWaitGL;
+  static const Function eglWaitNative = Message_Function_eglWaitNative;
+  static const Function eglSwapBuffers = Message_Function_eglSwapBuffers;
+  static const Function eglCopyBuffers = Message_Function_eglCopyBuffers;
+  static const Function eglGetError = Message_Function_eglGetError;
+  static const Function eglQueryString = Message_Function_eglQueryString;
+  static const Function eglGetProcAddress = Message_Function_eglGetProcAddress;
+  static const Function eglSurfaceAttrib = Message_Function_eglSurfaceAttrib;
+  static const Function eglBindTexImage = Message_Function_eglBindTexImage;
+  static const Function eglReleaseTexImage = Message_Function_eglReleaseTexImage;
+  static const Function eglSwapInterval = Message_Function_eglSwapInterval;
+  static const Function eglBindAPI = Message_Function_eglBindAPI;
+  static const Function eglQueryAPI = Message_Function_eglQueryAPI;
+  static const Function eglWaitClient = Message_Function_eglWaitClient;
+  static const Function eglReleaseThread = Message_Function_eglReleaseThread;
+  static const Function eglCreatePbufferFromClientBuffer = Message_Function_eglCreatePbufferFromClientBuffer;
+  static const Function eglLockSurfaceKHR = Message_Function_eglLockSurfaceKHR;
+  static const Function eglUnlockSurfaceKHR = Message_Function_eglUnlockSurfaceKHR;
+  static const Function eglCreateImageKHR = Message_Function_eglCreateImageKHR;
+  static const Function eglDestroyImageKHR = Message_Function_eglDestroyImageKHR;
+  static const Function eglCreateSyncKHR = Message_Function_eglCreateSyncKHR;
+  static const Function eglDestroySyncKHR = Message_Function_eglDestroySyncKHR;
+  static const Function eglClientWaitSyncKHR = Message_Function_eglClientWaitSyncKHR;
+  static const Function eglGetSyncAttribKHR = Message_Function_eglGetSyncAttribKHR;
+  static const Function eglSetSwapRectangleANDROID = Message_Function_eglSetSwapRectangleANDROID;
+  static const Function eglGetRenderBufferANDROID = Message_Function_eglGetRenderBufferANDROID;
+  static const Function ACK = Message_Function_ACK;
+  static const Function NEG = Message_Function_NEG;
+  static const Function CONTINUE = Message_Function_CONTINUE;
+  static const Function SKIP = Message_Function_SKIP;
+  static const Function SETPROP = Message_Function_SETPROP;
+  static const Function CAPTURE = Message_Function_CAPTURE;
+  static inline bool Function_IsValid(int value) {
+    return Message_Function_IsValid(value);
+  }
+  static const Function Function_MIN =
+    Message_Function_Function_MIN;
+  static const Function Function_MAX =
+    Message_Function_Function_MAX;
+  static const int Function_ARRAYSIZE =
+    Message_Function_Function_ARRAYSIZE;
+  
+  typedef Message_Type Type;
+  static const Type BeforeCall = Message_Type_BeforeCall;
+  static const Type AfterCall = Message_Type_AfterCall;
+  static const Type Response = Message_Type_Response;
+  static inline bool Type_IsValid(int value) {
+    return Message_Type_IsValid(value);
+  }
+  static const Type Type_MIN =
+    Message_Type_Type_MIN;
+  static const Type Type_MAX =
+    Message_Type_Type_MAX;
+  static const int Type_ARRAYSIZE =
+    Message_Type_Type_ARRAYSIZE;
+  
+  typedef Message_Prop Prop;
+  static const Prop Capture = Message_Prop_Capture;
+  static const Prop TimeMode = Message_Prop_TimeMode;
+  static inline bool Prop_IsValid(int value) {
+    return Message_Prop_IsValid(value);
+  }
+  static const Prop Prop_MIN =
+    Message_Prop_Prop_MIN;
+  static const Prop Prop_MAX =
+    Message_Prop_Prop_MAX;
+  static const int Prop_ARRAYSIZE =
+    Message_Prop_Prop_ARRAYSIZE;
+  
+  // accessors -------------------------------------------------------
+  
+  // required int32 context_id = 1;
+  inline bool has_context_id() const;
+  inline void clear_context_id();
+  static const int kContextIdFieldNumber = 1;
+  inline ::google::protobuf::int32 context_id() const;
+  inline void set_context_id(::google::protobuf::int32 value);
+  
+  // required .com.android.glesv2debugger.Message.Function function = 2 [default = NEG];
+  inline bool has_function() const;
+  inline void clear_function();
+  static const int kFunctionFieldNumber = 2;
+  inline ::com::android::glesv2debugger::Message_Function function() const;
+  inline void set_function(::com::android::glesv2debugger::Message_Function value);
+  
+  // required .com.android.glesv2debugger.Message.Type type = 3;
+  inline bool has_type() const;
+  inline void clear_type();
+  static const int kTypeFieldNumber = 3;
+  inline ::com::android::glesv2debugger::Message_Type type() const;
+  inline void set_type(::com::android::glesv2debugger::Message_Type value);
+  
+  // required bool expect_response = 4;
+  inline bool has_expect_response() const;
+  inline void clear_expect_response();
+  static const int kExpectResponseFieldNumber = 4;
+  inline bool expect_response() const;
+  inline void set_expect_response(bool value);
+  
+  // optional int32 ret = 5;
+  inline bool has_ret() const;
+  inline void clear_ret();
+  static const int kRetFieldNumber = 5;
+  inline ::google::protobuf::int32 ret() const;
+  inline void set_ret(::google::protobuf::int32 value);
+  
+  // optional int32 arg0 = 6;
+  inline bool has_arg0() const;
+  inline void clear_arg0();
+  static const int kArg0FieldNumber = 6;
+  inline ::google::protobuf::int32 arg0() const;
+  inline void set_arg0(::google::protobuf::int32 value);
+  
+  // optional int32 arg1 = 7;
+  inline bool has_arg1() const;
+  inline void clear_arg1();
+  static const int kArg1FieldNumber = 7;
+  inline ::google::protobuf::int32 arg1() const;
+  inline void set_arg1(::google::protobuf::int32 value);
+  
+  // optional int32 arg2 = 8;
+  inline bool has_arg2() const;
+  inline void clear_arg2();
+  static const int kArg2FieldNumber = 8;
+  inline ::google::protobuf::int32 arg2() const;
+  inline void set_arg2(::google::protobuf::int32 value);
+  
+  // optional int32 arg3 = 9;
+  inline bool has_arg3() const;
+  inline void clear_arg3();
+  static const int kArg3FieldNumber = 9;
+  inline ::google::protobuf::int32 arg3() const;
+  inline void set_arg3(::google::protobuf::int32 value);
+  
+  // optional int32 arg4 = 16;
+  inline bool has_arg4() const;
+  inline void clear_arg4();
+  static const int kArg4FieldNumber = 16;
+  inline ::google::protobuf::int32 arg4() const;
+  inline void set_arg4(::google::protobuf::int32 value);
+  
+  // optional int32 arg5 = 17;
+  inline bool has_arg5() const;
+  inline void clear_arg5();
+  static const int kArg5FieldNumber = 17;
+  inline ::google::protobuf::int32 arg5() const;
+  inline void set_arg5(::google::protobuf::int32 value);
+  
+  // optional int32 arg6 = 18;
+  inline bool has_arg6() const;
+  inline void clear_arg6();
+  static const int kArg6FieldNumber = 18;
+  inline ::google::protobuf::int32 arg6() const;
+  inline void set_arg6(::google::protobuf::int32 value);
+  
+  // optional int32 arg7 = 19;
+  inline bool has_arg7() const;
+  inline void clear_arg7();
+  static const int kArg7FieldNumber = 19;
+  inline ::google::protobuf::int32 arg7() const;
+  inline void set_arg7(::google::protobuf::int32 value);
+  
+  // optional int32 arg8 = 20;
+  inline bool has_arg8() const;
+  inline void clear_arg8();
+  static const int kArg8FieldNumber = 20;
+  inline ::google::protobuf::int32 arg8() const;
+  inline void set_arg8(::google::protobuf::int32 value);
+  
+  // optional bytes data = 10;
+  inline bool has_data() const;
+  inline void clear_data();
+  static const int kDataFieldNumber = 10;
+  inline const ::std::string& data() const;
+  inline void set_data(const ::std::string& value);
+  inline void set_data(const char* value);
+  inline void set_data(const void* value, size_t size);
+  inline ::std::string* mutable_data();
+  
+  // optional float time = 11;
+  inline bool has_time() const;
+  inline void clear_time();
+  static const int kTimeFieldNumber = 11;
+  inline float time() const;
+  inline void set_time(float value);
+  
+  // optional .com.android.glesv2debugger.Message.Prop prop = 21;
+  inline bool has_prop() const;
+  inline void clear_prop();
+  static const int kPropFieldNumber = 21;
+  inline ::com::android::glesv2debugger::Message_Prop prop() const;
+  inline void set_prop(::com::android::glesv2debugger::Message_Prop value);
+  
+  // optional float clock = 22;
+  inline bool has_clock() const;
+  inline void clear_clock();
+  static const int kClockFieldNumber = 22;
+  inline float clock() const;
+  inline void set_clock(float value);
+  
+  // @@protoc_insertion_point(class_scope:com.android.glesv2debugger.Message)
+ private:
+  mutable int _cached_size_;
+  
+  ::google::protobuf::int32 context_id_;
+  int function_;
+  int type_;
+  bool expect_response_;
+  ::google::protobuf::int32 ret_;
+  ::google::protobuf::int32 arg0_;
+  ::google::protobuf::int32 arg1_;
+  ::google::protobuf::int32 arg2_;
+  ::google::protobuf::int32 arg3_;
+  ::google::protobuf::int32 arg4_;
+  ::google::protobuf::int32 arg5_;
+  ::google::protobuf::int32 arg6_;
+  ::google::protobuf::int32 arg7_;
+  ::google::protobuf::int32 arg8_;
+  ::std::string* data_;
+  static const ::std::string _default_data_;
+  float time_;
+  int prop_;
+  float clock_;
+  friend void  protobuf_AddDesc_debugger_5fmessage_2eproto();
+  friend void protobuf_AssignDesc_debugger_5fmessage_2eproto();
+  friend void protobuf_ShutdownFile_debugger_5fmessage_2eproto();
+  
+  ::google::protobuf::uint32 _has_bits_[(18 + 31) / 32];
+  
+  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
+  inline bool _has_bit(int index) const {
+    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
+  }
+  inline void _set_bit(int index) {
+    _has_bits_[index / 32] |= (1u << (index % 32));
+  }
+  inline void _clear_bit(int index) {
+    _has_bits_[index / 32] &= ~(1u << (index % 32));
+  }
+  
+  void InitAsDefaultInstance();
+  static Message* default_instance_;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+// Message
+
+// required int32 context_id = 1;
+inline bool Message::has_context_id() const {
+  return _has_bit(0);
+}
+inline void Message::clear_context_id() {
+  context_id_ = 0;
+  _clear_bit(0);
+}
+inline ::google::protobuf::int32 Message::context_id() const {
+  return context_id_;
+}
+inline void Message::set_context_id(::google::protobuf::int32 value) {
+  _set_bit(0);
+  context_id_ = value;
+}
+
+// required .com.android.glesv2debugger.Message.Function function = 2 [default = NEG];
+inline bool Message::has_function() const {
+  return _has_bit(1);
+}
+inline void Message::clear_function() {
+  function_ = 187;
+  _clear_bit(1);
+}
+inline ::com::android::glesv2debugger::Message_Function Message::function() const {
+  return static_cast< ::com::android::glesv2debugger::Message_Function >(function_);
+}
+inline void Message::set_function(::com::android::glesv2debugger::Message_Function value) {
+  GOOGLE_DCHECK(::com::android::glesv2debugger::Message_Function_IsValid(value));
+  _set_bit(1);
+  function_ = value;
+}
+
+// required .com.android.glesv2debugger.Message.Type type = 3;
+inline bool Message::has_type() const {
+  return _has_bit(2);
+}
+inline void Message::clear_type() {
+  type_ = 0;
+  _clear_bit(2);
+}
+inline ::com::android::glesv2debugger::Message_Type Message::type() const {
+  return static_cast< ::com::android::glesv2debugger::Message_Type >(type_);
+}
+inline void Message::set_type(::com::android::glesv2debugger::Message_Type value) {
+  GOOGLE_DCHECK(::com::android::glesv2debugger::Message_Type_IsValid(value));
+  _set_bit(2);
+  type_ = value;
+}
+
+// required bool expect_response = 4;
+inline bool Message::has_expect_response() const {
+  return _has_bit(3);
+}
+inline void Message::clear_expect_response() {
+  expect_response_ = false;
+  _clear_bit(3);
+}
+inline bool Message::expect_response() const {
+  return expect_response_;
+}
+inline void Message::set_expect_response(bool value) {
+  _set_bit(3);
+  expect_response_ = value;
+}
+
+// optional int32 ret = 5;
+inline bool Message::has_ret() const {
+  return _has_bit(4);
+}
+inline void Message::clear_ret() {
+  ret_ = 0;
+  _clear_bit(4);
+}
+inline ::google::protobuf::int32 Message::ret() const {
+  return ret_;
+}
+inline void Message::set_ret(::google::protobuf::int32 value) {
+  _set_bit(4);
+  ret_ = value;
+}
+
+// optional int32 arg0 = 6;
+inline bool Message::has_arg0() const {
+  return _has_bit(5);
+}
+inline void Message::clear_arg0() {
+  arg0_ = 0;
+  _clear_bit(5);
+}
+inline ::google::protobuf::int32 Message::arg0() const {
+  return arg0_;
+}
+inline void Message::set_arg0(::google::protobuf::int32 value) {
+  _set_bit(5);
+  arg0_ = value;
+}
+
+// optional int32 arg1 = 7;
+inline bool Message::has_arg1() const {
+  return _has_bit(6);
+}
+inline void Message::clear_arg1() {
+  arg1_ = 0;
+  _clear_bit(6);
+}
+inline ::google::protobuf::int32 Message::arg1() const {
+  return arg1_;
+}
+inline void Message::set_arg1(::google::protobuf::int32 value) {
+  _set_bit(6);
+  arg1_ = value;
+}
+
+// optional int32 arg2 = 8;
+inline bool Message::has_arg2() const {
+  return _has_bit(7);
+}
+inline void Message::clear_arg2() {
+  arg2_ = 0;
+  _clear_bit(7);
+}
+inline ::google::protobuf::int32 Message::arg2() const {
+  return arg2_;
+}
+inline void Message::set_arg2(::google::protobuf::int32 value) {
+  _set_bit(7);
+  arg2_ = value;
+}
+
+// optional int32 arg3 = 9;
+inline bool Message::has_arg3() const {
+  return _has_bit(8);
+}
+inline void Message::clear_arg3() {
+  arg3_ = 0;
+  _clear_bit(8);
+}
+inline ::google::protobuf::int32 Message::arg3() const {
+  return arg3_;
+}
+inline void Message::set_arg3(::google::protobuf::int32 value) {
+  _set_bit(8);
+  arg3_ = value;
+}
+
+// optional int32 arg4 = 16;
+inline bool Message::has_arg4() const {
+  return _has_bit(9);
+}
+inline void Message::clear_arg4() {
+  arg4_ = 0;
+  _clear_bit(9);
+}
+inline ::google::protobuf::int32 Message::arg4() const {
+  return arg4_;
+}
+inline void Message::set_arg4(::google::protobuf::int32 value) {
+  _set_bit(9);
+  arg4_ = value;
+}
+
+// optional int32 arg5 = 17;
+inline bool Message::has_arg5() const {
+  return _has_bit(10);
+}
+inline void Message::clear_arg5() {
+  arg5_ = 0;
+  _clear_bit(10);
+}
+inline ::google::protobuf::int32 Message::arg5() const {
+  return arg5_;
+}
+inline void Message::set_arg5(::google::protobuf::int32 value) {
+  _set_bit(10);
+  arg5_ = value;
+}
+
+// optional int32 arg6 = 18;
+inline bool Message::has_arg6() const {
+  return _has_bit(11);
+}
+inline void Message::clear_arg6() {
+  arg6_ = 0;
+  _clear_bit(11);
+}
+inline ::google::protobuf::int32 Message::arg6() const {
+  return arg6_;
+}
+inline void Message::set_arg6(::google::protobuf::int32 value) {
+  _set_bit(11);
+  arg6_ = value;
+}
+
+// optional int32 arg7 = 19;
+inline bool Message::has_arg7() const {
+  return _has_bit(12);
+}
+inline void Message::clear_arg7() {
+  arg7_ = 0;
+  _clear_bit(12);
+}
+inline ::google::protobuf::int32 Message::arg7() const {
+  return arg7_;
+}
+inline void Message::set_arg7(::google::protobuf::int32 value) {
+  _set_bit(12);
+  arg7_ = value;
+}
+
+// optional int32 arg8 = 20;
+inline bool Message::has_arg8() const {
+  return _has_bit(13);
+}
+inline void Message::clear_arg8() {
+  arg8_ = 0;
+  _clear_bit(13);
+}
+inline ::google::protobuf::int32 Message::arg8() const {
+  return arg8_;
+}
+inline void Message::set_arg8(::google::protobuf::int32 value) {
+  _set_bit(13);
+  arg8_ = value;
+}
+
+// optional bytes data = 10;
+inline bool Message::has_data() const {
+  return _has_bit(14);
+}
+inline void Message::clear_data() {
+  if (data_ != &_default_data_) {
+    data_->clear();
+  }
+  _clear_bit(14);
+}
+inline const ::std::string& Message::data() const {
+  return *data_;
+}
+inline void Message::set_data(const ::std::string& value) {
+  _set_bit(14);
+  if (data_ == &_default_data_) {
+    data_ = new ::std::string;
+  }
+  data_->assign(value);
+}
+inline void Message::set_data(const char* value) {
+  _set_bit(14);
+  if (data_ == &_default_data_) {
+    data_ = new ::std::string;
+  }
+  data_->assign(value);
+}
+inline void Message::set_data(const void* value, size_t size) {
+  _set_bit(14);
+  if (data_ == &_default_data_) {
+    data_ = new ::std::string;
+  }
+  data_->assign(reinterpret_cast<const char*>(value), size);
+}
+inline ::std::string* Message::mutable_data() {
+  _set_bit(14);
+  if (data_ == &_default_data_) {
+    data_ = new ::std::string;
+  }
+  return data_;
+}
+
+// optional float time = 11;
+inline bool Message::has_time() const {
+  return _has_bit(15);
+}
+inline void Message::clear_time() {
+  time_ = 0;
+  _clear_bit(15);
+}
+inline float Message::time() const {
+  return time_;
+}
+inline void Message::set_time(float value) {
+  _set_bit(15);
+  time_ = value;
+}
+
+// optional .com.android.glesv2debugger.Message.Prop prop = 21;
+inline bool Message::has_prop() const {
+  return _has_bit(16);
+}
+inline void Message::clear_prop() {
+  prop_ = 0;
+  _clear_bit(16);
+}
+inline ::com::android::glesv2debugger::Message_Prop Message::prop() const {
+  return static_cast< ::com::android::glesv2debugger::Message_Prop >(prop_);
+}
+inline void Message::set_prop(::com::android::glesv2debugger::Message_Prop value) {
+  GOOGLE_DCHECK(::com::android::glesv2debugger::Message_Prop_IsValid(value));
+  _set_bit(16);
+  prop_ = value;
+}
+
+// optional float clock = 22;
+inline bool Message::has_clock() const {
+  return _has_bit(17);
+}
+inline void Message::clear_clock() {
+  clock_ = 0;
+  _clear_bit(17);
+}
+inline float Message::clock() const {
+  return clock_;
+}
+inline void Message::set_clock(float value) {
+  _set_bit(17);
+  clock_ = value;
+}
+
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace glesv2debugger
+}  // namespace android
+}  // namespace com
+
+// @@protoc_insertion_point(global_scope)
+
+#endif  // PROTOBUF_debugger_5fmessage_2eproto__INCLUDED
diff --git a/opengl/libs/GLES2_dbg/src/egl.cpp b/opengl/libs/GLES2_dbg/src/egl.cpp
new file mode 100644
index 0000000..b3979a3
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/src/egl.cpp
@@ -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));
+}
diff --git a/opengl/libs/GLES2_dbg/src/header.h b/opengl/libs/GLES2_dbg/src/header.h
index e1b194d..bb59ba0 100644
--- a/opengl/libs/GLES2_dbg/src/header.h
+++ b/opengl/libs/GLES2_dbg/src/header.h
@@ -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 @@
 
 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 {
diff --git a/opengl/libs/GLES2_dbg/src/server.cpp b/opengl/libs/GLES2_dbg/src/server.cpp
index 33f78e4..67f0e5b 100644
--- a/opengl/libs/GLES2_dbg/src/server.cpp
+++ b/opengl/libs/GLES2_dbg/src/server.cpp
@@ -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 @@
     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 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 @@
         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 {
diff --git a/opengl/libs/GLES2_dbg/src/shader.cpp b/opengl/libs/GLES2_dbg/src/shader.cpp
index c2b2557..924fc8f 100644
--- a/opengl/libs/GLES2_dbg/src/shader.cpp
+++ b/opengl/libs/GLES2_dbg/src/shader.cpp
@@ -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 @@
         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);
+}
\ No newline at end of file
diff --git a/opengl/libs/GLES2_dbg/src/texture.cpp b/opengl/libs/GLES2_dbg/src/texture.cpp
index a149487..3aa0aab 100644
--- a/opengl/libs/GLES2_dbg/src/texture.cpp
+++ b/opengl/libs/GLES2_dbg/src/texture.cpp
@@ -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 @@
             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 @@
     }
 }
 #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 @@
     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 @@
         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 @@
     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 @@
         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);
+}
\ No newline at end of file
diff --git a/opengl/libs/GLES2_dbg/src/vertex.cpp b/opengl/libs/GLES2_dbg/src/vertex.cpp
new file mode 100644
index 0000000..893e072
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/src/vertex.cpp
@@ -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;
+        }
+    }
+}