gltrace: transport buffering and context management
This patch adds two improvements: 1. Protobuf messages are buffered and sent in chunks. 2. Multiple EGL contexts are handled properly: Corresponding to each EGLContext, a GLTraceContext with a unique ID is created. On eglMakeCurrent, the appropriate GLTraceContext is set and is used while tracing subsequent GL Calls in that thread. Change-Id: I34076376d3e5af205c87c7396ea47659844abd6e
This commit is contained in:
@@ -84,6 +84,9 @@ void initEglTraceLevel() {
|
||||
sEGLTraceLevel = propertyLevel > applicationLevel ? propertyLevel : applicationLevel;
|
||||
|
||||
property_get("debug.egl.debug_proc", value, "");
|
||||
if (strlen(value) == 0)
|
||||
return;
|
||||
|
||||
long pid = getpid();
|
||||
char procPath[128] = {};
|
||||
sprintf(procPath, "/proc/%ld/cmdline", pid);
|
||||
@@ -91,8 +94,11 @@ void initEglTraceLevel() {
|
||||
if (file) {
|
||||
char cmdline[256] = {};
|
||||
if (fgets(cmdline, sizeof(cmdline) - 1, file)) {
|
||||
if (!strcmp(value, cmdline))
|
||||
if (!strncmp(value, cmdline, strlen(value))) {
|
||||
// set EGL debug if the "debug.egl.debug_proc" property
|
||||
// matches the prefix of this application's command line
|
||||
gEGLDebugLevel = 1;
|
||||
}
|
||||
}
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
@@ -662,7 +662,7 @@ EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
|
||||
egl_tls_t::setContext(ctx);
|
||||
#if EGL_TRACE
|
||||
if (gEGLDebugLevel > 0)
|
||||
GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version]);
|
||||
GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx);
|
||||
#endif
|
||||
_c.acquire();
|
||||
_r.acquire();
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <cutils/log.h>
|
||||
|
||||
extern "C" {
|
||||
#include "liblzf/lzf.h"
|
||||
@@ -42,12 +43,8 @@ void setGLTraceContext(GLTraceContext *c) {
|
||||
pthread_setspecific(sTLSKey, c);
|
||||
}
|
||||
|
||||
void initContext(unsigned version, gl_hooks_t *hooks) {
|
||||
void setupTraceContextThreadSpecific(GLTraceContext *context) {
|
||||
pthread_once(&sPthreadOnceKey, createTLSKey);
|
||||
|
||||
GLTraceContext *context = new GLTraceContext();
|
||||
context->hooks = hooks;
|
||||
|
||||
setGLTraceContext(context);
|
||||
}
|
||||
|
||||
@@ -59,9 +56,47 @@ void releaseContext() {
|
||||
}
|
||||
}
|
||||
|
||||
GLTraceContext::GLTraceContext() {
|
||||
GLTraceState::GLTraceState(TCPStream *stream) {
|
||||
mTraceContextIds = 0;
|
||||
mStream = stream;
|
||||
}
|
||||
|
||||
GLTraceState::~GLTraceState() {
|
||||
if (mStream) {
|
||||
mStream->closeStream();
|
||||
mStream = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
TCPStream *GLTraceState::getStream() {
|
||||
return mStream;
|
||||
}
|
||||
|
||||
GLTraceContext *GLTraceState::createTraceContext(int version, EGLContext eglContext) {
|
||||
int id = __sync_fetch_and_add(&mTraceContextIds, 1);
|
||||
|
||||
const size_t DEFAULT_BUFFER_SIZE = 8192;
|
||||
BufferedOutputStream *stream = new BufferedOutputStream(mStream, DEFAULT_BUFFER_SIZE);
|
||||
GLTraceContext *traceContext = new GLTraceContext(id, stream);
|
||||
mPerContextState[eglContext] = traceContext;
|
||||
|
||||
return traceContext;
|
||||
}
|
||||
|
||||
GLTraceContext *GLTraceState::getTraceContext(EGLContext c) {
|
||||
return mPerContextState[c];
|
||||
}
|
||||
|
||||
GLTraceContext::GLTraceContext(int id, BufferedOutputStream *stream) {
|
||||
mId = id;
|
||||
|
||||
fbcontents = fbcompressed = NULL;
|
||||
fbcontentsSize = 0;
|
||||
mBufferedOutputStream = stream;
|
||||
}
|
||||
|
||||
int GLTraceContext::getId() {
|
||||
return mId;
|
||||
}
|
||||
|
||||
void GLTraceContext::resizeFBMemory(unsigned minSize) {
|
||||
@@ -115,5 +150,16 @@ void GLTraceContext::getCompressedFB(void **fb, unsigned *fbsize, unsigned *fbwi
|
||||
*fbheight = viewport[3];
|
||||
}
|
||||
|
||||
void GLTraceContext::traceGLMessage(GLMessage *msg) {
|
||||
mBufferedOutputStream->send(msg);
|
||||
|
||||
GLMessage_Function func = msg->function();
|
||||
if (func == GLMessage::eglSwapBuffers
|
||||
|| func == GLMessage::glDrawArrays
|
||||
|| func == GLMessage::glDrawElements) {
|
||||
mBufferedOutputStream->flush();
|
||||
}
|
||||
}
|
||||
|
||||
}; // namespace gltrace
|
||||
}; // namespace android
|
||||
|
||||
@@ -17,7 +17,10 @@
|
||||
#ifndef __GLTRACE_CONTEXT_H_
|
||||
#define __GLTRACE_CONTEXT_H_
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "hooks.h"
|
||||
#include "gltrace_transport.h"
|
||||
|
||||
namespace android {
|
||||
namespace gltrace {
|
||||
@@ -26,24 +29,45 @@ using ::android::gl_hooks_t;
|
||||
|
||||
enum FBBinding {CURRENTLY_BOUND_FB, FB0};
|
||||
|
||||
/** GL Trace Context info associated with each EGLContext */
|
||||
class GLTraceContext {
|
||||
int mId; /* unique context id */
|
||||
|
||||
void *fbcontents; /* memory area to read framebuffer contents */
|
||||
void *fbcompressed; /* destination for lzf compressed framebuffer */
|
||||
unsigned fbcontentsSize; /* size of fbcontents & fbcompressed buffers */
|
||||
|
||||
BufferedOutputStream *mBufferedOutputStream; /* stream where trace info is sent */
|
||||
|
||||
void resizeFBMemory(unsigned minSize);
|
||||
public:
|
||||
gl_hooks_t *hooks;
|
||||
|
||||
GLTraceContext();
|
||||
GLTraceContext(int id, BufferedOutputStream *stream);
|
||||
int getId();
|
||||
void getCompressedFB(void **fb, unsigned *fbsize,
|
||||
unsigned *fbwidth, unsigned *fbheight,
|
||||
FBBinding fbToRead);
|
||||
void traceGLMessage(GLMessage *msg);
|
||||
};
|
||||
|
||||
/** Per process trace state. */
|
||||
class GLTraceState {
|
||||
int mTraceContextIds;
|
||||
TCPStream *mStream;
|
||||
std::map<EGLContext, GLTraceContext*> mPerContextState;
|
||||
public:
|
||||
GLTraceState(TCPStream *stream);
|
||||
~GLTraceState();
|
||||
|
||||
GLTraceContext *createTraceContext(int version, EGLContext c);
|
||||
GLTraceContext *getTraceContext(EGLContext c);
|
||||
|
||||
TCPStream *getStream();
|
||||
};
|
||||
|
||||
void setupTraceContextThreadSpecific(GLTraceContext *context);
|
||||
GLTraceContext *getGLTraceContext();
|
||||
void setGLTraceContext(GLTraceContext *c);
|
||||
void initContext(unsigned version, gl_hooks_t *hooks);
|
||||
void releaseContext();
|
||||
|
||||
};
|
||||
|
||||
@@ -24,16 +24,54 @@
|
||||
namespace android {
|
||||
namespace gltrace {
|
||||
|
||||
void GLTrace_eglCreateContext(int version, int contextId) {
|
||||
GLMessage glmessage;
|
||||
GLTraceContext *glContext = getGLTraceContext();
|
||||
|
||||
glmessage.set_context_id(contextId);
|
||||
glmessage.set_function(GLMessage::eglCreateContext);
|
||||
|
||||
// copy argument version
|
||||
GLMessage_DataType *arg_version = glmessage.add_args();
|
||||
arg_version->set_isarray(false);
|
||||
arg_version->set_type(GLMessage::DataType::INT);
|
||||
arg_version->add_intvalue(version);
|
||||
|
||||
// copy argument context
|
||||
GLMessage_DataType *arg_context = glmessage.add_args();
|
||||
arg_context->set_isarray(false);
|
||||
arg_context->set_type(GLMessage::DataType::INT);
|
||||
arg_context->add_intvalue(contextId);
|
||||
|
||||
glContext->traceGLMessage(&glmessage);
|
||||
}
|
||||
|
||||
void GLTrace_eglMakeCurrent(int contextId) {
|
||||
GLMessage glmessage;
|
||||
GLTraceContext *glContext = getGLTraceContext();
|
||||
|
||||
glmessage.set_context_id(contextId);
|
||||
glmessage.set_function(GLMessage::eglMakeCurrent);
|
||||
|
||||
// copy argument context
|
||||
GLMessage_DataType *arg_context = glmessage.add_args();
|
||||
arg_context->set_isarray(false);
|
||||
arg_context->set_type(GLMessage::DataType::INT);
|
||||
arg_context->add_intvalue(contextId);
|
||||
|
||||
glContext->traceGLMessage(&glmessage);
|
||||
}
|
||||
|
||||
void GLTrace_eglSwapBuffers(void *dpy, void *draw) {
|
||||
GLMessage glmessage;
|
||||
GLTraceContext *glContext = getGLTraceContext();
|
||||
|
||||
glmessage.set_context_id(1);
|
||||
glmessage.set_context_id(glContext->getId());
|
||||
glmessage.set_function(GLMessage::eglSwapBuffers);
|
||||
|
||||
// read FB0 since that is what is displayed on the screen
|
||||
fixup_addFBContents(&glmessage, FB0);
|
||||
traceGLMessage(&glmessage);
|
||||
fixup_addFBContents(glContext, &glmessage, FB0);
|
||||
glContext->traceGLMessage(&glmessage);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
namespace android {
|
||||
namespace gltrace {
|
||||
|
||||
void GLTrace_eglCreateContext(int version, int contextId);
|
||||
void GLTrace_eglMakeCurrent(int contextId);
|
||||
void GLTrace_eglSwapBuffers(void *dpy, void *draw);
|
||||
|
||||
};
|
||||
|
||||
@@ -28,17 +28,11 @@
|
||||
|
||||
namespace android {
|
||||
|
||||
void GLTrace_eglMakeCurrent(const unsigned version, gl_hooks_t *hooks) {
|
||||
gltrace::initContext(version, hooks);
|
||||
}
|
||||
using gltrace::GLTraceState;
|
||||
using gltrace::GLTraceContext;
|
||||
using gltrace::TCPStream;
|
||||
|
||||
void GLTrace_eglReleaseThread() {
|
||||
gltrace::releaseContext();
|
||||
}
|
||||
|
||||
void GLTrace_eglCreateContext(int version, EGLContext c) {
|
||||
// TODO
|
||||
}
|
||||
static GLTraceState *sGLTraceState;
|
||||
|
||||
void GLTrace_start() {
|
||||
char value[PROPERTY_VALUE_MAX];
|
||||
@@ -46,19 +40,53 @@ void GLTrace_start() {
|
||||
property_get("debug.egl.debug_port", value, "5039");
|
||||
const unsigned short port = (unsigned short)atoi(value);
|
||||
|
||||
gltrace::startServer(port);
|
||||
int clientSocket = gltrace::acceptClientConnection(port);
|
||||
if (clientSocket < 0) {
|
||||
LOGE("Error creating GLTrace server socket. Quitting application.");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// create communication channel to the host
|
||||
TCPStream *stream = new TCPStream(clientSocket);
|
||||
|
||||
// initialize tracing state
|
||||
sGLTraceState = new GLTraceState(stream);
|
||||
}
|
||||
|
||||
void GLTrace_stop() {
|
||||
gltrace::stopServer();
|
||||
delete sGLTraceState;
|
||||
sGLTraceState = NULL;
|
||||
}
|
||||
|
||||
gl_hooks_t *GLTrace_getGLHooks() {
|
||||
return gltrace::getGLHooks();
|
||||
void GLTrace_eglCreateContext(int version, EGLContext c) {
|
||||
// update trace state for new EGL context
|
||||
GLTraceContext *traceContext = sGLTraceState->createTraceContext(version, c);
|
||||
gltrace::setupTraceContextThreadSpecific(traceContext);
|
||||
|
||||
// trace command through to the host
|
||||
gltrace::GLTrace_eglCreateContext(version, traceContext->getId());
|
||||
}
|
||||
|
||||
void GLTrace_eglMakeCurrent(const unsigned version, gl_hooks_t *hooks, EGLContext c) {
|
||||
// setup per context state
|
||||
GLTraceContext *traceContext = sGLTraceState->getTraceContext(c);
|
||||
traceContext->hooks = hooks;
|
||||
gltrace::setupTraceContextThreadSpecific(traceContext);
|
||||
|
||||
// trace command through to the host
|
||||
gltrace::GLTrace_eglMakeCurrent(traceContext->getId());
|
||||
}
|
||||
|
||||
void GLTrace_eglReleaseThread() {
|
||||
gltrace::releaseContext();
|
||||
}
|
||||
|
||||
void GLTrace_eglSwapBuffers(void *dpy, void *draw) {
|
||||
gltrace::GLTrace_eglSwapBuffers(dpy, draw);
|
||||
}
|
||||
|
||||
gl_hooks_t *GLTrace_getGLHooks() {
|
||||
return gltrace::getGLHooks();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -96,10 +96,10 @@ void fixup_glGetString(GLMessage *glmsg) {
|
||||
}
|
||||
|
||||
/* Add the contents of the framebuffer to the protobuf message */
|
||||
void fixup_addFBContents(GLMessage *glmsg, FBBinding fbToRead) {
|
||||
void fixup_addFBContents(GLTraceContext *context, GLMessage *glmsg, FBBinding fbToRead) {
|
||||
void *fbcontents;
|
||||
unsigned fbsize, fbwidth, fbheight;
|
||||
getGLTraceContext()->getCompressedFB(&fbcontents, &fbsize, &fbwidth, &fbheight, fbToRead);
|
||||
context->getCompressedFB(&fbcontents, &fbsize, &fbwidth, &fbheight, fbToRead);
|
||||
|
||||
GLMessage_FrameBuffer *fb = glmsg->mutable_fb();
|
||||
fb->set_width(fbwidth);
|
||||
@@ -240,7 +240,11 @@ void fixup_glGetFloatv(GLMessage *glmsg) {
|
||||
arg_params->add_floatvalue(*src);
|
||||
}
|
||||
|
||||
void fixupGLMessage(GLMessage *glmsg) {
|
||||
void fixupGLMessage(GLTraceContext *context, GLMessage *glmsg) {
|
||||
// for all messages, set the current context id
|
||||
glmsg->set_context_id(context->getId());
|
||||
|
||||
// do any custom message dependent processing
|
||||
switch (glmsg->function()) {
|
||||
case GLMessage::glGenBuffers: /* void glGenBuffers(GLsizei n, GLuint * buffers); */
|
||||
case GLMessage::glGenFramebuffers: /* void glGenFramebuffers(GLsizei n, GLuint * buffers); */
|
||||
@@ -299,7 +303,7 @@ void fixupGLMessage(GLMessage *glmsg) {
|
||||
case GLMessage::glDrawElements:
|
||||
/* void glDrawArrays(GLenum mode, GLint first, GLsizei count) */
|
||||
/* void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) */
|
||||
fixup_addFBContents(glmsg, CURRENTLY_BOUND_FB);
|
||||
fixup_addFBContents(context, glmsg, CURRENTLY_BOUND_FB);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
namespace android {
|
||||
namespace gltrace {
|
||||
|
||||
void fixupGLMessage(GLMessage *message);
|
||||
void fixup_addFBContents(GLMessage *message, FBBinding fbToRead);
|
||||
void fixupGLMessage(GLTraceContext *curContext, GLMessage *message);
|
||||
void fixup_addFBContents(GLTraceContext *curContext, GLMessage *message, FBBinding fbToRead);
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
@@ -28,85 +28,119 @@
|
||||
namespace android {
|
||||
namespace gltrace {
|
||||
|
||||
int gServerSocket, gClientSocket;
|
||||
|
||||
void startServer(int port) {
|
||||
if (gServerSocket > 0) {
|
||||
ALOGD("startServer: server socket already open!");
|
||||
return;
|
||||
}
|
||||
|
||||
gServerSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (gServerSocket < 0) {
|
||||
int acceptClientConnection(int serverPort) {
|
||||
int serverSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (serverSocket < 0) {
|
||||
LOGE("Error (%d) while creating socket. Check if app has network permissions.",
|
||||
gServerSocket);
|
||||
exit(-1);
|
||||
serverSocket);
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct sockaddr_in server, client;
|
||||
|
||||
server.sin_family = AF_INET;
|
||||
server.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
server.sin_port = htons(port);
|
||||
server.sin_port = htons(serverPort);
|
||||
|
||||
socklen_t sockaddr_len = sizeof(sockaddr_in);
|
||||
if (bind(gServerSocket, (struct sockaddr *) &server, sizeof(server)) < 0) {
|
||||
close(gServerSocket);
|
||||
if (bind(serverSocket, (struct sockaddr *) &server, sizeof(server)) < 0) {
|
||||
close(serverSocket);
|
||||
LOGE("Failed to bind the server socket");
|
||||
exit(-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (listen(gServerSocket, 1) < 0) {
|
||||
close(gServerSocket);
|
||||
if (listen(serverSocket, 1) < 0) {
|
||||
close(serverSocket);
|
||||
LOGE("Failed to listen on server socket");
|
||||
exit(-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ALOGD("startServer: server started on %d", port);
|
||||
ALOGD("gltrace::waitForClientConnection: server listening @ port %d", serverPort);
|
||||
|
||||
/* Wait for client connection */
|
||||
if ((gClientSocket = accept(gServerSocket, (struct sockaddr *)&client, &sockaddr_len)) < 0) {
|
||||
close(gServerSocket);
|
||||
int clientSocket = accept(serverSocket, (struct sockaddr *)&client, &sockaddr_len);
|
||||
if (clientSocket < 0) {
|
||||
close(serverSocket);
|
||||
LOGE("Failed to accept client connection");
|
||||
exit(-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ALOGD("startServer: client connected: %s", inet_ntoa(client.sin_addr));
|
||||
ALOGD("gltrace::waitForClientConnection: client connected: %s", inet_ntoa(client.sin_addr));
|
||||
|
||||
// do not accept any more incoming connections
|
||||
close(serverSocket);
|
||||
|
||||
return clientSocket;
|
||||
}
|
||||
|
||||
void stopServer() {
|
||||
if (gServerSocket > 0) {
|
||||
close(gServerSocket);
|
||||
close(gClientSocket);
|
||||
gServerSocket = gClientSocket = 0;
|
||||
TCPStream::TCPStream(int socket) {
|
||||
mSocket = socket;
|
||||
pthread_mutex_init(&mSocketWriteMutex, NULL);
|
||||
}
|
||||
|
||||
TCPStream::~TCPStream() {
|
||||
pthread_mutex_destroy(&mSocketWriteMutex);
|
||||
}
|
||||
|
||||
void TCPStream::closeStream() {
|
||||
if (mSocket > 0) {
|
||||
close(mSocket);
|
||||
mSocket = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** Send GLMessage to the receiver on the host. */
|
||||
void traceGLMessage(GLMessage *call) {
|
||||
if (gClientSocket <= 0) {
|
||||
LOGE("traceGLMessage: Attempt to send while client connection is not established");
|
||||
return;
|
||||
int TCPStream::send(void *buf, size_t len) {
|
||||
if (mSocket <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::string str;
|
||||
call->SerializeToString(&str);
|
||||
const uint32_t len = str.length();
|
||||
pthread_mutex_lock(&mSocketWriteMutex);
|
||||
int n = write(mSocket, buf, len);
|
||||
pthread_mutex_unlock(&mSocketWriteMutex);
|
||||
|
||||
int n = write(gClientSocket, &len, sizeof len);
|
||||
if (n != sizeof len) {
|
||||
LOGE("traceGLMessage: Error (%d) while writing message length\n", n);
|
||||
stopServer();
|
||||
exit(-1);
|
||||
return n;
|
||||
}
|
||||
|
||||
int TCPStream::receive(void *data, size_t len) {
|
||||
if (mSocket <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
n = write(gClientSocket, str.data(), str.length());
|
||||
if (n != (int) str.length()) {
|
||||
LOGE("traceGLMessage: Error while writing out message, result = %d, length = %d\n",
|
||||
n, str.length());
|
||||
stopServer();
|
||||
exit(-1);
|
||||
return read(mSocket, data, len);
|
||||
}
|
||||
|
||||
BufferedOutputStream::BufferedOutputStream(TCPStream *stream, size_t bufferSize) {
|
||||
mStream = stream;
|
||||
|
||||
mBufferSize = bufferSize;
|
||||
mStringBuffer = "";
|
||||
mStringBuffer.reserve(bufferSize);
|
||||
}
|
||||
|
||||
int BufferedOutputStream::flush() {
|
||||
if (mStringBuffer.size() == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int n = mStream->send((void *)mStringBuffer.data(), mStringBuffer.size());
|
||||
mStringBuffer.clear();
|
||||
return n;
|
||||
}
|
||||
|
||||
void BufferedOutputStream::enqueueMessage(GLMessage *msg) {
|
||||
const uint32_t len = msg->ByteSize();
|
||||
|
||||
mStringBuffer.append((const char *)&len, sizeof(len)); // append header
|
||||
msg->AppendToString(&mStringBuffer); // append message
|
||||
}
|
||||
|
||||
int BufferedOutputStream::send(GLMessage *msg) {
|
||||
enqueueMessage(msg);
|
||||
|
||||
if (mStringBuffer.size() > mBufferSize) {
|
||||
return flush();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}; // namespace gltrace
|
||||
|
||||
@@ -17,15 +17,69 @@
|
||||
#ifndef __GLTRACE_TRANSPORT_H_
|
||||
#define __GLTRACE_TRANSPORT_H_
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "gltrace.pb.h"
|
||||
|
||||
namespace android {
|
||||
namespace gltrace {
|
||||
|
||||
void startServer(int port);
|
||||
void stopServer();
|
||||
/**
|
||||
* TCPStream provides a TCP based communication channel from the device to
|
||||
* the host for transferring GLMessages.
|
||||
*/
|
||||
class TCPStream {
|
||||
int mSocket;
|
||||
pthread_mutex_t mSocketWriteMutex;
|
||||
public:
|
||||
/** Create a TCP based communication channel over @socket */
|
||||
TCPStream(int socket);
|
||||
~TCPStream();
|
||||
|
||||
void traceGLMessage(GLMessage *msg);
|
||||
/** Close the channel. */
|
||||
void closeStream();
|
||||
|
||||
/** Send @data of size @len to host. . Returns -1 on error, 0 on success. */
|
||||
int send(void *data, size_t len);
|
||||
|
||||
/** Receive data into @buf from the remote end. This is a blocking call. */
|
||||
int receive(void *buf, size_t size);
|
||||
};
|
||||
|
||||
/**
|
||||
* BufferedOutputStream provides buffering of data sent to the underlying
|
||||
* unbuffered channel.
|
||||
*/
|
||||
class BufferedOutputStream {
|
||||
TCPStream *mStream;
|
||||
|
||||
size_t mBufferSize;
|
||||
std::string mStringBuffer;
|
||||
|
||||
/** Enqueue message into internal buffer. */
|
||||
void enqueueMessage(GLMessage *msg);
|
||||
public:
|
||||
/**
|
||||
* Construct a Buffered stream of size @bufferSize, using @stream as
|
||||
* its underlying channel for transport.
|
||||
*/
|
||||
BufferedOutputStream(TCPStream *stream, size_t bufferSize);
|
||||
|
||||
/**
|
||||
* Send @msg. The message could be buffered and sent later with a
|
||||
* subsequent message. Returns -1 on error, 0 on success.
|
||||
*/
|
||||
int send(GLMessage *msg);
|
||||
|
||||
/** Send any buffered messages, returns -1 on error, 0 on success. */
|
||||
int flush();
|
||||
};
|
||||
|
||||
/**
|
||||
* Utility method: start a server at @serverPort, and wait for a client
|
||||
* connection. Returns the connected client socket on success, or -1 on failure.
|
||||
*/
|
||||
int acceptClientConnection(int serverPort);
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
@@ -146,7 +146,6 @@ TRACE_CALL_TEMPLATE = pyratemp.Template(
|
||||
GLMessage glmsg;
|
||||
GLTraceContext *glContext = getGLTraceContext();
|
||||
|
||||
glmsg.set_context_id(1);
|
||||
glmsg.set_function(GLMessage::$!func!$);
|
||||
<!--(if len(parsedArgs) > 0)-->
|
||||
<!--(for argname, argtype in parsedArgs)-->
|
||||
@@ -174,8 +173,8 @@ TRACE_CALL_TEMPLATE = pyratemp.Template(
|
||||
rt->$!retDataType.getProtobufCall()!$retValue);
|
||||
<!--(end)-->
|
||||
|
||||
fixupGLMessage(&glmsg);
|
||||
traceGLMessage(&glmsg);
|
||||
fixupGLMessage(glContext, &glmsg);
|
||||
glContext->traceGLMessage(&glmsg);
|
||||
<!--(if retType != "void")-->
|
||||
|
||||
return retValue;
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace android {
|
||||
|
||||
/* Hooks to be called by "interesting" EGL functions. */
|
||||
void GLTrace_eglCreateContext(int version, EGLContext c);
|
||||
void GLTrace_eglMakeCurrent(unsigned version, gl_hooks_t *hooks);
|
||||
void GLTrace_eglMakeCurrent(unsigned version, gl_hooks_t *hooks, EGLContext c);
|
||||
void GLTrace_eglReleaseThread();
|
||||
void GLTrace_eglSwapBuffers(void*, void*);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user