diff options
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/GLTraceOptionsDialog.java')
-rw-r--r-- | eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/GLTraceOptionsDialog.java | 403 |
1 files changed, 403 insertions, 0 deletions
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 new file mode 100644 index 000000000..b4de3d151 --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/GLTraceOptionsDialog.java @@ -0,0 +1,403 @@ +/* + * 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 com.android.ddmlib.AndroidDebugBridge; +import com.android.ddmlib.IDevice; + +import org.eclipse.core.runtime.preferences.IEclipsePreferences; +import org.eclipse.core.runtime.preferences.InstanceScope; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.TitleAreaDialog; +import org.eclipse.swt.SWT; +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; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.osgi.service.prefs.BackingStoreException; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +/** Dialog displaying all the trace options before the user initiates tracing. */ +public class GLTraceOptionsDialog extends TitleAreaDialog { + private static final String TITLE = "OpenGL ES Trace Options"; + private static final String DEFAULT_MESSAGE = "Provide the application and activity to be traced."; + + private static final String PREF_APP_PACKAGE = "gl.trace.apppackage"; //$NON-NLS-1$ + private static final String PREF_ACTIVITY = "gl.trace.activity"; //$NON-NLS-1$ + private static final String PREF_TRACEFILE = "gl.trace.destfile"; //$NON-NLS-1$ + private static final String PREF_DEVICE = "gl.trace.device"; //$NON-NLS-1$ + private String mLastUsedDevice; + + private static String sSaveToFolder = System.getProperty("user.home"); //$NON-NLS-1$ + + private Button mOkButton; + + private Combo mDeviceCombo; + private Text mAppPackageToTraceText; + private Text mActivityToTraceText; + private Button mIsActivityFullyQualifiedButton; + private Text mTraceFilePathText; + + private String mSelectedDevice = ""; + private String mAppPackageToTrace = ""; + private String mActivityToTrace = ""; + private String mTraceFilePath = ""; + private boolean mAllowAppSelection; + + private static boolean sCollectFbOnEglSwap = true; + private static boolean sCollectFbOnGlDraw = false; + private static boolean sCollectTextureData = false; + private static boolean sIsActivityFullyQualified = false; + private IDevice[] mDevices; + + public GLTraceOptionsDialog(Shell parentShell) { + this(parentShell, true, null); + } + + /** + * Constructs a dialog displaying options for the tracer. + * @param allowAppSelection true if user can change the application to trace + * @param appToTrace default application package to trace + */ + public GLTraceOptionsDialog(Shell parentShell, boolean allowAppSelection, + String appToTrace) { + super(parentShell); + loadPreferences(); + + mAllowAppSelection = allowAppSelection; + if (appToTrace != null) { + mAppPackageToTrace = appToTrace; + } + } + + @Override + protected Control createDialogArea(Composite shell) { + setTitle(TITLE); + setMessage(DEFAULT_MESSAGE); + + Composite parent = (Composite) super.createDialogArea(shell); + Composite c = new Composite(parent, SWT.BORDER); + c.setLayout(new GridLayout(2, false)); + c.setLayoutData(new GridData(GridData.FILL_BOTH)); + + createLabel(c, "Device:"); + mDevices = AndroidDebugBridge.getBridge().getDevices(); + createDeviceDropdown(c, mDevices); + + createSeparator(c); + + createLabel(c, "Application Package:"); + createAppToTraceText(c, "e.g. com.example.package"); + + createLabel(c, "Activity to launch:"); + createActivityToTraceText(c, "Leave blank to launch default activity"); + + createLabel(c, ""); + createIsFullyQualifedActivityButton(c, + "Activity name is fully qualified, do not prefix with package name"); + + if (!mAllowAppSelection) { + mAppPackageToTraceText.setEnabled(false); + mActivityToTraceText.setEnabled(false); + mIsActivityFullyQualifiedButton.setEnabled(false); + } + + createSeparator(c); + + createLabel(c, "Data Collection Options:"); + createCaptureImageOptions(c); + + createSeparator(c); + + createLabel(c, "Destination File: "); + createSaveToField(c); + + return c; + } + + @Override + protected void createButtonsForButtonBar(Composite parent) { + super.createButtonsForButtonBar(parent); + + mOkButton = getButton(IDialogConstants.OK_ID); + mOkButton.setText("Trace"); + + DialogStatus status = validateDialog(); + mOkButton.setEnabled(status.valid); + } + + private void createSeparator(Composite c) { + Label l = new Label(c, SWT.SEPARATOR | SWT.HORIZONTAL); + GridData gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan = 2; + l.setLayoutData(gd); + } + + private void createSaveToField(Composite parent) { + Composite c = new Composite(parent, SWT.NONE); + c.setLayout(new GridLayout(2, false)); + c.setLayoutData(new GridData(GridData.FILL_BOTH)); + + mTraceFilePathText = new Text(c, SWT.BORDER); + mTraceFilePathText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + mTraceFilePathText.setText(mTraceFilePath); + mTraceFilePathText.addModifyListener(new ModifyListener() { + @Override + public void modifyText(ModifyEvent e) { + validateAndSetMessage(); + } + }); + + Button browse = new Button(c, SWT.PUSH); + browse.setText("Browse..."); + browse.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + String fName = openBrowseDialog(); + if (fName == null) { + return; + } + + mTraceFilePathText.setText(fName); + validateAndSetMessage(); + } + }); + } + + private String openBrowseDialog() { + FileDialog fd = new FileDialog(Display.getDefault().getActiveShell(), SWT.SAVE); + + fd.setText("Save To"); + fd.setFileName("trace1.gltrace"); + + fd.setFilterPath(sSaveToFolder); + fd.setFilterExtensions(new String[] { "*.gltrace" }); + + String fname = fd.open(); + if (fname == null || fname.trim().length() == 0) { + return null; + } + + sSaveToFolder = fd.getFilterPath(); + return fname; + } + + /** Options controlling when the FB should be captured. */ + 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)); + + final Button readFbOnEglSwapCheckBox = new Button(c, SWT.CHECK); + readFbOnEglSwapCheckBox.setText("Read back framebuffer 0 on eglSwapBuffers()"); + readFbOnEglSwapCheckBox.setSelection(sCollectFbOnEglSwap); + + final Button readFbOnGlDrawCheckBox = new Button(c, SWT.CHECK); + readFbOnGlDrawCheckBox.setText("Read back currently bound framebuffer On glDraw*()"); + readFbOnGlDrawCheckBox.setSelection(sCollectFbOnGlDraw); + + final Button readTextureDataCheckBox = new Button(c, SWT.CHECK); + readTextureDataCheckBox.setText("Collect texture data submitted using glTexImage*()"); + readTextureDataCheckBox.setSelection(sCollectTextureData); + + SelectionListener l = new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + sCollectFbOnEglSwap = readFbOnEglSwapCheckBox.getSelection(); + sCollectFbOnGlDraw = readFbOnGlDrawCheckBox.getSelection(); + sCollectTextureData = readTextureDataCheckBox.getSelection(); + } + }; + + readFbOnEglSwapCheckBox.addSelectionListener(l); + readFbOnGlDrawCheckBox.addSelectionListener(l); + readTextureDataCheckBox.addSelectionListener(l); + } + + private Text createAppToTraceText(Composite parent, String defaultMessage) { + mAppPackageToTraceText = new Text(parent, SWT.BORDER); + mAppPackageToTraceText.setMessage(defaultMessage); + mAppPackageToTraceText.setText(mAppPackageToTrace); + + mAppPackageToTraceText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + mAppPackageToTraceText.addModifyListener(new ModifyListener() { + @Override + public void modifyText(ModifyEvent e) { + validateAndSetMessage(); + } + }); + + return mActivityToTraceText; + } + + private Text createActivityToTraceText(Composite parent, String defaultMessage) { + mActivityToTraceText = new Text(parent, SWT.BORDER); + mActivityToTraceText.setMessage(defaultMessage); + mActivityToTraceText.setText(mActivityToTrace); + + mActivityToTraceText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + mActivityToTraceText.addModifyListener(new ModifyListener() { + @Override + public void modifyText(ModifyEvent e) { + validateAndSetMessage(); + } + }); + + return mActivityToTraceText; + } + + private Button createIsFullyQualifedActivityButton(Composite parent, String message) { + mIsActivityFullyQualifiedButton = new Button(parent, SWT.CHECK); + mIsActivityFullyQualifiedButton.setText(message); + mIsActivityFullyQualifiedButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + mIsActivityFullyQualifiedButton.setSelection(sIsActivityFullyQualified); + + return mIsActivityFullyQualifiedButton; + } + + private void validateAndSetMessage() { + DialogStatus status = validateDialog(); + mOkButton.setEnabled(status.valid); + setErrorMessage(status.message); + } + + private Combo createDeviceDropdown(Composite parent, IDevice[] devices) { + mDeviceCombo = new Combo(parent, SWT.READ_ONLY | SWT.BORDER); + + List<String> items = new ArrayList<String>(devices.length); + for (IDevice d : devices) { + items.add(d.getName()); + } + mDeviceCombo.setItems(items.toArray(new String[items.size()])); + + int index = 0; + if (items.contains(mLastUsedDevice)) { + index = items.indexOf(mLastUsedDevice); + } + if (index >= 0 && index < items.size()) { + mDeviceCombo.select(index); + } + return mDeviceCombo; + } + + private void createLabel(Composite parent, String text) { + Label l = new Label(parent, SWT.NONE); + l.setText(text); + GridData gd = new GridData(); + gd.horizontalAlignment = SWT.RIGHT; + gd.verticalAlignment = SWT.CENTER; + l.setLayoutData(gd); + } + + /** + * A tuple that specifies whether the current state of the inputs + * on the dialog is valid or not. If it is not valid, the message + * field stores the reason why it isn't. + */ + private final class DialogStatus { + final boolean valid; + final String message; + + private DialogStatus(boolean isValid, String errMessage) { + valid = isValid; + message = errMessage; + } + } + + private DialogStatus validateDialog() { + if (mDevices.length == 0) { + return new DialogStatus(false, "No connected devices."); + } + + if (mAppPackageToTraceText.getText().trim().isEmpty()) { + return new DialogStatus(false, "Provide an application name"); + } + + String traceFile = mTraceFilePathText.getText().trim(); + if (traceFile.isEmpty()) { + return new DialogStatus(false, "Specify the location where the trace will be saved."); + } + + File f = new File(traceFile).getParentFile(); + if (f != null && !f.exists()) { + return new DialogStatus(false, + String.format("Folder %s does not exist", f.getAbsolutePath())); + } + + return new DialogStatus(true, null); + } + + @Override + protected void okPressed() { + mAppPackageToTrace = mAppPackageToTraceText.getText().trim(); + mActivityToTrace = mActivityToTraceText.getText().trim(); + if (mActivityToTrace.startsWith(".")) { //$NON-NLS-1$ + mActivityToTrace = mActivityToTrace.substring(1); + } + sIsActivityFullyQualified = mIsActivityFullyQualifiedButton.getSelection(); + mTraceFilePath = mTraceFilePathText.getText().trim(); + mSelectedDevice = mDeviceCombo.getText(); + + savePreferences(); + + super.okPressed(); + } + + private void savePreferences() { + IEclipsePreferences prefs = new InstanceScope().getNode(GlTracePlugin.PLUGIN_ID); + prefs.put(PREF_APP_PACKAGE, mAppPackageToTrace); + prefs.put(PREF_ACTIVITY, mActivityToTrace); + prefs.put(PREF_TRACEFILE, mTraceFilePath); + prefs.put(PREF_DEVICE, mSelectedDevice); + try { + prefs.flush(); + } catch (BackingStoreException e) { + // ignore issues while persisting preferences + } + } + + private void loadPreferences() { + IEclipsePreferences prefs = new InstanceScope().getNode(GlTracePlugin.PLUGIN_ID); + mAppPackageToTrace = prefs.get(PREF_APP_PACKAGE, ""); + mActivityToTrace = prefs.get(PREF_ACTIVITY, ""); + mTraceFilePath = prefs.get(PREF_TRACEFILE, ""); + mLastUsedDevice = prefs.get(PREF_DEVICE, ""); + } + + public TraceOptions getTraceOptions() { + return new TraceOptions(mSelectedDevice, mAppPackageToTrace, mActivityToTrace, + sIsActivityFullyQualified, mTraceFilePath, sCollectFbOnEglSwap, + sCollectFbOnGlDraw, sCollectTextureData); + } +} |