• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  ** Copyright 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.glesv2debugger;
18 
19 import com.android.glesv2debugger.DebuggerMessage.Message;
20 import com.android.glesv2debugger.DebuggerMessage.Message.Function;
21 import com.android.glesv2debugger.DebuggerMessage.Message.Prop;
22 import com.android.glesv2debugger.DebuggerMessage.Message.Type;
23 import com.android.sdklib.util.SparseArray;
24 
25 import org.eclipse.jface.action.Action;
26 import org.eclipse.jface.action.IMenuListener;
27 import org.eclipse.jface.action.IMenuManager;
28 import org.eclipse.jface.action.IToolBarManager;
29 import org.eclipse.jface.action.MenuManager;
30 import org.eclipse.jface.action.Separator;
31 import org.eclipse.jface.dialogs.InputDialog;
32 import org.eclipse.jface.dialogs.MessageDialog;
33 import org.eclipse.jface.viewers.ISelectionChangedListener;
34 import org.eclipse.jface.viewers.IStructuredContentProvider;
35 import org.eclipse.jface.viewers.ITableLabelProvider;
36 import org.eclipse.jface.viewers.LabelProvider;
37 import org.eclipse.jface.viewers.ListViewer;
38 import org.eclipse.jface.viewers.SelectionChangedEvent;
39 import org.eclipse.jface.viewers.StructuredSelection;
40 import org.eclipse.jface.viewers.TreeViewer;
41 import org.eclipse.jface.viewers.Viewer;
42 import org.eclipse.jface.viewers.ViewerFilter;
43 import org.eclipse.jface.viewers.ViewerSorter;
44 import org.eclipse.jface.window.Window;
45 import org.eclipse.swt.SWT;
46 import org.eclipse.swt.events.SelectionEvent;
47 import org.eclipse.swt.events.SelectionListener;
48 import org.eclipse.swt.graphics.Font;
49 import org.eclipse.swt.graphics.GC;
50 import org.eclipse.swt.graphics.Image;
51 import org.eclipse.swt.graphics.Point;
52 import org.eclipse.swt.graphics.Rectangle;
53 import org.eclipse.swt.layout.GridData;
54 import org.eclipse.swt.layout.GridLayout;
55 import org.eclipse.swt.widgets.Canvas;
56 import org.eclipse.swt.widgets.Composite;
57 import org.eclipse.swt.widgets.Event;
58 import org.eclipse.swt.widgets.FileDialog;
59 import org.eclipse.swt.widgets.Listener;
60 import org.eclipse.swt.widgets.Menu;
61 import org.eclipse.swt.widgets.ScrollBar;
62 import org.eclipse.swt.widgets.Shell;
63 import org.eclipse.swt.widgets.Slider;
64 import org.eclipse.swt.widgets.TabFolder;
65 import org.eclipse.swt.widgets.TabItem;
66 import org.eclipse.swt.widgets.Text;
67 import org.eclipse.ui.IActionBars;
68 import org.eclipse.ui.IWorkbenchActionConstants;
69 import org.eclipse.ui.PlatformUI;
70 import org.eclipse.ui.part.ViewPart;
71 
72 import java.io.FileInputStream;
73 import java.io.FileNotFoundException;
74 import java.nio.ByteOrder;
75 
76 /**
77  * This sample class demonstrates how to plug-in a new workbench view. The view
78  * shows data obtained from the model. The sample creates a dummy model on the
79  * fly, but a real implementation would connect to the model available either in
80  * this or another plug-in (e.g. the workspace). The view is connected to the
81  * model using a content provider.
82  * <p>
83  * The view uses a label provider to define how model objects should be
84  * presented in the view. Each view can present the same model objects using
85  * different labels and icons, if needed. Alternatively, a single label provider
86  * can be shared between views in order to ensure that objects of the same type
87  * are presented in the same way everywhere.
88  * <p>
89  */
90 
91 public class SampleView extends ViewPart implements Runnable, SelectionListener {
92     public static final ByteOrder targetByteOrder = ByteOrder.LITTLE_ENDIAN;
93 
94     boolean running = false;
95     Thread thread;
96     MessageQueue messageQueue;
97     SparseArray<DebugContext> debugContexts = new SparseArray<DebugContext>();
98 
99     /** The ID of the view as specified by the extension. */
100     public static final String ID = "glesv2debuggerclient.views.SampleView";
101 
102     TabFolder tabFolder;
103     TabItem tabItemText, tabItemImage, tabItemBreakpointOption;
104     TabItem tabItemShaderEditor, tabContextViewer;
105     ListViewer viewer; // ListViewer / TableViewer
106     Slider frameNum; // scale max cannot overlap min, so max is array size
107     TreeViewer contextViewer;
108     BreakpointOption breakpointOption;
109     ShaderEditor shaderEditor;
110     Canvas canvas;
111     Text text;
112     Action actionConnect; // connect / disconnect
113 
114     Action actionAutoScroll;
115     Action actionFilter;
116     Action actionPort;
117 
118     Action actContext; // for toggling contexts
119     DebugContext current = null;
120 
121     Point origin = new Point(0, 0); // for smooth scrolling canvas
122     String[] filters = null;
123 
124     class ViewContentProvider extends LabelProvider implements IStructuredContentProvider,
125             ITableLabelProvider {
126         Frame frame = null;
127 
128         @Override
inputChanged(Viewer v, Object oldInput, Object newInput)129         public void inputChanged(Viewer v, Object oldInput, Object newInput) {
130             frame = (Frame) newInput;
131         }
132 
133         @Override
dispose()134         public void dispose() {
135         }
136 
137         @Override
getElements(Object parent)138         public Object[] getElements(Object parent) {
139             return frame.get().toArray();
140         }
141 
142         @Override
getText(Object obj)143         public String getText(Object obj) {
144             MessageData msgData = (MessageData) obj;
145             return msgData.text;
146         }
147 
148         @Override
getImage(Object obj)149         public Image getImage(Object obj) {
150             MessageData msgData = (MessageData) obj;
151             return msgData.getImage();
152         }
153 
154         @Override
getColumnText(Object obj, int index)155         public String getColumnText(Object obj, int index) {
156             MessageData msgData = (MessageData) obj;
157             if (index >= msgData.columns.length)
158                 return null;
159             return msgData.columns[index];
160         }
161 
162         @Override
getColumnImage(Object obj, int index)163         public Image getColumnImage(Object obj, int index) {
164             if (index > -1)
165                 return null;
166             MessageData msgData = (MessageData) obj;
167             return msgData.getImage();
168         }
169     }
170 
171     class NameSorter extends ViewerSorter {
172         @Override
compare(Viewer viewer, Object e1, Object e2)173         public int compare(Viewer viewer, Object e1, Object e2) {
174             MessageData m1 = (MessageData) e1;
175             MessageData m2 = (MessageData) e2;
176             return (int) ((m1.msg.getTime() - m2.msg.getTime()) * 100);
177         }
178     }
179 
180     class Filter extends ViewerFilter {
181         @Override
select(Viewer viewer, Object parentElement, Object element)182         public boolean select(Viewer viewer, Object parentElement,
183                 Object element) {
184             MessageData msgData = (MessageData) element;
185             if (null == filters)
186                 return true;
187             for (int i = 0; i < filters.length; i++)
188                 if (msgData.text.contains(filters[i]))
189                     return true;
190             return false;
191         }
192     }
193 
SampleView()194     public SampleView() {
195 
196     }
197 
createLeftPane(Composite parent)198     public void createLeftPane(Composite parent) {
199         Composite composite = new Composite(parent, 0);
200 
201         GridLayout gridLayout = new GridLayout();
202         gridLayout.numColumns = 1;
203         composite.setLayout(gridLayout);
204 
205         frameNum = new Slider(composite, SWT.BORDER | SWT.HORIZONTAL);
206         frameNum.setMinimum(0);
207         frameNum.setMaximum(1);
208         frameNum.setSelection(0);
209         frameNum.addSelectionListener(this);
210 
211         GridData gridData = new GridData();
212         gridData.horizontalAlignment = SWT.FILL;
213         gridData.grabExcessHorizontalSpace = true;
214         gridData.verticalAlignment = SWT.FILL;
215         frameNum.setLayoutData(gridData);
216 
217         // Table table = new Table(composite, SWT.H_SCROLL | SWT.V_SCROLL |
218         // SWT.MULTI
219         // | SWT.FULL_SELECTION);
220         // TableLayout layout = new TableLayout();
221         // table.setLayout(layout);
222         // table.setLinesVisible(true);
223         // table.setHeaderVisible(true);
224         // String[] headings = {
225         // "Name", "Elapsed (ms)", "Detail"
226         // };
227         // int[] weights = {
228         // 50, 16, 60
229         // };
230         // int[] widths = {
231         // 180, 90, 200
232         // };
233         // for (int i = 0; i < headings.length; i++) {
234         // layout.addColumnData(new ColumnWeightData(weights[i], widths[i],
235         // true));
236         // TableColumn nameCol = new TableColumn(table, SWT.NONE, i);
237         // nameCol.setText(headings[i]);
238         // }
239 
240         // viewer = new TableViewer(table);
241         viewer = new ListViewer(composite, SWT.DEFAULT);
242         viewer.getList().setFont(new Font(viewer.getList().getDisplay(),
243                 "Courier", 10, SWT.BOLD));
244         ViewContentProvider contentProvider = new ViewContentProvider();
245         viewer.setContentProvider(contentProvider);
246         viewer.setLabelProvider(contentProvider);
247         // viewer.setSorter(new NameSorter());
248         viewer.setFilters(new ViewerFilter[] {
249                 new Filter()
250         });
251 
252         gridData = new GridData();
253         gridData.horizontalAlignment = SWT.FILL;
254         gridData.grabExcessHorizontalSpace = true;
255         gridData.verticalAlignment = SWT.FILL;
256         gridData.grabExcessVerticalSpace = true;
257         viewer.getControl().setLayoutData(gridData);
258     }
259 
260     /**
261      * This is a callback that will allow us to create the viewer and initialize
262      * it.
263      */
264     @Override
createPartControl(Composite parent)265     public void createPartControl(Composite parent) {
266         createLeftPane(parent);
267 
268         // Create the help context id for the viewer's control
269         PlatformUI.getWorkbench().getHelpSystem()
270                 .setHelp(viewer.getControl(), "GLESv2DebuggerClient.viewer");
271 
272         tabFolder = new TabFolder(parent, SWT.BORDER);
273 
274         text = new Text(tabFolder, SWT.NO_BACKGROUND | SWT.READ_ONLY
275                 | SWT.V_SCROLL | SWT.H_SCROLL);
276 
277         tabItemText = new TabItem(tabFolder, SWT.NONE);
278         tabItemText.setText("Text");
279         tabItemText.setControl(text);
280 
281         canvas = new Canvas(tabFolder, SWT.NO_BACKGROUND | SWT.NO_REDRAW_RESIZE
282                 | SWT.V_SCROLL | SWT.H_SCROLL);
283         tabItemImage = new TabItem(tabFolder, SWT.NONE);
284         tabItemImage.setText("Image");
285         tabItemImage.setControl(canvas);
286 
287         breakpointOption = new BreakpointOption(this, tabFolder);
288         tabItemBreakpointOption = new TabItem(tabFolder, SWT.NONE);
289         tabItemBreakpointOption.setText("Breakpoint Option");
290         tabItemBreakpointOption.setControl(breakpointOption);
291 
292         shaderEditor = new ShaderEditor(this, tabFolder);
293         tabItemShaderEditor = new TabItem(tabFolder, SWT.NONE);
294         tabItemShaderEditor.setText("Shader Editor");
295         tabItemShaderEditor.setControl(shaderEditor);
296 
297         contextViewer = new TreeViewer(tabFolder);
298         ContextViewProvider contextViewProvider = new ContextViewProvider(this);
299         contextViewer.addSelectionChangedListener(contextViewProvider);
300         contextViewer.setContentProvider(contextViewProvider);
301         contextViewer.setLabelProvider(contextViewProvider);
302         tabContextViewer = new TabItem(tabFolder, SWT.NONE);
303         tabContextViewer.setText("Context Viewer");
304         tabContextViewer.setControl(contextViewer.getTree());
305 
306         final ScrollBar hBar = canvas.getHorizontalBar();
307         hBar.addListener(SWT.Selection, new Listener() {
308             @Override
309             public void handleEvent(Event e) {
310                 if (null == canvas.getBackgroundImage())
311                     return;
312                 Image image = canvas.getBackgroundImage();
313                 int hSelection = hBar.getSelection();
314                 int destX = -hSelection - origin.x;
315                 Rectangle rect = image.getBounds();
316                 canvas.scroll(destX, 0, 0, 0, rect.width, rect.height, false);
317                 origin.x = -hSelection;
318             }
319         });
320         final ScrollBar vBar = canvas.getVerticalBar();
321         vBar.addListener(SWT.Selection, new Listener() {
322             @Override
323             public void handleEvent(Event e) {
324                 if (null == canvas.getBackgroundImage())
325                     return;
326                 Image image = canvas.getBackgroundImage();
327                 int vSelection = vBar.getSelection();
328                 int destY = -vSelection - origin.y;
329                 Rectangle rect = image.getBounds();
330                 canvas.scroll(0, destY, 0, 0, rect.width, rect.height, false);
331                 origin.y = -vSelection;
332             }
333         });
334         canvas.addListener(SWT.Resize, new Listener() {
335             @Override
336             public void handleEvent(Event e) {
337                 if (null == canvas.getBackgroundImage())
338                     return;
339                 Image image = canvas.getBackgroundImage();
340                 Rectangle rect = image.getBounds();
341                 Rectangle client = canvas.getClientArea();
342                 hBar.setMaximum(rect.width);
343                 vBar.setMaximum(rect.height);
344                 hBar.setThumb(Math.min(rect.width, client.width));
345                 vBar.setThumb(Math.min(rect.height, client.height));
346                 int hPage = rect.width - client.width;
347                 int vPage = rect.height - client.height;
348                 int hSelection = hBar.getSelection();
349                 int vSelection = vBar.getSelection();
350                 if (hSelection >= hPage) {
351                     if (hPage <= 0)
352                         hSelection = 0;
353                     origin.x = -hSelection;
354                 }
355                 if (vSelection >= vPage) {
356                     if (vPage <= 0)
357                         vSelection = 0;
358                     origin.y = -vSelection;
359                 }
360                 canvas.redraw();
361             }
362         });
363         canvas.addListener(SWT.Paint, new Listener() {
364             @Override
365             public void handleEvent(Event e) {
366                 if (null == canvas.getBackgroundImage())
367                     return;
368                 Image image = canvas.getBackgroundImage();
369                 GC gc = e.gc;
370                 gc.drawImage(image, origin.x, origin.y);
371                 Rectangle rect = image.getBounds();
372                 Rectangle client = canvas.getClientArea();
373                 int marginWidth = client.width - rect.width;
374                 if (marginWidth > 0) {
375                     gc.fillRectangle(rect.width, 0, marginWidth, client.height);
376                 }
377                 int marginHeight = client.height - rect.height;
378                 if (marginHeight > 0) {
379                     gc.fillRectangle(0, rect.height, client.width, marginHeight);
380                 }
381             }
382         });
383 
384         hookContextMenu();
385         hookSelectionChanged();
386         contributeToActionBars();
387 
388         messageQueue = new MessageQueue(this, new ProcessMessage[] {
389                 breakpointOption, shaderEditor
390         });
391     }
392 
hookContextMenu()393     private void hookContextMenu() {
394         MenuManager menuMgr = new MenuManager("#PopupMenu");
395         menuMgr.setRemoveAllWhenShown(true);
396         menuMgr.addMenuListener(new IMenuListener() {
397             @Override
398             public void menuAboutToShow(IMenuManager manager) {
399                 SampleView.this.fillContextMenu(manager);
400             }
401         });
402         Menu menu = menuMgr.createContextMenu(viewer.getControl());
403         viewer.getControl().setMenu(menu);
404         getSite().registerContextMenu(menuMgr, viewer);
405     }
406 
contributeToActionBars()407     private void contributeToActionBars() {
408         IActionBars bars = getViewSite().getActionBars();
409         fillLocalPullDown(bars.getMenuManager());
410         fillLocalToolBar(bars.getToolBarManager());
411     }
412 
fillLocalPullDown(IMenuManager manager)413     private void fillLocalPullDown(IMenuManager manager) {
414         // manager.add(actionConnect);
415         // manager.add(new Separator());
416         // manager.add(actionDisconnect);
417     }
418 
fillContextMenu(IMenuManager manager)419     private void fillContextMenu(IMenuManager manager) {
420         // manager.add(actionConnect);
421         // manager.add(actionDisconnect);
422         // Other plug-ins can contribute there actions here
423         manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
424     }
425 
fillLocalToolBar(final IToolBarManager manager)426     private void fillLocalToolBar(final IToolBarManager manager) {
427         actionConnect = new Action("Connect", Action.AS_PUSH_BUTTON) {
428             @Override
429             public void run() {
430                 if (!running)
431                     changeContext(null); // viewer will switch to newest context
432                 connectDisconnect();
433             }
434         };
435         manager.add(actionConnect);
436 
437         manager.add(new Action("Open File", Action.AS_PUSH_BUTTON)
438         {
439             @Override
440             public void run()
441             {
442                 if (!running)
443                 {
444                     changeContext(null); // viewer will switch to newest context
445                     openFile();
446                 }
447             }
448         });
449 
450         final Shell shell = this.getViewSite().getShell();
451         actionAutoScroll = new Action("Auto Scroll", Action.AS_CHECK_BOX) {
452             @Override
453             public void run() {
454             }
455         };
456         actionAutoScroll.setChecked(true);
457         manager.add(actionAutoScroll);
458 
459         actionFilter = new Action("*", Action.AS_DROP_DOWN_MENU) {
460             @Override
461             public void run() {
462                 org.eclipse.jface.dialogs.InputDialog dialog = new org.eclipse.jface.dialogs.InputDialog(
463                         shell, "Contains Filter",
464                         "case sensitive substring or *",
465                         actionFilter.getText(), null);
466                 if (Window.OK == dialog.open()) {
467                     actionFilter.setText(dialog.getValue());
468                     manager.update(true);
469                     filters = dialog.getValue().split("\\|");
470                     if (filters.length == 1 && filters[0].equals("*"))
471                         filters = null;
472                     viewer.refresh();
473                 }
474 
475             }
476         };
477         manager.add(actionFilter);
478 
479         manager.add(new Action("CaptureDraw", Action.AS_DROP_DOWN_MENU)
480         {
481             @Override
482             public void run()
483             {
484                 int contextId = 0;
485                 if (current != null)
486                     contextId = current.contextId;
487                 InputDialog inputDialog = new InputDialog(shell,
488                         "Capture glDrawArrays/Elements",
489                         "Enter number of glDrawArrays/Elements to glReadPixels for "
490                                 + "context 0x" + Integer.toHexString(contextId) +
491                                 "\n(0x0 is any context)", "9001", null);
492                 if (inputDialog.open() != Window.OK)
493                     return;
494                 Message.Builder builder = Message.newBuilder();
495                 builder.setContextId(contextId);
496                 builder.setType(Type.Response);
497                 builder.setExpectResponse(false);
498                 builder.setFunction(Function.SETPROP);
499                 builder.setProp(Prop.CaptureDraw);
500                 builder.setArg0(Integer.parseInt(inputDialog.getValue()));
501                 messageQueue.addCommand(builder.build());
502             }
503         });
504 
505         manager.add(new Action("CaptureSwap", Action.AS_DROP_DOWN_MENU)
506         {
507             @Override
508             public void run()
509             {
510                 int contextId = 0;
511                 if (current != null)
512                     contextId = current.contextId;
513                 InputDialog inputDialog = new InputDialog(shell,
514                         "Capture eglSwapBuffers",
515                         "Enter number of eglSwapBuffers to glReadPixels for "
516                                 + "context 0x" + Integer.toHexString(contextId) +
517                                 "\n(0x0 is any context)", "9001", null);
518                 if (inputDialog.open() != Window.OK)
519                     return;
520                 Message.Builder builder = Message.newBuilder();
521                 builder.setContextId(contextId);
522                 builder.setType(Type.Response);
523                 builder.setExpectResponse(false);
524                 builder.setFunction(Function.SETPROP);
525                 builder.setProp(Prop.CaptureSwap);
526                 builder.setArg0(Integer.parseInt(inputDialog.getValue()));
527                 messageQueue.addCommand(builder.build());
528             }
529         });
530 
531         manager.add(new Action("SYSTEM_TIME_THREAD", Action.AS_DROP_DOWN_MENU)
532         {
533             @Override
534             public void run()
535             {
536                 final String[] timeModes = {
537                         "SYSTEM_TIME_REALTIME", "SYSTEM_TIME_MONOTONIC", "SYSTEM_TIME_PROCESS",
538                         "SYSTEM_TIME_THREAD"
539                 };
540                 int i = java.util.Arrays.asList(timeModes).indexOf(this.getText());
541                 i = (i + 1) % timeModes.length;
542                 Message.Builder builder = Message.newBuilder();
543                 builder.setContextId(0); // FIXME: proper context id
544                 builder.setType(Type.Response);
545                 builder.setExpectResponse(false);
546                 builder.setFunction(Message.Function.SETPROP);
547                 builder.setProp(Prop.TimeMode);
548                 builder.setArg0(i);
549                 messageQueue.addCommand(builder.build());
550                 this.setText(timeModes[i]);
551                 manager.update(true);
552             }
553         });
554 
555         actContext = new Action("Context: 0x", Action.AS_DROP_DOWN_MENU) {
556             @Override
557             public void run() {
558                 if (debugContexts.size() < 2)
559                     return;
560                 final String idStr = this.getText().substring(
561                                           "Context: 0x".length());
562                 if (idStr.length() == 0)
563                     return;
564                 final int contextId = Integer.parseInt(idStr, 16);
565                 int index = debugContexts.indexOfKey(contextId);
566                 index = (index + 1) % debugContexts.size();
567                 changeContext(debugContexts.valueAt(index));
568             }
569         };
570         manager.add(actContext);
571 
572         actionPort = new Action("5039", Action.AS_DROP_DOWN_MENU)
573         {
574             @Override
575             public void run() {
576                 InputDialog dialog = new InputDialog(shell, "Port", "Debugger port",
577                         actionPort.getText(), null);
578                 if (Window.OK == dialog.open()) {
579                     actionPort.setText(dialog.getValue());
580                     manager.update(true);
581                 }
582             }
583         };
584         manager.add(actionPort);
585 
586         manager.add(new Action("CodeGen Frame", Action.AS_PUSH_BUTTON)
587         {
588             @Override
589             public void run()
590             {
591                 if (current != null)
592                 {
593                     new CodeGen().codeGenFrame((Frame) viewer.getInput());
594                     // need to reload current frame
595                     viewer.setInput(current.getFrame(frameNum.getSelection()));
596                 }
597             }
598         });
599 
600         manager.add(new Action("CodeGen Frames", Action.AS_PUSH_BUTTON)
601         {
602             @Override
603             public void run()
604             {
605                 if (current != null)
606                 {
607                     new CodeGen().codeGenFrames(current, frameNum.getSelection() + 1,
608                             getSite().getShell());
609                     // need to reload current frame
610                     viewer.setInput(current.getFrame(frameNum.getSelection()));
611                 }
612             }
613         });
614     }
615 
openFile()616     private void openFile() {
617         FileDialog dialog = new FileDialog(getSite().getShell(), SWT.OPEN);
618         dialog.setText("Open");
619         dialog.setFilterExtensions(new String[] {
620                 "*.gles2dbg"
621         });
622         String filePath = dialog.open();
623         if (filePath == null)
624             return;
625         FileInputStream file = null;
626         try {
627             file = new FileInputStream(filePath);
628         } catch (FileNotFoundException e) {
629             e.printStackTrace();
630             return;
631         }
632         running = true;
633         messageQueue.start(targetByteOrder, file);
634         thread = new Thread(this);
635         thread.start();
636         actionConnect.setText("Disconnect");
637         getViewSite().getActionBars().getToolBarManager().update(true);
638     }
639 
connectDisconnect()640     private void connectDisconnect() {
641         if (!running) {
642             running = true;
643             messageQueue.start(targetByteOrder, null);
644             thread = new Thread(this);
645             thread.start();
646             actionConnect.setText("Disconnect");
647         } else {
648             running = false;
649             messageQueue.stop();
650             actionConnect.setText("Connect");
651         }
652         this.getSite().getShell().getDisplay().syncExec(new Runnable() {
653             @Override
654             public void run() {
655                 getViewSite().getActionBars().getToolBarManager().update(true);
656             }
657         });
658     }
659 
messageDataSelected(final MessageData msgData)660     void messageDataSelected(final MessageData msgData) {
661         if (null == msgData)
662             return;
663         if (frameNum.getSelection() == frameNum.getMaximum())
664             return; // scale max cannot overlap min, so max is array size
665         final Frame frame = current.getFrame(frameNum.getSelection());
666         final Context context = frame.computeContext(msgData);
667         contextViewer.setInput(context);
668         if (msgData.getImage() != null) {
669             canvas.setBackgroundImage(msgData.getImage());
670             tabFolder.setSelection(tabItemImage);
671             canvas.redraw();
672         } else if (null != msgData.shader) {
673             text.setText(msgData.shader);
674             tabFolder.setSelection(tabItemText);
675         } else if (null != msgData.attribs) {
676             StringBuilder builder = new StringBuilder();
677             final int maxAttrib = msgData.msg.getArg7();
678             for (int i = 0; i < msgData.attribs[0].length / 4; i++) {
679                 if (msgData.indices != null) {
680                     builder.append(msgData.indices[i] & 0xffff);
681                     builder.append(": ");
682                 }
683                 for (int j = 0; j < maxAttrib; j++) {
684                     for (int k = 0; k < 4; k++)
685                         builder.append(String.format("%.3g ", msgData.attribs[j][i * 4 + k]));
686                     if (j < maxAttrib - 1)
687                         builder.append("|| ");
688                 }
689                 builder.append('\n');
690             }
691             text.setText(builder.toString());
692             tabFolder.setSelection(tabItemText);
693         }
694     }
695 
hookSelectionChanged()696     private void hookSelectionChanged() {
697         viewer.addSelectionChangedListener(new ISelectionChangedListener() {
698             @Override
699             public void selectionChanged(SelectionChangedEvent event) {
700                 StructuredSelection selection = (StructuredSelection) event
701                         .getSelection();
702                 if (null == selection)
703                     return;
704                 MessageData msgData = (MessageData) selection.getFirstElement();
705                 messageDataSelected(msgData);
706             }
707         });
708     }
709 
showError(final Exception e)710     public void showError(final Exception e) {
711         viewer.getControl().getDisplay().syncExec(new Runnable() {
712             @Override
713             public void run() {
714                 MessageDialog.openError(viewer.getControl().getShell(),
715                         "GL ES 2.0 Debugger Client", e.getMessage());
716             }
717         });
718     }
719 
720     /**
721      * Passing the focus request to the viewer's control.
722      */
723     @Override
setFocus()724     public void setFocus() {
725         viewer.getControl().setFocus();
726     }
727 
728     @Override
run()729     public void run() {
730         int newMessages = 0;
731 
732         boolean shaderEditorUpdate = false;
733         while (running) {
734             final Message oriMsg = messageQueue.removeCompleteMessage(0);
735             if (oriMsg == null && !messageQueue.isRunning())
736                 break;
737             if (newMessages > 60 || (newMessages > 0 && null == oriMsg)) {
738                 newMessages = 0;
739                 if (current != null && current.uiUpdate)
740                     getSite().getShell().getDisplay().syncExec(new Runnable() {
741                         @Override
742                         public void run() {
743                             if (frameNum.getSelection() == current.frameCount() - 1 ||
744                                     frameNum.getSelection() == current.frameCount() - 2)
745                             {
746                                 viewer.refresh(false);
747                                 if (actionAutoScroll.isChecked())
748                                     viewer.getList().setSelection(
749                                             viewer.getList().getItemCount() - 1);
750                             }
751                             frameNum.setMaximum(current.frameCount());
752                         }
753                     });
754                 current.uiUpdate = false;
755 
756                 if (shaderEditorUpdate)
757                     this.getSite().getShell().getDisplay().syncExec(new Runnable() {
758                         @Override
759                         public void run() {
760                             shaderEditor.updateUI();
761                         }
762                     });
763                 shaderEditorUpdate = false;
764             }
765             if (null == oriMsg) {
766                 try {
767                     Thread.sleep(1);
768                     continue;
769                 } catch (InterruptedException e) {
770                     showError(e);
771                 }
772             }
773             DebugContext debugContext = debugContexts.get(oriMsg.getContextId());
774             if (debugContext == null) {
775                 debugContext = new DebugContext(oriMsg.getContextId());
776                 debugContexts.put(oriMsg.getContextId(), debugContext);
777             }
778             debugContext.processMessage(oriMsg);
779             shaderEditorUpdate |= debugContext.currentContext.serverShader.uiUpdate;
780             debugContext.currentContext.serverShader.uiUpdate = false;
781             if (current == null && debugContext.frameCount() > 0)
782                 changeContext(debugContext);
783             newMessages++;
784         }
785         if (running)
786             connectDisconnect(); // error occurred, disconnect
787     }
788 
789     /** can be called from non-UI thread */
changeContext(final DebugContext newContext)790     void changeContext(final DebugContext newContext) {
791         getSite().getShell().getDisplay().syncExec(new Runnable() {
792             @Override
793             public void run() {
794                 current = newContext;
795                 if (current != null)
796                 {
797                     frameNum.setMaximum(current.frameCount());
798                     if (frameNum.getSelection() >= current.frameCount())
799                         if (current.frameCount() > 0)
800                             frameNum.setSelection(current.frameCount() - 1);
801                         else
802                             frameNum.setSelection(0);
803                     viewer.setInput(current.getFrame(frameNum.getSelection()));
804                     actContext.setText("Context: 0x" + Integer.toHexString(current.contextId));
805                 }
806                 else
807                 {
808                     frameNum.setMaximum(1); // cannot overlap min
809                     frameNum.setSelection(0);
810                     viewer.setInput(null);
811                     actContext.setText("Context: 0x");
812                 }
813                 shaderEditor.updateUI();
814                 getViewSite().getActionBars().getToolBarManager().update(true);
815             }
816         });
817     }
818 
819     @Override
widgetSelected(SelectionEvent e)820     public void widgetSelected(SelectionEvent e) {
821         if (e.widget != frameNum)
822             assert false;
823         if (current == null)
824             return;
825         if (frameNum.getSelection() == current.frameCount())
826             return; // scale maximum cannot overlap minimum
827         Frame frame = current.getFrame(frameNum.getSelection());
828         viewer.setInput(frame);
829     }
830 
831     @Override
widgetDefaultSelected(SelectionEvent e)832     public void widgetDefaultSelected(SelectionEvent e) {
833         widgetSelected(e);
834     }
835 }
836