GLES2Dbg: reconstruct vertex attributes to match indices
Rather than converting glDrawElements into glDrawArrays and
uploading all attributes each draw call.
Also added CaptureDraw and CaptureSwap options.
Change-Id: If8ac6556a2674868ce83f074ce4068a6af2d3a0e
Signed-off-by: David Li <davidxli@google.com>
diff --git a/tools/glesv2debugger/generate_MessageParser_java.py b/tools/glesv2debugger/generate_MessageParser_java.py
index 0c5934b..9078d8e 100755
--- a/tools/glesv2debugger/generate_MessageParser_java.py
+++ b/tools/glesv2debugger/generate_MessageParser_java.py
@@ -81,25 +81,31 @@
ByteString ParseFloats(int count) {
ByteBuffer buffer = ByteBuffer.allocate(count * 4);
+ buffer.order(SampleView.targetByteOrder);
String [] arg = GetList();
for (int i = 0; i < count; i++)
buffer.putFloat(Float.parseFloat(arg[i].trim()));
+ buffer.rewind();
return ByteString.copyFrom(buffer);
}
ByteString ParseInts(int count) {
ByteBuffer buffer = ByteBuffer.allocate(count * 4);
+ buffer.order(SampleView.targetByteOrder);
String [] arg = GetList();
for (int i = 0; i < count; i++)
buffer.putInt(Integer.parseInt(arg[i].trim()));
+ buffer.rewind();
return ByteString.copyFrom(buffer);
}
ByteString ParseUInts(int count) {
ByteBuffer buffer = ByteBuffer.allocate(count * 4);
+ buffer.order(SampleView.targetByteOrder);
String [] arg = GetList();
for (int i = 0; i < count; i++)
buffer.putInt((int)(Long.parseLong(arg[i].trim()) & 0xffffffff));
+ buffer.rewind();
return ByteString.copyFrom(buffer);
}
diff --git a/tools/glesv2debugger/src/com/android/glesv2debugger/BreakpointOption.java b/tools/glesv2debugger/src/com/android/glesv2debugger/BreakpointOption.java
index 0733f28..2ed03c4 100644
--- a/tools/glesv2debugger/src/com/android/glesv2debugger/BreakpointOption.java
+++ b/tools/glesv2debugger/src/com/android/glesv2debugger/BreakpointOption.java
@@ -102,13 +102,15 @@
public boolean ProcessMessage(final MessageQueue queue, final Message msg) throws IOException {
// use DefaultProcessMessage just to register the GL call
// but do not send response
+ final int contextId = msg.getContextId();
if (msg.getType() == Type.BeforeCall || msg.getType() == Type.AfterCall)
queue.DefaultProcessMessage(msg, true, false);
final Message.Builder builder = Message.newBuilder();
- builder.setContextId(msg.getContextId());
+ builder.setContextId(contextId);
builder.setType(Type.Response);
builder.setExpectResponse(true);
final Shell shell = sampleView.getViewSite().getShell();
+ final boolean send[] = new boolean[1];
shell.getDisplay().syncExec(new Runnable() {
@Override
public void run() {
@@ -149,8 +151,8 @@
{
builder.setFunction(Function.SKIP);
// AfterCall is skipped, so push BeforeCall to complete
- if (msg.getType() == Type.BeforeCall)
- queue.CompletePartialMessage(msg.getContextId());
+ if (queue.GetPartialMessage(contextId) != null)
+ queue.CompletePartialMessage(contextId);
}
else if (s.startsWith("c"))
builder.setFunction(Function.CONTINUE);
@@ -165,9 +167,10 @@
{
MessageParserEx.instance.Parse(builder, inputDialog.getValue());
lastFunction = builder.getFunction();
+ builder.setExpectResponse(true);
// AfterCall is skipped, so push BeforeCall to complete
- if (msg.getType() == Type.BeforeCall)
- queue.CompletePartialMessage(msg.getContextId());
+ if (queue.GetPartialMessage(contextId) != null)
+ queue.CompletePartialMessage(contextId);
}
}
// else defaults to continue BeforeCall and skip AfterCall
diff --git a/tools/glesv2debugger/src/com/android/glesv2debugger/CodeGen.java b/tools/glesv2debugger/src/com/android/glesv2debugger/CodeGen.java
index 7f4bcef..d347bde 100644
--- a/tools/glesv2debugger/src/com/android/glesv2debugger/CodeGen.java
+++ b/tools/glesv2debugger/src/com/android/glesv2debugger/CodeGen.java
@@ -212,13 +212,13 @@
code.format("glTexParameteriv(%s, GL_TEXTURE_MAG_FILTER, (GLint[]){%s});CHKERR;\n",
tex.target, tex.mag);
}
- for (int i = 0; i < serverTexture.tmu2D.length && i < 16; i++) {
+ for (int i = 0; i < serverTexture.tmu2D.length; i++) {
code.format("glActiveTexture(%s);CHKERR;\n",
GLEnum.valueOf(GLEnum.GL_TEXTURE0.value + i));
code.format("glBindTexture(GL_TEXTURE_2D, texture_%d);CHKERR;\n",
serverTexture.tmu2D[i]);
}
- for (int i = 0; i < serverTexture.tmuCube.length && i < 16; i++) {
+ for (int i = 0; i < serverTexture.tmuCube.length; i++) {
code.format("glActiveTexture(%s);CHKERR;\n",
GLEnum.valueOf(GLEnum.GL_TEXTURE0.value + i));
code.format("glBindTexture(GL_TEXTURE_CUBE_MAP, texture_%d);CHKERR;\n",
@@ -414,54 +414,233 @@
if (namesArray.indexOfKey(name) < 0) {
namesHeader.format("extern GLuint %s;\n", id);
namesSource.format("GLuint %s = 0;\n", id);
- }
- code.format("%s = %d;\n", id, name);
+ } else if (namesArray.get(name) != name)
+ code.format("%s = %d;\n", id, name); // name was deleted
namesArray.put(name, name);
code.write(MessageFormatter.Format(msg, true));
code.write(";CHKERR;\n");
}
- private void CodeGenDrawArrays(final GLServerVertex v, final ByteBuffer[] attribs,
- final int mode, final int count) throws IOException {
- code.write("{\n");
- code.format(" FILE * attribFile = fopen(\"/sdcard/frame_data.bin\", \"rb\");CHKERR;\n");
- code.format(" assert(attribFile);CHKERR;\n");
- code.format(" fseek(attribFile, %d, SEEK_SET);CHKERR;\n", dataOut.getChannel()
- .position());
- code.format(" glBindBuffer(GL_ARRAY_BUFFER, 0);CHKERR;\n");
- for (int i = 0; i < attribs.length; i++) {
+ private void CodeGenDrawArrays(final GLServerVertex v, final MessageData msgData)
+ throws IOException {
+ final int maxAttrib = msgData.msg.getArg7();
+ if (maxAttrib < 1) {
+ code.write("// no vertex data\n");
+ return;
+ }
+ final byte[] data = msgData.msg.getData().toByteArray();
+ final GLEnum mode = GLEnum.valueOf(msgData.msg.getArg0());
+ final int first = msgData.msg.getArg1(), count = msgData.msg.getArg2();
+ int attribDataStride = 0;
+ for (int i = 0; i < maxAttrib; i++) {
final GLAttribPointer att = v.attribPointers[i];
if (!att.enabled)
continue;
- final byte[] data = attribs[i].array();
- final String typeName = "GL" + att.type.name().substring(3).toLowerCase();
- code.format(" %s * attrib%d = (%s *)malloc(%d);CHKERR;\n", typeName, i, typeName,
- data.length);
- dataOut.write(data);
- code.format(" fread(attrib%d, %d, 1, attribFile);CHKERR;\n", i, data.length);
- // code.format(" for (unsigned int i = 0; i < %d; i++)\n", count
- // * att.size);
- // code.format(" printf(\"%%f \\n\", attrib%d[i]);CHKERR;\n",
- // i);
- code.format(" glVertexAttribPointer(%d, %d, %s, %b, %d, attrib%d);CHKERR;\n",
- i, att.size, att.type, att.normalized,
- att.size * GLServerVertex.TypeSize(att.type), i);
+ if (att.buffer != null)
+ continue;
+ attribDataStride += att.elemSize;
}
- code.format(" fclose(attribFile);CHKERR;\n");
- code.format(" glDrawArrays(%s, 0, %d);CHKERR;\n", GLEnum.valueOf(mode), count);
- for (int i = 0; i < attribs.length; i++)
- if (v.attribPointers[i].enabled)
- code.format(" free(attrib%d);CHKERR;\n", i);
-
- if (v.attribBuffer != null)
- code.format(" glBindBuffer(GL_ARRAY_BUFFER, %d);CHKERR;\n",
- v.attribBuffer.name);
+ assert attribDataStride * count == data.length;
+ code.write("{\n");
+ if (attribDataStride > 0) {
+ code.format(" FILE * attribFile = fopen(\"/sdcard/frame_data.bin\", \"rb\");CHKERR;\n");
+ code.format(" assert(attribFile);CHKERR;\n");
+ code.format(" fseek(attribFile, %d, SEEK_SET);CHKERR;\n", dataOut.getChannel()
+ .position());
+ dataOut.write(data);
+ code.format(" char * const attribData = (char *)malloc(%d);\n", first
+ * attribDataStride + data.length);
+ code.format(" assert(attribData);\n");
+ code.format(" fread(attribData + %d, %d, 1, attribFile);\n",
+ first * attribDataStride, data.length);
+ code.format(" fclose(attribFile);\n");
+ code.format(" glBindBuffer(GL_ARRAY_BUFFER, 0);CHKERR;\n");
+ int attribDataOffset = 0;
+ for (int i = 0; i < maxAttrib; i++) {
+ final GLAttribPointer att = v.attribPointers[i];
+ if (!att.enabled)
+ continue;
+ if (att.buffer != null)
+ continue;
+ code.format(
+ " glVertexAttribPointer(%d, %d, %s, %b, %d, attribData + %d);CHKERR;\n",
+ i, att.size, att.type, att.normalized,
+ attribDataStride, attribDataOffset);
+ attribDataOffset += att.elemSize;
+ }
+ if (v.attribBuffer != null)
+ code.format(" glBindBuffer(GL_ARRAY_BUFFER, %d);CHKERR;\n",
+ v.attribBuffer.name);
+ }
+ code.format(" glDrawArrays(%s, %d, %d);CHKERR;\n", mode, first, count);
+ if (attribDataStride > 0)
+ code.format(" free(attribData);CHKERR;\n");
code.write("};\n");
}
- private void CodeGenFunction(final Context ctx, final MessageData msgData) throws IOException {
+ private void CodeGenDrawElements(final GLServerVertex v, final MessageData msgData)
+ throws IOException {
+ final int maxAttrib = msgData.msg.getArg7();
+ if (maxAttrib < 1) {
+ code.write("// no vertex data\n");
+ return;
+ }
+ final GLEnum mode = GLEnum.valueOf(msgData.msg.getArg0());
+ final int count = msgData.msg.getArg1();
+ final GLEnum type = GLEnum.valueOf(msgData.msg.getArg2());
+ String typeName = "GLubyte";
+ if (type == GLEnum.GL_UNSIGNED_SHORT)
+ typeName = "GLushort";
+ int attribDataStride = 0;
+ for (int i = 0; i < maxAttrib; i++) {
+ final GLAttribPointer att = v.attribPointers[i];
+ if (!att.enabled)
+ continue;
+ if (att.buffer != null)
+ continue;
+ attribDataStride += att.elemSize;
+ }
+ code.write("{\n");
+ if (v.indexBuffer == null || attribDataStride > 0) {
+ // need to load user pointer indices and/or attributes
+ final byte[] element = new byte[attribDataStride];
+ final ByteBuffer data = msgData.msg.getData().asReadOnlyByteBuffer();
+ data.order(SampleView.targetByteOrder);
+ final ByteBuffer indexData = ByteBuffer.allocate(count * GLServerVertex.TypeSize(type));
+ indexData.order(SampleView.targetByteOrder);
+ final ByteBuffer attribData = ByteBuffer.allocate(count * attribDataStride);
+ attribData.order(SampleView.targetByteOrder);
+ int maxIndex = -1;
+ ByteBuffer indexSrc = data;
+ if (v.indexBuffer != null) {
+ indexSrc = v.indexBuffer.data;
+ indexSrc.position(msgData.msg.getArg3());
+ }
+ indexSrc.order(SampleView.targetByteOrder);
+ for (int i = 0; i < count; i++) {
+ int index = -1;
+ if (type == GLEnum.GL_UNSIGNED_BYTE) {
+ byte idx = indexSrc.get();
+ index = idx & 0xff;
+ indexData.put(idx);
+ } else if (type == GLEnum.GL_UNSIGNED_SHORT) {
+ short idx = indexSrc.getShort();
+ index = idx & 0xffff;
+ indexData.putShort(idx);
+ } else
+ assert false;
+ data.get(element);
+ attribData.put(element);
+ if (index > maxIndex)
+ maxIndex = index;
+ }
+ code.format(" FILE * attribFile = fopen(\"/sdcard/frame_data.bin\", \"rb\");CHKERR;\n");
+ code.format(" assert(attribFile);CHKERR;\n");
+ code.format(" fseek(attribFile, 0x%X, SEEK_SET);CHKERR;\n",
+ dataOut.getChannel().position());
+ dataOut.write(indexData.array());
+ code.format(" %s * const indexData = (%s *)malloc(%d);\n", typeName, typeName,
+ indexData.capacity());
+ code.format(" assert(indexData);\n");
+ code.format(" fread(indexData, %d, 1, attribFile);\n", indexData.capacity());
+ if (attribDataStride > 0) {
+ code.format(" glBindBuffer(GL_ARRAY_BUFFER, 0);CHKERR;\n");
+ for (int i = 0; i < maxAttrib; i++) {
+ final GLAttribPointer att = v.attribPointers[i];
+ if (!att.enabled)
+ continue;
+ if (att.buffer != null)
+ continue;
+ code.format(" char * const attrib%d = (char *)malloc(%d);\n",
+ i, att.elemSize * (maxIndex + 1));
+ code.format(" assert(attrib%d);\n", i);
+ code.format(
+ " glVertexAttribPointer(%d, %d, %s, %b, %d, attrib%d);CHKERR;\n",
+ i, att.size, att.type, att.normalized, att.elemSize, i);
+ }
+ dataOut.write(attribData.array());
+ code.format(" for (%s i = 0; i < %d; i++) {\n", typeName, count);
+ for (int i = 0; i < maxAttrib; i++) {
+ final GLAttribPointer att = v.attribPointers[i];
+ if (!att.enabled)
+ continue;
+ if (att.buffer != null)
+ continue;
+ code.format(
+ " fread(attrib%d + indexData[i] * %d, %d, 1, attribFile);\n",
+ i, att.elemSize, att.elemSize);
+ }
+ code.format(" }\n");
+ if (v.attribBuffer != null)
+ code.format(" glBindBuffer(GL_ARRAY_BUFFER, %d);CHKERR;\n",
+ v.attribBuffer.name);
+ }
+ code.format(" fclose(attribFile);\n");
+ }
+ if (v.indexBuffer != null)
+ code.format(" glDrawElements(%s, %d, %s, (const void *)%d);CHKERR;\n",
+ mode, count, type, msgData.msg.getArg3());
+ else {
+ code.format(" glDrawElements(%s, %d, %s, indexData);CHKERR;\n",
+ mode, count, type);
+ code.format(" free(indexData);\n");
+ }
+ for (int i = 0; i < maxAttrib; i++) {
+ final GLAttribPointer att = v.attribPointers[i];
+ if (!att.enabled)
+ continue;
+ if (att.buffer != null)
+ continue;
+ code.format(" free(attrib%d);\n", i);
+ }
+ code.write("};\n");
+ }
+
+ private void CodeGenDraw(final GLServerVertex v, final MessageData msgData)
+ throws IOException {
+ final int maxAttrib = msgData.msg.getArg7();
+ if (maxAttrib < 1) {
+ code.write("// no vertex data\n");
+ return;
+ }
+ final int count = msgData.attribs[0].length / 4;
+ final GLEnum mode = GLEnum.valueOf(msgData.msg.getArg0());
+ final ByteBuffer attribData = ByteBuffer.allocate(maxAttrib * count * 16);
+ attribData.order(SampleView.targetByteOrder);
+ for (int i = 0; i < count; i++)
+ for (int j = 0; j < maxAttrib; j++)
+ for (int k = 0; k < 4; k++)
+ attribData.putFloat(msgData.attribs[j][i * 4 + k]);
+ assert attribData.remaining() == 0;
+ code.write("{\n");
+ code.format(" FILE * attribFile = fopen(\"/sdcard/frame_data.bin\", \"rb\");CHKERR;\n");
+ code.format(" assert(attribFile);CHKERR;\n");
+ code.format(" fseek(attribFile, 0x%X, SEEK_SET);CHKERR;\n",
+ dataOut.getChannel().position());
+ dataOut.write(attribData.array());
+ code.format(" char * const attribData = (char *)malloc(%d);\n", attribData.capacity());
+ code.format(" assert(attribData);\n");
+ code.format(" fread(attribData, %d, 1, attribFile);\n", attribData.capacity());
+ code.format(" fclose(attribFile);\n");
+ code.format(" glBindBuffer(GL_ARRAY_BUFFER, 0);CHKERR;\n");
+ for (int i = 0; i < maxAttrib; i++) {
+ final GLAttribPointer att = v.attribPointers[i];
+ assert msgData.attribs[i].length == count * 4;
+ code.format(
+ " glVertexAttribPointer(%d, %d, GL_FLOAT, GL_FALSE, %d, attribData + %d);CHKERR;\n",
+ i, att.size, maxAttrib * 16, i * 16);
+ }
+ code.format(" glDrawArrays(%s, 0, %d);CHKERR;\n", mode, count);
+ code.format(" free(attribData);\n");
+ if (v.attribBuffer != null)
+ code.format(" glBindBuffer(GL_ARRAY_BUFFER, %d);CHKERR;\n",
+ v.attribBuffer.name);
+ code.write("};\n");
+ }
+
+ private void CodeGenFunction(final Context ctx, final MessageData msgData)
+ throws IOException {
final Message msg = msgData.msg;
- final Message oriMsg = msgData.oriMsg;
String call = MessageFormatter.Format(msg, true);
switch (msg.getFunction()) {
case glActiveTexture:
@@ -536,10 +715,12 @@
case glDisableVertexAttribArray:
break;
case glDrawArrays:
- CodeGenDrawArrays(ctx.serverVertex, msgData.attribs, msg.getArg0(), msg.getArg2());
+ // CodeGenDraw(ctx.serverVertex, msgData);
+ CodeGenDrawArrays(ctx.serverVertex, msgData);
return;
case glDrawElements:
- CodeGenDrawArrays(ctx.serverVertex, msgData.attribs, msg.getArg0(), msg.getArg1());
+ // CodeGenDraw(ctx.serverVertex, msgData);
+ CodeGenDrawElements(ctx.serverVertex, msgData);
return;
case glEnable:
case glEnableVertexAttribArray:
@@ -677,8 +858,10 @@
case glVertexAttrib4fv:
break;
case glVertexAttribPointer:
- // pointer set during glDrawArrays/Elements from captured data
- call = call.replace("arg5", "NULL");
+ // if it's user pointer, then CodeGenDrawArrays/Elements will
+ // replace it with loaded data just before the draw
+ call = call.replace("arg5", "(const void *)0x" +
+ Integer.toHexString(msg.getArg5()));
break;
case glViewport:
break;
@@ -688,6 +871,12 @@
assert false;
return;
}
+ if (call.indexOf("glEnable(/*cap*/ GL_TEXTURE_2D)") >= 0)
+ return;
+ else if (call.indexOf("glDisable(/*cap*/ GL_TEXTURE_2D)") >= 0)
+ return;
+ else if (call.indexOf("glActiveTexture(/*texture*/ GL_TEXTURE_2D)") >= 0)
+ return;
code.write(call + ";CHKERR;\n");
}
@@ -716,7 +905,7 @@
namesHeader.write("#include <assert.h>\n");
namesHeader.write("#include <GLES2/gl2.h>\n");
namesHeader.write("#include <GLES2/gl2ext.h>\n");
- namesHeader.write("#define CHKERR /*assert(GL_NO_ERROR == glGetError());/**/\n");
+ namesHeader.write("#define CHKERR assert(GL_NO_ERROR == glGetError());/**/\n");
namesHeader.write("void FrameSetup();\n");
namesHeader.write("extern const unsigned int FrameCount;\n");
namesHeader.write("extern const GLuint program_0;\n");
@@ -776,6 +965,7 @@
private DebugContext dbgCtx;
private int count;
private IProgressMonitor progress;
+
@Override
public void run(IProgressMonitor monitor) throws InvocationTargetException,
InterruptedException {
@@ -800,7 +990,7 @@
final MessageData msgData = frame.Get(j);
code.format("/* frame function %d: %s %s*/\n", j, msgData.msg.getFunction(),
MessageFormatter.Format(msgData.msg, false));
- ctx.ProcessMessage(msgData.oriMsg);
+ ctx.ProcessMessage(msgData.msg);
try {
CodeGenFunction(ctx, msgData);
} catch (IOException e) {
@@ -865,7 +1055,7 @@
final MessageData msgData = frame.Get(i);
code.format("/* frame function %d: %s %s*/\n", i, msgData.msg.getFunction(),
MessageFormatter.Format(msgData.msg, false));
- ctx.ProcessMessage(msgData.oriMsg);
+ ctx.ProcessMessage(msgData.msg);
try {
CodeGenFunction(ctx, msgData);
} catch (IOException e) {
diff --git a/tools/glesv2debugger/src/com/android/glesv2debugger/Context.java b/tools/glesv2debugger/src/com/android/glesv2debugger/Context.java
index 23160c4..2296b31 100644
--- a/tools/glesv2debugger/src/com/android/glesv2debugger/Context.java
+++ b/tools/glesv2debugger/src/com/android/glesv2debugger/Context.java
@@ -17,9 +17,11 @@
package com.android.glesv2debugger;
import com.android.glesv2debugger.DebuggerMessage.Message;
+import com.android.glesv2debugger.DebuggerMessage.Message.DataType;
import com.android.glesv2debugger.DebuggerMessage.Message.Function;
import com.android.sdklib.util.SparseArray;
import com.android.sdklib.util.SparseIntArray;
+import com.google.protobuf.ByteString;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ITreeContentProvider;
@@ -68,7 +70,7 @@
if (call == calls.get(i))
return ctx;
else
- ctx.ProcessMessage(calls.get(i).oriMsg);
+ ctx.ProcessMessage(calls.get(i).msg);
assert false;
return ctx;
}
@@ -106,10 +108,9 @@
len = Integer.reverseBytes(len);
final byte[] data = new byte[len];
file.read(data);
- final Message oriMsg = Message.parseFrom(data);
- final Message msg = ctx.ProcessMessage(oriMsg);
- final MessageData msgData = new MessageData(Display.getCurrent(), msg, oriMsg, ctx);
- msgData.attribs = ctx.serverVertex.fetchedAttribs;
+ Message msg = Message.parseFrom(data);
+ ctx.ProcessMessage(msg);
+ final MessageData msgData = new MessageData(Display.getCurrent(), msg, ctx);
calls.add(msgData);
}
file.seek(oriPosition);
@@ -133,8 +134,8 @@
this.contextId = contextId;
currentContext = new Context(contextId);
try {
- file = new RandomAccessFile(Integer.toHexString(contextId) + ".gles2dbg",
- "rw");
+ file = new RandomAccessFile("0x" + Integer.toHexString(contextId) +
+ ".gles2dbg", "rw");
frames.add(new Frame(currentContext, file.getFilePointer()));
} catch (FileNotFoundException e) {
@@ -148,10 +149,25 @@
loadedFrame = lastFrame;
}
- /** Writes oriMsg to file, and formats into MessageData for current frame */
- void ProcessMessage(final Message oriMsg) {
+ /**
+ * Caches new Message, and formats into MessageData for current frame; this
+ * function is called exactly once for each new Message
+ */
+ void ProcessMessage(final Message newMsg) {
+ Message msg = newMsg;
+ currentContext.ProcessMessage(newMsg);
+ if (msg.hasDataType() && msg.getDataType() == DataType.ReferencedImage) {
+ final byte[] referenced = MessageProcessor.LZFDecompressChunks(msg.getData());
+ currentContext.readPixelRef = MessageProcessor.DecodeReferencedImage(
+ currentContext.readPixelRef, referenced);
+ final byte[] decoded = MessageProcessor.LZFCompressChunks(
+ currentContext.readPixelRef, referenced.length);
+ msg = newMsg.toBuilder().setDataType(DataType.NonreferencedImage)
+ .setData(ByteString.copyFrom(decoded)).build();
+ }
synchronized (file) {
- final byte[] data = oriMsg.toByteArray();
+ lastFrame.IncreaseCallsCount();
+ final byte[] data = msg.toByteArray();
final ByteBuffer len = ByteBuffer.allocate(4);
len.order(SampleView.targetByteOrder);
len.putInt(data.length);
@@ -166,13 +182,8 @@
assert false;
}
}
-
- lastFrame.IncreaseCallsCount();
- final Message msg = currentContext.ProcessMessage(oriMsg);
if (loadedFrame == lastFrame) {
- final MessageData msgData = new MessageData(Display.getCurrent(), msg, oriMsg,
- currentContext);
- msgData.attribs = currentContext.serverVertex.fetchedAttribs;
+ final MessageData msgData = new MessageData(Display.getCurrent(), msg, currentContext);
lastFrame.Add(msgData);
uiUpdate = true;
}
@@ -242,7 +253,8 @@
copy.serverShader = serverShader.clone(copy);
copy.serverState = serverState.clone();
copy.serverTexture = serverTexture.clone(copy);
- copy.readPixelRef = readPixelRef.clone();
+ // don't need to clone readPixelsRef, since referenced images
+ // are decoded when they are encountered
return copy;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
@@ -251,21 +263,16 @@
}
}
- /** returns processed Message, which could be a new Message */
- public Message ProcessMessage(Message msg) {
- if (serverVertex.Process(msg)) {
- if (serverVertex.processed != null)
- return serverVertex.processed;
- else
- return msg;
- }
+ /** mainly updating states */
+ public void ProcessMessage(Message msg) {
+ if (serverVertex.Process(msg))
+ return;
if (serverShader.ProcessMessage(msg))
- return msg;
+ return;
if (serverState.ProcessMessage(msg))
- return msg;
+ return;
if (serverTexture.ProcessMessage(msg))
- return msg;
- return msg;
+ return;
}
}
@@ -310,10 +317,10 @@
switch (msg.getFunction()) {
case glTexImage2D:
case glTexSubImage2D:
- return entry.image = new MessageData(Display.getCurrent(), msg, msg, null).image;
case glCopyTexImage2D:
case glCopyTexSubImage2D:
- return null; // TODO: compute context for reference frame
+ return entry.image = new MessageData(Display.getCurrent(), msg, null)
+ .GetImage();
default:
return null;
}
diff --git a/tools/glesv2debugger/src/com/android/glesv2debugger/DebuggerMessage.java b/tools/glesv2debugger/src/com/android/glesv2debugger/DebuggerMessage.java
index d871afb..996f749 100644
--- a/tools/glesv2debugger/src/com/android/glesv2debugger/DebuggerMessage.java
+++ b/tools/glesv2debugger/src/com/android/glesv2debugger/DebuggerMessage.java
@@ -528,9 +528,10 @@
public enum Prop
implements com.google.protobuf.Internal.EnumLite {
- Capture(0, 0),
+ CaptureDraw(0, 0),
TimeMode(1, 1),
ExpectResponse(2, 2),
+ CaptureSwap(3, 3),
;
@@ -538,9 +539,10 @@
public static Prop valueOf(int value) {
switch (value) {
- case 0: return Capture;
+ case 0: return CaptureDraw;
case 1: return TimeMode;
case 2: return ExpectResponse;
+ case 3: return CaptureSwap;
default: return null;
}
}
@@ -693,6 +695,20 @@
public boolean hasPixelType() { return hasPixelType; }
public int getPixelType() { return pixelType_; }
+ // optional int32 image_width = 26;
+ public static final int IMAGE_WIDTH_FIELD_NUMBER = 26;
+ private boolean hasImageWidth;
+ private int imageWidth_ = 0;
+ public boolean hasImageWidth() { return hasImageWidth; }
+ public int getImageWidth() { return imageWidth_; }
+
+ // optional int32 image_height = 27;
+ public static final int IMAGE_HEIGHT_FIELD_NUMBER = 27;
+ private boolean hasImageHeight;
+ private int imageHeight_ = 0;
+ public boolean hasImageHeight() { return hasImageHeight; }
+ public int getImageHeight() { return imageHeight_; }
+
// optional float time = 11;
public static final int TIME_FIELD_NUMBER = 11;
private boolean hasTime;
@@ -718,7 +734,7 @@
function_ = com.android.glesv2debugger.DebuggerMessage.Message.Function.NEG;
type_ = com.android.glesv2debugger.DebuggerMessage.Message.Type.BeforeCall;
dataType_ = com.android.glesv2debugger.DebuggerMessage.Message.DataType.ReferencedImage;
- prop_ = com.android.glesv2debugger.DebuggerMessage.Message.Prop.Capture;
+ prop_ = com.android.glesv2debugger.DebuggerMessage.Message.Prop.CaptureDraw;
}
public final boolean isInitialized() {
if (!hasContextId) return false;
@@ -794,6 +810,12 @@
if (hasPixelType()) {
output.writeInt32(25, getPixelType());
}
+ if (hasImageWidth()) {
+ output.writeInt32(26, getImageWidth());
+ }
+ if (hasImageHeight()) {
+ output.writeInt32(27, getImageHeight());
+ }
}
private int memoizedSerializedSize = -1;
@@ -886,6 +908,14 @@
size += com.google.protobuf.CodedOutputStream
.computeInt32Size(25, getPixelType());
}
+ if (hasImageWidth()) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeInt32Size(26, getImageWidth());
+ }
+ if (hasImageHeight()) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeInt32Size(27, getImageHeight());
+ }
memoizedSerializedSize = size;
return size;
}
@@ -1084,6 +1114,12 @@
if (other.hasPixelType()) {
setPixelType(other.getPixelType());
}
+ if (other.hasImageWidth()) {
+ setImageWidth(other.getImageWidth());
+ }
+ if (other.hasImageHeight()) {
+ setImageHeight(other.getImageHeight());
+ }
if (other.hasTime()) {
setTime(other.getTime());
}
@@ -1211,6 +1247,14 @@
setPixelType(input.readInt32());
break;
}
+ case 208: {
+ setImageWidth(input.readInt32());
+ break;
+ }
+ case 216: {
+ setImageHeight(input.readInt32());
+ break;
+ }
}
}
}
@@ -1552,6 +1596,42 @@
return this;
}
+ // optional int32 image_width = 26;
+ public boolean hasImageWidth() {
+ return result.hasImageWidth();
+ }
+ public int getImageWidth() {
+ return result.getImageWidth();
+ }
+ public Builder setImageWidth(int value) {
+ result.hasImageWidth = true;
+ result.imageWidth_ = value;
+ return this;
+ }
+ public Builder clearImageWidth() {
+ result.hasImageWidth = false;
+ result.imageWidth_ = 0;
+ return this;
+ }
+
+ // optional int32 image_height = 27;
+ public boolean hasImageHeight() {
+ return result.hasImageHeight();
+ }
+ public int getImageHeight() {
+ return result.getImageHeight();
+ }
+ public Builder setImageHeight(int value) {
+ result.hasImageHeight = true;
+ result.imageHeight_ = value;
+ return this;
+ }
+ public Builder clearImageHeight() {
+ result.hasImageHeight = false;
+ result.imageHeight_ = 0;
+ return this;
+ }
+
// optional float time = 11;
public boolean hasTime() {
return result.hasTime();
@@ -1587,7 +1667,7 @@
}
public Builder clearProp() {
result.hasProp = false;
- result.prop_ = com.android.glesv2debugger.DebuggerMessage.Message.Prop.Capture;
+ result.prop_ = com.android.glesv2debugger.DebuggerMessage.Message.Prop.CaptureDraw;
return this;
}
diff --git a/tools/glesv2debugger/src/com/android/glesv2debugger/GLServerTexture.java b/tools/glesv2debugger/src/com/android/glesv2debugger/GLServerTexture.java
index fe3a34c..5235d9b 100644
--- a/tools/glesv2debugger/src/com/android/glesv2debugger/GLServerTexture.java
+++ b/tools/glesv2debugger/src/com/android/glesv2debugger/GLServerTexture.java
@@ -83,8 +83,8 @@
Context context;
public GLEnum activeTexture = GLEnum.GL_TEXTURE0;
- public int[] tmu2D = new int[32];
- public int[] tmuCube = new int[32];
+ public int[] tmu2D = new int[16]; // TODO: MAX_COMBINED_TEXTURE_IMAGE_UNITS
+ public int[] tmuCube = new int[16];
public SparseArray<GLTexture> textures = new SparseArray<GLTexture>();
public GLTexture tex2D = null, texCube = null;
diff --git a/tools/glesv2debugger/src/com/android/glesv2debugger/GLServerVertex.java b/tools/glesv2debugger/src/com/android/glesv2debugger/GLServerVertex.java
index 8ee4c22..ed1572b 100644
--- a/tools/glesv2debugger/src/com/android/glesv2debugger/GLServerVertex.java
+++ b/tools/glesv2debugger/src/com/android/glesv2debugger/GLServerVertex.java
@@ -39,6 +39,7 @@
GLBuffer copy = (GLBuffer) super.clone();
if (data != null) {
copy.data = ByteBuffer.allocate(data.capacity());
+ copy.data.order(SampleView.targetByteOrder);
data.position(0);
copy.data.put(data);
}
@@ -55,6 +56,13 @@
public int size; // number of values per vertex
public GLEnum type; // data type
public int stride; // bytes
+ /**
+ * element stride in bytes, used when fetching from buffer; not for fetching
+ * from user pointer since server already packed elements
+ */
+ int elemStride; // in bytes
+ /** element size in bytes */
+ int elemSize;
public int ptr; // pointer in debugger server or byte offset into buffer
public GLBuffer buffer;
public boolean normalized;
@@ -80,9 +88,6 @@
public GLBuffer attribBuffer, indexBuffer; // current binding
public GLAttribPointer attribPointers[];
public float defaultAttribs[][];
- int maxAttrib;
-
- ByteBuffer[] fetchedAttribs;
public GLServerVertex() {
buffers.append(0, null);
@@ -131,11 +136,8 @@
}
}
- Message processed = null; // return; glDrawArrays/Elements with fetched data
-
/** returns true if processed */
public boolean Process(final Message msg) {
- processed = null;
switch (msg.getFunction()) {
case glBindBuffer:
glBindBuffer(msg);
@@ -150,12 +152,7 @@
glDeleteBuffers(msg);
return true;
case glDrawArrays:
- if (msg.hasArg7())
- processed = glDrawArrays(msg);
- return true;
case glDrawElements:
- if (msg.hasArg7())
- processed = glDrawElements(msg);
return true;
case glDisableVertexAttribArray:
glDisableVertexAttribArray(msg);
@@ -341,86 +338,72 @@
}
}
- void Fetch(int index, final ByteBuffer nonVBO, final ByteBuffer dst) {
+ void Fetch(final int maxAttrib, final int index, final int dstIdx, final ByteBuffer nonVBO,
+ final float[][] fetchedAttribs) {
for (int i = 0; i < maxAttrib; i++) {
final GLAttribPointer attrib = attribPointers[i];
int size = 0;
if (attrib.enabled) {
size = attrib.size;
- final ByteBuffer fetched = fetchedAttribs[i];
- final byte[] element = new byte[TypeSize(attrib.type) * size];
if (null != attrib.buffer) {
final ByteBuffer src = attrib.buffer.data;
- src.position(attrib.ptr + index * attrib.stride);
- src.get(element);
- src.position(attrib.ptr + index * attrib.stride);
+ src.position(attrib.ptr + index * attrib.elemStride);
for (int j = 0; j < size; j++)
- dst.putFloat(FetchConvert(src, attrib.type, attrib.normalized));
- } else {
- final int position = nonVBO.position();
- nonVBO.get(element);
- nonVBO.position(position);
+ fetchedAttribs[i][dstIdx * 4 + j] = FetchConvert(src, attrib.type,
+ attrib.normalized);
+ } else
for (int j = 0; j < size; j++)
- dst.putFloat(FetchConvert(nonVBO, attrib.type, attrib.normalized));
- }
- fetched.put(element);
+ fetchedAttribs[i][dstIdx * 4 + j] = FetchConvert(nonVBO, attrib.type,
+ attrib.normalized);
}
if (size < 1)
- dst.putFloat(defaultAttribs[i][0]);
+ fetchedAttribs[i][dstIdx * 4 + 0] = defaultAttribs[i][0];
if (size < 2)
- dst.putFloat(defaultAttribs[i][1]);
+ fetchedAttribs[i][dstIdx * 4 + 1] = defaultAttribs[i][1];
if (size < 3)
- dst.putFloat(defaultAttribs[i][2]);
+ fetchedAttribs[i][dstIdx * 4 + 2] = defaultAttribs[i][2];
if (size < 4)
- dst.putFloat(defaultAttribs[i][3]);
+ fetchedAttribs[i][dstIdx * 4 + 3] = defaultAttribs[i][3];
}
}
- // void glDrawArrays(GLenum mode, GLint first, GLsizei count)
- public Message glDrawArrays(Message msg) {
- maxAttrib = msg.getArg7();
- fetchedAttribs = new ByteBuffer[maxAttrib];
- for (int i = 0; i < maxAttrib; i++) {
- if (!attribPointers[i].enabled)
- continue;
- fetchedAttribs[i] = ByteBuffer.allocate(TypeSize(attribPointers[i].type)
- * attribPointers[i].size * msg.getArg2());
- }
+ /**
+ * fetches and converts vertex data from buffers, defaults and user pointers
+ * into MessageData; mainly for display use
+ */
+ public void glDrawArrays(MessageData msgData) {
+ final Message msg = msgData.msg;
+ if (!msg.hasArg7())
+ return;
+ final int maxAttrib = msg.getArg7();
final int first = msg.getArg1(), count = msg.getArg2();
- final ByteBuffer buffer = ByteBuffer.allocate(4 * 4 * maxAttrib * count);
+ msgData.attribs = new float[maxAttrib][count * 4];
ByteBuffer arrays = null;
if (msg.hasData()) // server sends user pointer attribs
{
arrays = msg.getData().asReadOnlyByteBuffer();
arrays.order(SampleView.targetByteOrder);
}
- for (int i = first; i < first + count; i++)
- Fetch(i, arrays, buffer);
+ for (int i = 0; i < count; i++)
+ Fetch(maxAttrib, first + i, i, arrays, msgData.attribs);
assert null == arrays || arrays.remaining() == 0;
- for (int i = 0; i < maxAttrib; i++) {
- if (!attribPointers[i].enabled)
- continue;
- assert fetchedAttribs[i].remaining() == 0;
- }
- buffer.rewind();
- return msg.toBuilder().setData(com.google.protobuf.ByteString.copyFrom(buffer))
- .setArg8(GLEnum.GL_FLOAT.value).build();
}
// void glDrawElements(GLenum mode, GLsizei count, GLenum type, const
// GLvoid* indices)
- public Message glDrawElements(Message msg) {
- maxAttrib = msg.getArg7();
- fetchedAttribs = new ByteBuffer[maxAttrib];
- for (int i = 0; i < maxAttrib; i++) {
- if (!attribPointers[i].enabled)
- continue;
- fetchedAttribs[i] = ByteBuffer.allocate(TypeSize(attribPointers[i].type)
- * attribPointers[i].size * msg.getArg1());
- }
+ /**
+ * fetches and converts vertex data from buffers, defaults and user pointers
+ * and indices from buffer/pointer into MessageData; mainly for display use
+ */
+ public void glDrawElements(MessageData msgData) {
+ final Message msg = msgData.msg;
+ if (!msg.hasArg7())
+ return;
+ final int maxAttrib = msg.getArg7();
final int count = msg.getArg1();
final GLEnum type = GLEnum.valueOf(msg.getArg2());
- final ByteBuffer buffer = ByteBuffer.allocate(4 * 4 * maxAttrib * count);
+ msgData.attribs = new float[maxAttrib][count * 4];
+ msgData.indices = new short[count];
ByteBuffer arrays = null, index = null;
if (msg.hasData()) // server sends user pointer attribs
{
@@ -431,26 +414,21 @@
index = arrays; // server also interleaves user pointer indices
else {
index = indexBuffer.data;
- index.order(SampleView.targetByteOrder);
index.position(msg.getArg3());
}
- if (GLEnum.GL_UNSIGNED_SHORT == type)
- for (int i = 0; i < count; i++)
- Fetch(index.getShort() & 0xffff, arrays, buffer);
- else if (GLEnum.GL_UNSIGNED_BYTE == type)
- for (int i = 0; i < count; i++)
- Fetch(index.get() & 0xff, arrays, buffer);
- else
+ if (GLEnum.GL_UNSIGNED_SHORT == type) {
+ for (int i = 0; i < count; i++) {
+ msgData.indices[i] = index.getShort();
+ Fetch(maxAttrib, msgData.indices[i] & 0xffff, i, arrays, msgData.attribs);
+ }
+ } else if (GLEnum.GL_UNSIGNED_BYTE == type) {
+ for (int i = 0; i < count; i++) {
+ msgData.indices[i] = (short) (index.get() & 0xff);
+ Fetch(maxAttrib, msgData.indices[i], i, arrays, msgData.attribs);
+ }
+ } else
assert false;
assert null == arrays || arrays.remaining() == 0;
- for (int i = 0; i < maxAttrib; i++) {
- if (!attribPointers[i].enabled)
- continue;
- assert fetchedAttribs[i].remaining() == 0;
- }
- buffer.rewind();
- return msg.toBuilder().setData(com.google.protobuf.ByteString.copyFrom(buffer))
- .setArg8(GLEnum.GL_FLOAT.value).build();
}
// void glEnableVertexAttribArray(GLuint index)
@@ -480,8 +458,11 @@
attrib.type = GLEnum.valueOf(msg.getArg2());
attrib.normalized = msg.getArg3() != 0;
attrib.stride = msg.getArg4();
- if (0 == attrib.stride)
- attrib.stride = attrib.size * TypeSize(attrib.type);
+ attrib.elemSize = attrib.size * TypeSize(attrib.type);
+ if (attrib.stride == 0)
+ attrib.elemStride = attrib.elemSize;
+ else
+ attrib.elemStride = attrib.stride;
attrib.ptr = msg.getArg5();
attrib.buffer = attribBuffer;
}
diff --git a/tools/glesv2debugger/src/com/android/glesv2debugger/MessageData.java b/tools/glesv2debugger/src/com/android/glesv2debugger/MessageData.java
index 1cd14d8..50fdf1c 100644
--- a/tools/glesv2debugger/src/com/android/glesv2debugger/MessageData.java
+++ b/tools/glesv2debugger/src/com/android/glesv2debugger/MessageData.java
@@ -17,35 +17,28 @@
package com.android.glesv2debugger;
import com.android.glesv2debugger.DebuggerMessage.Message;
-import com.android.glesv2debugger.DebuggerMessage.Message.DataType;
import com.android.glesv2debugger.DebuggerMessage.Message.Function;
import com.android.glesv2debugger.DebuggerMessage.Message.Type;
import org.eclipse.swt.graphics.Device;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
-
-import java.nio.ByteBuffer;
+import org.eclipse.swt.widgets.Display;
public class MessageData {
- public final Message msg, oriMsg;
- public Image image = null; // texture
+ public final Message msg;
+ private Image image = null; // texture
public String shader = null; // shader source
public String text;
public String[] columns = new String[3];
- public float[] data = null;
- public int maxAttrib; // used for formatting data
- public GLEnum dataType; // could be float, int; mainly for formatting use
- ByteBuffer[] attribs = null;
+ float[][] attribs = null;
+ short[] indices;
- public MessageData(final Device device, final Message msg, final Message oriMsg,
- final Context context) {
+ public MessageData(final Device device, final Message msg, final Context context) {
this.msg = msg;
- this.oriMsg = oriMsg;
StringBuilder builder = new StringBuilder();
final Function function = msg.getFunction();
- ImageData imageData = null;
if (function != Message.Function.ACK && msg.getType() != Type.BeforeCall)
assert msg.hasTime();
builder.append(columns[0] = function.name());
@@ -69,65 +62,67 @@
columns[2] += MessageFormatter.Format(msg, false);
builder.append(columns[2]);
switch (function) {
- case glDrawArrays: // msg was modified by GLServerVertex
- case glDrawElements:
- if (!msg.hasArg8() || !msg.hasData())
+ case glDrawArrays:
+ if (!msg.hasArg7())
break;
- dataType = GLEnum.valueOf(msg.getArg8());
- maxAttrib = msg.getArg7();
- data = MessageProcessor.ReceiveData(dataType, msg.getData());
+ context.serverVertex.glDrawArrays(this);
+ break;
+ case glDrawElements:
+ if (!msg.hasArg7())
+ break;
+ context.serverVertex.glDrawElements(this);
break;
case glShaderSource:
shader = msg.getData().toStringUtf8();
break;
+
+ }
+ text = builder.toString();
+ }
+
+ public Image GetImage() {
+ if (image != null)
+ return image;
+ ImageData imageData = null;
+ switch (msg.getFunction()) {
case glTexImage2D:
if (!msg.hasData())
- break;
+ return null;
imageData = MessageProcessor.ReceiveImage(msg.getArg3(), msg
.getArg4(), msg.getArg6(), msg.getArg7(), msg.getData());
- if (null == imageData)
- break;
- image = new Image(device, imageData);
- break;
+ return image = new Image(Display.getCurrent(), imageData);
case glTexSubImage2D:
assert msg.hasData();
imageData = MessageProcessor.ReceiveImage(msg.getArg4(), msg
.getArg5(), msg.getArg6(), msg.getArg7(), msg.getData());
- if (null == imageData)
- break;
- image = new Image(device, imageData);
- break;
+ return image = new Image(Display.getCurrent(), imageData);
case glCopyTexImage2D:
- assert msg.getDataType() == DataType.ReferencedImage;
- MessageProcessor.ref = context.readPixelRef;
imageData = MessageProcessor.ReceiveImage(msg.getArg5(), msg.getArg6(),
msg.getPixelFormat(), msg.getPixelType(), msg.getData());
- MessageProcessor.ref = null;
- image = new Image(device, imageData);
imageData = imageData.scaledTo(imageData.width, -imageData.height);
- break;
+ return image = new Image(Display.getCurrent(), imageData);
case glCopyTexSubImage2D:
- assert msg.getDataType() == DataType.ReferencedImage;
- MessageProcessor.ref = context.readPixelRef;
imageData = MessageProcessor.ReceiveImage(msg.getArg6(), msg.getArg7(),
msg.getPixelFormat(), msg.getPixelType(), msg.getData());
- MessageProcessor.ref = null;
imageData = imageData.scaledTo(imageData.width, -imageData.height);
- image = new Image(device, imageData);
- break;
+ return image = new Image(Display.getCurrent(), imageData);
case glReadPixels:
if (!msg.hasData())
- break;
- if (msg.getDataType() == DataType.ReferencedImage)
- MessageProcessor.ref = context.readPixelRef;
+ return null;
imageData = MessageProcessor.ReceiveImage(msg.getArg2(), msg.getArg3(),
msg.getArg4(), msg.getArg5(), msg.getData());
- context.readPixelRef = MessageProcessor.ref;
- MessageProcessor.ref = null;
imageData = imageData.scaledTo(imageData.width, -imageData.height);
- image = new Image(device, imageData);
- break;
+ return image = new Image(Display.getCurrent(), imageData);
+ case eglSwapBuffers:
+ if (!msg.hasData())
+ return null;
+ imageData = MessageProcessor.ReceiveImage(msg.getImageWidth(),
+ msg.getImageHeight(), msg.getPixelFormat(), msg.getPixelType(),
+ msg.getData());
+ imageData = imageData.scaledTo(imageData.width, -imageData.height);
+ return image = new Image(Display.getCurrent(), imageData);
+ default:
+ return null;
}
- text = builder.toString();
}
}
diff --git a/tools/glesv2debugger/src/com/android/glesv2debugger/MessageParser.java b/tools/glesv2debugger/src/com/android/glesv2debugger/MessageParser.java
index 545f261..4bcff32 100644
--- a/tools/glesv2debugger/src/com/android/glesv2debugger/MessageParser.java
+++ b/tools/glesv2debugger/src/com/android/glesv2debugger/MessageParser.java
@@ -45,25 +45,31 @@
ByteString ParseFloats(int count) {
ByteBuffer buffer = ByteBuffer.allocate(count * 4);
+ buffer.order(SampleView.targetByteOrder);
String [] arg = GetList();
for (int i = 0; i < count; i++)
buffer.putFloat(Float.parseFloat(arg[i].trim()));
+ buffer.rewind();
return ByteString.copyFrom(buffer);
}
ByteString ParseInts(int count) {
ByteBuffer buffer = ByteBuffer.allocate(count * 4);
+ buffer.order(SampleView.targetByteOrder);
String [] arg = GetList();
for (int i = 0; i < count; i++)
buffer.putInt(Integer.parseInt(arg[i].trim()));
+ buffer.rewind();
return ByteString.copyFrom(buffer);
}
ByteString ParseUInts(int count) {
ByteBuffer buffer = ByteBuffer.allocate(count * 4);
+ buffer.order(SampleView.targetByteOrder);
String [] arg = GetList();
for (int i = 0; i < count; i++)
buffer.putInt((int)(Long.parseLong(arg[i].trim()) & 0xffffffff));
+ buffer.rewind();
return ByteString.copyFrom(buffer);
}
diff --git a/tools/glesv2debugger/src/com/android/glesv2debugger/MessageProcessor.java b/tools/glesv2debugger/src/com/android/glesv2debugger/MessageProcessor.java
index 0fe7f22..ec1d51b 100644
--- a/tools/glesv2debugger/src/com/android/glesv2debugger/MessageProcessor.java
+++ b/tools/glesv2debugger/src/com/android/glesv2debugger/MessageProcessor.java
@@ -23,6 +23,7 @@
import org.eclipse.swt.graphics.PaletteData;
import java.nio.ByteBuffer;
+import java.util.Arrays;
public class MessageProcessor {
static void showError(final String message) {
@@ -30,8 +31,11 @@
MessageDialog.openError(null, "MessageProcessor", message);
}
- public static byte[] ref; // inout; used for glReadPixels
-
+ /**
+ * data layout: uint32 total decompressed length, (chunks: uint32 chunk
+ * decompressed size, uint32 chunk compressed size, chunk data)+. 0 chunk
+ * compressed size means chunk is not compressed
+ */
public static byte[] LZFDecompressChunks(final ByteString data) {
ByteBuffer in = data.asReadOnlyByteBuffer();
in.order(SampleView.targetByteOrder);
@@ -60,6 +64,44 @@
return out.array();
}
+ /** same data layout as LZFDecompressChunks */
+ public static byte[] LZFCompressChunks(final byte[] in, final int inSize) {
+ byte[] chunk = new byte[256 * 1024]; // chunk size is arbitrary
+ final ByteBuffer out = ByteBuffer.allocate(4 + (inSize + chunk.length - 1)
+ / chunk.length * (chunk.length + 4 * 2));
+ out.order(SampleView.targetByteOrder);
+ out.putInt(inSize);
+ for (int i = 0; i < inSize; i += chunk.length) {
+ int chunkIn = chunk.length;
+ if (i + chunkIn > inSize)
+ chunkIn = inSize - i;
+ final byte[] inChunk = java.util.Arrays.copyOfRange(in, i, i + chunkIn);
+ final int chunkOut = org.liblzf.CLZF
+ .lzf_compress(inChunk, chunkIn, chunk, chunk.length);
+ out.putInt(chunkIn);
+ out.putInt(chunkOut);
+ if (chunkOut == 0) // compressed bigger than chunk (uncompressed)
+ out.put(inChunk);
+ else
+ out.put(chunk, 0, chunkOut);
+ }
+ return Arrays.copyOf(out.array(), out.position());
+ }
+
+ /**
+ * returns new ref, which is also the decoded image; ref could be bigger
+ * than pixels, in which case the first pixels.length bytes form the image
+ */
+ public static byte[] DecodeReferencedImage(byte[] ref, byte[] pixels) {
+ if (ref.length < pixels.length)
+ ref = new byte[pixels.length];
+ for (int i = 0; i < pixels.length; i++)
+ ref[i] ^= pixels[i];
+ for (int i = pixels.length; i < ref.length; i++)
+ ref[i] = 0; // clear unused ref to maintain consistency
+ return ref;
+ }
+
public static ImageData ReceiveImage(int width, int height, int format,
int type, final ByteString data) {
assert width > 0 && height > 0;
@@ -75,6 +117,7 @@
break;
default:
showError("unsupported texture type " + type);
+ return null;
}
switch (GLEnum.valueOf(format)) {
@@ -122,42 +165,9 @@
showError("unsupported texture format: " + format);
return null;
}
-
byte[] pixels = LZFDecompressChunks(data);
assert pixels.length == width * height * (bpp / 8);
-
PaletteData palette = new PaletteData(redMask, greenMask, blueMask);
- if (null != ref) {
- if (ref.length < pixels.length)
- ref = new byte[width * height * (bpp / 8)];
- for (int i = 0; i < pixels.length; i++)
- ref[i] ^= pixels[i];
- for (int i = pixels.length; i < ref.length; i++)
- ref[i] = 0; // clear unused ref to maintain consistency
- return new ImageData(width, height, bpp, palette, 1, ref);
- } else
- return new ImageData(width, height, bpp, palette, 1, pixels);
- }
-
- static public float[] ReceiveData(final GLEnum type, final ByteString data) {
- final ByteBuffer buffer = data.asReadOnlyByteBuffer();
- if (type == GLEnum.GL_FLOAT) {
- float[] elements = new float[buffer.remaining() / 4];
- for (int i = 0; i < elements.length; i++)
- elements[i] = buffer.getFloat();
- return elements;
- } else if (type == GLEnum.GL_UNSIGNED_SHORT) {
- float[] elements = new float[buffer.remaining() / 2];
- for (int i = 0; i < elements.length; i++)
- elements[i] = buffer.getShort() & 0xffff;
- return elements;
- } else if (type == GLEnum.GL_UNSIGNED_BYTE) {
- float[] elements = new float[buffer.remaining() / 4];
- for (int i = 0; i < elements.length; i++)
- elements[i] = buffer.get() & 0xff;
- return elements;
- } else
- assert false;
- return null;
+ return new ImageData(width, height, bpp, palette, 1, pixels);
}
}
diff --git a/tools/glesv2debugger/src/com/android/glesv2debugger/SampleView.java b/tools/glesv2debugger/src/com/android/glesv2debugger/SampleView.java
index 3b267ff..dfadf23 100644
--- a/tools/glesv2debugger/src/com/android/glesv2debugger/SampleView.java
+++ b/tools/glesv2debugger/src/com/android/glesv2debugger/SampleView.java
@@ -30,7 +30,6 @@
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.dialogs.MessageDialog;
-import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.ITableLabelProvider;
@@ -38,7 +37,6 @@
import org.eclipse.jface.viewers.ListViewer;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
-import org.eclipse.jface.viewers.TableLayout;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
@@ -65,8 +63,6 @@
import org.eclipse.swt.widgets.Slider;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
-import org.eclipse.swt.widgets.Table;
-import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IWorkbenchActionConstants;
@@ -108,7 +104,7 @@
TabFolder tabFolder;
TabItem tabItemText, tabItemImage, tabItemBreakpointOption;
TabItem tabItemShaderEditor, tabContextViewer;
- ListViewer viewer; // or TableViewer
+ ListViewer viewer; // ListViewer / TableViewer
Slider frameNum; // scale max cannot overlap min, so max is array size
TreeViewer contextViewer;
BreakpointOption breakpointOption;
@@ -119,7 +115,6 @@
Action actionAutoScroll;
Action actionFilter;
- Action actionCapture;
Action actionPort;
Action actContext; // for toggling contexts
@@ -155,7 +150,7 @@
@Override
public Image getImage(Object obj) {
MessageData msgData = (MessageData) obj;
- return msgData.image;
+ return msgData.GetImage();
}
@Override
@@ -171,9 +166,7 @@
if (index > -1)
return null;
MessageData msgData = (MessageData) obj;
- if (msgData.image == null)
- return null;
- return msgData.image;
+ return msgData.GetImage();
}
}
@@ -228,31 +221,33 @@
gridData.verticalAlignment = SWT.FILL;
frameNum.setLayoutData(gridData);
- Table table = new Table(composite, SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI
- | SWT.FULL_SELECTION);
- TableLayout layout = new TableLayout();
- table.setLayout(layout);
- table.setLinesVisible(true);
- table.setHeaderVisible(true);
- String[] headings = {
- "Name", "Elapsed (ms)", "Detail"
- };
- int[] weights = {
- 50, 16, 60
- };
- int[] widths = {
- 180, 90, 200
- };
- for (int i = 0; i < headings.length; i++) {
- layout.addColumnData(new ColumnWeightData(weights[i], widths[i],
- true));
- TableColumn nameCol = new TableColumn(table, SWT.NONE, i);
- nameCol.setText(headings[i]);
- }
+ // Table table = new Table(composite, SWT.H_SCROLL | SWT.V_SCROLL |
+ // SWT.MULTI
+ // | SWT.FULL_SELECTION);
+ // TableLayout layout = new TableLayout();
+ // table.setLayout(layout);
+ // table.setLinesVisible(true);
+ // table.setHeaderVisible(true);
+ // String[] headings = {
+ // "Name", "Elapsed (ms)", "Detail"
+ // };
+ // int[] weights = {
+ // 50, 16, 60
+ // };
+ // int[] widths = {
+ // 180, 90, 200
+ // };
+ // for (int i = 0; i < headings.length; i++) {
+ // layout.addColumnData(new ColumnWeightData(weights[i], widths[i],
+ // true));
+ // TableColumn nameCol = new TableColumn(table, SWT.NONE, i);
+ // nameCol.setText(headings[i]);
+ // }
// viewer = new TableViewer(table);
viewer = new ListViewer(composite, SWT.DEFAULT);
- viewer.getList().setFont(new Font(viewer.getList().getDisplay(), "Courier", 10, SWT.BOLD));
+ viewer.getList().setFont(new Font(viewer.getList().getDisplay(),
+ "Courier", 10, SWT.BOLD));
ViewContentProvider contentProvider = new ViewContentProvider();
viewer.setContentProvider(contentProvider);
viewer.setLabelProvider(contentProvider);
@@ -435,6 +430,8 @@
actionConnect = new Action("Connect", Action.AS_PUSH_BUTTON) {
@Override
public void run() {
+ if (!running)
+ ChangeContext(null); // viewer will switch to newest context
ConnectDisconnect();
}
};
@@ -446,7 +443,10 @@
public void run()
{
if (!running)
+ {
+ ChangeContext(null); // viewer will switch to newest context
OpenFile();
+ }
}
});
@@ -479,22 +479,57 @@
};
manager.add(actionFilter);
- actionCapture = new Action("Capture", Action.AS_CHECK_BOX) {
+ manager.add(new Action("CaptureDraw", Action.AS_DROP_DOWN_MENU)
+ {
@Override
- public void run() {
+ public void run()
+ {
+ int contextId = 0;
+ if (current != null)
+ contextId = current.contextId;
+ InputDialog inputDialog = new InputDialog(shell,
+ "Capture glDrawArrays/Elements",
+ "Enter number of glDrawArrays/Elements to glReadPixels for "
+ + "context 0x" + Integer.toHexString(contextId) +
+ "\n(0x0 is any context)", "9001", null);
+ if (inputDialog.open() != Window.OK)
+ return;
Message.Builder builder = Message.newBuilder();
- builder.setContextId(0); // FIXME: proper context id
+ builder.setContextId(contextId);
builder.setType(Type.Response);
builder.setExpectResponse(false);
builder.setFunction(Function.SETPROP);
- builder.setProp(Prop.Capture);
- builder.setArg0(isChecked() ? 1 : 0);
+ builder.setProp(Prop.CaptureDraw);
+ builder.setArg0(Integer.parseInt(inputDialog.getValue()));
messageQueue.AddCommand(builder.build());
- manager.update(true);
}
- };
- actionCapture.setChecked(false);
- manager.add(actionCapture);
+ });
+
+ manager.add(new Action("CaptureSwap", Action.AS_DROP_DOWN_MENU)
+ {
+ @Override
+ public void run()
+ {
+ int contextId = 0;
+ if (current != null)
+ contextId = current.contextId;
+ InputDialog inputDialog = new InputDialog(shell,
+ "Capture eglSwapBuffers",
+ "Enter number of eglSwapBuffers to glReadPixels for "
+ + "context 0x" + Integer.toHexString(contextId) +
+ "\n(0x0 is any context)", "9001", null);
+ if (inputDialog.open() != Window.OK)
+ return;
+ Message.Builder builder = Message.newBuilder();
+ builder.setContextId(contextId);
+ builder.setType(Type.Response);
+ builder.setExpectResponse(false);
+ builder.setFunction(Function.SETPROP);
+ builder.setProp(Prop.CaptureSwap);
+ builder.setArg0(Integer.parseInt(inputDialog.getValue()));
+ messageQueue.AddCommand(builder.build());
+ }
+ });
manager.add(new Action("SYSTEM_TIME_THREAD", Action.AS_DROP_DOWN_MENU)
{
@@ -633,23 +668,28 @@
final Frame frame = current.GetFrame(frameNum.getSelection());
final Context context = frame.ComputeContext(msgData);
contextViewer.setInput(context);
- if (null != msgData.image) {
- canvas.setBackgroundImage(msgData.image);
+ if (msgData.GetImage() != null) {
+ canvas.setBackgroundImage(msgData.GetImage());
tabFolder.setSelection(tabItemImage);
canvas.redraw();
} else if (null != msgData.shader) {
text.setText(msgData.shader);
tabFolder.setSelection(tabItemText);
- } else if (null != msgData.data) {
+ } else if (null != msgData.attribs) {
StringBuilder builder = new StringBuilder();
- for (int i = 0; i < msgData.data.length; i++) {
- builder.append(String.format("%.3g", msgData.data[i]));
- if (i % (4 * msgData.maxAttrib) == (4 * msgData.maxAttrib - 1))
- builder.append('\n');
- else if (i % 4 == 3)
- builder.append(" -");
- if (i < msgData.data.length - 1)
- builder.append(' ');
+ final int maxAttrib = msgData.msg.getArg7();
+ for (int i = 0; i < msgData.attribs[0].length / 4; i++) {
+ if (msgData.indices != null) {
+ builder.append(msgData.indices[i] & 0xffff);
+ builder.append(": ");
+ }
+ for (int j = 0; j < maxAttrib; j++) {
+ for (int k = 0; k < 4; k++)
+ builder.append(String.format("%.3g ", msgData.attribs[j][i * 4 + k]));
+ if (j < maxAttrib - 1)
+ builder.append("|| ");
+ }
+ builder.append('\n');
}
text.setText(builder.toString());
tabFolder.setSelection(tabItemText);
@@ -703,9 +743,8 @@
getSite().getShell().getDisplay().syncExec(new Runnable() {
@Override
public void run() {
- if (current == null)
- ChangeContext(debugContexts.valueAt(0));
- else if (frameNum.getSelection() == current.FrameCount() - 1)
+ if (frameNum.getSelection() == current.FrameCount() - 1 ||
+ frameNum.getSelection() == current.FrameCount() - 2)
{
viewer.refresh(false);
if (actionAutoScroll.isChecked())
@@ -734,18 +773,16 @@
showError(e);
}
}
-
DebugContext debugContext = debugContexts.get(oriMsg.getContextId());
if (debugContext == null) {
debugContext = new DebugContext(oriMsg.getContextId());
debugContexts.put(oriMsg.getContextId(), debugContext);
}
-
debugContext.ProcessMessage(oriMsg);
-
shaderEditorUpdate |= debugContext.currentContext.serverShader.uiUpdate;
debugContext.currentContext.serverShader.uiUpdate = false;
-
+ if (current == null)
+ ChangeContext(debugContext);
newMessages++;
}
if (running)
@@ -758,11 +795,25 @@
@Override
public void run() {
current = newContext;
- frameNum.setMaximum(current.FrameCount());
- frameNum.setSelection(0);
- viewer.setInput(current.GetFrame(frameNum.getSelection()));
+ if (current != null)
+ {
+ frameNum.setMaximum(current.FrameCount());
+ if (frameNum.getSelection() >= current.FrameCount())
+ if (current.FrameCount() > 0)
+ frameNum.setSelection(current.FrameCount() - 1);
+ else
+ frameNum.setSelection(0);
+ viewer.setInput(current.GetFrame(frameNum.getSelection()));
+ actContext.setText("Context: 0x" + Integer.toHexString(current.contextId));
+ }
+ else
+ {
+ frameNum.setMaximum(1); // cannot overlap min
+ frameNum.setSelection(0);
+ viewer.setInput(null);
+ actContext.setText("Context: 0x");
+ }
shaderEditor.Update();
- actContext.setText("Context: 0x" + Integer.toHexString(current.contextId));
getViewSite().getActionBars().getToolBarManager().update(true);
}
});