GLES2Dbg: added CaptureDraw and CaptureSwap options

CaptureDraw specifies how many glDrawArrays/Elements to glReadPixel
CaptureSwap similarly applies to eglSwapBuffers

Change-Id: Ie7a7e3392b4ecdc0659dcee04f4bab97c35267dc
Signed-off-by: David Li <davidxli@google.com>
This commit is contained in:
David Li 2011-04-08 18:45:45 -07:00
parent 499c6f02e6
commit c2ca836b17
8 changed files with 203 additions and 51 deletions

View File

@ -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

View File

@ -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)

View File

@ -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_);

View File

@ -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;
}

View File

@ -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<int>(dpy));
msg.set_arg1(reinterpret_cast<int>(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<EGLBoolean>(reinterpret_cast<int>(ret));
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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: