diff options
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/format/GLMessageFormatter.java')
-rw-r--r-- | eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/format/GLMessageFormatter.java | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/format/GLMessageFormatter.java b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/format/GLMessageFormatter.java new file mode 100644 index 000000000..6c34005ac --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/format/GLMessageFormatter.java @@ -0,0 +1,166 @@ +/* + * 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.format; + +import com.android.ide.eclipse.gltrace.GLEnum; +import com.android.ide.eclipse.gltrace.GLProtoBuf.GLMessage; +import com.android.ide.eclipse.gltrace.GLProtoBuf.GLMessage.DataType; +import com.android.ide.eclipse.gltrace.GLProtoBuf.GLMessage.DataType.Type; + +import java.util.List; +import java.util.Map; + +/** + * GLMessageFormatter is used to format and create a string representation for a {@link GLMessage}. + * It is provided with a specification for all GL Functions. Using this information, each + * GLMessage is parsed and formatted appropriately for display. + */ +public class GLMessageFormatter { + private static final String GL_NO_ERROR = "GL_NO_ERROR"; + private Map<String, GLAPISpec> mAPISpecs; + private enum DataTypeContext { CONTEXT_ARGUMENT, CONTEXT_RETURNVALUE }; + + public GLMessageFormatter(Map<String, GLAPISpec> specs) { + mAPISpecs = specs; + } + + public String formatGLMessage(GLMessage glMessage) { + GLAPISpec apiSpec = mAPISpecs.get(glMessage.getFunction().toString()); + if (apiSpec == null) { + return glMessage.getFunction().toString(); + } + + return formatCall(apiSpec, glMessage) + formatReturnValue(apiSpec, glMessage); + } + + private String formatReturnValue(GLAPISpec apiSpec, GLMessage glMessage) { + if (apiSpec.getReturnValue().getDataType() == Type.VOID) { + return ""; + } + + GLDataTypeSpec returnSpec = apiSpec.getReturnValue(); + return String.format(" = (%s) %s", returnSpec.getCType(), //$NON-NLS-1$ + formatDataValue(glMessage.getReturnValue(), + returnSpec, + DataTypeContext.CONTEXT_RETURNVALUE)); + } + + private String formatCall(GLAPISpec apiSpec, GLMessage glMessage) { + return String.format("%s(%s)", apiSpec.getFunction(), //$NON-NLS-1$ + formatArgs(glMessage, apiSpec.getArgs())); + } + + private String formatArgs(GLMessage glMessage, List<GLDataTypeSpec> argSpecs) { + int sizeEstimate = 10 + argSpecs.size() * 5; + StringBuilder sb = new StringBuilder(sizeEstimate); + + for (int i = 0; i < argSpecs.size(); i++) { + GLDataTypeSpec argSpec = argSpecs.get(i); + + if (argSpec.getDataType() == Type.VOID && !argSpec.isPointer()) { + sb.append("void"); //$NON-NLS-1$ + } else { + sb.append(argSpec.getArgName()); + sb.append(" = "); //$NON-NLS-1$ + sb.append(formatDataValue(glMessage.getArgs(i), + argSpec, + DataTypeContext.CONTEXT_ARGUMENT)); + } + + if (i < argSpecs.size() - 1) { + sb.append(", "); //$NON-NLS-1$ + } + } + + return sb.toString(); + } + + private String formatDataValue(DataType var, GLDataTypeSpec typeSpec, DataTypeContext context) { + if (typeSpec.isPointer()) { + return formatPointer(var, typeSpec.getDataType()); + } + + switch (typeSpec.getDataType()) { + case VOID: + return ""; + case BOOL: + return Boolean.toString(var.getBoolValue(0)); + case FLOAT: + return String.format("%f", var.getFloatValue(0)); //$NON-NLS-1$ + case INT: + return Integer.toString(var.getIntValue(0)); + case ENUM: + if (var.getIntValue(0) == 0 && context == DataTypeContext.CONTEXT_RETURNVALUE) { + return GL_NO_ERROR; + } else { + return GLEnum.valueOf(var.getIntValue(0)).toString(); + } + default: + return "(unknown type)"; //$NON-NLS-1$ + } + } + + private String formatPointer(DataType var, Type typeSpec) { + if (var.getType() != typeSpec && !isEnumTypeWithIntData(var, typeSpec)) { + // the type of the data in the message does not match expected specification. + // in such a case, just print the data as a pointer and don't try to interpret it. + if (var.getIntValueCount() > 0) { + return String.format("0x%x", var.getIntValue(0)); //$NON-NLS-1$ + } else { + return "0x??"; //$NON-NLS-1$ + } + } + + // Display as array if possible + switch (typeSpec) { + case BOOL: + return var.getBoolValueList().toString(); + case FLOAT: + return var.getFloatValueList().toString(); + case INT: + return var.getIntValueList().toString(); + case CHAR: + return var.getCharValueList().get(0).toStringUtf8(); + case ENUM: + List<Integer> vals = var.getIntValueList(); + StringBuilder sb = new StringBuilder(vals.size() * 5); + sb.append('['); + for (Integer v: vals) { + sb.append(GLEnum.valueOf(v.intValue())); + } + sb.append(']'); + return sb.toString(); + case VOID: + if (var.getRawBytesList().size() > 0) { + return String.format("[ %d bytes ]", var.getRawBytesList().get(0).size()); //$NON-NLS-1$ + } + return "[]"; //$NON-NLS-1$ + } + + // We have a pointer, but we don't have the data pointed to. + // Just format and return the pointer (points to device memory) + if (var.getIntValue(0) == 0) { + return "NULL"; //$NON-NLS-1$ + } else { + return String.format("0x%x", var.getIntValue(0)); //$NON-NLS-1$ + } + } + + private boolean isEnumTypeWithIntData(DataType var, Type typeSpec) { + return var.getType() == Type.INT && typeSpec == Type.ENUM; + } +} |