TimeMode = 1; // arg0 = SYSTEM_TIME_* in utils/Timers.h
ExpectResponse = 2; // arg0 = enum Function, arg1 = true/false
CaptureSwap = 3; // arg0 = number of eglSwapBuffers to glReadPixels
+ GLConstant = 4; // arg0 = GLenum, arg1 = constant; send GL impl. constants
};
optional Prop prop = 21; // used with SETPROP, value in arg0
optional float clock = 22; // wall clock in seconds
GLint readFormat, readType;
hooks->gl.glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &readFormat);
hooks->gl.glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &readType);
- return new DbgContext(version, hooks, MAX_VERTEX_ATTRIBS, readFormat, readType);
+ DbgContext * const dbg = new DbgContext(version, hooks, MAX_VERTEX_ATTRIBS, readFormat, readType);
+
+ glesv2debugger::Message msg, cmd;
+ msg.set_context_id(reinterpret_cast<int>(dbg));
+ msg.set_expect_response(false);
+ msg.set_type(msg.Response);
+ msg.set_function(msg.SETPROP);
+ msg.set_prop(msg.GLConstant);
+ msg.set_arg0(GL_MAX_VERTEX_ATTRIBS);
+ msg.set_arg1(MAX_VERTEX_ATTRIBS);
+ Send(msg, cmd);
+
+ GLint MAX_COMBINED_TEXTURE_IMAGE_UNITS = 0;
+ hooks->gl.glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &MAX_COMBINED_TEXTURE_IMAGE_UNITS);
+ msg.set_arg0(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS);
+ msg.set_arg1(MAX_COMBINED_TEXTURE_IMAGE_UNITS);
+ Send(msg, cmd);
+ return dbg;
}
void DestroyDbgContext(DbgContext * const dbg)
case 1:
case 2:
case 3:
+ case 4:
return true;
default:
return false;
const Message_Prop Message::TimeMode;
const Message_Prop Message::ExpectResponse;
const Message_Prop Message::CaptureSwap;
+const Message_Prop Message::GLConstant;
const Message_Prop Message::Prop_MIN;
const Message_Prop Message::Prop_MAX;
const int Message::Prop_ARRAYSIZE;
if (input->ExpectTag(208)) goto parse_image_width;
break;
}
-
+
// optional int32 image_width = 26;
case 26: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
if (input->ExpectTag(216)) goto parse_image_height;
break;
}
-
+
// optional int32 image_height = 27;
case 27: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
if (_has_bit(18)) {
::google::protobuf::internal::WireFormatLite::WriteInt32(26, this->image_width(), output);
}
-
+
// optional int32 image_height = 27;
if (_has_bit(19)) {
::google::protobuf::internal::WireFormatLite::WriteInt32(27, this->image_height(), output);
}
-
+
}
int Message::ByteSize() const {
::google::protobuf::internal::WireFormatLite::Int32Size(
this->image_width());
}
-
+
// optional int32 image_height = 27;
if (has_image_height()) {
total_size += 2 +
::google::protobuf::internal::WireFormatLite::Int32Size(
this->image_height());
}
-
+
// optional float time = 11;
if (has_time()) {
total_size += 1 + 4;
Message_Prop_CaptureDraw = 0,
Message_Prop_TimeMode = 1,
Message_Prop_ExpectResponse = 2,
- Message_Prop_CaptureSwap = 3
+ Message_Prop_CaptureSwap = 3,
+ Message_Prop_GLConstant = 4
};
bool Message_Prop_IsValid(int value);
const Message_Prop Message_Prop_Prop_MIN = Message_Prop_CaptureDraw;
-const Message_Prop Message_Prop_Prop_MAX = Message_Prop_CaptureSwap;
+const Message_Prop Message_Prop_Prop_MAX = Message_Prop_GLConstant;
const int Message_Prop_Prop_ARRAYSIZE = Message_Prop_Prop_MAX + 1;
// ===================================================================
static const Prop TimeMode = Message_Prop_TimeMode;
static const Prop ExpectResponse = Message_Prop_ExpectResponse;
static const Prop CaptureSwap = Message_Prop_CaptureSwap;
+ static const Prop GLConstant = Message_Prop_GLConstant;
static inline bool Prop_IsValid(int value) {
return Message_Prop_IsValid(value);
}
static const int kImageWidthFieldNumber = 26;
inline ::google::protobuf::int32 image_width() const;
inline void set_image_width(::google::protobuf::int32 value);
-
+
// optional int32 image_height = 27;
inline bool has_image_height() const;
inline void clear_image_height();
static const int kImageHeightFieldNumber = 27;
inline ::google::protobuf::int32 image_height() const;
inline void set_image_height(::google::protobuf::int32 value);
-
+
// optional float time = 11;
inline bool has_time() const;
inline void clear_time();
float Send(const glesv2debugger::Message & msg, glesv2debugger::Message & cmd)
{
+ // TODO: use per DbgContext send/receive buffer and async socket
+ // instead of mutex and blocking io; watch out for large messages
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
- pthread_mutex_lock(&mutex); // TODO: this is just temporary
+ struct Autolock {
+ Autolock() {
+ pthread_mutex_lock(&mutex);
+ }
+ ~Autolock() {
+ pthread_mutex_unlock(&mutex);
+ }
+ } autolock;
if (msg.function() != glesv2debugger::Message_Function_ACK)
assert(msg.has_context_id() && msg.context_id() != 0);
Die("MAX_FILE_SIZE reached");
}
}
- pthread_mutex_unlock(&mutex);
return 0;
}
int sent = -1;
LOGD("actual sent=%d expected=%d clientSock=%d", sent, str.length(), clientSock);
Die("Failed to send message");
}
-
+ // TODO: factor Receive & TryReceive out and into MessageLoop, or add control argument.
+ // mean while, if server is sending a SETPROP then don't try to receive,
+ // because server will not be processing received command
+ if (msg.function() == msg.SETPROP)
+ return t;
// try to receive commands even though not expecting response,
// since client can send SETPROP and other commands anytime
if (!msg.expect_response()) {
}
} else
Receive(cmd);
-
- pthread_mutex_unlock(&mutex);
return t;
}
msg.ParseFromArray(buffer, len);
delete buffer;
}
-};
-
+ void CheckNoAvailable() {
+ const long pos = ftell(file);
+ fseek(file, 0, SEEK_END);
+ EXPECT_EQ(pos, ftell(file)) << "check no available";
+ }
+};
TEST_F(ServerFileTest, Send)
{
EXPECT_EQ(msg.type(), read.type());
}
+TEST_F(ServerFileTest, CreateDbgContext)
+{
+ gl_hooks_t hooks;
+ struct Constant {
+ GLenum pname;
+ GLint param;
+ };
+ static const Constant constants [] = {
+ {GL_MAX_VERTEX_ATTRIBS, 16},
+ {GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, 32},
+ {GL_IMPLEMENTATION_COLOR_READ_FORMAT, GL_RGBA},
+ {GL_IMPLEMENTATION_COLOR_READ_TYPE, GL_UNSIGNED_BYTE},
+ };
+ struct HookMock {
+ static void GetIntegerv(GLenum pname, GLint* params) {
+ ASSERT_TRUE(params != NULL);
+ for (unsigned int i = 0; i < sizeof(constants) / sizeof(*constants); i++)
+ if (pname == constants[i].pname) {
+ *params = constants[i].param;
+ return;
+ }
+ FAIL() << "GetIntegerv unknown pname: " << pname;
+ }
+ static GLenum GetError() {
+ return GL_NO_ERROR;
+ }
+ };
+ hooks.gl.glGetError = HookMock::GetError;
+ hooks.gl.glGetIntegerv = HookMock::GetIntegerv;
+ DbgContext * const dbg = CreateDbgContext(-1, 1, &hooks);
+ ASSERT_TRUE(dbg != NULL);
+ EXPECT_TRUE(dbg->vertexAttribs != NULL);
+
+ rewind(file);
+ glesv2debugger::Message read;
+ for (unsigned int i = 0; i < 2; i++) {
+ Read(read);
+ EXPECT_EQ(reinterpret_cast<int>(dbg), read.context_id());
+ EXPECT_FALSE(read.expect_response());
+ EXPECT_EQ(read.Response, read.type());
+ EXPECT_EQ(read.SETPROP, read.function());
+ EXPECT_EQ(read.GLConstant, read.prop());
+ GLint expectedConstant = 0;
+ HookMock::GetIntegerv(read.arg0(), &expectedConstant);
+ EXPECT_EQ(expectedConstant, read.arg1());
+ }
+ CheckNoAvailable();
+ DestroyDbgContext(dbg);
+}
+
void * glNoop()
{
return 0;
pthread_key_create(&dbgEGLThreadLocalStorageKey, NULL);
ASSERT_NE(-1, dbgEGLThreadLocalStorageKey);
tls.dbg = new DbgContext(1, &hooks, 32, GL_RGBA, GL_UNSIGNED_BYTE);
- ASSERT_NE((void *)NULL, tls.dbg);
+ ASSERT_TRUE(tls.dbg != NULL);
pthread_setspecific(dbgEGLThreadLocalStorageKey, &tls);
for (unsigned int i = 0; i < sizeof(hooks) / sizeof(void *); i++)
((void **)&hooks)[i] = (void *)glNoop;
if (len > bufferSize) {
bufferSize = len;
buffer = new char[bufferSize];
- ASSERT_NE((char *)NULL, buffer);
+ ASSERT_TRUE(buffer != NULL);
}
ASSERT_EQ(len, recv(sock, buffer, len, 0));
msg.Clear();
EXPECT_EQ(_height, height);
EXPECT_EQ(GL_RGBA, format);
EXPECT_EQ(GL_UNSIGNED_BYTE, type);
- ASSERT_NE((void *)NULL, pixels);
+ ASSERT_TRUE(pixels != NULL);
memcpy(pixels, _pixels, sizeof(_pixels));
readPixels++;
}