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:
David Li 2011-03-21 10:02:30 -07:00
parent bfa1f89014
commit c615816679
7 changed files with 55 additions and 133 deletions

View File

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

View File

@ -16,6 +16,7 @@ LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/../ \
external/stlport/stlport \
external/protobuf/src \
external \
bionic
#LOCAL_CFLAGS += -O0 -g -DDEBUG -UNDEBUG

View File

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

View File

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

View File

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

View File

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

View File

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