aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/editors/GLCallGroups.java
diff options
context:
space:
mode:
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/editors/GLCallGroups.java')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/editors/GLCallGroups.java202
1 files changed, 202 insertions, 0 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/editors/GLCallGroups.java b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/editors/GLCallGroups.java
new file mode 100644
index 000000000..226d4831a
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/editors/GLCallGroups.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2012 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.editors;
+
+import com.android.ide.eclipse.gltrace.GLProtoBuf.GLMessage.Function;
+import com.android.ide.eclipse.gltrace.model.GLCall;
+import com.android.ide.eclipse.gltrace.model.GLTrace;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Stack;
+
+public class GLCallGroups {
+ /**
+ * A {@link GLCallNode} is a simple wrapper around a {@link GLCall} that
+ * adds the notion of hierarchy.
+ */
+ public interface GLCallNode {
+ /** Does this call have child nodes? */
+ boolean hasChildren();
+
+ /** Returns a list of child nodes of this call. */
+ List<GLCallNode> getChildren();
+
+ /** Returns the {@link GLCall} that is wrapped by this node. */
+ GLCall getCall();
+
+ /** Returns the parent of this node, the parent is null if this is a top level node */
+ GLCallNode getParent();
+
+ /** Set the parent node. */
+ void setParent(GLCallNode parent);
+ }
+
+ private static class GLTreeNode implements GLCallNode {
+ private final GLCall mCall;
+ private GLCallNode mParent;
+ private List<GLCallNode> mGLCallNodes;
+
+ public GLTreeNode(GLCall call) {
+ mCall = call;
+ mGLCallNodes = new ArrayList<GLCallNode>();
+ }
+
+ @Override
+ public boolean hasChildren() {
+ return true;
+ }
+
+ @Override
+ public GLCallNode getParent() {
+ return mParent;
+ }
+
+ @Override
+ public void setParent(GLCallNode parent) {
+ mParent = parent;
+ }
+
+ @Override
+ public List<GLCallNode> getChildren() {
+ return mGLCallNodes;
+ }
+
+ public void addChild(GLCallNode n) {
+ mGLCallNodes.add(n);
+ n.setParent(this);
+ }
+
+ @Override
+ public GLCall getCall() {
+ return mCall;
+ }
+ }
+
+ private static class GLLeafNode implements GLCallNode {
+ private final GLCall mCall;
+ private GLCallNode mParent;
+
+ public GLLeafNode(GLCall call) {
+ mCall = call;
+ }
+
+ @Override
+ public boolean hasChildren() {
+ return false;
+ }
+
+ @Override
+ public List<GLCallNode> getChildren() {
+ return null;
+ }
+
+ @Override
+ public GLCallNode getParent() {
+ return mParent;
+ }
+
+ @Override
+ public void setParent(GLCallNode parent) {
+ mParent = parent;
+ }
+
+ @Override
+ public GLCall getCall() {
+ return mCall;
+ }
+ }
+
+ /**
+ * Impose a hierarchy on a list of {@link GLCall}'s based on the presence of
+ * {@link Function#glPushGroupMarkerEXT} and {@link Function#glPopGroupMarkerEXT} calls.
+ * Such a hierarchy is possible only if calls from a single context are considered.
+ * @param trace trace to look at
+ * @param start starting call index
+ * @param end ending call index
+ * @param contextToGroup context from which calls should be grouped. If no such context
+ * is present, then all calls in the given range will be returned back as a flat
+ * list.
+ * @return a tree structured list of {@link GLCallNode} objects
+ */
+ public static List<GLCallNode> constructCallHierarchy(GLTrace trace, int start, int end,
+ int contextToGroup) {
+ if (trace == null) {
+ return Collections.emptyList();
+ }
+
+ if (contextToGroup < 0 || contextToGroup > trace.getContexts().size()) {
+ return flatHierarchy(trace, start, end);
+ }
+
+ List<GLCall> calls = trace.getGLCalls();
+
+ Stack<GLTreeNode> hierarchyStack = new Stack<GLTreeNode>();
+ List<GLCallNode> items = new ArrayList<GLCallNode>();
+
+ for (int i = start; i < end; i++) {
+ GLCall c = calls.get(i);
+ if (c.getContextId() != contextToGroup) {
+ // skip this call if it is not part of the context we need to display
+ continue;
+ }
+
+ if (c.getFunction() == Function.glPushGroupMarkerEXT) {
+ GLTreeNode group = new GLTreeNode(c);
+ if (hierarchyStack.size() > 0) {
+ hierarchyStack.peek().addChild(group);
+ } else {
+ items.add(group);
+ }
+ hierarchyStack.push(group);
+ } else if (c.getFunction() == Function.glPopGroupMarkerEXT) {
+ if (hierarchyStack.size() > 0) {
+ hierarchyStack.pop();
+ } else {
+ // FIXME: If we are attempting to pop from an empty stack,
+ // that implies that a push marker was seen in a prior frame
+ // (in a call before @start). In such a case, we simply continue
+ // adding further calls to the root of the hierarchy rather than
+ // searching backwards in the call list for the corresponding
+ // push markers.
+ items.add(new GLLeafNode(c));
+ }
+ } else {
+ GLLeafNode leaf = new GLLeafNode(c);
+ if (hierarchyStack.size() > 0) {
+ hierarchyStack.peek().addChild(leaf);
+ } else {
+ items.add(leaf);
+ }
+ }
+ }
+
+ return items;
+ }
+
+ private static List<GLCallNode> flatHierarchy(GLTrace trace, int start, int end) {
+ List<GLCallNode> items = new ArrayList<GLCallNode>();
+
+ List<GLCall> calls = trace.getGLCalls();
+ for (int i = start; i < end; i++) {
+ items.add(new GLLeafNode(calls.get(i)));
+ }
+
+ return items;
+ }
+}