GLES2Debugger: Make command exchange async to improve performance.

In message loop, use select to check for available commands from client,
 rather than always expecting commands in eglSwapBuffers.

Change-Id: Ifc34dd77c2528c8b9c71f594e3eda4f93400cd2b
Signed-off-by: David Li <davidxli@google.com>
This commit is contained in:
David Li
2011-03-10 19:07:42 -08:00
parent 08758fad84
commit 940c3f8b36
10 changed files with 98 additions and 69 deletions

View File

@@ -340,7 +340,10 @@ static void initEglTraceLevel() {
}
if (gEGLDebugLevel > 0)
StartDebugServer();
{
property_get("debug.egl.debug_port", value, "5039");
StartDebugServer(atoi(value));
}
}
static void setGLHooksThreadSpecific(gl_hooks_t const *value) {
@@ -350,7 +353,6 @@ static void setGLHooksThreadSpecific(gl_hooks_t const *value) {
} else if (gEGLDebugLevel > 0 && value != &gHooksNoContext) {
setGlTraceThreadSpecific(value);
setGlThreadSpecific(&gHooksDebug);
LOGD("\n* setGLHooksThreadSpecific gHooksDebug");
} else {
setGlThreadSpecific(value);
}

View File

@@ -98,9 +98,6 @@ message Message
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

View File

@@ -65,8 +65,9 @@ void DbgContext::Fetch(const unsigned index, std::string * const data) const
void DbgContext::glUseProgram(GLuint program)
{
assert(GL_NO_ERROR == hooks->gl.glGetError());
while (GLenum error = hooks->gl.glGetError())
LOGD("DbgContext::glUseProgram: before glGetError() = 0x%.4X", error);
this->program = program;
GLint activeAttributes = 0;
@@ -106,6 +107,9 @@ void DbgContext::glUseProgram(GLuint program)
maxAttrib = slot;
}
delete name;
while (GLenum error = hooks->gl.glGetError())
LOGD("DbgContext::glUseProgram: after glGetError() = 0x%.4X", error);
}
static bool HasNonVBOAttribs(const DbgContext * const ctx)

View File

