GLES2Dbg: use libLZF for compressing images
liblzf is in external/liblzf, it's BSD-type licence (optionally GPL2) Change-Id: Idc7883fe2155f366cda384e64796a1493335ae4f Signed-off-by: David Li <davidxli@google.com>
This commit is contained in:
parent
bfa1f89014
commit
c615816679
|
@ -13,7 +13,7 @@ LOCAL_SRC_FILES:= \
|
|||
EGL/hooks.cpp \
|
||||
EGL/Loader.cpp \
|
||||
#
|
||||
LOCAL_STATIC_LIBRARIES += libGLESv2_dbg libprotobuf-cpp-2.3.0-lite
|
||||
LOCAL_STATIC_LIBRARIES += libGLESv2_dbg libprotobuf-cpp-2.3.0-lite liblzf
|
||||
LOCAL_SHARED_LIBRARIES += libcutils libutils libstlport
|
||||
LOCAL_LDLIBS := -lpthread -ldl
|
||||
LOCAL_MODULE:= libEGL
|
||||
|
|
|
@ -16,6 +16,7 @@ LOCAL_C_INCLUDES := \
|
|||
$(LOCAL_PATH)/../ \
|
||||
external/stlport/stlport \
|
||||
external/protobuf/src \
|
||||
external \
|
||||
bionic
|
||||
|
||||
#LOCAL_CFLAGS += -O0 -g -DDEBUG -UNDEBUG
|
||||
|
|
|
@ -17,7 +17,9 @@
|
|||
#define EXTEND_Debug_glCopyTexImage2D \
|
||||
void * pixels = malloc(width * height * 4); \
|
||||
getGLTraceThreadSpecific()->gl.glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); \
|
||||
msg.set_data(pixels, width * height * 4); \
|
||||
DbgContext * const dbg = getDbgContextThreadSpecific(); \
|
||||
const unsigned compressed = dbg->Compress(pixels, width * height * 4); \
|
||||
msg.set_data(dbg->lzf_buf, compressed); \
|
||||
free(pixels);
|
||||
|
||||
#define EXTEND_Debug_glCopyTexSubImage2D EXTEND_Debug_glCopyTexImage2D
|
||||
|
|
|
@ -13,15 +13,20 @@
|
|||
** See the License for the specific language governing permissions and
|
||||
** limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
#include "header.h"
|
||||
|
||||
extern "C" {
|
||||
#include "liblzf/lzf.h"
|
||||
}
|
||||
|
||||
namespace android
|
||||
{
|
||||
|
||||
DbgContext::DbgContext(const unsigned version, const gl_hooks_t * const hooks,
|
||||
const unsigned MAX_VERTEX_ATTRIBS)
|
||||
: version(version), hooks(hooks)
|
||||
: lzf_buf(NULL), lzf_bufSize(0)
|
||||
, version(version), hooks(hooks)
|
||||
, MAX_VERTEX_ATTRIBS(MAX_VERTEX_ATTRIBS)
|
||||
, vertexAttribs(new VertexAttrib[MAX_VERTEX_ATTRIBS])
|
||||
, hasNonVBOAttribs(false), indexBuffers(NULL), indexBuffer(NULL)
|
||||
|
@ -33,6 +38,7 @@ DbgContext::DbgContext(const unsigned version, const gl_hooks_t * const hooks,
|
|||
DbgContext::~DbgContext()
|
||||
{
|
||||
delete vertexAttribs;
|
||||
free(lzf_buf);
|
||||
}
|
||||
|
||||
DbgContext * CreateDbgContext(const unsigned version, const gl_hooks_t * const hooks)
|
||||
|
@ -63,11 +69,24 @@ void DbgContext::Fetch(const unsigned index, std::string * const data) const
|
|||
}
|
||||
}
|
||||
|
||||
unsigned DbgContext::Compress(const void * in_data, unsigned in_len)
|
||||
{
|
||||
if (lzf_bufSize < in_len + 256) {
|
||||
lzf_bufSize = in_len + 256;
|
||||
lzf_buf = (char *)realloc(lzf_buf, lzf_bufSize);
|
||||
}
|
||||
unsigned compressedSize = lzf_compress((const char *)in_data,
|
||||
in_len, lzf_buf, lzf_bufSize);
|
||||
LOGD("DbgContext::lzf_compress in=%u out=%u", in_len, compressedSize);
|
||||
assert (0 < compressedSize);
|
||||
return compressedSize;
|
||||
}
|
||||
|
||||
void DbgContext::glUseProgram(GLuint program)
|
||||
{
|
||||
while (GLenum error = hooks->gl.glGetError())
|
||||
LOGD("DbgContext::glUseProgram: before glGetError() = 0x%.4X", error);
|
||||
|
||||
|
||||
this->program = program;
|
||||
|
||||
GLint activeAttributes = 0;
|
||||
|
@ -107,7 +126,7 @@ void DbgContext::glUseProgram(GLuint program)
|
|||
maxAttrib = slot;
|
||||
}
|
||||
delete name;
|
||||
|
||||
|
||||
while (GLenum error = hooks->gl.glGetError())
|
||||
LOGD("DbgContext::glUseProgram: after glGetError() = 0x%.4X", error);
|
||||
}
|
||||
|
|
|
@ -57,6 +57,12 @@ namespace android
|
|||
{
|
||||
|
||||
struct DbgContext {
|
||||
private:
|
||||
unsigned lzf_bufSize;
|
||||
|
||||
public:
|
||||
char * lzf_buf;
|
||||
|
||||
const unsigned version; // 0 is GLES1, 1 is GLES2
|
||||
const gl_hooks_t * const hooks;
|
||||
const unsigned MAX_VERTEX_ATTRIBS;
|
||||
|
@ -93,7 +99,8 @@ struct DbgContext {
|
|||
~DbgContext();
|
||||
|
||||
void Fetch(const unsigned index, std::string * const data) const;
|
||||
|
||||
unsigned Compress(const void * in_data, unsigned in_len); // compressed to lzf_buf
|
||||
|
||||
void glUseProgram(GLuint program);
|
||||
void glEnableVertexAttribArray(GLuint index);
|
||||
void glDisableVertexAttribArray(GLuint index);
|
||||
|
|
|
@ -50,89 +50,11 @@ unsigned GetBytesPerPixel(const GLenum format, const GLenum type)
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#define USE_RLE 0
|
||||
#if USE_RLE
|
||||
export template<typename T>
|
||||
void * RLEEncode(const void * pixels, unsigned count, unsigned * encodedSize)
|
||||
{
|
||||
// first is a byte indicating data size [1,2,4] bytes
|
||||
// then an unsigned indicating decompressed size
|
||||
// then a byte of header: MSB == 1 indicates run, else literal
|
||||
// LSB7 is run or literal length (actual length - 1)
|
||||
|
||||
const T * data = (T *)pixels;
|
||||
unsigned bufferSize = sizeof(T) * count / 2 + 8;
|
||||
unsigned char * buffer = (unsigned char *)malloc(bufferSize);
|
||||
buffer[0] = sizeof(T);
|
||||
unsigned bufferWritten = 1; // number of bytes written
|
||||
*(unsigned *)(buffer + bufferWritten) = count;
|
||||
bufferWritten += sizeof(count);
|
||||
while (count) {
|
||||
unsigned char run = 1;
|
||||
bool repeat = true;
|
||||
for (run = 1; run < count; run++)
|
||||
if (data[0] != data[run]) {
|
||||
repeat = false;
|
||||
break;
|
||||
} else if (run > 126)
|
||||
break;
|
||||
if (!repeat) {
|
||||
// find literal length
|
||||
for (run = 1; run < count; run++)
|
||||
if (data[run - 1] == data[run])
|
||||
break;
|
||||
else if (run > 126)
|
||||
break;
|
||||
unsigned bytesToWrite = 1 + sizeof(T) * run;
|
||||
if (bufferWritten + bytesToWrite > bufferSize) {
|
||||
bufferSize += sizeof(T) * run + 256;
|
||||
buffer = (unsigned char *)realloc(buffer, bufferSize);
|
||||
}
|
||||
buffer[bufferWritten++] = run - 1;
|
||||
for (unsigned i = 0; i < run; i++) {
|
||||
*(T *)(buffer + bufferWritten) = *data;
|
||||
bufferWritten += sizeof(T);
|
||||
data++;
|
||||
}
|
||||
count -= run;
|
||||
} else {
|
||||
unsigned bytesToWrite = 1 + sizeof(T);
|
||||
if (bufferWritten + bytesToWrite > bufferSize) {
|
||||
bufferSize += 256;
|
||||
buffer = (unsigned char *)realloc(buffer, bufferSize);
|
||||
}
|
||||
buffer[bufferWritten++] = (run - 1) | 0x80;
|
||||
*(T *)(buffer + bufferWritten) = data[0];
|
||||
bufferWritten += sizeof(T);
|
||||
data += run;
|
||||
count -= run;
|
||||
}
|
||||
}
|
||||
if (encodedSize)
|
||||
*encodedSize = bufferWritten;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void * RLEEncode(const void * pixels, const unsigned bytesPerPixel, const unsigned count, unsigned * encodedSize)
|
||||
{
|
||||
switch (bytesPerPixel) {
|
||||
case 4:
|
||||
return RLEEncode<int>(pixels, count, encodedSize);
|
||||
case 2:
|
||||
return RLEEncode<short>(pixels, count, encodedSize);
|
||||
case 1:
|
||||
return RLEEncode<char>(pixels, count, encodedSize);
|
||||
default:
|
||||
assert(0);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}; // namespace android
|
||||
|
||||
void Debug_glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels)
|
||||
{
|
||||
DbgContext * const dbg = getDbgContextThreadSpecific();
|
||||
glesv2debugger::Message msg;
|
||||
const bool expectResponse = false;
|
||||
struct : public FunctionCall {
|
||||
|
@ -179,27 +101,19 @@ void Debug_glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsize
|
|||
|
||||
unsigned bytesPerPixel = GetBytesPerPixel(format, type);
|
||||
assert(0 < bytesPerPixel);
|
||||
|
||||
// LOGD("GLESv2_dbg: glTexImage2D width=%d height=%d level=%d bytesPerPixel=%d",
|
||||
// width, height, level, bytesPerPixel);
|
||||
#if USE_RLE
|
||||
unsigned encodedSize = 0;
|
||||
void * data = RLEEncode(pixels, bytesPerPixel, width * height, &encodedSize);
|
||||
msg.set_data(data, encodedSize);
|
||||
free(data);
|
||||
if (encodedSize > bytesPerPixel * width * height)
|
||||
LOGD("GLESv2_dbg: glTexImage2D sending data encodedSize=%d size=%d", encodedSize, bytesPerPixel * width * height);
|
||||
#else
|
||||
msg.set_data(pixels, bytesPerPixel * width * height);
|
||||
#endif
|
||||
unsigned compressedSize = dbg->Compress(pixels, bytesPerPixel * width * height);
|
||||
msg.set_data(dbg->lzf_buf, compressedSize);
|
||||
}
|
||||
|
||||
|
||||
int * ret = MessageLoop(caller, msg, expectResponse,
|
||||
glesv2debugger::Message_Function_glTexImage2D);
|
||||
}
|
||||
|
||||
void Debug_glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels)
|
||||
{
|
||||
DbgContext * const dbg = getDbgContextThreadSpecific();
|
||||
glesv2debugger::Message msg;
|
||||
const bool expectResponse = false;
|
||||
struct : public FunctionCall {
|
||||
|
@ -244,22 +158,12 @@ void Debug_glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoff
|
|||
if (pixels) {
|
||||
unsigned bytesPerPixel = GetBytesPerPixel(format, type);
|
||||
assert(0 < bytesPerPixel);
|
||||
|
||||
// LOGD("GLESv2_dbg: glTexSubImage2D width=%d height=%d level=%d bytesPerPixel=%d",
|
||||
// width, height, level, bytesPerPixel);
|
||||
|
||||
#if USE_RLE
|
||||
unsigned encodedSize = 0;
|
||||
void * data = RLEEncode(pixels, bytesPerPixel, width * height, &encodedSize);
|
||||
msg.set_data(data, encodedSize);
|
||||
free(data);
|
||||
if (encodedSize > bytesPerPixel * width * height)
|
||||
LOGD("GLESv2_dbg: glTexImage2D sending data encodedSize=%d size=%d", encodedSize, bytesPerPixel * width * height);
|
||||
#else
|
||||
msg.set_data(pixels, bytesPerPixel * width * height);
|
||||
#endif
|
||||
unsigned compressedSize = dbg->Compress(pixels, bytesPerPixel * width * height);
|
||||
msg.set_data(dbg->lzf_buf, compressedSize);
|
||||
}
|
||||
|
||||
|
||||
int * ret = MessageLoop(caller, msg, expectResponse,
|
||||
glesv2debugger::Message_Function_glTexSubImage2D);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,8 +19,6 @@
|
|||
namespace android
|
||||
{
|
||||
bool capture; // capture after each glDraw*
|
||||
|
||||
void * RLEEncode(const void * pixels, const unsigned bytesPerPixel, const unsigned count, unsigned * encodedSize);
|
||||
}
|
||||
|
||||
void Debug_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
|
||||
|
@ -39,8 +37,9 @@ void Debug_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
|
|||
msg.set_arg4(format);
|
||||
msg.set_arg5(type);
|
||||
msg.set_arg6(reinterpret_cast<int>(pixels));
|
||||
//void * data = NULL;
|
||||
//unsigned encodedSize = 0;
|
||||
|
||||
const unsigned size = width * height * GetBytesPerPixel(format, type);
|
||||
unsigned compressed = 0;
|
||||
if (!expectResponse)
|
||||
cmd.set_function(glesv2debugger::Message_Function_CONTINUE);
|
||||
Send(msg, cmd);
|
||||
|
@ -56,21 +55,11 @@ void Debug_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
|
|||
msg.set_function(glesv2debugger::Message_Function_glReadPixels);
|
||||
msg.set_type(glesv2debugger::Message_Type_AfterCall);
|
||||
msg.set_expect_response(expectResponse);
|
||||
//data = RLEEncode(pixels, GetBytesPerPixel(format, type), width * height, &encodedSize);
|
||||
msg.set_data(pixels, width * height * GetBytesPerPixel(format, type));
|
||||
//msg.set_data(data, encodedSize);
|
||||
//free(data);
|
||||
c0 = systemTime(timeMode);
|
||||
compressed = dbg->Compress(pixels, size);
|
||||
msg.set_data(dbg->lzf_buf, compressed);
|
||||
if (!expectResponse)
|
||||
cmd.set_function(glesv2debugger::Message_Function_SKIP);
|
||||
t = Send(msg, cmd);
|
||||
msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
|
||||
msg.set_clock(t);
|
||||
// time is total send time in seconds, clock is msg serialization time in seconds
|
||||
msg.clear_data();
|
||||
msg.set_expect_response(false);
|
||||
msg.set_type(glesv2debugger::Message_Type_AfterCall);
|
||||
//Send(msg, cmd);
|
||||
Send(msg, cmd);
|
||||
break;
|
||||
case glesv2debugger::Message_Function_SKIP:
|
||||
return;
|
||||
|
@ -129,8 +118,8 @@ void Debug_glDrawArrays(GLenum mode, GLint first, GLsizei count)
|
|||
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);
|
||||
// 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 = malloc(viewport[2] * viewport[3] * 4);
|
||||
Debug_glReadPixels(viewport[0], viewport[1], viewport[2], viewport[3],
|
||||
readFormat, readType, pixels);
|
||||
|
@ -215,8 +204,8 @@ void Debug_glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid*
|
|||
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);
|
||||
// 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 = malloc(viewport[2] * viewport[3] * 4);
|
||||
Debug_glReadPixels(viewport[0], viewport[1], viewport[2], viewport[3],
|
||||
readFormat, readType, pixels);
|
||||
|
|
Loading…
Reference in New Issue