From a130006227e9d66b9b7112c98970935275bcc1ea Mon Sep 17 00:00:00 2001 From: David Li Date: Fri, 22 Apr 2011 18:18:30 -0700 Subject: [PATCH] GLES2Dbg: more tests and minor fixes/improvements Change-Id: I55c360372623c019da0c1ba2eebbc68f73f0f211 Signed-off-by: David Li --- tools/glesv2debugger/README.android | 20 +++ .../generate_MessageParser_java.py | 30 +++-- tools/glesv2debugger/setup.sh | 35 ++++++ .../com/android/glesv2debugger/Context.java | 9 +- .../glesv2debugger/GLServerTexture.java | 3 +- .../glesv2debugger/GLServerVertex.java | 2 + .../android/glesv2debugger/MessageParser.java | 32 +++-- .../android/glesv2debugger/SampleView.java | 7 +- .../android/glesv2debugger/ShaderEditor.java | 68 ++++++----- .../glesv2debugger/MessageParserExTest.java | 115 ++++++++++++++++++ 10 files changed, 253 insertions(+), 68 deletions(-) create mode 100644 tools/glesv2debugger/README.android create mode 100755 tools/glesv2debugger/setup.sh create mode 100644 tools/glesv2debugger/test/com/android/glesv2debugger/MessageParserExTest.java diff --git a/tools/glesv2debugger/README.android b/tools/glesv2debugger/README.android new file mode 100644 index 000000000..ae954630f --- /dev/null +++ b/tools/glesv2debugger/README.android @@ -0,0 +1,20 @@ +The following is taken from slide 3 & 4 of https://docs.google.com/a/google.com/present/edit?id=0AcZLV3icFYi0ZGZxa3NqZndfMGRqa2tiOXB4&authkey=CMfb8ukI&hl=en +The spec doc is at https://docs.google.com/a/google.com/document/d/1dsASXCF9Suq8KOGcxwB2mAwgdRlrFj4QhMxkfaRJlA0/edit?hl=en&authkey=CPj4tKkO# + + +Building and Running + +Debugger server is linked into EGL, code is in framework/base/opengl/libs/GLES2_dbg and already included in latest master builds, no action needed. +Use development/tools/glesv2debugger/setup.sh to build and copy the jars: libprotobuf-java-2.3.0-lite, liblzf, sdklib into development/tools/glesv2debugger/lib +Install Eclipse SDK for Eclipse: Eclipse->Help->Install New Software. Select "All Available Sites" in the "Work with:" drop down, then find "Eclipse SDK". (If Eclipse reports dependency conflicts, try install updates first) +Debugger client is an Eclipse plug-in, code is at development/tools/glesv2debugger, built in Eclipse +Optional: build glsl_compiler and copy to plug-in working directory; this is used for shader syntax check + + +"Attaching" to a Process + +adb shell setprop debug.egl.debug_proc before running process. ie: com.example.android.apis +EGL checks /proc//cmdline for match during init and sets debug functions in eglMakeCurrent +EGL will bind to socket and wait for incoming connection, so need to adb forward tcp:5039 tcp:5039. Port can be overridden by adb shell setprop debug.egl.debug_port +If create socket failed, EGL will try to open /data/local/tmp/dump.gles2dbg for write, and exit when 8MB is written. The relevant properties are ...debug_forceUseFile, ...debug_maxFileSize, and ...debug_filePath +Now manually start the process on device; on host, open development/tools/glesv2debugger/.project and run/debug as Eclipse application, then Window->Show View->Other->Debug->OpenGL ES 2.0 Debugger, then Connect or Open File diff --git a/tools/glesv2debugger/generate_MessageParser_java.py b/tools/glesv2debugger/generate_MessageParser_java.py index 8dcb50f10..b6e828281 100755 --- a/tools/glesv2debugger/generate_MessageParser_java.py +++ b/tools/glesv2debugger/generate_MessageParser_java.py @@ -67,16 +67,21 @@ public abstract class MessageParser { String[] getList() { - assert args.charAt(0) == '{'; String arg = args; args = args.substring(args.lastIndexOf('}') + 1); - int comma = args.indexOf(','); + final int comma = args.indexOf(','); if (comma >= 0) args = args.substring(comma + 1).trim(); else args = null; + + final int comment = arg.indexOf('='); + if (comment >= 0) + arg = arg.substring(comment + 1); + arg = arg.trim(); + assert arg.charAt(0) == '{'; arg = arg.substring(1, arg.lastIndexOf('}')).trim(); - return arg.split(","); + return arg.split("\\s*,\\s*"); } ByteString parseFloats(int count) { @@ -110,7 +115,7 @@ public abstract class MessageParser { } ByteString parseMatrix(int columns, int count) { - return parseFloats(columns * count); + return parseFloats(columns * columns * count); } ByteString parseString() { @@ -127,21 +132,22 @@ public abstract class MessageParser { String getArgument() { - int comma = args.indexOf(","); + final int comma = args.indexOf(','); String arg = null; if (comma >= 0) { - arg = args.substring(0, comma).trim(); - args = args.substring(comma + 1).trim(); + arg = args.substring(0, comma); + args = args.substring(comma + 1); } else { arg = args; args = null; } - if (arg.indexOf("=") >= 0) - arg = arg.substring(arg.indexOf("=") + 1); - return arg; + final int comment = arg.indexOf('='); + if (comment >= 0) + arg = arg.substring(comment + 1); + return arg.trim(); } int parseArgument() @@ -242,8 +248,8 @@ public abstract class MessageParser { assert columns * columns == count assert countArg != "" assert paramType == "GLfloat" - dataSetter = "builder.setData(parseMatrix(%d, %d * builder.getArg%d()));" % ( - columns, count, paramNames.index(countArg)) + dataSetter = "builder.setData(parseMatrix(%d, builder.getArg%d()));" % ( + columns, paramNames.index(countArg)) elif annotation == "GLstring": dataSetter = "builder.setData(parseString());" elif paramType.find("void") >= 0: diff --git a/tools/glesv2debugger/setup.sh b/tools/glesv2debugger/setup.sh new file mode 100755 index 000000000..839019d05 --- /dev/null +++ b/tools/glesv2debugger/setup.sh @@ -0,0 +1,35 @@ +source ../../../build/envsetup.sh +pushd ../../../ + +# need lunch before building jars +if [ -z "$TARGET_PRODUCT" ]; then + lunch +fi + +pushd external/liblzf/ +mm +popd + +pushd external/protobuf/ +mm +popd + +pushd sdk/sdkmanager/libs/sdklib +mm +popd + +# glsl_compiler is optional +# make glsl_compiler -j3 + +popd + +mkdir -p lib +cp "$ANDROID_HOST_OUT/framework/host-libprotobuf-java-2.3.0-lite.jar" lib/ +cp "$ANDROID_HOST_OUT/framework/liblzf.jar" lib/ +cp "$ANDROID_HOST_OUT/framework/sdklib.jar" lib/ + +# optional; usually for linux +#cp "$ANDROID_HOST_OUT/bin/glsl_compiler" ~/ + +# optional; usually for mac, need to replace eclipse.app with actual path +#cp "$ANDROID_HOST_OUT/bin/glsl_compiler" eclipse.app/Contents/MacOS diff --git a/tools/glesv2debugger/src/com/android/glesv2debugger/Context.java b/tools/glesv2debugger/src/com/android/glesv2debugger/Context.java index e1395d7a9..122695b59 100644 --- a/tools/glesv2debugger/src/com/android/glesv2debugger/Context.java +++ b/tools/glesv2debugger/src/com/android/glesv2debugger/Context.java @@ -359,9 +359,12 @@ class ContextViewProvider extends LabelProvider implements ITreeContentProvider, case glTexImage2D: case glTexSubImage2D: case glCopyTexImage2D: - case glCopyTexSubImage2D: - return entry.image = new MessageData(Display.getCurrent(), msg, null) - .getImage(); + case glCopyTexSubImage2D: { + entry.image = new MessageData(Display.getCurrent(), msg, null).getImage(); + if (entry.image == null) + return null; + return new Image(Display.getCurrent(), entry.image.getImageData().scaledTo(96, 96)); + } default: return null; } diff --git a/tools/glesv2debugger/src/com/android/glesv2debugger/GLServerTexture.java b/tools/glesv2debugger/src/com/android/glesv2debugger/GLServerTexture.java index 4d95684fd..27676ddd7 100644 --- a/tools/glesv2debugger/src/com/android/glesv2debugger/GLServerTexture.java +++ b/tools/glesv2debugger/src/com/android/glesv2debugger/GLServerTexture.java @@ -75,7 +75,8 @@ class GLTexture implements Cloneable { @Override public String toString() { - return target.name() + " " + contentChanges.size() + " content change(s)"; + return String.format("%s %s %d*%d %d change(s)", target, format, width, height, + contentChanges.size()); } } diff --git a/tools/glesv2debugger/src/com/android/glesv2debugger/GLServerVertex.java b/tools/glesv2debugger/src/com/android/glesv2debugger/GLServerVertex.java index a07f0a4a4..5f9d51310 100644 --- a/tools/glesv2debugger/src/com/android/glesv2debugger/GLServerVertex.java +++ b/tools/glesv2debugger/src/com/android/glesv2debugger/GLServerVertex.java @@ -521,6 +521,8 @@ public class GLServerVertex implements Cloneable { } void glVertexAttrib4f(int indx, float x, float y, float z, float w) { + if (indx < 0 || indx >= defaultAttribs.length) + return; defaultAttribs[indx][0] = x; defaultAttribs[indx][1] = y; defaultAttribs[indx][2] = z; diff --git a/tools/glesv2debugger/src/com/android/glesv2debugger/MessageParser.java b/tools/glesv2debugger/src/com/android/glesv2debugger/MessageParser.java index 8a0c0ece5..8536728f5 100644 --- a/tools/glesv2debugger/src/com/android/glesv2debugger/MessageParser.java +++ b/tools/glesv2debugger/src/com/android/glesv2debugger/MessageParser.java @@ -31,16 +31,21 @@ public abstract class MessageParser { String[] getList() { - assert args.charAt(0) == '{'; String arg = args; args = args.substring(args.lastIndexOf('}') + 1); - int comma = args.indexOf(','); + final int comma = args.indexOf(','); if (comma >= 0) args = args.substring(comma + 1).trim(); else args = null; + + final int comment = arg.indexOf('='); + if (comment >= 0) + arg = arg.substring(comment + 1); + arg = arg.trim(); + assert arg.charAt(0) == '{'; arg = arg.substring(1, arg.lastIndexOf('}')).trim(); - return arg.split(","); + return arg.split("\\s*,\\s*"); } ByteString parseFloats(int count) { @@ -74,7 +79,7 @@ public abstract class MessageParser { } ByteString parseMatrix(int columns, int count) { - return parseFloats(columns * count); + return parseFloats(columns * columns * count); } ByteString parseString() { @@ -91,21 +96,22 @@ public abstract class MessageParser { String getArgument() { - int comma = args.indexOf(","); + final int comma = args.indexOf(','); String arg = null; if (comma >= 0) { - arg = args.substring(0, comma).trim(); - args = args.substring(comma + 1).trim(); + arg = args.substring(0, comma); + args = args.substring(comma + 1); } else { arg = args; args = null; } - if (arg.indexOf("=") >= 0) - arg = arg.substring(arg.indexOf("=") + 1); - return arg; + final int comment = arg.indexOf('='); + if (comment >= 0) + arg = arg.substring(comment + 1); + return arg.trim(); } int parseArgument() @@ -634,19 +640,19 @@ public abstract class MessageParser { builder.setArg0(parseArgument()); // GLint location builder.setArg1(parseArgument()); // GLsizei count builder.setArg2(parseArgument()); // GLboolean transpose - builder.setData(parseMatrix(2, 4 * builder.getArg1())); // GLfloat value + builder.setData(parseMatrix(2, builder.getArg1())); // GLfloat value break; case glUniformMatrix3fv: builder.setArg0(parseArgument()); // GLint location builder.setArg1(parseArgument()); // GLsizei count builder.setArg2(parseArgument()); // GLboolean transpose - builder.setData(parseMatrix(3, 9 * builder.getArg1())); // GLfloat value + builder.setData(parseMatrix(3, builder.getArg1())); // GLfloat value break; case glUniformMatrix4fv: builder.setArg0(parseArgument()); // GLint location builder.setArg1(parseArgument()); // GLsizei count builder.setArg2(parseArgument()); // GLboolean transpose - builder.setData(parseMatrix(4, 16 * builder.getArg1())); // GLfloat value + builder.setData(parseMatrix(4, builder.getArg1())); // GLfloat value break; case glUseProgram: builder.setArg0(parseArgument()); // GLuint program diff --git a/tools/glesv2debugger/src/com/android/glesv2debugger/SampleView.java b/tools/glesv2debugger/src/com/android/glesv2debugger/SampleView.java index 91e352e08..4a8cdc99c 100644 --- a/tools/glesv2debugger/src/com/android/glesv2debugger/SampleView.java +++ b/tools/glesv2debugger/src/com/android/glesv2debugger/SampleView.java @@ -192,12 +192,7 @@ public class SampleView extends ViewPart implements Runnable, SelectionListener } public SampleView() { - MessageParserEx messageParserEx = new MessageParserEx(); - Message.Builder builder = Message.newBuilder(); - messageParserEx.parse(builder, "glUniform4fv(1,2,{0,1,2,3,4,5,6,7})"); - messageParserEx - .parse(builder, - "void glShaderSource(shader=4, count=1, string=\"dksjafhskjahourehghskjg\", length=0x0)"); + } public void createLeftPane(Composite parent) { diff --git a/tools/glesv2debugger/src/com/android/glesv2debugger/ShaderEditor.java b/tools/glesv2debugger/src/com/android/glesv2debugger/ShaderEditor.java index cdd55c2f9..c1251434e 100644 --- a/tools/glesv2debugger/src/com/android/glesv2debugger/ShaderEditor.java +++ b/tools/glesv2debugger/src/com/android/glesv2debugger/ShaderEditor.java @@ -146,43 +146,45 @@ public class ShaderEditor extends Composite implements SelectionListener, Extend void uploadShader() { current.source = styledText.getText(); - try { - File file = File.createTempFile("shader", - current.type == GLEnum.GL_VERTEX_SHADER ? ".vert" : ".frag"); - FileWriter fileWriter = new FileWriter(file, false); - fileWriter.write(current.source); - fileWriter.close(); + // optional syntax check by glsl_compiler, built from external/mesa3d + if (new File("./glsl_compiler").exists()) + try { + File file = File.createTempFile("shader", + current.type == GLEnum.GL_VERTEX_SHADER ? ".vert" : ".frag"); + FileWriter fileWriter = new FileWriter(file, false); + fileWriter.write(current.source); + fileWriter.close(); - ProcessBuilder processBuilder = new ProcessBuilder( - "./glsl_compiler", "--glsl-es", file.getAbsolutePath()); - final Process process = processBuilder.start(); - InputStream is = process.getInputStream(); - InputStreamReader isr = new InputStreamReader(is); - BufferedReader br = new BufferedReader(isr); - String line; - String infolog = ""; + ProcessBuilder processBuilder = new ProcessBuilder( + "./glsl_compiler", "--glsl-es", file.getAbsolutePath()); + final Process process = processBuilder.start(); + InputStream is = process.getInputStream(); + InputStreamReader isr = new InputStreamReader(is); + BufferedReader br = new BufferedReader(isr); + String line; + String infolog = ""; - styledText.setLineBackground(0, styledText.getLineCount(), null); + styledText.setLineBackground(0, styledText.getLineCount(), null); - while ((line = br.readLine()) != null) { - infolog += line; - if (!line.startsWith("0:")) - continue; - String[] details = line.split(":|\\(|\\)"); - final int ln = Integer.parseInt(details[1]); - if (ln > 0) // usually line 0 means errors other than syntax - styledText.setLineBackground(ln - 1, 1, - new Color(Display.getCurrent(), 255, 230, 230)); + while ((line = br.readLine()) != null) { + infolog += line; + if (!line.startsWith("0:")) + continue; + String[] details = line.split(":|\\(|\\)"); + final int ln = Integer.parseInt(details[1]); + if (ln > 0) // usually line 0 means errors other than syntax + styledText.setLineBackground(ln - 1, 1, + new Color(Display.getCurrent(), 255, 230, 230)); + } + file.delete(); + if (infolog.length() > 0) { + if (!MessageDialog.openConfirm(getShell(), + "Shader Syntax Error, Continue?", infolog)) + return; + } + } catch (IOException e) { + sampleView.showError(e); } - file.delete(); - if (infolog.length() > 0) { - if (!MessageDialog.openConfirm(getShell(), - "Shader Syntax Error, Continue?", infolog)) - return; - } - } catch (IOException e) { - sampleView.showError(e); - } // add the initial command, which when read by server will set // expectResponse for the message loop and go into message exchange diff --git a/tools/glesv2debugger/test/com/android/glesv2debugger/MessageParserExTest.java b/tools/glesv2debugger/test/com/android/glesv2debugger/MessageParserExTest.java new file mode 100644 index 000000000..d2a9a7eb9 --- /dev/null +++ b/tools/glesv2debugger/test/com/android/glesv2debugger/MessageParserExTest.java @@ -0,0 +1,115 @@ +/* + ** Copyright 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.glesv2debugger; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import com.android.glesv2debugger.DebuggerMessage.Message; +import com.android.glesv2debugger.DebuggerMessage.Message.Function; +import com.android.glesv2debugger.DebuggerMessage.Message.Type; +import com.google.protobuf.ByteString; + +import org.junit.Before; +import org.junit.Test; + +import java.nio.ByteBuffer; + +public class MessageParserExTest { + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + } + + @Test + public void testParseFloats() { + final MessageParserEx parser = new MessageParserEx(); + final String args = "{0, 1 ,2,3 }"; + parser.args = args; + final ByteBuffer data = parser.parseFloats(4).asReadOnlyByteBuffer(); + data.order(SampleView.targetByteOrder); + for (int i = 0; i < 4; i++) + assertEquals(i, data.getFloat(), 0); + } + + @Test + public void testParseArgument() { + final MessageParserEx parser = new MessageParserEx(); + final String args = "sdfa = GL_VERTEX_SHADER , -5421 ,0x443=0x54f"; + parser.args = args; + assertEquals(GLEnum.GL_VERTEX_SHADER.value, parser.parseArgument()); + assertEquals(-5421, parser.parseArgument()); + assertEquals(0x54f, parser.parseArgument()); + } + + /** + * Test method for + * {@link com.android.glesv2debugger.MessageParserEx#parse_glShaderSource(com.android.glesv2debugger.DebuggerMessage.Message.Builder)} + * . + */ + @Test + public void testParse_glShaderSource() { + final Message.Builder builder = Message.newBuilder(); + final MessageParserEx messageParserEx = new MessageParserEx(); + final String source = "dks \n jafhskjaho { urehg ; } hskjg"; + messageParserEx.parse(builder, "void glShaderSource ( shader=4, count= 1, " + + "string =\"" + source + "\" , 0x0)"); + assertEquals(Function.glShaderSource, builder.getFunction()); + assertEquals(4, builder.getArg0()); + assertEquals(1, builder.getArg1()); + assertEquals(source, builder.getData().toStringUtf8()); + assertEquals(0, builder.getArg3()); + } + + @Test + public void testParse_glBlendEquation() { + assertNotNull(MessageParserEx.instance); + final Message.Builder builder = Message.newBuilder(); + MessageParserEx.instance.parse(builder, "void glBlendEquation ( mode= GL_ADD ) ; "); + assertEquals(Function.glBlendEquation, builder.getFunction()); + assertEquals(GLEnum.GL_ADD.value, builder.getArg0()); + } + + /** loopback testing of typical generated MessageFormatter and MessageParser */ + @Test + public void testParseFormatterMessage() { + final ByteBuffer srcData = ByteBuffer.allocate(4 * 2 * 4); + srcData.order(SampleView.targetByteOrder); + for (int i = 0; i < 4 * 2; i++) + srcData.putFloat(i); + srcData.rewind(); + Message.Builder builder = Message.newBuilder(); + builder.setContextId(3752).setExpectResponse(false).setType(Type.CompleteCall); + builder.setFunction(Function.glUniformMatrix2fv); + builder.setArg0(54).setArg1(2).setArg2(0).setData(ByteString.copyFrom(srcData)); + Message msg = builder.build(); + builder = msg.toBuilder(); + String formatted = MessageFormatter.format(msg, false); + formatted = formatted.substring(0, formatted.indexOf('(')) + ' ' + builder.getFunction() + + formatted.substring(formatted.indexOf('(')); + Message.Builder parsed = Message.newBuilder(); + MessageParserEx.instance.parse(parsed, formatted); + assertEquals(builder.getFunction(), parsed.getFunction()); + assertEquals(builder.getArg0(), parsed.getArg0()); + assertEquals(builder.getArg1(), parsed.getArg1()); + assertEquals(builder.getArg2(), parsed.getArg2()); + assertEquals(builder.getData().toStringUtf8(), parsed.getData().toStringUtf8()); + } + +}