@@ -229,7 +229,6 @@ bool Message_Function_IsValid(int value) {
case 188:
case 189:
case 190:
case 191:
return true;
default:
return false;
@@ -428,7 +427,6 @@ 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;

View File

@@ -226,12 +226,11 @@ enum Message_Function {
Message_Function_NEG = 187,
Message_Function_CONTINUE = 188,
Message_Function_SKIP = 189,
Message_Function_SETPROP = 190,
Message_Function_CAPTURE = 191
Message_Function_SETPROP = 190
};
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 Message_Function Message_Function_Function_MAX = Message_Function_SETPROP;
const int Message_Function_Function_ARRAYSIZE = Message_Function_Function_MAX + 1;
enum Message_Type {
@@ -488,7 +487,6 @@ class Message : public ::google::protobuf::MessageLite {
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);
}

View File

@@ -19,7 +19,7 @@
EGLBoolean Debug_eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
{
glesv2debugger::Message msg;
const bool expectResponse = true;
const bool expectResponse = false;
struct : public FunctionCall {
EGLDisplay dpy;
EGLSurface draw;

View File

@@ -113,7 +113,7 @@ struct FunctionCall {
virtual ~FunctionCall() {}
};
// move these into DbgContext
// move these into DbgContext as static
extern bool capture;
extern int timeMode; // SYSTEM_TIME_
@@ -121,8 +121,10 @@ extern int clientSock, serverSock;
unsigned GetBytesPerPixel(const GLenum format, const GLenum type);
// every Debug_gl* function calls this to send message to client and possibly receive commands
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);

View File

@@ -38,7 +38,7 @@ static void Die(const char * msg)
exit(1);
}
void StartDebugServer()
void StartDebugServer(unsigned short port)
{
LOGD("GLESv2_dbg: StartDebugServer");
if (serverSock >= 0)
@@ -53,8 +53,8 @@ void StartDebugServer()
}
/* Construct the server sockaddr_in structure */
server.sin_family = AF_INET; /* Internet/IP */
server.sin_addr.s_addr = htonl(INADDR_ANY); /* Incoming addr */
server.sin_port = htons(5039); /* server port */
server.sin_addr.s_addr = htonl(INADDR_LOOPBACK); /* Incoming addr */
server.sin_port = htons(port); /* server port */
/* Bind the server socket */
socklen_t sizeofSockaddr_in = sizeof(sockaddr_in);
@@ -79,13 +79,6 @@ void StartDebugServer()
LOGD("Client connected: %s\n", inet_ntoa(client.sin_addr));
// fcntl(clientSock, F_SETFL, O_NONBLOCK);
glesv2debugger::Message msg, cmd;
msg.set_context_id(0);
msg.set_function(glesv2debugger::Message_Function_ACK);
msg.set_type(glesv2debugger::Message_Type_Response);
msg.set_expect_response(false);
Send(msg, cmd);
}
void StopDebugServer()
@@ -130,6 +123,27 @@ void Receive(glesv2debugger::Message & cmd)
cmd.ParseFromArray(buffer, len);
}
bool TryReceive(glesv2debugger::Message & cmd)
{
fd_set readSet;
FD_ZERO(&readSet);
FD_SET(clientSock, &readSet);
timeval timeout;
timeout.tv_sec = timeout.tv_usec = 0;
int rc = select(clientSock + 1, &readSet, NULL, NULL, &timeout);
if (rc < 0)
Die("failed to select clientSock");
bool received = false;
if (FD_ISSET(clientSock, &readSet)) {
LOGD("TryReceive: avaiable for read");
Receive(cmd);
return true;
}
return false;
}
float Send(const glesv2debugger::Message & msg, glesv2debugger::Message & cmd)
{
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -155,12 +169,18 @@ float Send(const glesv2debugger::Message & msg, glesv2debugger::Message & cmd)
Die("Failed to send message");
}
// try to receive commands even though not expecting response,
// since client can send SETPROP commands anytime
if (!msg.expect_response()) {
pthread_mutex_unlock(&mutex);
return t;
}
Receive(cmd);
if (TryReceive(cmd)) {
LOGD("Send: TryReceived");
if (glesv2debugger::Message_Function_SETPROP == cmd.function())
LOGD("Send: received SETPROP");
else
LOGD("Send: received something else");
}
} else
Receive(cmd);
//LOGD("Message sent tid=%lu len=%d", pthread_self(), str.length());
pthread_mutex_unlock(&mutex);
@@ -193,24 +213,26 @@ int * MessageLoop(FunctionCall & functionCall, glesv2debugger::Message & msg,
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);
Send(msg, cmd);
while (true) {
msg.Clear();
nsecs_t c0 = systemTime(timeMode);
switch (cmd.function()) {
case glesv2debugger::Message_Function_CONTINUE:
ret = functionCall(&dbg->hooks->gl, msg);
while (GLenum error = dbg->hooks->gl.glGetError())
LOGD("Function=%u glGetError() = 0x%.4X", function, error);
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(reinterpret_cast<int>(dbg));
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);
Send(msg, cmd);
break;
case glesv2debugger::Message_Function_SKIP:
return const_cast<int *>(ret);

View File

@@ -41,10 +41,10 @@ void Debug_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
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);
Send(msg, cmd);
float t = 0;
while (true) {
msg.Clear();
nsecs_t c0 = systemTime(timeMode);
@@ -61,6 +61,8 @@ void Debug_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
//msg.set_data(data, encodedSize);
//free(data);
c0 = systemTime(timeMode);
if (!expectResponse)
cmd.set_function(glesv2debugger::Message_Function_SKIP);
t = Send(msg, cmd);
msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
msg.set_clock(t);
@@ -69,11 +71,13 @@ void Debug_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
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;
case glesv2debugger::Message_Function_SETPROP:
SetProp(cmd);
Receive(cmd);
break;
default:
assert(0); //GenerateCall(msg, cmd);
break;
@@ -104,9 +108,9 @@ void Debug_glDrawArrays(GLenum mode, GLint first, GLsizei count)
void * pixels = NULL;
GLint readFormat = 0, readType = 0;
int viewport[4] = {};
Send(msg, cmd);
if (!expectResponse)
cmd.set_function(glesv2debugger::Message_Function_CONTINUE);
Send(msg, cmd);
while (true) {
msg.Clear();
nsecs_t c0 = systemTime(timeMode);
@@ -118,25 +122,26 @@ void Debug_glDrawArrays(GLenum mode, GLint first, GLsizei count)
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)
if (!expectResponse)
cmd.set_function(glesv2debugger::Message_Function_SKIP);
Send(msg, cmd);
if (capture) {
dbg->hooks->gl.glGetIntegerv(GL_VIEWPORT, viewport);
dbg->hooks->gl.glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &readFormat);
dbg->hooks->gl.glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &readType);
LOGD("glDrawArrays CAPTURE: x=%d y=%d width=%d height=%d format=0x%.4X type=0x%.4X",
viewport[0], viewport[1], viewport[2], viewport[3], readFormat, readType);
pixels = malloc(viewport[2] * viewport[3] * 4);
Debug_glReadPixels(viewport[0], viewport[1], viewport[2], viewport[3],
readFormat, readType, pixels);
free(pixels);
}
break;
case glesv2debugger::Message_Function_SKIP:
return;
case glesv2debugger::Message_Function_CAPTURE:
dbg->hooks->gl.glGetIntegerv(GL_VIEWPORT, viewport);
dbg->hooks->gl.glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &readFormat);
dbg->hooks->gl.glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &readType);
LOGD("glDrawArrays CAPTURE: x=%d y=%d width=%d height=%d format=0x%.4X type=0x%.4X",
viewport[0], viewport[1], viewport[2], viewport[3], readFormat, readType);
pixels = malloc(viewport[2] * viewport[3] * 4);
Debug_glReadPixels(viewport[0], viewport[1], viewport[2], viewport[3],
readFormat, readType, pixels);
free(pixels);
cmd.set_function(glesv2debugger::Message_Function_SKIP);
case glesv2debugger::Message_Function_SETPROP:
SetProp(cmd);
Receive(cmd);
break;
default:
assert(0); //GenerateCall(msg, cmd);
@@ -189,9 +194,9 @@ void Debug_glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid*
void * pixels = NULL;
GLint readFormat = 0, readType = 0;
int viewport[4] = {};
Send(msg, cmd);
if (!expectResponse)
cmd.set_function(glesv2debugger::Message_Function_CONTINUE);
Send(msg, cmd);
while (true) {
msg.Clear();
nsecs_t c0 = systemTime(timeMode);
@@ -203,25 +208,26 @@ void Debug_glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid*
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)
if (!expectResponse)
cmd.set_function(glesv2debugger::Message_Function_SKIP);
Send(msg, cmd);
if (capture) {
dbg->hooks->gl.glGetIntegerv(GL_VIEWPORT, viewport);
dbg->hooks->gl.glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &readFormat);
dbg->hooks->gl.glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &readType);
LOGD("glDrawArrays CAPTURE: x=%d y=%d width=%d height=%d format=0x%.4X type=0x%.4X",
viewport[0], viewport[1], viewport[2], viewport[3], readFormat, readType);
pixels = malloc(viewport[2] * viewport[3] * 4);
Debug_glReadPixels(viewport[0], viewport[1], viewport[2], viewport[3],
readFormat, readType, pixels);
free(pixels);
}
break;
case glesv2debugger::Message_Function_SKIP:
return;
case glesv2debugger::Message_Function_CAPTURE:
dbg->hooks->gl.glGetIntegerv(GL_VIEWPORT, viewport);
dbg->hooks->gl.glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &readFormat);
dbg->hooks->gl.glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &readType);
LOGD("glDrawArrays CAPTURE: x=%d y=%d width=%d height=%d format=0x%.4X type=0x%.4X",
viewport[0], viewport[1], viewport[2], viewport[3], readFormat, readType);
pixels = malloc(viewport[2] * viewport[3] * 4);
Debug_glReadPixels(viewport[0], viewport[1], viewport[2], viewport[3],
readFormat, readType, pixels);
free(pixels);
cmd.set_function(glesv2debugger::Message_Function_SKIP);
case glesv2debugger::Message_Function_SETPROP:
SetProp(cmd);
Receive(cmd);
break;
default:
assert(0); //GenerateCall(msg, cmd);

View File

@@ -24,7 +24,7 @@ namespace android
DbgContext * CreateDbgContext(const unsigned version, const gl_hooks_t * const hooks);
void DestroyDbgContext(DbgContext * const dbg);
void StartDebugServer(); // create and bind socket if haven't already
void StartDebugServer(unsigned short port); // create and bind socket if haven't already
void StopDebugServer(); // close socket if open
}; // namespace android