diff options
author | David Li <davidxli@google.com> | 2011-03-01 16:08:10 -0800 |
---|---|---|
committer | David Li <davidxli@google.com> | 2011-03-03 18:28:43 -0800 |
commit | 28ca2abb1ab92b2cc3a5c9119ec2f697ec3401b2 (patch) | |
tree | f6bcb82ff2a68a5bd30218326def0f95fb6734f2 /opengl/libs/GLES2_dbg/src/texture.cpp | |
parent | e5f823ccf1cce4cab5699f1a07c1ee2290a69169 (diff) | |
download | frameworks_base-28ca2abb1ab92b2cc3a5c9119ec2f697ec3401b2.zip frameworks_base-28ca2abb1ab92b2cc3a5c9119ec2f697ec3401b2.tar.gz frameworks_base-28ca2abb1ab92b2cc3a5c9119ec2f697ec3401b2.tar.bz2 |
Initial commit of GLESv2 debugger server
Use debug.egl.debug_proc property to match process cmdline.
Binds to TCP:5039 and waits for client connection.
Sends function call parameters, textures and shaders using Protobuf.
Java Eclipse client plug-in is next.
Change-Id: I183b755263663f87e86dde1ad12f527d0445fd57
Signed-off-by: David Li <davidxli@google.com>
Diffstat (limited to 'opengl/libs/GLES2_dbg/src/texture.cpp')
-rw-r--r-- | opengl/libs/GLES2_dbg/src/texture.cpp | 300 |
1 files changed, 300 insertions, 0 deletions
diff --git a/opengl/libs/GLES2_dbg/src/texture.cpp b/opengl/libs/GLES2_dbg/src/texture.cpp new file mode 100644 index 0000000..a149487 --- /dev/null +++ b/opengl/libs/GLES2_dbg/src/texture.cpp @@ -0,0 +1,300 @@ +/* + ** Copyright 2011, The Android Open Source Project + ** + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** + ** http://www.apache.org/licenses/LICENSE-2.0 + ** + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + */ + +#include "header.h" + +static inline void GetFormatAndBytesPerPixel(const GLenum format, unsigned & bytesPerPixel) +{ + switch (format) { + case GL_ALPHA: + bytesPerPixel = 1; + break; + case GL_LUMINANCE: + bytesPerPixel = 1; + break; + case GL_LUMINANCE_ALPHA: + bytesPerPixel = 2; + break; + case GL_RGB: + bytesPerPixel = 3; + break; + case GL_RGBA: + bytesPerPixel = 4; + break; + + // internal formats to avoid conversion + case GL_UNSIGNED_SHORT_5_6_5: + bytesPerPixel = 2; + break; + case GL_UNSIGNED_SHORT_4_4_4_4: + bytesPerPixel = 2; + break; + case GL_UNSIGNED_SHORT_5_5_5_1: + bytesPerPixel = 2; + break; + default: + assert(0); + return; + } +} + +#define USE_RLE 0 +#if USE_RLE +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 > 127) + break; + if (!repeat) { + // find literal length + for (run = 1; run < count; run++) + if (data[run - 1] == data[run]) + break; + else if (run > 127) + 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 + +void API_ENTRY(glTexImage2D)(GLenum target, GLint level, GLint internalformat, GLsizei width, + GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid * pixels) +{ +// LOGD("\n*\n* GLESv2_dbg: %s \n*", "glTexImage2D"); + gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl; + + GLESv2Debugger::Message msg, cmd; + msg.set_context_id(0); + msg.set_has_next_message(true); + const bool expectResponse = false; + msg.set_expect_response(expectResponse); + msg.set_function(GLESv2Debugger::Message_Function_glTexImage2D); + + msg.set_arg0(target); + msg.set_arg1(level); + msg.set_arg2(internalformat); + msg.set_arg3(width); + msg.set_arg4(height); + msg.set_arg5(border); + msg.set_arg6(format); + msg.set_arg7(type); + + if (pixels) { + assert(internalformat == format); + assert(0 == border); + + GLenum newFormat = internalformat; + switch (type) { + case GL_UNSIGNED_BYTE: + break; + case GL_UNSIGNED_SHORT_5_6_5: + case GL_UNSIGNED_SHORT_4_4_4_4: + case GL_UNSIGNED_SHORT_5_5_5_1: + newFormat = type; + break; + default: + LOGD("GLESv2_dbg: glTexImage2D type=0x%.4X", type); + assert(0); + } + unsigned bytesPerPixel = 0; + GetFormatAndBytesPerPixel(newFormat, bytesPerPixel); + 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 + } + assert(msg.has_arg3()); + Send(msg, cmd); + if (!expectResponse) + cmd.set_function(GLESv2Debugger::Message_Function_CONTINUE); + + while (true) { + msg.Clear(); + clock_t c0 = clock(); + switch (cmd.function()) { + case GLESv2Debugger::Message_Function_CONTINUE: + _c->glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels); + msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC); + msg.set_context_id(0); + msg.set_function(GLESv2Debugger::Message_Function_glTexImage2D); + msg.set_has_next_message(false); + msg.set_expect_response(expectResponse); + assert(!msg.has_arg3()); + Send(msg, cmd); + if (!expectResponse) + cmd.set_function(GLESv2Debugger::Message_Function_SKIP); + break; + case GLESv2Debugger::Message_Function_SKIP: + return; + default: + ASSERT(0); //GenerateCall(msg, cmd); + break; + } + } +} + +void API_ENTRY(glTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels) +{ +// LOGD("\n*\n* GLESv2_dbg: %s \n*", "glTexSubImage2D"); + gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl; + + GLESv2Debugger::Message msg, cmd; + msg.set_context_id(0); + msg.set_has_next_message(true); + const bool expectResponse = false; + msg.set_expect_response(expectResponse); + msg.set_function(GLESv2Debugger::Message_Function_glTexSubImage2D); + + msg.set_arg0(target); + msg.set_arg1(level); + msg.set_arg2(xoffset); + msg.set_arg3(yoffset); + msg.set_arg4(width); + msg.set_arg5(height); + msg.set_arg6(format); + msg.set_arg7(type); + + assert(pixels); + if (pixels) { + GLenum newFormat = format; + switch (type) { + case GL_UNSIGNED_BYTE: + break; + case GL_UNSIGNED_SHORT_5_6_5: + case GL_UNSIGNED_SHORT_4_4_4_4: + case GL_UNSIGNED_SHORT_5_5_5_1: + newFormat = type; + break; + default: + assert(0); + } + unsigned bytesPerPixel = 0; + GetFormatAndBytesPerPixel(newFormat, bytesPerPixel); + 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 + } + + Send(msg, cmd); + if (!expectResponse) + cmd.set_function(GLESv2Debugger::Message_Function_CONTINUE); + + while (true) { + msg.Clear(); + clock_t c0 = clock(); + switch (cmd.function()) { + case GLESv2Debugger::Message_Function_CONTINUE: + _c->glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels); + msg.set_time((float(clock()) - c0) / CLOCKS_PER_SEC); + msg.set_function(GLESv2Debugger::Message_Function_glTexImage2D); + msg.set_context_id(0); + msg.set_has_next_message(false); + msg.set_expect_response(expectResponse); + Send(msg, cmd); + if (!expectResponse) + cmd.set_function(GLESv2Debugger::Message_Function_SKIP); + break; + case GLESv2Debugger::Message_Function_SKIP: + return; + default: + ASSERT(0); //GenerateCall(msg, cmd); + break; + } + } +} |