diff --git a/opengl/libs/GLES2_dbg/generate_debugger_message_proto.py b/opengl/libs/GLES2_dbg/generate_debugger_message_proto.py index 62ccb1af6..914ea2463 100755 --- a/opengl/libs/GLES2_dbg/generate_debugger_message_proto.py +++ b/opengl/libs/GLES2_dbg/generate_debugger_message_proto.py @@ -127,16 +127,21 @@ message Message ReferencedImage = 0; // for image sourced from ReadPixels NonreferencedImage = 1; // for image sourced from ReadPixels }; - optional DataType data_type = 23; // most data types can be inferred from function - optional int32 pixel_format = 24; // used for image data if format and type - optional int32 pixel_type = 25; // cannot be determined from arg + // most data types can be inferred from function + optional DataType data_type = 23; + // these are used for image data when they cannot be determined from args + optional int32 pixel_format = 24; + optional int32 pixel_type = 25; + optional int32 image_width = 26; + optional int32 image_height = 27; optional float time = 11; // duration of previous GL call (ms) enum Prop { - Capture = 0; // arg0 = true | false + CaptureDraw = 0; // arg0 = number of glDrawArrays/Elements to glReadPixels 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 }; 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 3e8e852b4..fe9387481 100644 --- a/opengl/libs/GLES2_dbg/src/dbgcontext.cpp +++ b/opengl/libs/GLES2_dbg/src/dbgcontext.cpp @@ -34,10 +34,14 @@ DbgContext * getDbgContextThreadSpecific() } DbgContext::DbgContext(const unsigned version, const gl_hooks_t * const hooks, - const unsigned MAX_VERTEX_ATTRIBS) + const unsigned MAX_VERTEX_ATTRIBS, const GLenum readFormat, + const GLenum readType) : lzf_buf(NULL), lzf_readIndex(0), lzf_refSize(0), lzf_refBufSize(0) , version(version), hooks(hooks) , MAX_VERTEX_ATTRIBS(MAX_VERTEX_ATTRIBS) + , readFormat(readFormat), readType(readType) + , readBytesPerPixel(GetBytesPerPixel(readFormat, readType)) + , captureSwap(0), captureDraw(0) , vertexAttribs(new VertexAttrib[MAX_VERTEX_ATTRIBS]) , hasNonVBOAttribs(false), indexBuffers(NULL), indexBuffer(NULL) , program(0), maxAttrib(0) @@ -64,7 +68,10 @@ DbgContext * CreateDbgContext(const pthread_key_t EGLThreadLocalStorageKey, assert(GL_NO_ERROR == hooks->gl.glGetError()); GLint MAX_VERTEX_ATTRIBS = 0; hooks->gl.glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &MAX_VERTEX_ATTRIBS); - return new DbgContext(version, hooks, MAX_VERTEX_ATTRIBS); + 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); } 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 b0f639db9..40478c357 100644 --- a/opengl/libs/GLES2_dbg/src/debugger_message.pb.cpp +++ b/opengl/libs/GLES2_dbg/src/debugger_message.pb.cpp @@ -476,6 +476,7 @@ bool Message_Prop_IsValid(int value) { case 0: case 1: case 2: + case 3: return true; default: return false; @@ -483,9 +484,10 @@ bool Message_Prop_IsValid(int value) { } #ifndef _MSC_VER -const Message_Prop Message::Capture; +const Message_Prop Message::CaptureDraw; const Message_Prop Message::TimeMode; const Message_Prop Message::ExpectResponse; +const Message_Prop Message::CaptureSwap; const Message_Prop Message::Prop_MIN; const Message_Prop Message::Prop_MAX; const int Message::Prop_ARRAYSIZE; @@ -510,6 +512,8 @@ const int Message::kDataFieldNumber; const int Message::kDataTypeFieldNumber; const int Message::kPixelFormatFieldNumber; const int Message::kPixelTypeFieldNumber; +const int Message::kImageWidthFieldNumber; +const int Message::kImageHeightFieldNumber; const int Message::kTimeFieldNumber; const int Message::kPropFieldNumber; const int Message::kClockFieldNumber; @@ -549,6 +553,8 @@ void Message::SharedCtor() { data_type_ = 0; pixel_format_ = 0; pixel_type_ = 0; + image_width_ = 0; + image_height_ = 0; time_ = 0; prop_ = 0; clock_ = 0; @@ -610,6 +616,8 @@ void Message::Clear() { if (_has_bits_[16 / 32] & (0xffu << (16 % 32))) { pixel_format_ = 0; pixel_type_ = 0; + image_width_ = 0; + image_height_ = 0; time_ = 0; prop_ = 0; clock_ = 0; @@ -794,7 +802,7 @@ bool Message::MergePartialFromCodedStream( DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( input, &time_))); - _set_bit(18); + _set_bit(20); } else { goto handle_uninterpreted; } @@ -909,7 +917,7 @@ bool Message::MergePartialFromCodedStream( DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( input, &clock_))); - _set_bit(20); + _set_bit(22); } else { goto handle_uninterpreted; } @@ -964,6 +972,38 @@ bool Message::MergePartialFromCodedStream( } else { goto handle_uninterpreted; } + if (input->ExpectTag(208)) goto parse_image_width; + break; + } + + // optional int32 image_width = 26; + case 26: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_image_width: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + input, &image_width_))); + _set_bit(18); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(216)) goto parse_image_height; + break; + } + + // optional int32 image_height = 27; + case 27: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_image_height: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + input, &image_height_))); + _set_bit(19); + } else { + goto handle_uninterpreted; + } if (input->ExpectAtEnd()) return true; break; } @@ -1039,7 +1079,7 @@ void Message::SerializeWithCachedSizes( } // optional float time = 11; - if (_has_bit(18)) { + if (_has_bit(20)) { ::google::protobuf::internal::WireFormatLite::WriteFloat(11, this->time(), output); } @@ -1069,13 +1109,13 @@ void Message::SerializeWithCachedSizes( } // optional .com.android.glesv2debugger.Message.Prop prop = 21; - if (_has_bit(19)) { + if (_has_bit(21)) { ::google::protobuf::internal::WireFormatLite::WriteEnum( 21, this->prop(), output); } // optional float clock = 22; - if (_has_bit(20)) { + if (_has_bit(22)) { ::google::protobuf::internal::WireFormatLite::WriteFloat(22, this->clock(), output); } @@ -1095,6 +1135,16 @@ void Message::SerializeWithCachedSizes( ::google::protobuf::internal::WireFormatLite::WriteInt32(25, this->pixel_type(), output); } + // optional int32 image_width = 26; + 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 { @@ -1226,6 +1276,20 @@ int Message::ByteSize() const { this->pixel_type()); } + // optional int32 image_width = 26; + if (has_image_width()) { + total_size += 2 + + ::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; @@ -1316,12 +1380,18 @@ void Message::MergeFrom(const Message& from) { set_pixel_type(from.pixel_type()); } if (from._has_bit(18)) { - set_time(from.time()); + set_image_width(from.image_width()); } if (from._has_bit(19)) { - set_prop(from.prop()); + set_image_height(from.image_height()); } if (from._has_bit(20)) { + set_time(from.time()); + } + if (from._has_bit(21)) { + set_prop(from.prop()); + } + if (from._has_bit(22)) { set_clock(from.clock()); } } @@ -1359,6 +1429,8 @@ void Message::Swap(Message* other) { std::swap(data_type_, other->data_type_); std::swap(pixel_format_, other->pixel_format_); std::swap(pixel_type_, other->pixel_type_); + std::swap(image_width_, other->image_width_); + std::swap(image_height_, other->image_height_); std::swap(time_, other->time_); std::swap(prop_, other->prop_); std::swap(clock_, other->clock_); diff --git a/opengl/libs/GLES2_dbg/src/debugger_message.pb.h b/opengl/libs/GLES2_dbg/src/debugger_message.pb.h index c3f98bad7..4ccfebb2c 100644 --- a/opengl/libs/GLES2_dbg/src/debugger_message.pb.h +++ b/opengl/libs/GLES2_dbg/src/debugger_message.pb.h @@ -255,13 +255,14 @@ const Message_DataType Message_DataType_DataType_MAX = Message_DataType_Nonrefer const int Message_DataType_DataType_ARRAYSIZE = Message_DataType_DataType_MAX + 1; enum Message_Prop { - Message_Prop_Capture = 0, + Message_Prop_CaptureDraw = 0, Message_Prop_TimeMode = 1, - Message_Prop_ExpectResponse = 2 + Message_Prop_ExpectResponse = 2, + Message_Prop_CaptureSwap = 3 }; 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_ExpectResponse; +const Message_Prop Message_Prop_Prop_MIN = Message_Prop_CaptureDraw; +const Message_Prop Message_Prop_Prop_MAX = Message_Prop_CaptureSwap; const int Message_Prop_Prop_ARRAYSIZE = Message_Prop_Prop_MAX + 1; // =================================================================== @@ -539,9 +540,10 @@ class Message : public ::google::protobuf::MessageLite { Message_DataType_DataType_ARRAYSIZE; typedef Message_Prop Prop; - static const Prop Capture = Message_Prop_Capture; + static const Prop CaptureDraw = Message_Prop_CaptureDraw; static const Prop TimeMode = Message_Prop_TimeMode; static const Prop ExpectResponse = Message_Prop_ExpectResponse; + static const Prop CaptureSwap = Message_Prop_CaptureSwap; static inline bool Prop_IsValid(int value) { return Message_Prop_IsValid(value); } @@ -683,6 +685,20 @@ class Message : public ::google::protobuf::MessageLite { inline ::google::protobuf::int32 pixel_type() const; inline void set_pixel_type(::google::protobuf::int32 value); + // optional int32 image_width = 26; + inline bool has_image_width() const; + inline void clear_image_width(); + 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(); @@ -727,6 +743,8 @@ class Message : public ::google::protobuf::MessageLite { int data_type_; ::google::protobuf::int32 pixel_format_; ::google::protobuf::int32 pixel_type_; + ::google::protobuf::int32 image_width_; + ::google::protobuf::int32 image_height_; float time_; int prop_; float clock_; @@ -734,7 +752,7 @@ class Message : public ::google::protobuf::MessageLite { friend void protobuf_AssignDesc_debugger_5fmessage_2eproto(); friend void protobuf_ShutdownFile_debugger_5fmessage_2eproto(); - ::google::protobuf::uint32 _has_bits_[(21 + 31) / 32]; + ::google::protobuf::uint32 _has_bits_[(23 + 31) / 32]; // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? inline bool _has_bit(int index) const { @@ -1074,52 +1092,84 @@ inline void Message::set_pixel_type(::google::protobuf::int32 value) { pixel_type_ = value; } +// optional int32 image_width = 26; +inline bool Message::has_image_width() const { + return _has_bit(18); +} +inline void Message::clear_image_width() { + image_width_ = 0; + _clear_bit(18); +} +inline ::google::protobuf::int32 Message::image_width() const { + return image_width_; +} +inline void Message::set_image_width(::google::protobuf::int32 value) { + _set_bit(18); + image_width_ = value; +} + +// optional int32 image_height = 27; +inline bool Message::has_image_height() const { + return _has_bit(19); +} +inline void Message::clear_image_height() { + image_height_ = 0; + _clear_bit(19); +} +inline ::google::protobuf::int32 Message::image_height() const { + return image_height_; +} +inline void Message::set_image_height(::google::protobuf::int32 value) { + _set_bit(19); + image_height_ = value; +} + // optional float time = 11; inline bool Message::has_time() const { - return _has_bit(18); + return _has_bit(20); } inline void Message::clear_time() { time_ = 0; - _clear_bit(18); + _clear_bit(20); } inline float Message::time() const { return time_; } inline void Message::set_time(float value) { - _set_bit(18); + _set_bit(20); time_ = value; } // optional .com.android.glesv2debugger.Message.Prop prop = 21; inline bool Message::has_prop() const { - return _has_bit(19); + return _has_bit(21); } inline void Message::clear_prop() { prop_ = 0; - _clear_bit(19); + _clear_bit(21); } 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(19); + _set_bit(21); prop_ = value; } // optional float clock = 22; inline bool Message::has_clock() const { - return _has_bit(20); + return _has_bit(22); } inline void Message::clear_clock() { clock_ = 0; - _clear_bit(20); + _clear_bit(22); } inline float Message::clock() const { return clock_; } inline void Message::set_clock(float value) { - _set_bit(20); + _set_bit(22); clock_ = value; } diff --git a/opengl/libs/GLES2_dbg/src/egl.cpp b/opengl/libs/GLES2_dbg/src/egl.cpp index 3a20e21ba..eb28d0607 100644 --- a/opengl/libs/GLES2_dbg/src/egl.cpp +++ b/opengl/libs/GLES2_dbg/src/egl.cpp @@ -18,6 +18,7 @@ EGLBoolean Debug_eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) { + DbgContext * const dbg = getDbgContextThreadSpecific(); glesv2debugger::Message msg; struct : public FunctionCall { EGLDisplay dpy; @@ -33,7 +34,21 @@ EGLBoolean Debug_eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) msg.set_arg0(reinterpret_cast(dpy)); msg.set_arg1(reinterpret_cast(draw)); - + if (dbg->captureSwap > 0) { + dbg->captureSwap--; + int viewport[4] = {}; + dbg->hooks->gl.glGetIntegerv(GL_VIEWPORT, viewport); + void * pixels = dbg->GetReadPixelsBuffer(viewport[2] * viewport[3] * + dbg->readBytesPerPixel); + dbg->hooks->gl.glReadPixels(viewport[0], viewport[1], viewport[2], + viewport[3], dbg->readFormat, dbg->readType, pixels); + dbg->CompressReadPixelBuffer(msg.mutable_data()); + msg.set_data_type(msg.ReferencedImage); + msg.set_pixel_format(dbg->readFormat); + msg.set_pixel_type(dbg->readType); + msg.set_image_width(viewport[2]); + msg.set_image_height(viewport[3]); + } int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_eglSwapBuffers); return static_cast(reinterpret_cast(ret)); } diff --git a/opengl/libs/GLES2_dbg/src/header.h b/opengl/libs/GLES2_dbg/src/header.h index 83ddf7025..c9e6c4167 100644 --- a/opengl/libs/GLES2_dbg/src/header.h +++ b/opengl/libs/GLES2_dbg/src/header.h @@ -83,9 +83,14 @@ private: unsigned lzf_refSize, lzf_refBufSize; // bytes public: - const unsigned version; // 0 is GLES1, 1 is GLES2 + const unsigned int version; // 0 is GLES1, 1 is GLES2 const gl_hooks_t * const hooks; - const unsigned MAX_VERTEX_ATTRIBS; + const unsigned int MAX_VERTEX_ATTRIBS; + const GLenum readFormat, readType; // implementation supported glReadPixels + const unsigned int readBytesPerPixel; + + unsigned int captureSwap; // number of eglSwapBuffers to glReadPixels + unsigned int captureDraw; // number of glDrawArrays/Elements to glReadPixels GLFunctionBitfield expectResponse; @@ -118,7 +123,8 @@ public: unsigned maxAttrib; // number of slots used by program DbgContext(const unsigned version, const gl_hooks_t * const hooks, - const unsigned MAX_VERTEX_ATTRIBS); + const unsigned MAX_VERTEX_ATTRIBS, const GLenum readFormat, + const GLenum readType); ~DbgContext(); void Fetch(const unsigned index, std::string * const data) const; @@ -151,7 +157,6 @@ struct FunctionCall { }; // move these into DbgContext as static -extern bool capture; extern int timeMode; // SYSTEM_TIME_ extern int clientSock, serverSock; diff --git a/opengl/libs/GLES2_dbg/src/server.cpp b/opengl/libs/GLES2_dbg/src/server.cpp index c354bd057..f13d6cc84 100644 --- a/opengl/libs/GLES2_dbg/src/server.cpp +++ b/opengl/libs/GLES2_dbg/src/server.cpp @@ -212,9 +212,9 @@ float Send(const glesv2debugger::Message & msg, glesv2debugger::Message & cmd) void SetProp(DbgContext * const dbg, const glesv2debugger::Message & cmd) { switch (cmd.prop()) { - case glesv2debugger::Message_Prop_Capture: - LOGD("SetProp Message_Prop_Capture %d", cmd.arg0()); - capture = cmd.arg0(); + case glesv2debugger::Message_Prop_CaptureDraw: + LOGD("SetProp Message_Prop_CaptureDraw %d", cmd.arg0()); + dbg->captureDraw = cmd.arg0(); break; case glesv2debugger::Message_Prop_TimeMode: LOGD("SetProp Message_Prop_TimeMode %d", cmd.arg0()); @@ -224,6 +224,10 @@ void SetProp(DbgContext * const dbg, const glesv2debugger::Message & cmd) LOGD("SetProp Message_Prop_ExpectResponse %d=%d", cmd.arg0(), cmd.arg1()); dbg->expectResponse.Bit((glesv2debugger::Message_Function)cmd.arg0(), cmd.arg1()); break; + case glesv2debugger::Message_Prop_CaptureSwap: + LOGD("SetProp CaptureSwap %d", cmd.arg0()); + dbg->captureSwap = cmd.arg0(); + break; default: assert(0); } diff --git a/opengl/libs/GLES2_dbg/src/vertex.cpp b/opengl/libs/GLES2_dbg/src/vertex.cpp index 3abea67a7..7edc05033 100644 --- a/opengl/libs/GLES2_dbg/src/vertex.cpp +++ b/opengl/libs/GLES2_dbg/src/vertex.cpp @@ -42,7 +42,6 @@ void Debug_glDrawArrays(GLenum mode, GLint first, GLsizei count) } void * pixels = NULL; - GLint readFormat = 0, readType = 0; int viewport[4] = {}; if (!expectResponse) { cmd.set_function(glesv2debugger::Message_Function_CONTINUE); @@ -74,16 +73,15 @@ void Debug_glDrawArrays(GLenum mode, GLint first, GLsizei count) // TODO: pack glReadPixels data with vertex data instead of // relying on sperate call for transport, this would allow // auto generated message loop using EXTEND_Debug macro - if (capture) { + if (dbg->captureDraw > 0) { + dbg->captureDraw--; 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 = dbg->GetReadPixelsBuffer(viewport[2] * viewport[3] * - GetBytesPerPixel(readFormat, readType)); + dbg->readBytesPerPixel); Debug_glReadPixels(viewport[0], viewport[1], viewport[2], viewport[3], - readFormat, readType, pixels); + dbg->readFormat, dbg->readType, pixels); } break; case glesv2debugger::Message_Function_SKIP: @@ -155,7 +153,6 @@ void Debug_glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* assert(0); void * pixels = NULL; - GLint readFormat = 0, readType = 0; int viewport[4] = {}; if (!expectResponse) { cmd.set_function(glesv2debugger::Message_Function_CONTINUE); @@ -187,16 +184,13 @@ void Debug_glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* // TODO: pack glReadPixels data with vertex data instead of // relying on sperate call for transport, this would allow // auto generated message loop using EXTEND_Debug macro - if (capture) { + if (dbg->captureDraw > 0) { + dbg->captureDraw--; 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 = dbg->GetReadPixelsBuffer(viewport[2] * viewport[3] * - GetBytesPerPixel(readFormat, readType)); + dbg->readBytesPerPixel); Debug_glReadPixels(viewport[0], viewport[1], viewport[2], viewport[3], - readFormat, readType, pixels); + dbg->readFormat, dbg->readType, pixels); } break; case glesv2debugger::Message_Function_SKIP: