diff --git a/opengl/libs/GLES2_dbg/generate_debugger_message_proto.py b/opengl/libs/GLES2_dbg/generate_debugger_message_proto.py index 914ea2463..57e008caf 100755 --- a/opengl/libs/GLES2_dbg/generate_debugger_message_proto.py +++ b/opengl/libs/GLES2_dbg/generate_debugger_message_proto.py @@ -142,6 +142,7 @@ message Message 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 diff --git a/opengl/libs/GLES2_dbg/src/dbgcontext.cpp b/opengl/libs/GLES2_dbg/src/dbgcontext.cpp index 71892d3a1..7f5b27b39 100644 --- a/opengl/libs/GLES2_dbg/src/dbgcontext.cpp +++ b/opengl/libs/GLES2_dbg/src/dbgcontext.cpp @@ -71,7 +71,24 @@ DbgContext * CreateDbgContext(const pthread_key_t EGLThreadLocalStorageKey, 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(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) diff --git a/opengl/libs/GLES2_dbg/src/debugger_message.pb.cpp b/opengl/libs/GLES2_dbg/src/debugger_message.pb.cpp index 40478c357..50f70f7df 100644 --- a/opengl/libs/GLES2_dbg/src/debugger_message.pb.cpp +++ b/opengl/libs/GLES2_dbg/src/debugger_message.pb.cpp @@ -477,6 +477,7 @@ bool Message_Prop_IsValid(int value) { case 1: case 2: case 3: + case 4: return true; default: return false; @@ -488,6 +489,7 @@ const Message_Prop Message::CaptureDraw; 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; @@ -975,7 +977,7 @@ bool Message::MergePartialFromCodedStream( if (input->ExpectTag(208)) goto parse_image_width; break; } - + // optional int32 image_width = 26; case 26: { if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == @@ -991,7 +993,7 @@ bool Message::MergePartialFromCodedStream( if (input->ExpectTag(216)) goto parse_image_height; break; } - + // optional int32 image_height = 27; case 27: { if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == @@ -1139,12 +1141,12 @@ void Message::SerializeWithCachedSizes( 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 { @@ -1282,14 +1284,14 @@ 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; diff --git a/opengl/libs/GLES2_dbg/src/debugger_message.pb.h b/opengl/libs/GLES2_dbg/src/debugger_message.pb.h index 4ccfebb2c..5c946644a 100644 --- a/opengl/libs/GLES2_dbg/src/debugger_message.pb.h +++ b/opengl/libs/GLES2_dbg/src/debugger_message.pb.h @@ -258,11 +258,12 @@ enum Message_Prop { 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; // =================================================================== @@ -544,6 +545,7 @@ class Message : public ::google::protobuf::MessageLite { 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); } @@ -691,14 +693,14 @@ class Message : public ::google::protobuf::MessageLite { 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(); diff --git a/opengl/libs/GLES2_dbg/src/server.cpp b/opengl/libs/GLES2_dbg/src/server.cpp index ba4960dd9..0c711bf20 100644 --- a/opengl/libs/GLES2_dbg/src/server.cpp +++ b/opengl/libs/GLES2_dbg/src/server.cpp @@ -159,8 +159,17 @@ bool TryReceive(glesv2debugger::Message & cmd) 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); @@ -176,7 +185,6 @@ float Send(const glesv2debugger::Message & msg, glesv2debugger::Message & cmd) Die("MAX_FILE_SIZE reached"); } } - pthread_mutex_unlock(&mutex); return 0; } int sent = -1; @@ -192,7 +200,11 @@ float Send(const glesv2debugger::Message & msg, glesv2debugger::Message & cmd) 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()) { @@ -204,8 +216,6 @@ float Send(const glesv2debugger::Message & msg, glesv2debugger::Message & cmd) } } else Receive(cmd); - - pthread_mutex_unlock(&mutex); return t; } diff --git a/opengl/libs/GLES2_dbg/test/test_server.cpp b/opengl/libs/GLES2_dbg/test/test_server.cpp index 7fb87ea11..b6401e0c7 100644 --- a/opengl/libs/GLES2_dbg/test/test_server.cpp +++ b/opengl/libs/GLES2_dbg/test/test_server.cpp @@ -60,10 +60,14 @@ protected: 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) { glesv2debugger::Message msg, cmd, read; @@ -81,6 +85,56 @@ 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(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; diff --git a/opengl/libs/GLES2_dbg/test/test_socket.cpp b/opengl/libs/GLES2_dbg/test/test_socket.cpp index 1c31a94a9..617292e28 100644 --- a/opengl/libs/GLES2_dbg/test/test_socket.cpp +++ b/opengl/libs/GLES2_dbg/test/test_socket.cpp @@ -50,7 +50,7 @@ protected: 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; @@ -95,7 +95,7 @@ protected: 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(); @@ -427,7 +427,7 @@ TEST_F(SocketContextTest, CopyTexImage2D) 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++; }