Bläddra i källkod

GLTracer: generate syntax highlighting and easier to read output

Kirill Vainer 10 år sedan
förälder
incheckning
e9245a753b
1 ändrade filer med 281 tillägg och 77 borttagningar
  1. 281 77
      jme3-core/src/main/java/com/jme3/renderer/opengl/GLTracer.java

+ 281 - 77
jme3-core/src/main/java/com/jme3/renderer/opengl/GLTracer.java

@@ -36,8 +36,14 @@ import java.lang.reflect.Field;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.DoubleBuffer;
+import java.nio.FloatBuffer;
 import java.nio.IntBuffer;
+import java.nio.LongBuffer;
+import java.nio.ShortBuffer;
 import java.util.HashMap;
 
 /**
@@ -51,6 +57,17 @@ public final class GLTracer implements InvocationHandler {
     private final IntMap<String> constMap;
     private static final HashMap<String, IntMap<Void>> nonEnumArgMap = new HashMap<String, IntMap<Void>>();
     
+    private static final String ANSI_RESET = "\u001B[0m";
+    private static final String ANSI_BRIGHT = "\u001B[1m";
+    private static final String ANSI_BLACK = "\u001B[30m";
+    private static final String ANSI_RED = "\u001B[31m";
+    private static final String ANSI_GREEN = "\u001B[32m";
+    private static final String ANSI_YELLOW = "\u001B[33m";
+    private static final String ANSI_BLUE = "\u001B[34m";
+    private static final String ANSI_MAGENTA = "\u001B[35m";
+    private static final String ANSI_CYAN = "\u001B[36m";
+    private static final String ANSI_WHITE = "\u001B[37m";
+
     private static void noEnumArgs(String method, int... argSlots) {
         IntMap<Void> argSlotsMap = new IntMap<Void>();
         for (int argSlot : argSlots) {
@@ -174,100 +191,287 @@ public final class GLTracer implements InvocationHandler {
                                       new GLTracer(glInterface, constMap));
     }
     
-    private String translateInteger(String method, int value, int argIndex) {
-        IntMap<Void> argSlotMap = nonEnumArgMap.get(method);
-        if (argSlotMap != null && argSlotMap.containsKey(argIndex)) {
-            return Integer.toString(value);
-        }
+    private void printStyle(String style, String string) {
+        System.out.print(style + string + ANSI_RESET);
+    }
+    
+    private void print(String string) {
+        System.out.print(string);
+    }
+    
+    private void printInt(int value) {
+        print(Integer.toString(value));
+    }
+    
+    private void printEnum(int value) {
         String enumName = constMap.get(value);
         if (enumName != null) {
-            return enumName;
+            if (enumName.startsWith("GL_")) {
+                enumName = enumName.substring(3);
+            }
+            if (enumName.endsWith("_EXT") || enumName.endsWith("_ARB")) {
+                enumName = enumName.substring(0, enumName.length() - 4);
+            }
+            printStyle(ANSI_GREEN, enumName);
+        } else {
+            printStyle(ANSI_GREEN, "ENUM_" + Integer.toHexString(value));
+        }
+    }
+    
+    private void printIntOrEnum(String method, int value, int argIndex) {
+        IntMap<Void> argSlotMap = nonEnumArgMap.get(method);
+        if (argSlotMap != null && argSlotMap.containsKey(argIndex)) {
+            printInt(value);
         } else {
-            return "GL_ENUM_" + Integer.toHexString(value);
-            //throw new IllegalStateException("Untranslatable enum encountered on " + method + 
-            //                                " at argument " + argIndex + " with value " + value);
+            printEnum(value);
         }
     }
     
-    private String translateString(String value) {
-        return "\"" + value.replaceAll("\0", "\\\\0") + "\"";
+    private void printNewLine() {
+        System.out.println();
     }
     
-    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
-        Object result = method.invoke(obj, args);
-        String methodName = method.getName();
+    private void printString(String value) {
+        if (value.length() > 150) {
+            value = value.substring(0, 150) + "...";
+        }
+        StringBuilder sb = new StringBuilder();
+        sb.append(ANSI_YELLOW);
+        sb.append("\"");
+        sb.append(ANSI_RESET);
+        for (String line : value.split("\n")) {
+            sb.append(ANSI_YELLOW);
+            sb.append(line.replaceAll("\0", "\\\\0"));
+            sb.append(ANSI_RESET);
+            sb.append("\n");
+        }
+        if (sb.length() > 1 && sb.charAt(sb.length() - 1) == '\n') {
+            sb.setLength(sb.length() - 1);
+        }
+        sb.append(ANSI_YELLOW);
+        sb.append("\"");
+        sb.append(ANSI_RESET);
+        print(sb.toString());
+    }
+    
+    private void printBoolean(boolean bool) {
+        printStyle(ANSI_BLUE, bool ? "true" : "false");
+    }
+    
+    private void printBuffer(Buffer buffer) {
+        StringBuilder sb = new StringBuilder();
+        sb.append(ANSI_MAGENTA);
+        if (buffer instanceof ByteBuffer) {
+            sb.append("byte");
+        } else if (buffer instanceof ShortBuffer) {
+            sb.append("short");
+        } else if (buffer instanceof CharBuffer) { 
+            sb.append("char");
+        } else if (buffer instanceof FloatBuffer) {
+            sb.append("float");
+        } else if (buffer instanceof IntBuffer) {
+            sb.append("int");
+        } else if (buffer instanceof LongBuffer) {
+            sb.append("long");
+        } else if (buffer instanceof DoubleBuffer) {
+            sb.append("double");
+        } else {
+            throw new UnsupportedOperationException();
+        }
+        sb.append(ANSI_RESET);
+        sb.append("[");
+        
+        if (buffer.position() == 0
+                && buffer.limit() == buffer.capacity()) {
+            // Common case. Just print buffer size.
+            sb.append(buffer.capacity());
+        } else {
+            sb.append("pos=").append(buffer.position());
+            sb.append(" lim=").append(buffer.limit());
+            sb.append(" cap=").append(buffer.capacity());
+        }
+        
+        sb.append("]");
+        print(sb.toString());
+    }
+    
+    private void printMethodName(String methodName) {
         if (methodName.startsWith("gl")) {
-            System.out.print(methodName);
-            System.out.print("(");
-            if (args != null) {
-                Class<?>[] paramTypes = method.getParameterTypes();
-                for (int i = 0; i < args.length; i++) {
-                    if (paramTypes[i] == int.class) {
-                        int val = (Integer)args[i];
-                        System.out.print(translateInteger(methodName, val, i));
-                    } else if (paramTypes[i] == String.class) {
-                        System.out.print(translateString((String)args[i]));
-                    } else if (paramTypes[i] == String[].class) {
-                        String[] arr = (String[]) args[i];
-                        if (arr.length == 1) {
-                            if (arr[0].length() > 150) {
-                                System.out.print("\"" + arr[0].substring(0, 150) + "...\"");
-                            } else {
-                                System.out.print("\"" + arr[0] + "\"");
-                            }
-                        } else {
-                            System.out.print("String[" + arr.length + "]");
-                        }
-                    } else if (args[i] instanceof IntBuffer) {
-                        IntBuffer buf = (IntBuffer) args[i];
-                        if (buf.capacity() == 16) {
-                            int val = buf.get(0);
-                            System.out.print("out=" + translateInteger(methodName, val, i));
-                        } else if (buf.capacity() == 1) {
-                            System.out.print("out=" + buf.get(0));
-                        } else {
-                            System.out.print(args[i]);
-                        }
-                    } else if (args[i] instanceof ByteBuffer) {
-                        ByteBuffer bb = (ByteBuffer)args[i];
-                        if (bb.capacity() == 250) {
-                            if (bb.get(0) != 0) {
-                                System.out.print("out=GL_TRUE");
-                            } else {
-                                System.out.print("out=GL_FALSE");
-                            }
-                        } else {
-                            System.out.print(args[i]);
-                        }
-                    } else {
-                        System.out.print(args[i]);
-                    }
-
-                    if (i != args.length - 1) {
-                        System.out.print(", ");
-                    }
+            // GL calls which actually draw (as opposed to change state)
+            // will be printed in darker color
+            methodName = methodName.substring(2);
+            if (methodName.equals("Clear")
+                    || methodName.equals("DrawRangeElements")) {
+                print(methodName);
+            } else {
+                if (methodName.endsWith("EXT")) {
+                    methodName = methodName.substring(0, methodName.length() - 3);
                 }
+                printStyle(ANSI_BRIGHT, methodName);
             }
+        } else if (methodName.equals("resetStats")) {
+            printStyle(ANSI_RED, "-- frame boundary --");
+        }
+    }
+    
+    private void printArgsClear(int mask) {
+        boolean needAPipe = false;
+        print("(");
+        if ((mask & GL.GL_COLOR_BUFFER_BIT) != 0) {
+            printStyle(ANSI_GREEN, "COLOR_BUFFER_BIT");
+            needAPipe = true;
+        }
+        if ((mask & GL.GL_DEPTH_BUFFER_BIT) != 0) {
+            if (needAPipe) {
+                print(" | ");
+            }
+            printStyle(ANSI_GREEN, "DEPTH_BUFFER_BIT");
+        }
+        if ((mask & GL.GL_STENCIL_BUFFER_BIT) != 0) {
+            if (needAPipe) {
+                print(" | ");
+            }
+            printStyle(ANSI_GREEN, "STENCIL_BUFFER_BIT");
+        }
+        print(")");
+    }
+    
+    private void printArgsTexParameter(Object[] args) {
+        print("(");
 
-            System.out.print(")");
+        int target = (Integer) args[0];
+        int param = (Integer) args[1];
+        int value = (Integer) args[2];
 
-            if (method.getReturnType() != void.class) {
-                if (result instanceof String) {
-                    System.out.println(" = " + translateString((String)result));
-                } else if (method.getReturnType() == int.class) {
-                    int val = (Integer)result;
-                    System.out.println(" = " + translateInteger(methodName, val, -1));
-                } else if (method.getReturnType() == boolean.class) {
-                    boolean val = (Boolean)result;
-                    if (val) System.out.println(" = GL_TRUE");
-                    else System.out.println(" = GL_FALSE");
+        printEnum(target);
+        print(", ");
+        printEnum(param);
+        print(", ");
+        
+        if (param == GL.GL_TEXTURE_BASE_LEVEL
+                || param == GL.GL_TEXTURE_MAX_LEVEL) {
+            printInt(value);
+        } else {
+            printEnum(value);
+        }
+        
+        print(")");
+    }
+    
+    private void printOut() {
+        printStyle(ANSI_CYAN, "out=");
+    }
+    
+    private void printResult(String methodName, Object result, Class<?> returnType) {
+        if (returnType != void.class) {
+            print(" = ");
+            if (result instanceof String) {
+                printString((String) result);
+            } else if (returnType == int.class) {
+                int val = (Integer) result;
+                printIntOrEnum(methodName, val, -1);
+            } else if (returnType == boolean.class) {
+                printBoolean((Boolean)result);
+            } else {
+                print(" = ???");
+            }
+        }
+    }
+    
+    private void printNull() {
+        printStyle(ANSI_BLUE, "null");
+    }
+    
+    private void printArgs(String methodName, Object[] args, Class<?>[] paramTypes) {
+        if (methodName.equals("glClear")) {
+            printArgsClear((Integer)args[0]);
+            return;
+        } else if (methodName.equals("glTexParameteri")) {
+            printArgsTexParameter(args);
+            return;
+        }
+        
+        if (args == null) {
+            print("()");
+            return;
+        }
+        
+        print("(");
+        for (int i = 0; i < args.length; i++) {
+            if (paramTypes[i] == int.class) {
+                int val = (Integer)args[i];
+                printIntOrEnum(methodName, val, i);
+            } else if (paramTypes[i] == boolean.class) {
+                printBoolean((Boolean)args[i]);
+            } else if (paramTypes[i] == String.class) {
+                printString((String)args[i]);
+            } else if (paramTypes[i] == String[].class) {
+                String[] arr = (String[]) args[i];
+                if (arr.length == 1) {
+                    printString(arr[0]);
                 } else {
-                    System.out.println(" = ???");
+                    print("string[" + arr.length + "]");
                 }
+            } else if (args[i] instanceof IntBuffer) {
+                IntBuffer buf = (IntBuffer) args[i];
+                if (buf.capacity() == 16) {
+                    int val = buf.get(0);
+                    printOut();
+                    printIntOrEnum(methodName, val, i);
+                } else if (buf.capacity() == 1) {
+                    printOut();
+                    print(Integer.toString(buf.get(0)));
+                } else {
+                    printBuffer(buf);
+                }
+            } else if (args[i] instanceof ByteBuffer) {
+                ByteBuffer bb = (ByteBuffer)args[i];
+                if (bb.capacity() == 250) {
+                    printOut();
+                    printBoolean(bb.get(0) != 0);
+                } else {
+                    printBuffer(bb);
+                }
+            } else if (args[i] instanceof Buffer) {
+                printBuffer((Buffer)args[i]);
+            } else if (args[i] != null) {
+                print(args[i].toString());
             } else {
-                System.out.println();
+                printNull();
+            }
+
+            if (i != args.length - 1) {
+                System.out.print(", ");
+            }
+        }
+        print(")");
+    }
+    
+    @Override
+    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+        String methodName = method.getName();
+        printMethodName(methodName);
+        
+        if (methodName.startsWith("gl")) {
+            try {
+                // Try to evaluate result first, so we can see output values.
+                Object result = method.invoke(obj, args);
+                printArgs(methodName, args, method.getParameterTypes());
+                printResult(methodName, result, method.getReturnType());
+                printNewLine();
+                return result;
+            } catch (Throwable ex) {
+                // Execution failed, print args anyway
+                // but output values will be incorrect.
+                printArgs(methodName, args, method.getParameterTypes());
+                printNewLine();
+                System.out.println("\tException occurred!");
+                System.out.println(ex.toString());
+                throw ex;
             }
+        } else {
+            printNewLine();
+            return method.invoke(obj, args);
         }
-        return result;
     }
 }