aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSiva Velusamy <vsiva@google.com>2012-01-03 10:53:20 -0800
committerSiva Velusamy <vsiva@google.com>2012-01-03 15:09:02 -0800
commitf51d3b0eaf95bccb521f01b02c8c0ba332c9dd6d (patch)
tree430a41fc0fe96880b66f2d82e716ffbc44a00a0c
parentab36f4e7488358dea4ab6b54ee2b7bef3da0232b (diff)
downloadsdk-f51d3b0eaf95bccb521f01b02c8c0ba332c9dd6d.zip
sdk-f51d3b0eaf95bccb521f01b02c8c0ba332c9dd6d.tar.gz
sdk-f51d3b0eaf95bccb521f01b02c8c0ba332c9dd6d.tar.bz2
gltrace: Enable trace options.
Provide user options that control how much data is collected. The user can control whether framebuffer data is read on eglSwap() or glDraw*(), and whether texture images submitted via glTexImage() are read. Change-Id: I99b71d31a985295f0793d94887c0efcc25083fc6
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/CollectTraceAction.java73
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/GLTraceCollectorDialog.java198
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/GLTraceOptionsDialog.java107
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/TraceCommandWriter.java57
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/TraceFileWriter.java (renamed from eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/GLTraceWriter.java)113
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/TraceOptions.java47
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/editors/GLFunctionTraceViewer.java20
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/model/GLCall.java8
8 files changed, 445 insertions, 178 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/CollectTraceAction.java b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/CollectTraceAction.java
index 33b9fd1..7b1b959 100644
--- a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/CollectTraceAction.java
+++ b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/CollectTraceAction.java
@@ -33,9 +33,12 @@ import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.net.Socket;
public class CollectTraceAction implements IWorkbenchWindowActionDelegate {
public void run(IAction action) {
@@ -60,13 +63,10 @@ public class CollectTraceAction implements IWorkbenchWindowActionDelegate {
return;
}
- String activityName = dlg.getApplicationToTrace();
- String traceDestination = dlg.getTraceDestination();
- String deviceName = dlg.getDevice();
+ TraceOptions traceOptions = dlg.getTraceOptions();
- IDevice device = getDevice(deviceName);
-
- String appName = activityName.split("/")[0];
+ IDevice device = getDevice(traceOptions.device);
+ String appName = traceOptions.activityToTrace.split("/")[0]; //$NON-NLS-1$
killApp(device, appName);
try {
@@ -84,7 +84,7 @@ public class CollectTraceAction implements IWorkbenchWindowActionDelegate {
}
try {
- startActivity(device, activityName);
+ startActivity(device, traceOptions.activityToTrace);
} catch (Exception e) {
MessageDialog.openError(shell, "Setup GL Trace",
"Error while launching application: " + e.getMessage());
@@ -99,19 +99,67 @@ public class CollectTraceAction implements IWorkbenchWindowActionDelegate {
// if everything went well, the app should now be waiting for the gl debugger
// to connect
- startTracing(shell, traceDestination, port);
+ startTracing(shell, traceOptions, port);
}
- private void startTracing(Shell shell, String traceDestination, int port) {
+ private void startTracing(Shell shell, TraceOptions traceOptions, int port) {
FileOutputStream fos = null;
try {
- fos = new FileOutputStream(traceDestination, false);
+ fos = new FileOutputStream(traceOptions.traceDestination, false);
} catch (FileNotFoundException e) {
// input path is valid, so this cannot occur
}
- GLTraceWriter writer = new GLTraceWriter(fos, port, new GLTraceCollectorDialog(shell));
- writer.start();
+ Socket socket = new Socket();
+ DataInputStream traceDataStream = null;
+ DataOutputStream traceCommandsStream = null;
+ try {
+ socket.connect(new java.net.InetSocketAddress("127.0.0.1", port)); //$NON-NLS-1$
+ socket.setTcpNoDelay(true);
+ traceDataStream = new DataInputStream(socket.getInputStream());
+ traceCommandsStream = new DataOutputStream(socket.getOutputStream());
+ } catch (IOException e) {
+ MessageDialog.openError(shell,
+ "OpenGL Trace",
+ "Unable to connect to remote GL Trace Server: " + e.getMessage());
+ return;
+ }
+
+ // create channel to send trace commands to device
+ TraceCommandWriter traceCommandWriter = new TraceCommandWriter(traceCommandsStream);
+ try {
+ traceCommandWriter.setTraceOptions(traceOptions.collectFbOnEglSwap,
+ traceOptions.collectFbOnGlDraw,
+ traceOptions.collectTextureData);
+ } catch (IOException e) {
+ MessageDialog.openError(shell,
+ "OpenGL Trace",
+ "Unexpected error while setting trace options: " + e.getMessage());
+ closeSocket(socket);
+ return;
+ }
+
+ // create trace writer that writes to a trace file
+ TraceFileWriter traceFileWriter = new TraceFileWriter(fos, traceDataStream);
+ traceFileWriter.start();
+
+ GLTraceCollectorDialog dlg = new GLTraceCollectorDialog(shell,
+ traceFileWriter,
+ traceCommandWriter,
+ traceOptions);
+ dlg.open();
+
+ traceFileWriter.stopTracing();
+ traceCommandWriter.close();
+ closeSocket(socket);
+ }
+
+ private void closeSocket(Socket socket) {
+ try {
+ socket.close();
+ } catch (IOException e) {
+ // ignore error while closing socket
+ }
}
private void startActivity(IDevice device, String appName)
@@ -120,7 +168,6 @@ public class CollectTraceAction implements IWorkbenchWindowActionDelegate {
String startAppCmd = String.format(
"am start %s -a android.intent.action.MAIN -c android.intent.category.LAUNCHER", //$NON-NLS-1$
appName);
- System.out.println(startAppCmd);
device.executeShellCommand(startAppCmd, new IgnoreOutputReceiver());
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/GLTraceCollectorDialog.java b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/GLTraceCollectorDialog.java
index 04944c2..e7897ec 100644
--- a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/GLTraceCollectorDialog.java
+++ b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/GLTraceCollectorDialog.java
@@ -16,29 +16,45 @@
package com.android.ide.eclipse.gltrace;
-import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.ProgressBar;
import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.Text;
+
+import java.io.IOException;
/** Dialog displayed while the trace is being streamed from device to host. */
-public class GLTraceCollectorDialog extends Dialog {
- private Text mFramesCollectedText;
- private Text mTraceFileSizeText;
- private GLTraceWriter mWriter;
- private int mFramesCollected;
- private int mTraceFileSize;
-
- protected GLTraceCollectorDialog(Shell parentShell) {
+public class GLTraceCollectorDialog extends TitleAreaDialog {
+ private static final String TITLE = "OpenGL ES Trace";
+ private static final String DEFAULT_MESSAGE = "Trace collection in progress.";
+
+ private TraceOptions mTraceOptions;
+ private final TraceFileWriter mTraceFileWriter;
+ private final TraceCommandWriter mTraceCommandWriter;
+
+ private Label mFramesCollectedLabel;
+ private Label mTraceFileSizeLabel;
+ private StatusRefreshTask mRefreshTask;
+
+ protected GLTraceCollectorDialog(Shell parentShell, TraceFileWriter traceFileWriter,
+ TraceCommandWriter traceCommandWriter, TraceOptions traceOptions) {
super(parentShell);
+ mTraceFileWriter = traceFileWriter;
+ mTraceCommandWriter = traceCommandWriter;
+ mTraceOptions = traceOptions;
}
@Override
@@ -55,84 +71,154 @@ public class GLTraceCollectorDialog extends Dialog {
@Override
protected Control createDialogArea(Composite parent) {
- Composite c = new Composite(parent, SWT.NONE);
- c.setLayout(new GridLayout(2, false));
- c.setLayoutData(new GridData(GridData.FILL_BOTH));
+ parent.setLayout(new GridLayout());
+
+ setTitle(TITLE);
+ setMessage(DEFAULT_MESSAGE);
+
+ Group controlGroup = new Group(parent, SWT.BORDER);
+ controlGroup.setLayout(new GridLayout(2, false));
+ controlGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ controlGroup.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_BLUE));
+ controlGroup.setText("Trace Options");
+
+ createLabel(controlGroup, "Collect Framebuffer contents on eglSwapBuffers()");
+ final Button eglSwapCheckBox = createButton(controlGroup,
+ mTraceOptions.collectFbOnEglSwap);
+
+ createLabel(controlGroup, "Collect Framebuffer contents on glDraw*()");
+ final Button glDrawCheckBox = createButton(controlGroup, mTraceOptions.collectFbOnGlDraw);
+
+ createLabel(controlGroup, "Collect texture data for glTexImage*()");
+ final Button glTexImageCheckBox = createButton(controlGroup,
+ mTraceOptions.collectTextureData);
+
+ SelectionListener l = new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent event) {
+ boolean eglSwap = eglSwapCheckBox.getSelection();
+ boolean glDraw = glDrawCheckBox.getSelection();
+ boolean glTexImage = glTexImageCheckBox.getSelection();
+
+ try {
+ mTraceCommandWriter.setTraceOptions(eglSwap, glDraw, glTexImage);
+ } catch (IOException e) {
+ eglSwapCheckBox.setEnabled(false);
+ glDrawCheckBox.setEnabled(false);
+ glTexImageCheckBox.setEnabled(false);
+
+ MessageDialog.openError(Display.getDefault().getActiveShell(),
+ "OpenGL ES Trace",
+ "Error while setting trace options: " + e.getMessage());
+ }
- createLabel(c, "Frames Collected:");
- mFramesCollectedText = createText(c);
+ // update the text on the button
+ if (!(event.getSource() instanceof Button)) {
+ return;
+ }
+ Button sourceButton = (Button) event.getSource();
+ sourceButton.setText(getToggleActionText(sourceButton.getSelection()));
+ sourceButton.pack();
+ }
+ };
+
+ eglSwapCheckBox.addSelectionListener(l);
+ glDrawCheckBox.addSelectionListener(l);
+ glTexImageCheckBox.addSelectionListener(l);
+
+ Group statusGroup = new Group(parent, SWT.NONE);
+ statusGroup.setLayout(new GridLayout(2, false));
+ statusGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ statusGroup.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_BLUE));
+ statusGroup.setText("Trace Status");
- createLabel(c, "Trace File Size:");
- mTraceFileSizeText = createText(c);
+ createLabel(statusGroup, "Frames Collected:");
+ mFramesCollectedLabel = createLabel(statusGroup, "");
- ProgressBar pb = new ProgressBar(c, SWT.INDETERMINATE);
+ createLabel(statusGroup, "Trace File Size:");
+ mTraceFileSizeLabel = createLabel(statusGroup, "");
+
+ ProgressBar pb = new ProgressBar(statusGroup, SWT.INDETERMINATE);
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalSpan = 2;
pb.setLayoutData(gd);
+ mRefreshTask = new StatusRefreshTask();
+ new Thread(mRefreshTask, "Trace Status Refresh Thread").start();
+
return super.createDialogArea(parent);
}
- private Text createText(Composite c) {
- Text t = new Text(c, SWT.BORDER);
-
- GridData gd = new GridData();
- gd.widthHint = 100;
- t.setLayoutData(gd);
+ private Button createButton(Composite controlComposite, boolean selection) {
+ Button b = new Button(controlComposite, SWT.TOGGLE);
+ b.setText(getToggleActionText(selection));
+ b.setSelection(selection);
+ return b;
+ }
- return t;
+ /** Get text to show on toggle box given its current selection. */
+ private String getToggleActionText(boolean en) {
+ return en ? "Disable" : "Enable";
}
- private void createLabel(Composite parent, String text) {
+ private Label createLabel(Composite parent, String text) {
Label l = new Label(parent, SWT.NONE);
l.setText(text);
- GridData gd = new GridData();
- gd.horizontalAlignment = SWT.RIGHT;
+ GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalAlignment = SWT.LEFT;
gd.verticalAlignment = SWT.CENTER;
l.setLayoutData(gd);
+
+ return l;
}
@Override
protected void okPressed() {
- if (mWriter != null) {
- mWriter.stopTracing();
- }
-
+ mRefreshTask.cancel();
super.okPressed();
}
- public void setFrameCount(final int n) {
- mFramesCollected = n;
- scheduleDisplayUpdate();
- }
+ /** Periodically refresh the trace status. */
+ private class StatusRefreshTask implements Runnable {
+ private static final int REFRESH_INTERVAL = 1000;
+ private volatile boolean mIsCancelled = false;
- public void setTraceFileSize(final int n) {
- mTraceFileSize = n;
- scheduleDisplayUpdate();
- }
+ public void run() {
+ if (mTraceFileWriter == null) {
+ return;
+ }
+
+ while (!mIsCancelled) {
+ final String frameCount = Integer.toString(mTraceFileWriter.getCurrentFrameCount());
+
+ double fileSize = (double) mTraceFileWriter.getCurrentFileSize();
+ fileSize /= (1024 * 1024); // convert to size in MB
+ final String frameSize = String.format("%.2g MB", fileSize); //$NON-NLS-1$
- private Runnable mRefreshTask = null;
+ Display.getDefault().syncExec(new Runnable() {
+ public void run() {
+ if (mFramesCollectedLabel.isDisposed()) {
+ return;
+ }
- /** Schedule a refresh UI task if one is not already pending. */
- private void scheduleDisplayUpdate() {
- if (mRefreshTask == null) {
- mRefreshTask = new Runnable() {
- public void run() {
- mRefreshTask = null;
+ mFramesCollectedLabel.setText(frameCount);
+ mTraceFileSizeLabel.setText(frameSize);
- if (mFramesCollectedText.isDisposed()) {
- return;
+ mFramesCollectedLabel.pack();
+ mTraceFileSizeLabel.pack();
}
+ });
- mFramesCollectedText.setText(Integer.toString(mFramesCollected));
- mTraceFileSizeText.setText(Integer.toString(mTraceFileSize) + " bytes");
+ try {
+ Thread.sleep(REFRESH_INTERVAL);
+ } catch (InterruptedException e) {
+ return;
}
- };
- Display.getDefault().asyncExec(mRefreshTask);
+ }
}
- }
- public void setTraceWriter(GLTraceWriter writer) {
- mWriter = writer;
+ public void cancel() {
+ mIsCancelled = true;
+ }
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/GLTraceOptionsDialog.java b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/GLTraceOptionsDialog.java
index 33d22ab..18f9968 100644
--- a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/GLTraceOptionsDialog.java
+++ b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/GLTraceOptionsDialog.java
@@ -29,6 +29,7 @@ import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
@@ -45,13 +46,10 @@ import org.osgi.service.prefs.BackingStoreException;
import java.util.ArrayList;
import java.util.List;
-// FIXME: Not all elements in this dialog are functional. They are there for UI review,
-// and once we figure out what needs to be there and what not, we'll fix this.
/** Dialog displaying all the trace options before the user initiates tracing. */
public class GLTraceOptionsDialog extends TitleAreaDialog {
- private static final String TITLE = "OpenGL ES 2.0 Trace Options";
- private static final String DEFAULT_MESSAGE = "Provide the application to be traced. The application needs to have INTERNET permission for tracing.";
- private static final String DEFAULT_NUM_FRAMES_TEXT = "10";
+ private static final String TITLE = "OpenGL ES Trace Options";
+ private static final String DEFAULT_MESSAGE = "Provide the application and activity to be traced. The application needs to have INTERNET permission for tracing.";
private static final String PREF_APPNAME = "gl.trace.appname";
private static final String PREF_TRACEFILE = "gl.trace.destfile";
@@ -61,13 +59,17 @@ public class GLTraceOptionsDialog extends TitleAreaDialog {
private Button mOkButton;
private Combo mDeviceCombo;
- private Text mAppToTraceText;
+ private Text mActivityToTraceText;
private Text mTraceFilePathText;
private String mSelectedDevice = "";
- private String mAppToTrace = "";
+ private String mActivityToTrace = "";
private String mTraceFilePath = "";
+ private boolean mCollectFbOnEglSwap = true;
+ private boolean mCollectFbOnGlDraw = false;
+ private boolean mCollectTextureData = false;
+
public GLTraceOptionsDialog(Shell parentShell) {
super(parentShell);
loadPreferences();
@@ -89,11 +91,8 @@ public class GLTraceOptionsDialog extends TitleAreaDialog {
createLabel(c, "Activity:");
createAppToTraceText(c, "e.g. com.example.android.apis");
- createLabel(c, "Capture Mode:");
- createCaptureModeOptions(c);
-
- createLabel(c, "Capture Framebuffer:");
- createCaptureFBOptions(c);
+ createLabel(c, "Capture Image:");
+ createCaptureImageOptions(c);
createSeparator(c);
@@ -166,60 +165,51 @@ public class GLTraceOptionsDialog extends TitleAreaDialog {
}
/** Options controlling when the FB should be captured. */
- private void createCaptureFBOptions(Composite parent) {
+ private void createCaptureImageOptions(Composite parent) {
Composite c = new Composite(parent, SWT.NONE);
c.setLayout(new GridLayout(1, false));
c.setLayoutData(new GridData(GridData.FILL_BOTH));
- Button b1 = new Button(c, SWT.CHECK);
- b1.setText("On eglSwap()");
- b1.setSelection(true);
+ final Button readFbOnEglSwapCheckBox = new Button(c, SWT.CHECK);
+ readFbOnEglSwapCheckBox.setText("Read back framebuffer 0 on eglSwapBuffers()");
+ readFbOnEglSwapCheckBox.setSelection(mCollectFbOnEglSwap);
- Button b2 = new Button(c, SWT.CHECK);
- b2.setText("On glDrawElements() and glDrawArrays()");
- b2.setSelection(false);
- }
+ final Button readFbOnGlDrawCheckBox = new Button(c, SWT.CHECK);
+ readFbOnGlDrawCheckBox.setText("Read back currently bound framebuffer On glDraw*()");
+ readFbOnGlDrawCheckBox.setSelection(mCollectFbOnGlDraw);
- private void createCaptureModeOptions(Composite parent) {
- Composite c = new Composite(parent, SWT.NONE);
- c.setLayout(new GridLayout(2, false));
- c.setLayoutData(new GridData(GridData.FILL_BOTH));
-
- Button b1 = new Button(c, SWT.RADIO);
- b1.setText("Infinite Buffer");
- GridData gd = new GridData();
- gd.horizontalSpan = 2;
- b1.setLayoutData(gd);
+ final Button readTextureDataCheckBox = new Button(c, SWT.CHECK);
+ readTextureDataCheckBox.setText("Collect texture data submitted using glTexImage*()");
+ readTextureDataCheckBox.setSelection(mCollectTextureData);
- Button b2 = new Button(c, SWT.RADIO);
- b2.setText("Last N frames");
- b2.setEnabled(false);
-
- b1.setSelection(true);
+ SelectionListener l = new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ mCollectFbOnEglSwap = readFbOnEglSwapCheckBox.getSelection();
+ mCollectFbOnGlDraw = readFbOnGlDrawCheckBox.getSelection();
+ mCollectTextureData = readTextureDataCheckBox.getSelection();
+ }
+ };
- Text t = new Text(c, SWT.BORDER);
- t.setMessage(DEFAULT_NUM_FRAMES_TEXT);
- gd = new GridData();
- gd.widthHint = 30;
- t.setLayoutData(gd);
- t.setEditable(false);
- t.setEnabled(false);
+ readFbOnEglSwapCheckBox.addSelectionListener(l);
+ readFbOnGlDrawCheckBox.addSelectionListener(l);
+ readTextureDataCheckBox.addSelectionListener(l);
}
private Text createAppToTraceText(Composite parent, String defaultMessage) {
- mAppToTraceText = new Text(parent, SWT.BORDER);
- mAppToTraceText.setMessage(defaultMessage);
- mAppToTraceText.setText(mAppToTrace);
+ mActivityToTraceText = new Text(parent, SWT.BORDER);
+ mActivityToTraceText.setMessage(defaultMessage);
+ mActivityToTraceText.setText(mActivityToTrace);
- mAppToTraceText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ mActivityToTraceText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
- mAppToTraceText.addModifyListener(new ModifyListener() {
+ mActivityToTraceText.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
validateAndSetMessage();
}
});
- return mAppToTraceText;
+ return mActivityToTraceText;
}
private void validateAndSetMessage() {
@@ -269,7 +259,7 @@ public class GLTraceOptionsDialog extends TitleAreaDialog {
}
private DialogStatus validateDialog() {
- if (mAppToTraceText.getText().trim().length() == 0) {
+ if (mActivityToTraceText.getText().trim().length() == 0) {
return new DialogStatus(false, "Provide an application name");
}
@@ -282,7 +272,7 @@ public class GLTraceOptionsDialog extends TitleAreaDialog {
@Override
protected void okPressed() {
- mAppToTrace = mAppToTraceText.getText();
+ mActivityToTrace = mActivityToTraceText.getText();
mTraceFilePath = mTraceFilePathText.getText();
mSelectedDevice = mDeviceCombo.getText();
@@ -293,7 +283,7 @@ public class GLTraceOptionsDialog extends TitleAreaDialog {
private void savePreferences() {
IEclipsePreferences prefs = new InstanceScope().getNode(Activator.PLUGIN_ID);
- prefs.put(PREF_APPNAME, mAppToTrace);
+ prefs.put(PREF_APPNAME, mActivityToTrace);
prefs.put(PREF_TRACEFILE, mTraceFilePath);
try {
prefs.flush();
@@ -304,19 +294,12 @@ public class GLTraceOptionsDialog extends TitleAreaDialog {
private void loadPreferences() {
IEclipsePreferences prefs = new InstanceScope().getNode(Activator.PLUGIN_ID);
- mAppToTrace = prefs.get(PREF_APPNAME, "");
+ mActivityToTrace = prefs.get(PREF_APPNAME, "");
mTraceFilePath = prefs.get(PREF_TRACEFILE, "");
}
- public String getDevice() {
- return mSelectedDevice;
- }
-
- public String getApplicationToTrace() {
- return mAppToTrace.trim();
- }
-
- public String getTraceDestination() {
- return mTraceFilePath;
+ public TraceOptions getTraceOptions() {
+ return new TraceOptions(mSelectedDevice, mActivityToTrace.trim(), mTraceFilePath,
+ mCollectFbOnEglSwap, mCollectFbOnGlDraw, mCollectTextureData);
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/TraceCommandWriter.java b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/TraceCommandWriter.java
new file mode 100644
index 0000000..f8d97b7
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/TraceCommandWriter.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.eclipse.gltrace;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+/**
+ * Write trace control options to the trace backend.
+ * Currently, the number of options is limited, so all the options are packed into a
+ * single integer. Any changes to this protocol have to be updated on the device as well.
+ */
+public class TraceCommandWriter {
+ private static final int READ_FB_ON_EGLSWAP_BIT = 0;
+ private static final int READ_FB_ON_GLDRAW_BIT = 1;
+ private static final int READ_TEXTURE_DATA_ON_GLTEXIMAGE_BIT = 2;
+
+ private final DataOutputStream mStream;;
+
+ public TraceCommandWriter(DataOutputStream traceCommandStream) {
+ mStream = traceCommandStream;
+ }
+
+ public void setTraceOptions(boolean readFbOnEglSwap, boolean readFbOnGlDraw,
+ boolean readTextureOnGlTexImage) throws IOException {
+ int eglSwap = readFbOnEglSwap ? (1 << READ_FB_ON_EGLSWAP_BIT) : 0;
+ int glDraw = readFbOnGlDraw ? (1 << READ_FB_ON_GLDRAW_BIT) : 0;
+ int tex = readTextureOnGlTexImage ? ( 1 << READ_TEXTURE_DATA_ON_GLTEXIMAGE_BIT) : 0;
+
+ int cmd = eglSwap | glDraw | tex;
+
+ mStream.writeInt(cmd);
+ mStream.flush();
+ }
+
+ public void close() {
+ try {
+ mStream.close();
+ } catch (IOException e) {
+ // ignore exception while closing stream
+ }
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/GLTraceWriter.java b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/TraceFileWriter.java
index d57d677..a6c02c4 100644
--- a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/GLTraceWriter.java
+++ b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/TraceFileWriter.java
@@ -17,30 +17,31 @@
package com.android.ide.eclipse.gltrace;
import com.android.ide.eclipse.gltrace.GLProtoBuf.GLMessage;
+import com.android.ide.eclipse.gltrace.GLProtoBuf.GLMessage.Function;
import com.google.protobuf.InvalidProtocolBufferException;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
-import java.net.Socket;
/** A class that streams data received from a socket into the trace file. */
-public class GLTraceWriter {
+public class TraceFileWriter {
+ private DataInputStream mInputStream;
private DataOutputStream mOutputStream;
- private int mPort;
- private GLTraceCollectorDialog mDialog;
- private volatile boolean stopTracing = false;
private Thread mReceiverThread;
private int mFileSize = 0;
private int mFrameCount = 0;
- public GLTraceWriter(FileOutputStream fos, int port,
- GLTraceCollectorDialog glTraceCollectorDialog) {
+ /**
+ * Construct a trace file writer.
+ * @param fos output stream to write trace data to
+ * @param is input stream from which trace data is read
+ */
+ public TraceFileWriter(FileOutputStream fos, DataInputStream is) {
mOutputStream = new DataOutputStream(fos);
- mPort = port;
- mDialog = glTraceCollectorDialog;
+ mInputStream = is;
}
public void start() {
@@ -48,15 +49,15 @@ public class GLTraceWriter {
mReceiverThread = new Thread(new GLTraceReceiverTask());
mReceiverThread.setName("GL Trace Receiver");
mReceiverThread.start();
-
- // launch dialog
- mDialog.setTraceWriter(this);
- mDialog.open();
}
public void stopTracing() {
- // stop thread
- stopTracing = true;
+ // close socket to stop the receiver thread
+ try {
+ mInputStream.close();
+ } catch (IOException e) {
+ // ignore exception while closing socket
+ }
// wait for receiver to complete
try {
@@ -73,62 +74,82 @@ public class GLTraceWriter {
}
}
+ /**
+ * The GLTraceReceiverTask collects trace data from the device and writes it
+ * into a file while collecting some stats on the way.
+ */
private class GLTraceReceiverTask implements Runnable {
public void run() {
- try {
- Socket socket = new Socket();
- socket.connect(new java.net.InetSocketAddress("127.0.0.1", mPort));
- DataInputStream dis = new DataInputStream(socket.getInputStream());
-
- while (!stopTracing) {
- if (dis.available() > 0) {
- readMessage(dis);
- mDialog.setFrameCount(mFrameCount);
- mDialog.setTraceFileSize(mFileSize);
- } else {
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- // ignore, as this thread is not interrupted by any other thread.
- }
- }
+ while (true) {
+ byte[] buffer = readTraceData(mInputStream);
+ if (buffer == null) {
+ break;
}
- socket.close();
- } catch (IOException e) {
+ try {
+ writeTraceData(buffer, mOutputStream);
+ } catch (IOException e) {
+ break;
+ }
+
+ updateTraceStats(buffer);
}
}
}
- private void readMessage(DataInputStream dis) throws IOException {
- int len = dis.readInt();
+ private byte[] readTraceData(DataInputStream dis) {
+ int len;
+ try {
+ len = dis.readInt();
+ } catch (IOException e1) {
+ return null;
+ }
len = Integer.reverseBytes(len); // readInt is big endian, we want little endian
byte[] buffer = new byte[len];
int readLen = 0;
while (readLen < len) {
- int read = dis.read(buffer, readLen, len - readLen);
- if (read < 0) {
- throw new IOException();
- } else {
- readLen += read;
+ try {
+ int read = dis.read(buffer, readLen, len - readLen);
+ if (read < 0) {
+ return null;
+ } else {
+ readLen += read;
+ }
+ } catch (IOException e) {
+ return null;
}
}
+ return buffer;
+ }
+
+
+ private void writeTraceData(byte[] buffer, DataOutputStream stream) throws IOException {
+ stream.writeInt(buffer.length);
+ stream.write(buffer);
+ }
+
+ private void updateTraceStats(byte[] buffer) {
GLMessage msg = null;
try {
msg = GLMessage.parseFrom(buffer);
} catch (InvalidProtocolBufferException e) {
- System.out.println("Invalid protocol buffer: " + e.getMessage());
return;
}
- mOutputStream.writeInt(len);
- mOutputStream.write(buffer);
- mFileSize += readLen;
+ mFileSize += buffer.length;
- if (msg.getFunction() == GLMessage.Function.eglSwapBuffers) {
+ if (msg.getFunction() == Function.eglSwapBuffers) {
mFrameCount++;
}
}
+
+ public int getCurrentFileSize() {
+ return mFileSize;
+ }
+
+ public int getCurrentFrameCount() {
+ return mFrameCount;
+ }
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/TraceOptions.java b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/TraceOptions.java
new file mode 100644
index 0000000..d67d167
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/TraceOptions.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.eclipse.gltrace;
+
+public class TraceOptions {
+ /** Device on which the application should be run. */
+ public final String device;
+
+ /** Activity to trace. */
+ public final String activityToTrace;
+
+ /** Path where the trace file should be saved. */
+ public final String traceDestination;
+
+ /** Flag indicating whether Framebuffer should be captured on eglSwap() */
+ public final boolean collectFbOnEglSwap;
+
+ /** Flag indicating whether Framebuffer should be captured on glDraw*() */
+ public final boolean collectFbOnGlDraw;
+
+ /** Flag indicating whether texture data should be captured on glTexImage*() */
+ public final boolean collectTextureData;
+
+ public TraceOptions(String device, String activity, String destinationPath,
+ boolean collectFbOnEglSwap, boolean collectFbOnGlDraw, boolean collectTextureData) {
+ this.device = device;
+ this.activityToTrace = activity;
+ this.traceDestination = destinationPath;
+ this.collectFbOnEglSwap = collectFbOnEglSwap;
+ this.collectFbOnGlDraw = collectFbOnGlDraw;
+ this.collectTextureData = collectTextureData;
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/editors/GLFunctionTraceViewer.java b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/editors/GLFunctionTraceViewer.java
index fc6ce18..31d48c8 100644
--- a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/editors/GLFunctionTraceViewer.java
+++ b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/editors/GLFunctionTraceViewer.java
@@ -260,7 +260,21 @@ public class GLFunctionTraceViewer extends EditorPart implements ISelectionProvi
tvc.setLabelProvider(labelProvider);
TableColumn column = tvc.getColumn();
column.setText("Context");
- column.setWidth(50);
+ column.setWidth(150);
+
+ // column showing the GL function called
+ tvc = new TableViewerColumn(mFrameTableViewer, SWT.NONE);
+ tvc.setLabelProvider(labelProvider);
+ column = tvc.getColumn();
+ column.setText("Start");
+ column.setWidth(150);
+
+ // column showing the GL function called
+ tvc = new TableViewerColumn(mFrameTableViewer, SWT.NONE);
+ tvc.setLabelProvider(labelProvider);
+ column = tvc.getColumn();
+ column.setText("Duration");
+ column.setWidth(150);
// column showing the GL function called
tvc = new TableViewerColumn(mFrameTableViewer, SWT.NONE);
@@ -359,6 +373,10 @@ public class GLFunctionTraceViewer extends EditorPart implements ISelectionProvi
switch (columnIndex) {
case 0:
return Integer.toString(c.getContextId());
+ case 1:
+ return Long.toString(c.getStartTime());
+ case 2:
+ return Integer.toString(c.getDuration());
default:
try {
return sGLCallFormatter.formatGLCall(c);
diff --git a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/model/GLCall.java b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/model/GLCall.java
index c868bde..98b1db6 100644
--- a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/model/GLCall.java
+++ b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/model/GLCall.java
@@ -101,4 +101,12 @@ public class GLCall {
public Image getThumbnailImage() {
return mThumbnailImage;
}
+
+ public long getStartTime() {
+ return mMessage.getStartTime();
+ }
+
+ public int getDuration() {
+ return mMessage.getDuration();
+ }
}