summaryrefslogtreecommitdiffstats
path: root/opengl/libs/GLES2_dbg/src/texture.cpp
diff options
context:
space:
mode:
authorDavid Li <davidxli@google.com>2011-03-01 16:08:10 -0800
committerDavid Li <davidxli@google.com>2011-03-03 18:28:43 -0800
commit28ca2abb1ab92b2cc3a5c9119ec2f697ec3401b2 (patch)
treef6bcb82ff2a68a5bd30218326def0f95fb6734f2 /opengl/libs/GLES2_dbg/src/texture.cpp
parente5f823ccf1cce4cab5699f1a07c1ee2290a69169 (diff)
downloadframeworks_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.cpp300
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;
+ }
+ }
+}