From 6f85d436f3d13109f53f3f5c27089d2f6e23a964 Mon Sep 17 00:00:00 2001 From: David Li Date: Fri, 11 Mar 2011 11:11:41 -0800 Subject: [PATCH] GLES2Debugger: Make command exchange async to improve performance. In message loop, use select to check for available commands from client, rather than always expecting commands in eglSwapBuffers. Client can send commands at any time. Change-Id: I607c8fa571a896996c0a3300de904b6e263fc281 Signed-off-by: David Li --- .../glesv2debugger/DebuggerMessage.java | 2 - .../android/glesv2debugger/MessageData.java | 8 +- .../android/glesv2debugger/MessageQueue.java | 101 +++++++----------- .../android/glesv2debugger/SampleView.java | 53 +++++++-- 4 files changed, 88 insertions(+), 76 deletions(-) diff --git a/tools/glesv2debugger/src/com/android/glesv2debugger/DebuggerMessage.java b/tools/glesv2debugger/src/com/android/glesv2debugger/DebuggerMessage.java index fa1d7eda1..ddc875a64 100644 --- a/tools/glesv2debugger/src/com/android/glesv2debugger/DebuggerMessage.java +++ b/tools/glesv2debugger/src/com/android/glesv2debugger/DebuggerMessage.java @@ -218,7 +218,6 @@ public final class DebuggerMessage { CONTINUE(188, 188), SKIP(189, 189), SETPROP(190, 190), - CAPTURE(191, 191), ; @@ -417,7 +416,6 @@ public final class DebuggerMessage { case 188: return CONTINUE; case 189: return SKIP; case 190: return SETPROP; - case 191: return CAPTURE; default: return null; } } diff --git a/tools/glesv2debugger/src/com/android/glesv2debugger/MessageData.java b/tools/glesv2debugger/src/com/android/glesv2debugger/MessageData.java index 110c6f8b9..e62283049 100644 --- a/tools/glesv2debugger/src/com/android/glesv2debugger/MessageData.java +++ b/tools/glesv2debugger/src/com/android/glesv2debugger/MessageData.java @@ -16,12 +16,14 @@ package com.android.glesv2debugger; +import com.android.glesv2debugger.DebuggerMessage.Message; + import org.eclipse.swt.graphics.Device; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.ImageData; public class MessageData { - public DebuggerMessage.Message.Function function; + public Message.Function function; public Image image; // texture public String shader; // shader source public String[] columns; @@ -29,14 +31,14 @@ public class MessageData { public int maxAttrib; // used for formatting data public GLEnum dataType; // could be float, int; mainly for formatting use - public MessageData(final Device device, final DebuggerMessage.Message msg) { + public MessageData(final Device device, final Message msg) { image = null; shader = null; data = null; StringBuilder builder = new StringBuilder(); function = msg.getFunction(); ImageData imageData = null; - if (function != DebuggerMessage.Message.Function.ACK) + if (function != Message.Function.ACK) assert msg.hasTime(); columns = new String [4]; columns[0] = function.toString(); diff --git a/tools/glesv2debugger/src/com/android/glesv2debugger/MessageQueue.java b/tools/glesv2debugger/src/com/android/glesv2debugger/MessageQueue.java index afa7e91ea..454fbf1be 100644 --- a/tools/glesv2debugger/src/com/android/glesv2debugger/MessageQueue.java +++ b/tools/glesv2debugger/src/com/android/glesv2debugger/MessageQueue.java @@ -16,6 +16,8 @@ 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 java.io.DataInputStream; @@ -30,8 +32,8 @@ public class MessageQueue implements Runnable { boolean running = false; Thread thread = null; - ArrayList complete = new ArrayList(); - ArrayList commands = new ArrayList(); + ArrayList complete = new ArrayList(); + ArrayList commands = new ArrayList(); SampleView sampleView; HashMap serversVertex = new HashMap(); @@ -58,24 +60,24 @@ public class MessageQueue implements Runnable { return running; } - void SendCommands(final DataOutputStream dos, final int contextId) throws IOException { + boolean SendCommands(final DataOutputStream dos, final int contextId) throws IOException { + boolean sent = false; synchronized (commands) { for (int i = 0; i < commands.size(); i++) { - DebuggerMessage.Message command = commands.get(i); - if (command.getContextId() == contextId || contextId == 0) { // FIXME: - // proper - // context - // id + Message command = commands.get(i); + // FIXME: proper context id + if (command.getContextId() == contextId || contextId == 0) { SendMessage(dos, command); commands.remove(i); i--; + sent = true; } } } - SendResponse(dos, contextId, DebuggerMessage.Message.Function.SKIP); + return sent; } - public void AddCommand(DebuggerMessage.Message command) { + public void AddCommand(Message command) { synchronized (commands) { commands.add(command); } @@ -86,7 +88,7 @@ public class MessageQueue implements Runnable { Socket socket = new Socket(); DataInputStream dis = null; DataOutputStream dos = null; - HashMap> incoming = new HashMap>(); + HashMap> incoming = new HashMap>(); try { socket.connect(new java.net.InetSocketAddress("127.0.0.1", 5039)); dis = new DataInputStream(socket.getInputStream()); @@ -98,9 +100,9 @@ public class MessageQueue implements Runnable { // try { while (running) { - DebuggerMessage.Message msg = null; + Message msg = null; if (incoming.size() > 0) { // find queued incoming - for (ArrayList messages : incoming + for (ArrayList messages : incoming .values()) if (messages.size() > 0) { msg = messages.get(0); @@ -111,20 +113,7 @@ public class MessageQueue implements Runnable { if (null == msg) { // get incoming from network try { msg = ReadMessage(dis); - if (msg.getExpectResponse()) { - if (msg.getType() == Type.BeforeCall) - SendResponse(dos, msg.getContextId(), - DebuggerMessage.Message.Function.CONTINUE); - else if (msg.getType() == Type.AfterCall) - // after GL function call - SendCommands(dos, 0); // FIXME: proper context id - // SendResponse(dos, msg.getContextId(), - // DebuggerMessage.Message.Function.SKIP); - else if (msg.getType() == Type.Response) - assert true; - else - assert false; - } + SendResponse(dos, msg); } catch (IOException e) { Error(e); running = false; @@ -135,13 +124,13 @@ public class MessageQueue implements Runnable { int contextId = msg.getContextId(); if (!incoming.containsKey(contextId)) incoming.put(contextId, - new ArrayList()); + new ArrayList()); // FIXME: the expected sequence will change for interactive mode while (msg.getType() == Type.BeforeCall) { - DebuggerMessage.Message next = null; + Message next = null; // get existing message part for this context - ArrayList messages = incoming + ArrayList messages = incoming .get(contextId); if (messages.size() > 0) { next = messages.get(0); @@ -150,21 +139,7 @@ public class MessageQueue implements Runnable { if (null == next) { // read new part for message try { next = ReadMessage(dis); - - if (next.getExpectResponse()) { - if (next.getType() == Type.BeforeCall) - SendResponse( - dos, - next.getContextId(), - DebuggerMessage.Message.Function.CONTINUE); - else if (next.getType() == Type.AfterCall) - SendCommands(dos, 0); // FIXME: proper context - // id - else if (msg.getType() == Type.Response) - assert true; - else - assert false; - } + SendResponse(dos, next); } catch (IOException e) { Error(e); running = false; @@ -176,13 +151,13 @@ public class MessageQueue implements Runnable { if (!incoming.containsKey(next.getContextId())) incoming.put( next.getContextId(), - new ArrayList()); + new ArrayList()); incoming.get(next.getContextId()).add(next); continue; } } - DebuggerMessage.Message.Builder builder = msg.toBuilder(); + Message.Builder builder = msg.toBuilder(); // builder.mergeFrom(next); seems to merge incorrectly if (next.hasRet()) builder.setRet(next.getRet()); @@ -277,18 +252,18 @@ public class MessageQueue implements Runnable { // } } - public DebuggerMessage.Message RemoveMessage(int contextId) { + public Message RemoveMessage(int contextId) { synchronized (complete) { if (complete.size() == 0) return null; - if (0 == contextId) // get a message of any + if (0 == contextId) // get a message for any context { - DebuggerMessage.Message msg = complete.get(0); + Message msg = complete.get(0); complete.remove(0); return msg; } for (int i = 0; i < complete.size(); i++) { - DebuggerMessage.Message msg = complete.get(i); + Message msg = complete.get(i); if (msg.getContextId() == contextId) { complete.remove(i); return msg; @@ -298,7 +273,7 @@ public class MessageQueue implements Runnable { return null; } - DebuggerMessage.Message ReadMessage(final DataInputStream dis) + Message ReadMessage(final DataInputStream dis) throws IOException { int len = 0; try { @@ -321,26 +296,30 @@ public class MessageQueue implements Runnable { } else readLen += read; } - DebuggerMessage.Message msg = DebuggerMessage.Message.parseFrom(buffer); + Message msg = Message.parseFrom(buffer); return msg; } - void SendMessage(final DataOutputStream dos, final DebuggerMessage.Message message) + void SendMessage(final DataOutputStream dos, final Message message) throws IOException { final byte[] data = message.toByteArray(); dos.writeInt(data.length); dos.write(data); } - void SendResponse(final DataOutputStream dos, final int contextId, - final DebuggerMessage.Message.Function function) throws IOException { - DebuggerMessage.Message.Builder builder = DebuggerMessage.Message - .newBuilder(); - builder.setContextId(contextId); - builder.setFunction(function); + void SendResponse(final DataOutputStream dos, final Message msg) throws IOException { + Message.Builder builder = Message.newBuilder(); + builder.setContextId(msg.getContextId()); + if (msg.getType() == Type.BeforeCall) + builder.setFunction(Function.CONTINUE); + else if (msg.getType() == Type.AfterCall) + builder.setFunction(Function.SKIP); builder.setType(Type.Response); builder.setExpectResponse(false); - SendMessage(dos, builder.build()); + // FIXME: consider using proper context id + if (SendCommands(dos, 0) || msg.getExpectResponse()) + if (builder.hasFunction()) + SendMessage(dos, builder.build()); } void Error(Exception e) { diff --git a/tools/glesv2debugger/src/com/android/glesv2debugger/SampleView.java b/tools/glesv2debugger/src/com/android/glesv2debugger/SampleView.java index 41a0bb2b9..690556590 100755 --- a/tools/glesv2debugger/src/com/android/glesv2debugger/SampleView.java +++ b/tools/glesv2debugger/src/com/android/glesv2debugger/SampleView.java @@ -16,6 +16,7 @@ package com.android.glesv2debugger; +import com.android.glesv2debugger.DebuggerMessage.Message; import com.android.glesv2debugger.DebuggerMessage.Message.Function; import com.android.glesv2debugger.DebuggerMessage.Message.Prop; import com.android.glesv2debugger.DebuggerMessage.Message.Type; @@ -66,7 +67,12 @@ import org.eclipse.ui.IWorkbenchActionConstants; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.part.ViewPart; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Calendar; /** * This sample class demonstrates how to plug-in a new workbench view. The view @@ -115,7 +121,7 @@ public class SampleView extends ViewPart implements Runnable { */ class ViewContentProvider implements IStructuredContentProvider { - ArrayList entries = new ArrayList(); + ArrayList entries = new ArrayList(); public void add(final ArrayList msgs) { entries.addAll(msgs); @@ -152,7 +158,7 @@ public class SampleView extends ViewPart implements Runnable { ITableLabelProvider { @Override public String getColumnText(Object obj, int index) { - com.android.glesv2debugger.MessageData msgData = (com.android.glesv2debugger.MessageData) obj; + MessageData msgData = (MessageData) obj; if (null == msgData) return getText(obj); if (index >= msgData.columns.length) @@ -164,7 +170,7 @@ public class SampleView extends ViewPart implements Runnable { public Image getColumnImage(Object obj, int index) { if (index > 0) return null; - com.android.glesv2debugger.MessageData msgData = (com.android.glesv2debugger.MessageData) obj; + MessageData msgData = (MessageData) obj; if (null == msgData) return getImage(obj); if (null == msgData.image) @@ -186,7 +192,7 @@ public class SampleView extends ViewPart implements Runnable { @Override public boolean select(Viewer viewer, Object parentElement, Object element) { - com.android.glesv2debugger.MessageData msgData = (com.android.glesv2debugger.MessageData) element; + MessageData msgData = (MessageData) element; if (null == filters) return true; for (int i = 0; i < filters.length; i++) @@ -430,7 +436,7 @@ public class SampleView extends ViewPart implements Runnable { actionCapture = new Action("Capture", Action.AS_CHECK_BOX) { @Override public void run() { - DebuggerMessage.Message.Builder builder = DebuggerMessage.Message.newBuilder(); + Message.Builder builder = Message.newBuilder(); builder.setContextId(0); // FIXME: proper context id builder.setType(Type.Response); builder.setExpectResponse(false); @@ -455,11 +461,11 @@ public class SampleView extends ViewPart implements Runnable { }; int i = java.util.Arrays.asList(timeModes).indexOf(this.getText()); i = (i + 1) % timeModes.length; - DebuggerMessage.Message.Builder builder = DebuggerMessage.Message.newBuilder(); + Message.Builder builder = Message.newBuilder(); builder.setContextId(0); // FIXME: proper context id builder.setType(Type.Response); builder.setExpectResponse(false); - builder.setFunction(DebuggerMessage.Message.Function.SETPROP); + builder.setFunction(Message.Function.SETPROP); builder.setProp(Prop.TimeMode); builder.setArg0(i); messageQueue.AddCommand(builder.build()); @@ -638,14 +644,24 @@ public class SampleView extends ViewPart implements Runnable { @Override public void run() { - boolean refresh = false; + 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())); + } catch (IOException e1) { + showError(e1); + } ArrayList msgs = new ArrayList(); while (running) { if (!messageQueue.IsRunning()) break; - DebuggerMessage.Message msg = messageQueue.RemoveMessage(0); - if (msgs.size() > 20) { + Message msg = messageQueue.RemoveMessage(0); + if (msgs.size() > 40) { viewContentProvider.add(msgs); msgs.clear(); } @@ -659,9 +675,26 @@ public class SampleView extends ViewPart implements Runnable { } final MessageData msgData = new MessageData(this.getViewSite() .getShell().getDisplay(), msg); + if (null != writer) { + writer.write(msgData.columns[0]); + for (int i = 0; i < 30 - msgData.columns[0].length(); i++) + writer.write(" "); + writer.write("\t"); + writer.write(msgData.columns[1] + " \t "); + writer.write(msgData.columns[2] + " \t "); + writer.write(msgData.columns[3] + " \n"); + if (msgData.columns[0] == "eglSwapBuffers") { + writer.write("\n-------\n"); + writer.flush(); + } + } msgs.add(msgData); } if (running) ConnectDisconnect(); // error occurred, disconnect + if (null != writer) { + writer.flush(); + writer.close(); + } } }