GLES2Dbg: cache Messages to RandomAccessFile
-Load and format Message when the frame is selected to save memory. Change-Id: I4ff9edf049dc724a73d6643bde1d53ec8b625114 Signed-off-by: David Li <davidxli@google.com>
This commit is contained in:
@@ -20,13 +20,19 @@ import com.android.glesv2debugger.DebuggerMessage.Message;
|
||||
import com.android.glesv2debugger.DebuggerMessage.Message.Function;
|
||||
import com.android.sdklib.util.SparseIntArray;
|
||||
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
|
||||
import org.eclipse.jface.operation.IRunnableWithProgress;
|
||||
import org.eclipse.swt.widgets.Shell;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class CodeGen {
|
||||
public class CodeGen implements IRunnableWithProgress {
|
||||
private FileWriter codeFile, makeFile, namesHeaderFile, namesSourceFile;
|
||||
private PrintWriter code, make, namesHeader, namesSource;
|
||||
private FileOutputStream dataOut;
|
||||
@@ -65,7 +71,7 @@ public class CodeGen {
|
||||
code.write(";CHKERR;\n");
|
||||
return true;
|
||||
}
|
||||
assert msg.getArg2() == msg.getPixelFormat(); // TODO
|
||||
// FIXME: check the texture format & type, and convert
|
||||
s = "//" + MessageFormatter.Format(msg, true) + "\n";
|
||||
s += String.format(
|
||||
"glTexSubImage2D(%s, %d, %d, %d, %d, %d, %s, %s, texData);CHKERR;",
|
||||
@@ -710,7 +716,7 @@ public class CodeGen {
|
||||
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");
|
||||
@@ -767,9 +773,16 @@ public class CodeGen {
|
||||
renderbufferNames = null;
|
||||
}
|
||||
|
||||
void CodeGenFrames(final DebugContext dbgCtx, int count) {
|
||||
Context ctx = dbgCtx.frames.get(0).startContext.clone();
|
||||
private DebugContext dbgCtx;
|
||||
private int count;
|
||||
private IProgressMonitor progress;
|
||||
@Override
|
||||
public void run(IProgressMonitor monitor) throws InvocationTargetException,
|
||||
InterruptedException {
|
||||
progress.beginTask("CodeGenFrames", count + 2);
|
||||
Context ctx = dbgCtx.GetFrame(0).startContext.clone();
|
||||
CodeGenSetup(ctx);
|
||||
progress.worked(1);
|
||||
for (int i = 0; i < count; i++) {
|
||||
try {
|
||||
codeFile = new FileWriter("frame" + i + ".cpp", false);
|
||||
@@ -782,9 +795,9 @@ public class CodeGen {
|
||||
|
||||
code.write("#include \"frame_names.h\"\n");
|
||||
code.format("void Frame%d(){\n", i);
|
||||
final Frame frame = dbgCtx.frames.get(i);
|
||||
for (int j = 0; j < frame.calls.size(); j++) {
|
||||
final MessageData msgData = frame.calls.get(j);
|
||||
final Frame frame = dbgCtx.GetFrame(i);
|
||||
for (int j = 0; j < frame.Size(); j++) {
|
||||
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);
|
||||
@@ -802,6 +815,7 @@ public class CodeGen {
|
||||
e.printStackTrace();
|
||||
assert false;
|
||||
}
|
||||
progress.worked(1);
|
||||
}
|
||||
for (int i = 0; i < count; i++)
|
||||
namesHeader.format("void Frame%d();\n", i);
|
||||
@@ -813,6 +827,25 @@ public class CodeGen {
|
||||
namesSource.write("};\n");
|
||||
namesSource.format("const unsigned int FrameCount = %d;\n", count);
|
||||
CodeGenCleanup();
|
||||
progress.worked(1);
|
||||
}
|
||||
|
||||
void CodeGenFrames(final DebugContext dbgCtx, int count, final Shell shell) {
|
||||
this.dbgCtx = dbgCtx;
|
||||
this.count = count;
|
||||
ProgressMonitorDialog dialog = new ProgressMonitorDialog(shell);
|
||||
this.progress = dialog.getProgressMonitor();
|
||||
try {
|
||||
dialog.run(false, true, this);
|
||||
} catch (InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
assert false;
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
this.dbgCtx = null;
|
||||
this.count = 0;
|
||||
progress = null;
|
||||
}
|
||||
|
||||
void CodeGenFrame(final Frame frame) {
|
||||
@@ -828,8 +861,8 @@ public class CodeGen {
|
||||
make.format(" frame0.cpp \\\n");
|
||||
code.write("#include \"frame_names.h\"\n");
|
||||
code.format("void Frame0(){\n");
|
||||
for (int i = 0; i < frame.calls.size(); i++) {
|
||||
final MessageData msgData = frame.calls.get(i);
|
||||
for (int i = 0; i < frame.Size(); i++) {
|
||||
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);
|
||||
|
||||
@@ -30,59 +30,188 @@ import org.eclipse.jface.viewers.Viewer;
|
||||
import org.eclipse.swt.graphics.Image;
|
||||
import org.eclipse.swt.widgets.Display;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
class Frame {
|
||||
final Context startContext;
|
||||
ArrayList<MessageData> calls = new ArrayList<MessageData>();
|
||||
public final long filePosition;
|
||||
private int callsCount;
|
||||
|
||||
Frame(final Context context) {
|
||||
final Context startContext;
|
||||
private ArrayList<MessageData> calls = new ArrayList<MessageData>();
|
||||
|
||||
Frame(final Context context, final long filePosition) {
|
||||
this.startContext = context.clone();
|
||||
this.filePosition = filePosition;
|
||||
}
|
||||
|
||||
void Add(final MessageData msgData) {
|
||||
calls.add(msgData);
|
||||
}
|
||||
|
||||
void IncreaseCallsCount() {
|
||||
callsCount++;
|
||||
}
|
||||
|
||||
Context ComputeContext(final MessageData call) {
|
||||
Context ctx = startContext.clone();
|
||||
for (int i = 0; i < calls.size(); i++)
|
||||
if (call == calls.get(i))
|
||||
return ctx;
|
||||
else
|
||||
ctx.ProcessMessage(calls.get(i).oriMsg);
|
||||
assert false;
|
||||
return ctx;
|
||||
}
|
||||
|
||||
int Size() {
|
||||
return callsCount;
|
||||
}
|
||||
|
||||
MessageData Get(final int i) {
|
||||
return calls.get(i);
|
||||
}
|
||||
|
||||
ArrayList<MessageData> Get() {
|
||||
return calls;
|
||||
}
|
||||
|
||||
void Unload() {
|
||||
if (calls == null)
|
||||
return;
|
||||
calls.clear();
|
||||
calls = null;
|
||||
}
|
||||
|
||||
void Load(final RandomAccessFile file) {
|
||||
if (calls != null && calls.size() == callsCount)
|
||||
return;
|
||||
try {
|
||||
Context ctx = startContext.clone();
|
||||
calls = new ArrayList<MessageData>(callsCount);
|
||||
final long oriPosition = file.getFilePointer();
|
||||
file.seek(filePosition);
|
||||
for (int i = 0; i < callsCount; i++) {
|
||||
int len = file.readInt();
|
||||
if (SampleView.targetByteOrder == ByteOrder.LITTLE_ENDIAN)
|
||||
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;
|
||||
calls.add(msgData);
|
||||
}
|
||||
file.seek(oriPosition);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
assert false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DebugContext {
|
||||
boolean uiUpdate = false;
|
||||
final int contextId;
|
||||
Context currentContext;
|
||||
ArrayList<Frame> frames = new ArrayList<Frame>(128);
|
||||
private Frame currentFrame;
|
||||
private ArrayList<Frame> frames = new ArrayList<Frame>(128);
|
||||
private Frame lastFrame;
|
||||
private Frame loadedFrame;
|
||||
private RandomAccessFile file;
|
||||
|
||||
DebugContext(final int contextId) {
|
||||
this.contextId = contextId;
|
||||
currentContext = new Context(contextId);
|
||||
frames.add(new Frame(currentContext));
|
||||
currentFrame = frames.get(0);
|
||||
try {
|
||||
file = new RandomAccessFile(Integer.toHexString(contextId) + ".gles2dbg",
|
||||
"rw");
|
||||
frames.add(new Frame(currentContext, file.getFilePointer()));
|
||||
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
assert false;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
assert false;
|
||||
}
|
||||
lastFrame = frames.get(0);
|
||||
loadedFrame = lastFrame;
|
||||
}
|
||||
|
||||
MessageData ProcessMessage(final Message oriMsg) {
|
||||
currentContext.ProcessMessage(oriMsg);
|
||||
Message msg = oriMsg;
|
||||
if (currentContext.processed != null)
|
||||
msg = currentContext.processed;
|
||||
currentContext.processed = null;
|
||||
MessageData msgData = new MessageData(Display.getCurrent(), msg, oriMsg, currentContext);
|
||||
msgData.attribs = currentContext.serverVertex.fetchedAttribs;
|
||||
currentFrame.calls.add(msgData);
|
||||
/** Writes oriMsg to file, and formats into MessageData for current frame */
|
||||
void ProcessMessage(final Message oriMsg) {
|
||||
synchronized (file) {
|
||||
final byte[] data = oriMsg.toByteArray();
|
||||
final ByteBuffer len = ByteBuffer.allocate(4);
|
||||
len.order(SampleView.targetByteOrder);
|
||||
len.putInt(data.length);
|
||||
try {
|
||||
if (SampleView.targetByteOrder == ByteOrder.BIG_ENDIAN)
|
||||
file.writeInt(data.length);
|
||||
else
|
||||
file.writeInt(Integer.reverseBytes(data.length));
|
||||
file.write(data);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
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;
|
||||
lastFrame.Add(msgData);
|
||||
uiUpdate = true;
|
||||
}
|
||||
if (msg.getFunction() != Function.eglSwapBuffers)
|
||||
return msgData;
|
||||
frames.add(currentFrame = new Frame(currentContext));
|
||||
return msgData;
|
||||
return;
|
||||
synchronized (frames) {
|
||||
if (loadedFrame != lastFrame)
|
||||
lastFrame.Unload();
|
||||
try {
|
||||
frames.add(lastFrame = new Frame(currentContext, file.getFilePointer()));
|
||||
// file.getChannel().force(false);
|
||||
uiUpdate = true;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
assert false;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Context ComputeContext(final Frame frame, final MessageData call) {
|
||||
Context ctx = frame.startContext.clone();
|
||||
for (int i = 0; i < frame.calls.size(); i++)
|
||||
if (call == frame.calls.get(i))
|
||||
return ctx;
|
||||
else
|
||||
ctx.ProcessMessage(frame.calls.get(i).oriMsg);
|
||||
assert false;
|
||||
return ctx;
|
||||
Frame GetFrame(int index) {
|
||||
synchronized (frames) {
|
||||
Frame newFrame = frames.get(index);
|
||||
if (loadedFrame != null && loadedFrame != lastFrame && newFrame != loadedFrame) {
|
||||
loadedFrame.Unload();
|
||||
uiUpdate = true;
|
||||
}
|
||||
loadedFrame = newFrame;
|
||||
synchronized (file) {
|
||||
loadedFrame.Load(file);
|
||||
}
|
||||
return loadedFrame;
|
||||
}
|
||||
}
|
||||
|
||||
int FrameCount() {
|
||||
synchronized (frames) {
|
||||
return frames.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,8 +226,6 @@ public class Context implements Cloneable {
|
||||
|
||||
byte[] readPixelRef = new byte[0];
|
||||
|
||||
Message processed = null; // return; processed Message
|
||||
|
||||
public Context(int contextId) {
|
||||
this.contextId = contextId;
|
||||
shares.add(this);
|
||||
@@ -115,6 +242,7 @@ public class Context implements Cloneable {
|
||||
copy.serverShader = serverShader.clone(copy);
|
||||
copy.serverState = serverState.clone();
|
||||
copy.serverTexture = serverTexture.clone(copy);
|
||||
copy.readPixelRef = readPixelRef.clone();
|
||||
return copy;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
e.printStackTrace();
|
||||
@@ -123,17 +251,21 @@ public class Context implements Cloneable {
|
||||
}
|
||||
}
|
||||
|
||||
public void ProcessMessage(Message msg) {
|
||||
/** returns processed Message, which could be a new Message */
|
||||
public Message ProcessMessage(Message msg) {
|
||||
if (serverVertex.Process(msg)) {
|
||||
processed = serverVertex.processed;
|
||||
return;
|
||||
if (serverVertex.processed != null)
|
||||
return serverVertex.processed;
|
||||
else
|
||||
return msg;
|
||||
}
|
||||
if (serverShader.ProcessMessage(msg))
|
||||
return;
|
||||
return msg;
|
||||
if (serverState.ProcessMessage(msg))
|
||||
return;
|
||||
return msg;
|
||||
if (serverTexture.ProcessMessage(msg))
|
||||
return;
|
||||
return msg;
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,15 +307,16 @@ class ContextViewProvider extends LabelProvider implements ITreeContentProvider,
|
||||
if (!(entry.obj instanceof Message))
|
||||
return null;
|
||||
final Message msg = (Message) entry.obj;
|
||||
for (int i = 0; i <= sampleView.frameNum.getSelection(); i++) {
|
||||
if (i == sampleView.current.frames.size())
|
||||
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
|
||||
default:
|
||||
return null;
|
||||
final Frame frame = sampleView.current.frames.get(i);
|
||||
for (final MessageData msgData : frame.calls)
|
||||
if (msgData.oriMsg == msg)
|
||||
return entry.image = msgData.image;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -448,6 +448,7 @@ public final class DebuggerMessage {
|
||||
AfterCall(1, 1),
|
||||
AfterGeneratedCall(2, 2),
|
||||
Response(3, 3),
|
||||
CompleteCall(4, 4),
|
||||
;
|
||||
|
||||
|
||||
@@ -459,6 +460,7 @@ public final class DebuggerMessage {
|
||||
case 1: return AfterCall;
|
||||
case 2: return AfterGeneratedCall;
|
||||
case 3: return Response;
|
||||
case 4: return CompleteCall;
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
@@ -490,10 +492,10 @@ public final class DebuggerMessage {
|
||||
ReferencedImage(0, 0),
|
||||
NonreferencedImage(1, 1),
|
||||
;
|
||||
|
||||
|
||||
|
||||
|
||||
public final int getNumber() { return value; }
|
||||
|
||||
|
||||
public static DataType valueOf(int value) {
|
||||
switch (value) {
|
||||
case 0: return ReferencedImage;
|
||||
@@ -501,7 +503,7 @@ public final class DebuggerMessage {
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static com.google.protobuf.Internal.EnumLiteMap<DataType>
|
||||
internalGetValueMap() {
|
||||
return internalValueMap;
|
||||
@@ -513,17 +515,17 @@ public final class DebuggerMessage {
|
||||
return DataType.valueOf(number)
|
||||
; }
|
||||
};
|
||||
|
||||
|
||||
private final int index;
|
||||
private final int value;
|
||||
private DataType(int index, int value) {
|
||||
this.index = index;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
|
||||
// @@protoc_insertion_point(enum_scope:com.android.glesv2debugger.Message.DataType)
|
||||
}
|
||||
|
||||
|
||||
public enum Prop
|
||||
implements com.google.protobuf.Internal.EnumLite {
|
||||
Capture(0, 0),
|
||||
@@ -676,21 +678,21 @@ public final class DebuggerMessage {
|
||||
private com.android.glesv2debugger.DebuggerMessage.Message.DataType dataType_;
|
||||
public boolean hasDataType() { return hasDataType; }
|
||||
public com.android.glesv2debugger.DebuggerMessage.Message.DataType getDataType() { return dataType_; }
|
||||
|
||||
|
||||
// optional int32 pixel_format = 24;
|
||||
public static final int PIXEL_FORMAT_FIELD_NUMBER = 24;
|
||||
private boolean hasPixelFormat;
|
||||
private int pixelFormat_ = 0;
|
||||
public boolean hasPixelFormat() { return hasPixelFormat; }
|
||||
public int getPixelFormat() { return pixelFormat_; }
|
||||
|
||||
|
||||
// optional int32 pixel_type = 25;
|
||||
public static final int PIXEL_TYPE_FIELD_NUMBER = 25;
|
||||
private boolean hasPixelType;
|
||||
private int pixelType_ = 0;
|
||||
public boolean hasPixelType() { return hasPixelType; }
|
||||
public int getPixelType() { return pixelType_; }
|
||||
|
||||
|
||||
// optional float time = 11;
|
||||
public static final int TIME_FIELD_NUMBER = 11;
|
||||
private boolean hasTime;
|
||||
@@ -1513,7 +1515,7 @@ public final class DebuggerMessage {
|
||||
result.dataType_ = com.android.glesv2debugger.DebuggerMessage.Message.DataType.ReferencedImage;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
// optional int32 pixel_format = 24;
|
||||
public boolean hasPixelFormat() {
|
||||
return result.hasPixelFormat();
|
||||
@@ -1531,7 +1533,7 @@ public final class DebuggerMessage {
|
||||
result.pixelFormat_ = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
// optional int32 pixel_type = 25;
|
||||
public boolean hasPixelType() {
|
||||
return result.hasPixelType();
|
||||
@@ -1549,7 +1551,7 @@ public final class DebuggerMessage {
|
||||
result.pixelType_ = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
// optional float time = 11;
|
||||
public boolean hasTime() {
|
||||
return result.hasTime();
|
||||
|
||||
@@ -29,14 +29,13 @@ import java.nio.ByteBuffer;
|
||||
|
||||
public class MessageData {
|
||||
public final Message msg, oriMsg;
|
||||
public Image image; // texture
|
||||
public String shader; // shader source
|
||||
public Image image = null; // texture
|
||||
public String shader = null; // shader source
|
||||
public String text;
|
||||
public String[] columns = new String[3];
|
||||
public float[] data;
|
||||
public float[] data = null;
|
||||
public int maxAttrib; // used for formatting data
|
||||
public GLEnum dataType; // could be float, int; mainly for formatting use
|
||||
Context context; // the context before this call
|
||||
|
||||
ByteBuffer[] attribs = null;
|
||||
|
||||
@@ -44,14 +43,10 @@ public class MessageData {
|
||||
final Context context) {
|
||||
this.msg = msg;
|
||||
this.oriMsg = oriMsg;
|
||||
this.context = context;
|
||||
image = null;
|
||||
shader = null;
|
||||
data = null;
|
||||
StringBuilder builder = new StringBuilder();
|
||||
final Function function = msg.getFunction();
|
||||
ImageData imageData = null;
|
||||
if (function != Message.Function.ACK)
|
||||
if (function != Message.Function.ACK && msg.getType() != Type.BeforeCall)
|
||||
assert msg.hasTime();
|
||||
builder.append(columns[0] = function.name());
|
||||
while (builder.length() < 30)
|
||||
@@ -70,7 +65,7 @@ public class MessageData {
|
||||
else if (msg.getType() == Type.AfterGeneratedCall)
|
||||
columns[2] = "[AfterGeneratedCall] ";
|
||||
else
|
||||
assert msg.getType() == Type.AfterCall;
|
||||
assert msg.getType() == Type.CompleteCall;
|
||||
columns[2] += MessageFormatter.Format(msg, false);
|
||||
builder.append(columns[2]);
|
||||
switch (function) {
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.glesv2debugger;
|
||||
import com.android.glesv2debugger.DebuggerMessage.Message;
|
||||
import com.android.glesv2debugger.DebuggerMessage.Message.Function;
|
||||
import com.android.glesv2debugger.DebuggerMessage.Message.Type;
|
||||
import com.android.sdklib.util.SparseArray;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
@@ -28,17 +29,16 @@ import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class MessageQueue implements Runnable {
|
||||
|
||||
boolean running = false;
|
||||
private boolean running = false;
|
||||
private ByteOrder byteOrder;
|
||||
private FileInputStream file; // if null, create and use socket
|
||||
Thread thread = null;
|
||||
ArrayList<Message> complete = new ArrayList<Message>(); // need synchronized
|
||||
ArrayList<Message> commands = new ArrayList<Message>(); // need synchronized
|
||||
SampleView sampleView;
|
||||
private Thread thread = null;
|
||||
private ArrayList<Message> complete = new ArrayList<Message>(); // synchronized
|
||||
private ArrayList<Message> commands = new ArrayList<Message>(); // synchronized
|
||||
private SampleView sampleView;
|
||||
|
||||
public MessageQueue(SampleView sampleView) {
|
||||
this.sampleView = sampleView;
|
||||
@@ -64,7 +64,7 @@ public class MessageQueue implements Runnable {
|
||||
return running;
|
||||
}
|
||||
|
||||
void SendCommands(final int contextId) throws IOException {
|
||||
private void SendCommands(final int contextId) throws IOException {
|
||||
synchronized (commands) {
|
||||
for (int i = 0; i < commands.size(); i++) {
|
||||
Message command = commands.get(i);
|
||||
@@ -86,7 +86,7 @@ public class MessageQueue implements Runnable {
|
||||
// access call chain starts with run()
|
||||
private DataInputStream dis = null;
|
||||
private DataOutputStream dos = null;
|
||||
private HashMap<Integer, ArrayList<Message>> incoming = new HashMap<Integer, ArrayList<Message>>();
|
||||
private SparseArray<ArrayList<Message>> incoming = new SparseArray<ArrayList<Message>>();
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -118,11 +118,13 @@ public class MessageQueue implements Runnable {
|
||||
|
||||
Message msg = null;
|
||||
if (incoming.size() > 0) { // find queued incoming
|
||||
for (ArrayList<Message> messages : incoming.values())
|
||||
for (int i = 0; i < incoming.size(); i++) {
|
||||
final ArrayList<Message> messages = incoming.valueAt(i);
|
||||
if (messages.size() > 0) {
|
||||
msg = messages.remove(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
if (null == msg) // get incoming from network
|
||||
@@ -167,8 +169,8 @@ public class MessageQueue implements Runnable {
|
||||
SendMessage(dos, msg);
|
||||
}
|
||||
|
||||
// should only used by DefaultProcessMessage
|
||||
private HashMap<Integer, Message> partials = new HashMap<Integer, Message>();
|
||||
// should only be used by DefaultProcessMessage
|
||||
private SparseArray<Message> partials = new SparseArray<Message>();
|
||||
|
||||
Message GetPartialMessage(final int contextId) {
|
||||
return partials.get(contextId);
|
||||
@@ -176,7 +178,8 @@ public class MessageQueue implements Runnable {
|
||||
|
||||
// used to add BeforeCall to complete if it was skipped
|
||||
void CompletePartialMessage(final int contextId) {
|
||||
final Message msg = partials.remove(contextId);
|
||||
final Message msg = partials.get(contextId);
|
||||
partials.remove(contextId);
|
||||
assert msg != null;
|
||||
assert msg.getType() == Type.BeforeCall;
|
||||
synchronized (complete) {
|
||||
@@ -189,29 +192,44 @@ public class MessageQueue implements Runnable {
|
||||
boolean sendResponse)
|
||||
throws IOException {
|
||||
final int contextId = msg.getContextId();
|
||||
final Message.Builder builder = Message.newBuilder();
|
||||
builder.setContextId(contextId);
|
||||
builder.setType(Type.Response);
|
||||
builder.setExpectResponse(expectResponse);
|
||||
if (msg.getType() == Type.BeforeCall) {
|
||||
if (sendResponse) {
|
||||
final Message.Builder builder = Message.newBuilder();
|
||||
builder.setContextId(contextId);
|
||||
builder.setType(Type.Response);
|
||||
builder.setExpectResponse(expectResponse);
|
||||
builder.setFunction(Function.CONTINUE);
|
||||
SendMessage(dos, builder.build());
|
||||
}
|
||||
assert !partials.containsKey(contextId);
|
||||
assert partials.indexOfKey(contextId) < 0;
|
||||
partials.put(contextId, msg);
|
||||
} else if (msg.getType() == Type.AfterCall) {
|
||||
if (sendResponse) {
|
||||
builder.setFunction(Function.CONTINUE);
|
||||
final Message.Builder builder = Message.newBuilder();
|
||||
builder.setContextId(contextId);
|
||||
builder.setType(Type.Response);
|
||||
builder.setExpectResponse(expectResponse);
|
||||
builder.setFunction(Function.SKIP);
|
||||
SendMessage(dos, builder.build());
|
||||
}
|
||||
assert partials.containsKey(contextId);
|
||||
final Message before = partials.remove(contextId);
|
||||
assert partials.indexOfKey(contextId) >= 0;
|
||||
final Message before = partials.get(contextId);
|
||||
partials.remove(contextId);
|
||||
assert before.getFunction() == msg.getFunction();
|
||||
final Message completed = before.toBuilder().mergeFrom(msg).build();
|
||||
final Message completed = before.toBuilder().mergeFrom(msg)
|
||||
.setType(Type.CompleteCall).build();
|
||||
synchronized (complete) {
|
||||
complete.add(completed);
|
||||
}
|
||||
} else if (msg.getType() == Type.CompleteCall) {
|
||||
// this type should only be encountered on client after processing
|
||||
assert file != null;
|
||||
assert !msg.getExpectResponse();
|
||||
assert !sendResponse;
|
||||
assert partials.indexOfKey(contextId) < 0;
|
||||
synchronized (complete) {
|
||||
complete.add(msg);
|
||||
}
|
||||
} else
|
||||
assert false;
|
||||
}
|
||||
@@ -265,6 +283,8 @@ public class MessageQueue implements Runnable {
|
||||
|
||||
private void SendMessage(final DataOutputStream dos, final Message message)
|
||||
throws IOException {
|
||||
if (dos == null)
|
||||
return;
|
||||
assert message.getFunction() != Function.NEG;
|
||||
final byte[] data = message.toByteArray();
|
||||
if (byteOrder == ByteOrder.BIG_ENDIAN)
|
||||
|
||||
@@ -75,12 +75,7 @@ import org.eclipse.ui.part.ViewPart;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.ByteOrder;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
|
||||
/**
|
||||
* This sample class demonstrates how to plug-in a new workbench view. The view
|
||||
@@ -148,7 +143,7 @@ public class SampleView extends ViewPart implements Runnable, SelectionListener
|
||||
|
||||
@Override
|
||||
public Object[] getElements(Object parent) {
|
||||
return frame.calls.toArray();
|
||||
return frame.Get().toArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -562,7 +557,11 @@ public class SampleView extends ViewPart implements Runnable, SelectionListener
|
||||
public void run()
|
||||
{
|
||||
if (current != null)
|
||||
{
|
||||
new CodeGen().CodeGenFrame((Frame) viewer.getInput());
|
||||
// need to reload current frame
|
||||
viewer.setInput(current.GetFrame(frameNum.getSelection()));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -572,7 +571,12 @@ public class SampleView extends ViewPart implements Runnable, SelectionListener
|
||||
public void run()
|
||||
{
|
||||
if (current != null)
|
||||
new CodeGen().CodeGenFrames(current, frameNum.getSelection() + 1);
|
||||
{
|
||||
new CodeGen().CodeGenFrames(current, frameNum.getSelection() + 1,
|
||||
getSite().getShell());
|
||||
// need to reload current frame
|
||||
viewer.setInput(current.GetFrame(frameNum.getSelection()));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -626,8 +630,8 @@ public class SampleView extends ViewPart implements Runnable, SelectionListener
|
||||
return;
|
||||
if (frameNum.getSelection() == frameNum.getMaximum())
|
||||
return; // scale max cannot overlap min, so max is array size
|
||||
final Frame frame = current.frames.get(frameNum.getSelection());
|
||||
final Context context = current.ComputeContext(frame, msgData);
|
||||
final Frame frame = current.GetFrame(frameNum.getSelection());
|
||||
final Context context = frame.ComputeContext(msgData);
|
||||
contextViewer.setInput(context);
|
||||
if (null != msgData.image) {
|
||||
canvas.setBackgroundImage(msgData.image);
|
||||
@@ -686,46 +690,32 @@ public class SampleView extends ViewPart implements Runnable, SelectionListener
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
FileWriter file = null;
|
||||
PrintWriter writer = null;
|
||||
try {
|
||||
file = new FileWriter("GLES2Debugger.log", true);
|
||||
writer = new PrintWriter(file);
|
||||
writer.write("\n\n");
|
||||
writer.write(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Calendar.getInstance()
|
||||
.getTime()));
|
||||
writer.write("\n\n");
|
||||
} catch (IOException e1) {
|
||||
showError(e1);
|
||||
}
|
||||
|
||||
int newMessages = 0;
|
||||
|
||||
boolean shaderEditorUpdate = false, currentUpdate = false;
|
||||
boolean shaderEditorUpdate = false;
|
||||
while (running) {
|
||||
final Message oriMsg = messageQueue.RemoveCompleteMessage(0);
|
||||
if (oriMsg == null && !messageQueue.IsRunning())
|
||||
break;
|
||||
if (newMessages > 60 || (newMessages > 0 && null == oriMsg)) {
|
||||
newMessages = 0;
|
||||
|
||||
if (currentUpdate || current == null)
|
||||
if (current == null || current.uiUpdate)
|
||||
getSite().getShell().getDisplay().syncExec(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (current == null)
|
||||
ChangeContext(debugContexts.valueAt(0));
|
||||
else if (frameNum.getSelection() == current.frames.size() - 1)
|
||||
else if (frameNum.getSelection() == current.FrameCount() - 1)
|
||||
{
|
||||
viewer.refresh(false);
|
||||
if (actionAutoScroll.isChecked())
|
||||
viewer.getList().setSelection(
|
||||
viewer.getList().getItemCount() - 1);
|
||||
}
|
||||
frameNum.setMaximum(current.frames.size());
|
||||
frameNum.setMaximum(current.FrameCount());
|
||||
}
|
||||
});
|
||||
currentUpdate = false;
|
||||
current.uiUpdate = false;
|
||||
|
||||
if (shaderEditorUpdate)
|
||||
this.getSite().getShell().getDisplay().syncExec(new Runnable() {
|
||||
@@ -751,29 +741,15 @@ public class SampleView extends ViewPart implements Runnable, SelectionListener
|
||||
debugContexts.put(oriMsg.getContextId(), debugContext);
|
||||
}
|
||||
|
||||
final MessageData msgData = debugContext.ProcessMessage(oriMsg);
|
||||
if (current == debugContext) {
|
||||
currentUpdate = true;
|
||||
}
|
||||
debugContext.ProcessMessage(oriMsg);
|
||||
|
||||
shaderEditorUpdate |= debugContext.currentContext.serverShader.uiUpdate;
|
||||
debugContext.currentContext.serverShader.uiUpdate = false;
|
||||
|
||||
if (null != writer) {
|
||||
writer.write(msgData.text + "\n");
|
||||
if (msgData.msg.getFunction() == Function.eglSwapBuffers) {
|
||||
writer.write("\n-------\n");
|
||||
writer.flush();
|
||||
}
|
||||
}
|
||||
newMessages++;
|
||||
}
|
||||
if (running)
|
||||
ConnectDisconnect(); // error occurred, disconnect
|
||||
if (null != writer) {
|
||||
writer.flush();
|
||||
writer.close();
|
||||
}
|
||||
}
|
||||
|
||||
/** can be called from non-UI thread */
|
||||
@@ -782,9 +758,9 @@ public class SampleView extends ViewPart implements Runnable, SelectionListener
|
||||
@Override
|
||||
public void run() {
|
||||
current = newContext;
|
||||
frameNum.setMaximum(current.frames.size());
|
||||
frameNum.setMaximum(current.FrameCount());
|
||||
frameNum.setSelection(0);
|
||||
viewer.setInput(current.frames.get(frameNum.getSelection()));
|
||||
viewer.setInput(current.GetFrame(frameNum.getSelection()));
|
||||
shaderEditor.Update();
|
||||
actContext.setText("Context: 0x" + Integer.toHexString(current.contextId));
|
||||
getViewSite().getActionBars().getToolBarManager().update(true);
|
||||
@@ -798,9 +774,9 @@ public class SampleView extends ViewPart implements Runnable, SelectionListener
|
||||
assert false;
|
||||
if (current == null)
|
||||
return;
|
||||
if (frameNum.getSelection() == current.frames.size())
|
||||
if (frameNum.getSelection() == current.FrameCount())
|
||||
return; // scale maximum cannot overlap minimum
|
||||
Frame frame = current.frames.get(frameNum.getSelection());
|
||||
Frame frame = current.GetFrame(frameNum.getSelection());
|
||||
viewer.setInput(frame);
|
||||
}
|
||||
|
||||
|
||||
@@ -95,6 +95,7 @@ public class ShaderEditor extends Composite implements SelectionListener, Extend
|
||||
gridData.grabExcessHorizontalSpace = true;
|
||||
gridData.verticalAlignment = SWT.FILL;
|
||||
gridData.grabExcessVerticalSpace = true;
|
||||
gridData.verticalSpan = 2;
|
||||
styledText.setLayoutData(gridData);
|
||||
styledText.addExtendedModifyListener(this);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user