1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.ide.eclipse.gltrace; 18 19 import org.eclipse.jface.dialogs.IDialogConstants; 20 import org.eclipse.jface.dialogs.MessageDialog; 21 import org.eclipse.jface.dialogs.TitleAreaDialog; 22 import org.eclipse.swt.SWT; 23 import org.eclipse.swt.events.SelectionAdapter; 24 import org.eclipse.swt.events.SelectionEvent; 25 import org.eclipse.swt.events.SelectionListener; 26 import org.eclipse.swt.layout.GridData; 27 import org.eclipse.swt.layout.GridLayout; 28 import org.eclipse.swt.widgets.Button; 29 import org.eclipse.swt.widgets.Composite; 30 import org.eclipse.swt.widgets.Control; 31 import org.eclipse.swt.widgets.Display; 32 import org.eclipse.swt.widgets.Group; 33 import org.eclipse.swt.widgets.Label; 34 import org.eclipse.swt.widgets.ProgressBar; 35 import org.eclipse.swt.widgets.Shell; 36 37 import java.io.IOException; 38 import java.text.DecimalFormat; 39 40 /** Dialog displayed while the trace is being streamed from device to host. */ 41 public class GLTraceCollectorDialog extends TitleAreaDialog { 42 private static final String TITLE = "OpenGL ES Trace"; 43 private static final String DEFAULT_MESSAGE = "Trace collection in progress."; 44 private static final DecimalFormat SIZE_FORMATTER = new DecimalFormat("#.##"); //$NON-NLS-1$ 45 46 private TraceOptions mTraceOptions; 47 private final TraceFileWriter mTraceFileWriter; 48 private final TraceCommandWriter mTraceCommandWriter; 49 50 private Label mFramesCollectedLabel; 51 private Label mTraceFileSizeLabel; 52 private StatusRefreshTask mRefreshTask; 53 54 protected GLTraceCollectorDialog(Shell parentShell, TraceFileWriter traceFileWriter, 55 TraceCommandWriter traceCommandWriter, TraceOptions traceOptions) { 56 super(parentShell); 57 mTraceFileWriter = traceFileWriter; 58 mTraceCommandWriter = traceCommandWriter; 59 mTraceOptions = traceOptions; 60 } 61 62 @Override 63 protected Control createButtonBar(Composite parent) { 64 Composite c = new Composite(parent, SWT.NONE); 65 c.setLayout(new GridLayout(0, false)); 66 GridData gd = new GridData(GridData.FILL_HORIZONTAL); 67 gd.horizontalAlignment = GridData.CENTER; 68 c.setLayoutData(gd); 69 70 createButton(c, IDialogConstants.OK_ID, "Stop Tracing", true); 71 return c; 72 } 73 74 @Override 75 protected Control createDialogArea(Composite parent) { 76 parent.setLayout(new GridLayout()); 77 78 setTitle(TITLE); 79 setMessage(DEFAULT_MESSAGE); 80 81 Group controlGroup = new Group(parent, SWT.BORDER); 82 controlGroup.setLayout(new GridLayout(2, false)); 83 controlGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); 84 controlGroup.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_BLUE)); 85 controlGroup.setText("Trace Options"); 86 87 createLabel(controlGroup, "Collect Framebuffer contents on eglSwapBuffers()"); 88 final Button eglSwapCheckBox = createButton(controlGroup, 89 mTraceOptions.collectFbOnEglSwap); 90 91 createLabel(controlGroup, "Collect Framebuffer contents on glDraw*()"); 92 final Button glDrawCheckBox = createButton(controlGroup, mTraceOptions.collectFbOnGlDraw); 93 94 createLabel(controlGroup, "Collect texture data for glTexImage*()"); 95 final Button glTexImageCheckBox = createButton(controlGroup, 96 mTraceOptions.collectTextureData); 97 98 SelectionListener l = new SelectionAdapter() { 99 @Override 100 public void widgetSelected(SelectionEvent event) { 101 boolean eglSwap = eglSwapCheckBox.getSelection(); 102 boolean glDraw = glDrawCheckBox.getSelection(); 103 boolean glTexImage = glTexImageCheckBox.getSelection(); 104 105 try { 106 mTraceCommandWriter.setTraceOptions(eglSwap, glDraw, glTexImage); 107 } catch (IOException e) { 108 eglSwapCheckBox.setEnabled(false); 109 glDrawCheckBox.setEnabled(false); 110 glTexImageCheckBox.setEnabled(false); 111 112 MessageDialog.openError(Display.getDefault().getActiveShell(), 113 "OpenGL ES Trace", 114 "Error while setting trace options: " + e.getMessage()); 115 } 116 117 // update the text on the button 118 if (!(event.getSource() instanceof Button)) { 119 return; 120 } 121 Button sourceButton = (Button) event.getSource(); 122 sourceButton.setText(getToggleActionText(sourceButton.getSelection())); 123 sourceButton.pack(); 124 } 125 }; 126 127 eglSwapCheckBox.addSelectionListener(l); 128 glDrawCheckBox.addSelectionListener(l); 129 glTexImageCheckBox.addSelectionListener(l); 130 131 Group statusGroup = new Group(parent, SWT.NONE); 132 statusGroup.setLayout(new GridLayout(2, false)); 133 statusGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); 134 statusGroup.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_BLUE)); 135 statusGroup.setText("Trace Status"); 136 137 createLabel(statusGroup, "Frames Collected:"); 138 mFramesCollectedLabel = createLabel(statusGroup, ""); 139 140 createLabel(statusGroup, "Trace File Size:"); 141 mTraceFileSizeLabel = createLabel(statusGroup, ""); 142 143 ProgressBar pb = new ProgressBar(statusGroup, SWT.INDETERMINATE); 144 GridData gd = new GridData(GridData.FILL_HORIZONTAL); 145 gd.horizontalSpan = 2; 146 pb.setLayoutData(gd); 147 148 mRefreshTask = new StatusRefreshTask(); 149 new Thread(mRefreshTask, "Trace Status Refresh Thread").start(); 150 151 return super.createDialogArea(parent); 152 } 153 154 private Button createButton(Composite controlComposite, boolean selection) { 155 Button b = new Button(controlComposite, SWT.TOGGLE); 156 b.setText(getToggleActionText(selection)); 157 b.setSelection(selection); 158 return b; 159 } 160 161 /** Get text to show on toggle box given its current selection. */ 162 private String getToggleActionText(boolean en) { 163 return en ? "Disable" : "Enable"; 164 } 165 166 private Label createLabel(Composite parent, String text) { 167 Label l = new Label(parent, SWT.NONE); 168 l.setText(text); 169 GridData gd = new GridData(GridData.FILL_HORIZONTAL); 170 gd.horizontalAlignment = SWT.LEFT; 171 gd.verticalAlignment = SWT.CENTER; 172 l.setLayoutData(gd); 173 174 return l; 175 } 176 177 @Override 178 protected void okPressed() { 179 mRefreshTask.cancel(); 180 super.okPressed(); 181 } 182 183 /** Periodically refresh the trace status. */ 184 private class StatusRefreshTask implements Runnable { 185 private static final int REFRESH_INTERVAL = 1000; 186 private volatile boolean mIsCancelled = false; 187 188 @Override 189 public void run() { 190 if (mTraceFileWriter == null) { 191 return; 192 } 193 194 while (!mIsCancelled) { 195 final String frameCount = Integer.toString(mTraceFileWriter.getCurrentFrameCount()); 196 197 double fileSize = mTraceFileWriter.getCurrentFileSize(); 198 fileSize /= (1024 * 1024); // convert to size in MB 199 final String frameSize = SIZE_FORMATTER.format(fileSize) + " MB"; 200 201 Display.getDefault().syncExec(new Runnable() { 202 @Override 203 public void run() { 204 if (mFramesCollectedLabel.isDisposed()) { 205 return; 206 } 207 208 mFramesCollectedLabel.setText(frameCount); 209 mTraceFileSizeLabel.setText(frameSize); 210 211 mFramesCollectedLabel.pack(); 212 mTraceFileSizeLabel.pack(); 213 } 214 }); 215 216 try { 217 Thread.sleep(REFRESH_INTERVAL); 218 } catch (InterruptedException e) { 219 return; 220 } 221 } 222 } 223 224 public void cancel() { 225 mIsCancelled = true; 226 } 227 } 228 } 229