Merge "GLES2Dbg: add more state tracking and snapshot of state per GL call"

This commit is contained in:
David Li
2011-04-18 15:14:29 -07:00
committed by Android (Google) Code Review
10 changed files with 681 additions and 184 deletions

View File

@@ -1,9 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<classpath> <classpath>
<classpathentry kind="lib" path="lib/sdklib.jar"/>
<classpathentry kind="lib" path="lib/liblzf.jar"/>
<classpathentry kind="lib" path="lib/host-libprotobuf-java-2.3.0-lite.jar"/> <classpathentry kind="lib" path="lib/host-libprotobuf-java-2.3.0-lite.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src"/> <classpathentry kind="src" path="src"/>
<classpathentry kind="lib" path="lib/liblzf.jar"/>
<classpathentry kind="output" path="bin"/> <classpathentry kind="output" path="bin"/>
</classpath> </classpath>

View File

@@ -10,4 +10,5 @@ Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-ClassPath: lib/host-libprotobuf-java-2.3.0-lite.jar, Bundle-ClassPath: lib/host-libprotobuf-java-2.3.0-lite.jar,
lib/liblzf.jar, lib/liblzf.jar,
lib/sdklib.jar,
. .

View File

@@ -3,7 +3,8 @@ output.. = bin/
bin.includes = plugin.xml,\ bin.includes = plugin.xml,\
META-INF/,\ META-INF/,\
.,\ .,\
icons/,\ icons/,\
contexts.xml,\ contexts.xml,\
lib/host-libprotobuf-java-2.3.0-lite.jar,\ lib/host-libprotobuf-java-2.3.0-lite.jar,\
lib/liblzf.jar lib/liblzf.jar,\
lib/sdklib.jar

View File

@@ -17,81 +17,205 @@
package com.android.glesv2debugger; package com.android.glesv2debugger;
import com.android.glesv2debugger.DebuggerMessage.Message; import com.android.glesv2debugger.DebuggerMessage.Message;
import com.android.glesv2debugger.DebuggerMessage.Message.Function;
import com.android.sdklib.util.SparseArray;
import com.android.sdklib.util.SparseIntArray;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.graphics.Image;
import java.lang.reflect.Field;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
public class Context { public class Context implements Cloneable {
public final int contextId; public final int contextId;
ArrayList<Context> shares = new ArrayList<Context>(); // includes self public ArrayList<Context> shares = new ArrayList<Context>(); // self too
public GLServerVertex serverVertex = new GLServerVertex(); public GLServerVertex serverVertex = new GLServerVertex();
public GLServerShader serverShader = new GLServerShader(this); public GLServerShader serverShader = new GLServerShader(this);
public byte[] readPixelRef = new byte[0]; public GLServerState serverState = new GLServerState(this);
byte[] readPixelRef = new byte[0];
Message processed = null; // return; processed Message
public Context(int contextId) { public Context(int contextId) {
this.contextId = contextId; this.contextId = contextId;
shares.add(this); shares.add(this);
} }
public Message ProcessMessage(Message msg) { // returns instance TODO: return new instance if changed
switch (msg.getFunction()) { public Context ProcessMessage(Message msg) {
case glBindBuffer: GLServerVertex newVertex = serverVertex.Process(msg);
serverVertex.glBindBuffer(msg); if (newVertex != null) {
break; processed = newVertex.processed;
case glBufferData: assert newVertex == serverVertex;
serverVertex.glBufferData(msg); return this;
break;
case glBufferSubData:
serverVertex.glBufferSubData(msg);
break;
case glDeleteBuffers:
serverVertex.glDeleteBuffers(msg);
break;
case glDrawArrays:
if (msg.hasArg7())
msg = serverVertex.glDrawArrays(msg);
break;
case glDrawElements:
if (msg.hasArg7())
msg = serverVertex.glDrawElements(msg);
break;
case glDisableVertexAttribArray:
serverVertex.glDisableVertexAttribArray(msg);
break;
case glEnableVertexAttribArray:
serverVertex.glEnableVertexAttribArray(msg);
break;
case glGenBuffers:
serverVertex.glGenBuffers(msg);
break;
case glVertexAttribPointer:
serverVertex.glVertexAttribPointer(msg);
break;
case glVertexAttrib1f:
serverVertex.glVertexAttrib1f(msg);
break;
case glVertexAttrib1fv:
serverVertex.glVertexAttrib1fv(msg);
break;
case glVertexAttrib2f:
serverVertex.glVertexAttrib2f(msg);
break;
case glVertexAttrib2fv:
serverVertex.glVertexAttrib2fv(msg);
break;
case glVertexAttrib3f:
serverVertex.glVertexAttrib3f(msg);
break;
case glVertexAttrib3fv:
serverVertex.glVertexAttrib3fv(msg);
break;
case glVertexAttrib4f:
serverVertex.glVertexAttrib4f(msg);
break;
case glVertexAttrib4fv:
serverVertex.glVertexAttrib4fv(msg);
break;
} }
serverShader.ProcessMessage(msg);
return msg; GLServerShader newShader = serverShader.ProcessMessage(msg);
if (newShader != null) {
assert newShader == serverShader;
return this;
}
GLServerState newState = serverState.ProcessMessage(msg);
if (newState != null) {
if (newState == serverState)
return this;
Context newContext = null;
try {
newContext = (Context) clone();
} catch (CloneNotSupportedException e) {
assert false;
}
newContext.serverState = newState;
newContext.serverShader.context = newContext;
return newContext;
}
return this;
}
}
class ContextViewProvider extends LabelProvider implements ITreeContentProvider {
Context context;
@Override
public void dispose() {
}
@Override
public String getText(Object obj) {
if (obj == null)
return "null";
if (obj instanceof Entry) {
Entry entry = (Entry) obj;
if (entry != null)
return entry.name + " = " + entry.obj;
}
return obj.toString();
}
@Override
public Image getImage(Object obj) {
return null;
}
@Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
context = (Context) newInput;
}
class Entry {
String name;
Object obj;
Entry(String name, Object obj) {
this.name = name;
this.obj = obj;
}
}
@Override
public Object[] getElements(Object inputElement) {
if (inputElement != context)
return null;
return getChildren(new Entry("Context", inputElement));
}
@Override
public Object[] getChildren(Object parentElement) {
if (!(parentElement instanceof Entry))
return null;
Entry entry = (Entry) parentElement;
ArrayList<Object> children = new ArrayList<Object>();
if (entry.obj == context.serverState.enableDisables) {
for (int i = 0; i < context.serverState.enableDisables.size(); i++) {
final int key = context.serverState.enableDisables.keyAt(i);
final int value = context.serverState.enableDisables.valueAt(i);
children.add(GLEnum.valueOf(key).name() + " = " + value);
}
} else if (entry.obj == context.serverState.lastSetter) {
for (int i = 0; i < context.serverState.lastSetter.size(); i++) {
final int key = context.serverState.lastSetter.keyAt(i);
final Message msg = context.serverState.lastSetter.valueAt(i);
if (msg == null)
children.add(Function.valueOf(key).name() + " : default");
else
children.add(Function.valueOf(key).name() + " : "
+ MessageFormatter.Format(msg));
}
} else if (entry.obj instanceof SparseArray) {
SparseArray sa = (SparseArray) entry.obj;
for (int i = 0; i < sa.size(); i++)
children.add(new Entry(entry.name + "[" + sa.keyAt(i) + "]", sa.valueAt(i)));
} else if (entry.obj instanceof Map) {
Set set = ((Map) entry.obj).entrySet();
for (Object o : set) {
Map.Entry e = (Map.Entry) o;
children.add(new Entry(e.getKey().toString(), e.getValue()));
}
} else if (entry.obj instanceof SparseIntArray) {
SparseIntArray sa = (SparseIntArray) entry.obj;
for (int i = 0; i < sa.size(); i++)
children.add(entry.name + "[" + sa.keyAt(i) + "] = " + sa.valueAt(i));
} else if (entry.obj instanceof Collection) {
Collection collection = (Collection) entry.obj;
for (Object o : collection)
children.add(new Entry(entry.name, o));
} else if (entry.obj.getClass().isArray()) {
Object[] list = (Object[]) entry.obj;
for (Object o : list)
children.add(new Entry(entry.name, o));
} else {
Field[] fields = entry.obj.getClass().getFields();
for (Field f : fields) {
try {
children.add(new Entry(f.getName(), f.get(entry.obj)));
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
return children.toArray();
}
@Override
public Object getParent(Object element) {
return null;
}
@Override
public boolean hasChildren(Object element) {
if (element == null)
return false;
if (element.getClass().isPrimitive())
return false;
if (element.getClass().equals(String.class))
return false;
if (element instanceof Entry) {
Entry entry = (Entry) element;
if (entry.obj != null) {
if (entry.obj instanceof SparseArray)
return ((SparseArray) entry.obj).size() > 0;
else if (entry.obj instanceof SparseIntArray)
return ((SparseIntArray) entry.obj).size() > 0;
else if (entry.obj instanceof Collection)
return ((Collection) entry.obj).size() > 0;
else if (entry.obj instanceof Map)
return ((Map) entry.obj).size() > 0;
else if (entry.obj.getClass().isArray())
return ((Object[]) entry.obj).length > 0;
return entry.obj.getClass().getFields().length > 0;
}
}
return false;
} }
} }

View File

@@ -17,79 +17,130 @@
package com.android.glesv2debugger; package com.android.glesv2debugger;
import com.android.glesv2debugger.DebuggerMessage.Message; import com.android.glesv2debugger.DebuggerMessage.Message;
import com.android.sdklib.util.SparseArray;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
class GLShader { class GLShader implements Cloneable {
final int name; public final int name;
final GLServerShader context; // the context this was created in final GLServerShader context; // the context this was created in
final GLEnum type; public final GLEnum type;
boolean delete; public boolean delete;
ArrayList<GLProgram> programs = new ArrayList<GLProgram>(); public ArrayList<Integer> programs = new ArrayList<Integer>();
String source, originalSource; public String source, originalSource;
GLShader(final int name, final GLServerShader context, final GLEnum type) { GLShader(final int name, final GLServerShader context, final GLEnum type) {
this.name = name; this.name = name;
this.context = context; this.context = context;
this.type = type; this.type = type;
} }
@Override
// deep copy except for context, which is set afterwards
public Object clone() {
try {
GLShader shader = (GLShader) super.clone();
shader.programs = (ArrayList<Integer>) programs.clone();
return shader;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
assert false;
return null;
}
}
} }
class GLProgram { class GLProgram implements Cloneable {
final int name; public final int name;
final GLServerShader context; // the context this was created in final GLServerShader context; // the context this was created in
boolean delete; public boolean delete;
GLShader vert, frag; public int vert, frag;
GLProgram(final int name, final GLServerShader context) { GLProgram(final int name, final GLServerShader context) {
this.name = name; this.name = name;
this.context = context; this.context = context;
} }
@Override
// deep copy except for context, which is set afterwards
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
assert false;
return null;
}
}
} }
public class GLServerShader { public class GLServerShader implements Cloneable {
final Context context; Context context;
HashMap<Integer, GLShader> privateShaders = new HashMap<Integer, GLShader>(); public SparseArray<GLShader> shaders = new SparseArray<GLShader>();
HashMap<Integer, GLProgram> privatePrograms = new HashMap<Integer, GLProgram>(); public SparseArray<GLProgram> programs = new SparseArray<GLProgram>();
GLProgram current = null; public GLProgram current = null;
public boolean uiUpdate = false; boolean uiUpdate = false;
GLServerShader(final Context context) { GLServerShader(Context context) {
this.context = context; this.context = context;
} }
public void ProcessMessage(final Message msg) { @Override
// deep copy except for context, which is set afterwards
public Object clone() {
try {
GLServerShader copy = (GLServerShader) super.clone();
copy.shaders = new SparseArray<GLShader>(shaders.size());
for (int i = 0; i < shaders.size(); i++)
copy.shaders.append(shaders.keyAt(i), (GLShader) shaders.valueAt(i).clone());
copy.programs = new SparseArray<GLProgram>(programs.size());
for (int i = 0; i < programs.size(); i++)
copy.programs.append(programs.keyAt(i), (GLProgram) programs.valueAt(i).clone());
if (current != null)
copy.current = (GLProgram) current.clone();
return copy;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
assert false;
return null;
}
}
// returns instance if processed
public GLServerShader ProcessMessage(final Message msg) {
boolean oldUiUpdate = uiUpdate; boolean oldUiUpdate = uiUpdate;
uiUpdate = true; uiUpdate = true;
switch (msg.getFunction()) { switch (msg.getFunction()) {
case glAttachShader: case glAttachShader:
glAttachShader(msg); glAttachShader(msg);
break; return this;
case glCreateProgram: case glCreateProgram:
glCreateProgram(msg); glCreateProgram(msg);
break; return this;
case glCreateShader: case glCreateShader:
glCreateShader(msg); glCreateShader(msg);
break; return this;
case glDeleteProgram: case glDeleteProgram:
glDeleteProgram(msg); glDeleteProgram(msg);
break; return this;
case glDeleteShader: case glDeleteShader:
glDeleteShader(msg); glDeleteShader(msg);
break; return this;
case glDetachShader: case glDetachShader:
glDetachShader(msg); glDetachShader(msg);
break; return this;
case glShaderSource: case glShaderSource:
glShaderSource(msg); glShaderSource(msg);
break; return this;
case glUseProgram: case glUseProgram:
glUseProgram(msg); glUseProgram(msg);
break; return this;
default: default:
uiUpdate = oldUiUpdate; uiUpdate = oldUiUpdate;
break; return null;
} }
} }
@@ -97,7 +148,7 @@ public class GLServerShader {
if (name == 0) if (name == 0)
return null; return null;
for (Context ctx : context.shares) { for (Context ctx : context.shares) {
GLShader shader = ctx.serverShader.privateShaders.get(name); GLShader shader = ctx.serverShader.shaders.get(name);
if (shader != null) if (shader != null)
return shader; return shader;
} }
@@ -109,7 +160,7 @@ public class GLServerShader {
if (name == 0) if (name == 0)
return null; return null;
for (Context ctx : context.shares) { for (Context ctx : context.shares) {
GLProgram program = ctx.serverShader.privatePrograms.get(name); GLProgram program = ctx.serverShader.programs.get(name);
if (program != null) if (program != null)
return program; return program;
} }
@@ -122,20 +173,20 @@ public class GLServerShader {
GLProgram program = GetProgram(msg.getArg0()); GLProgram program = GetProgram(msg.getArg0());
GLShader shader = GetShader(msg.getArg1()); GLShader shader = GetShader(msg.getArg1());
if (GLEnum.GL_VERTEX_SHADER == shader.type) if (GLEnum.GL_VERTEX_SHADER == shader.type)
program.vert = shader; program.vert = shader.name;
else else
program.frag = shader; program.frag = shader.name;
shader.programs.add(program); shader.programs.add(program.name);
} }
// GLuint API_ENTRY(glCreateProgram)(void) // GLuint API_ENTRY(glCreateProgram)(void)
void glCreateProgram(final Message msg) { void glCreateProgram(final Message msg) {
privatePrograms.put(msg.getRet(), new GLProgram(msg.getRet(), this)); programs.put(msg.getRet(), new GLProgram(msg.getRet(), this));
} }
// GLuint API_ENTRY(glCreateShader)(GLenum type) // GLuint API_ENTRY(glCreateShader)(GLenum type)
void glCreateShader(final Message msg) { void glCreateShader(final Message msg) {
privateShaders.put(msg.getRet(), shaders.put(msg.getRet(),
new GLShader(msg.getRet(), this, GLEnum.valueOf(msg.getArg0()))); new GLShader(msg.getRet(), this, GLEnum.valueOf(msg.getArg0())));
} }
@@ -148,9 +199,9 @@ public class GLServerShader {
for (Context ctx : context.shares) for (Context ctx : context.shares)
if (ctx.serverShader.current == program) if (ctx.serverShader.current == program)
return; return;
glDetachShader(program, program.vert); glDetachShader(program, GetShader(program.vert));
glDetachShader(program, program.frag); glDetachShader(program, GetShader(program.frag));
privatePrograms.remove(program.name); programs.remove(program.name);
} }
// void API_ENTRY(glDeleteShader)(GLuint shader) // void API_ENTRY(glDeleteShader)(GLuint shader)
@@ -160,7 +211,7 @@ public class GLServerShader {
GLShader shader = GetShader(msg.getArg0()); GLShader shader = GetShader(msg.getArg0());
shader.delete = true; shader.delete = true;
if (shader.programs.size() == 0) if (shader.programs.size() == 0)
privateShaders.remove(shader.name); shaders.remove(shader.name);
} }
// void API_ENTRY(glDetachShader)(GLuint program, GLuint shader) // void API_ENTRY(glDetachShader)(GLuint program, GLuint shader)
@@ -171,15 +222,15 @@ public class GLServerShader {
void glDetachShader(final GLProgram program, final GLShader shader) { void glDetachShader(final GLProgram program, final GLShader shader) {
if (program == null) if (program == null)
return; return;
if (program.vert == shader) if (program.vert == shader.name)
program.vert = null; program.vert = 0;
else if (program.frag == shader) else if (program.frag == shader.name)
program.frag = null; program.frag = 0;
else else
return; return;
shader.programs.remove(program); shader.programs.remove(program.name);
if (shader.delete && shader.programs.size() == 0) if (shader.delete && shader.programs.size() == 0)
shader.context.privateShaders.remove(shader.name); shaders.remove(shader.name);
} }
// void API_ENTRY(glShaderSource)(GLuint shader, GLsizei count, const // void API_ENTRY(glShaderSource)(GLuint shader, GLsizei count, const
@@ -195,12 +246,11 @@ public class GLServerShader {
void glUseProgram(final Message msg) { void glUseProgram(final Message msg) {
GLProgram oldCurrent = current; GLProgram oldCurrent = current;
current = GetProgram(msg.getArg0()); current = GetProgram(msg.getArg0());
if (null != oldCurrent && oldCurrent.delete && oldCurrent != current) if (null != oldCurrent && oldCurrent.delete && oldCurrent != current) {
{
for (Context ctx : context.shares) for (Context ctx : context.shares)
if (ctx.serverShader.current == oldCurrent) if (ctx.serverShader.current == oldCurrent)
return; return;
oldCurrent.context.privatePrograms.remove(oldCurrent.name); oldCurrent.context.programs.remove(oldCurrent.name);
} }
} }
} }

View File

@@ -0,0 +1,237 @@
/*
** 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 com.android.glesv2debugger.DebuggerMessage.Message;
import com.android.glesv2debugger.DebuggerMessage.Message.Function;
import com.android.sdklib.util.SparseArray;
import com.android.sdklib.util.SparseIntArray;
class GLStencilState implements Cloneable {
public int ref, mask;
public GLEnum func;
public GLEnum sf, df, dp; // operation
@Override
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
return null;
}
}
}
public class GLServerState implements Cloneable {
final Context context;
public GLStencilState front = new GLStencilState(), back = new GLStencilState();
public SparseIntArray enableDisables;
public SparseArray<Message> lastSetter; // keyed by Function.getNumber()
GLServerState(final Context context) {
this.context = context;
enableDisables = new SparseIntArray(9);
enableDisables.put(GLEnum.GL_BLEND.value, 0);
enableDisables.put(GLEnum.GL_DITHER.value, 1);
enableDisables.put(GLEnum.GL_DEPTH_TEST.value, 0);
enableDisables.put(GLEnum.GL_STENCIL_TEST.value, 0);
enableDisables.put(GLEnum.GL_SCISSOR_TEST.value, 0);
enableDisables.put(GLEnum.GL_SAMPLE_COVERAGE.value, 0);
enableDisables.put(GLEnum.GL_SAMPLE_ALPHA_TO_COVERAGE.value, 0);
enableDisables.put(GLEnum.GL_POLYGON_OFFSET_FILL.value, 0);
enableDisables.put(GLEnum.GL_CULL_FACE.value, 0);
lastSetter = new SparseArray<Message>();
lastSetter.put(Function.glBlendColor.getNumber(), null);
// glBlendEquation overwrites glBlendEquationSeparate
lastSetter.put(Function.glBlendEquationSeparate.getNumber(), null);
// glBlendFunc overwrites glBlendFuncSeparate
lastSetter.put(Function.glBlendFuncSeparate.getNumber(), null);
lastSetter.put(Function.glColorMask.getNumber(), null);
lastSetter.put(Function.glDepthMask.getNumber(), null);
lastSetter.put(Function.glDepthFunc.getNumber(), null);
lastSetter.put(Function.glScissor.getNumber(), null);
lastSetter.put(Function.glStencilMaskSeparate.getNumber(), null);
}
// returns instance if processed (returns new instance if changed)
public GLServerState ProcessMessage(final Message msg) {
switch (msg.getFunction()) {
case glBlendColor:
return Setter(msg);
case glBlendEquation:
return Setter(msg);
case glBlendEquationSeparate:
return Setter(msg);
case glBlendFunc:
return Setter(msg);
case glBlendFuncSeparate:
return Setter(msg);
case glColorMask:
return Setter(msg);
case glDepthMask:
return Setter(msg);
case glDepthFunc:
return Setter(msg);
case glDisable:
return EnableDisable(false, msg);
case glEnable:
return EnableDisable(true, msg);
case glScissor:
return Setter(msg);
case glStencilFunc: {
Message.Builder builder = msg.toBuilder();
builder.setArg2(msg.getArg1());
builder.setArg1(msg.getArg0());
builder.setArg0(GLEnum.GL_FRONT_AND_BACK.value);
return glStencilFuncSeparate(builder.build());
}
case glStencilFuncSeparate:
return glStencilFuncSeparate(msg);
case glStencilMask:
return Setter(msg);
case glStencilMaskSeparate:
return Setter(msg);
case glStencilOp: {
Message.Builder builder = msg.toBuilder();
builder.setArg3(msg.getArg2());
builder.setArg2(msg.getArg1());
builder.setArg1(msg.getArg0());
builder.setArg0(GLEnum.GL_FRONT_AND_BACK.value);
return glStencilOpSeparate(builder.build());
}
case glStencilOpSeparate:
return glStencilOpSeparate(msg);
default:
return null;
}
}
GLServerState Setter(final Message msg) {
GLServerState newState = (GLServerState) this.clone();
// TODO: compare for change
switch (msg.getFunction()) {
case glBlendFunc:
newState.lastSetter.put(Function.glBlendFuncSeparate.getNumber(), msg);
break;
case glBlendEquation:
newState.lastSetter.put(Function.glBlendEquationSeparate.getNumber(), msg);
break;
case glStencilMask:
newState.lastSetter.put(Function.glStencilMaskSeparate.getNumber(), msg);
break;
default:
newState.lastSetter.put(msg.getFunction().getNumber(), msg);
break;
}
return newState;
}
GLServerState EnableDisable(boolean enable, final Message msg) {
int index = enableDisables.indexOfKey(msg.getArg0());
assert index >= 0;
if ((enableDisables.valueAt(index) != 0) == enable)
return this;
GLServerState newState0 = (GLServerState) this.clone();
newState0.enableDisables.put(msg.getArg0(), enable ? 1 : 0);
return newState0;
}
// void StencilFuncSeparate( enum face, enum func, int ref, uint mask )
GLServerState glStencilFuncSeparate(final Message msg) {
GLEnum ff = front.func, bf = back.func;
int fr = front.ref, br = back.ref;
int fm = front.mask, bm = back.mask;
final GLEnum face = GLEnum.valueOf(msg.getArg0());
if (face == GLEnum.GL_FRONT || face == GLEnum.GL_FRONT_AND_BACK) {
ff = GLEnum.valueOf(msg.getArg1());
fr = msg.getArg2();
fm = msg.getArg3();
}
if (face == GLEnum.GL_BACK || face == GLEnum.GL_FRONT_AND_BACK) {
bf = GLEnum.valueOf(msg.getArg1());
br = msg.getArg2();
bm = msg.getArg3();
}
if (ff == front.func && fr == front.ref && fm == front.mask)
if (bf == back.func && br == back.ref && bm == back.mask)
return this;
GLServerState newState = (GLServerState) this.clone();
newState.front.func = ff;
newState.front.ref = fr;
newState.front.mask = fm;
newState.back.func = bf;
newState.back.ref = br;
newState.back.mask = bm;
return newState;
}
// void StencilOpSeparate( enum face, enum sfail, enum dpfail, enum dppass )
GLServerState glStencilOpSeparate(final Message msg) {
GLEnum fsf = front.sf, fdf = front.df, fdp = front.dp;
GLEnum bsf = back.sf, bdf = back.df, bdp = back.dp;
final GLEnum face = GLEnum.valueOf(msg.getArg0());
if (face == GLEnum.GL_FRONT || face == GLEnum.GL_FRONT_AND_BACK) {
fsf = GLEnum.valueOf(msg.getArg1());
fdf = GLEnum.valueOf(msg.getArg2());
fdp = GLEnum.valueOf(msg.getArg3());
}
if (face == GLEnum.GL_BACK || face == GLEnum.GL_FRONT_AND_BACK) {
bsf = GLEnum.valueOf(msg.getArg1());
bdf = GLEnum.valueOf(msg.getArg2());
bdp = GLEnum.valueOf(msg.getArg3());
}
if (fsf == front.sf && fdf == front.df && fdp == front.dp)
if (bsf == back.sf && bdf == back.df && bdp == back.dp)
return this;
GLServerState newState = (GLServerState) this.clone();
newState.front.sf = fsf;
newState.front.df = fdf;
newState.front.dp = fdp;
newState.back.sf = bsf;
newState.back.df = bdf;
newState.back.dp = bdp;
return newState;
}
@Override
public Object clone() {
try {
GLServerState newState = (GLServerState) super.clone();
newState.front = (GLStencilState) front.clone();
newState.back = (GLStencilState) back.clone();
newState.enableDisables = new SparseIntArray(enableDisables.size());
for (int i = 0; i < enableDisables.size(); i++) {
final int key = enableDisables.keyAt(i);
newState.enableDisables.append(key, enableDisables.valueAt(i));
}
newState.lastSetter = new SparseArray<Message>(lastSetter.size());
for (int i = 0; i < lastSetter.size(); i++) {
final int key = lastSetter.keyAt(i);
newState.lastSetter.append(key, lastSetter.valueAt(i));
}
return newState;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
return null;
}
}
}

View File

@@ -22,27 +22,27 @@ import java.nio.ByteBuffer;
import java.util.HashMap; import java.util.HashMap;
class GLBuffer { class GLBuffer {
GLEnum usage; public GLEnum usage;
GLEnum target; public GLEnum target;
ByteBuffer data; public ByteBuffer data;
} }
class GLAttribPointer { class GLAttribPointer {
int size; // number of values per vertex public int size; // number of values per vertex
GLEnum type; // data type public GLEnum type; // data type
int stride; // bytes public int stride; // bytes
int ptr; // pointer in debugger server or byte offset into buffer public int ptr; // pointer in debugger server or byte offset into buffer
GLBuffer buffer; public GLBuffer buffer;
boolean normalized; public boolean normalized;
boolean enabled; public boolean enabled;
} }
public class GLServerVertex { public class GLServerVertex {
HashMap<Integer, GLBuffer> buffers; public HashMap<Integer, GLBuffer> buffers;
GLBuffer attribBuffer, indexBuffer; // current binding public GLBuffer attribBuffer, indexBuffer; // current binding
GLAttribPointer attribPointers[]; public GLAttribPointer attribPointers[];
float defaultAttribs[][]; public float defaultAttribs[][];
int maxAttrib; int maxAttrib;
public GLServerVertex() { public GLServerVertex() {
@@ -60,6 +60,73 @@ public class GLServerVertex {
} }
} }
Message processed = null; // return; glDrawArrays/Elements with fetched data
// returns instance if processed TODO: return new instance if changed
public GLServerVertex Process(final Message msg) {
processed = null;
switch (msg.getFunction()) {
case glBindBuffer:
glBindBuffer(msg);
return this;
case glBufferData:
glBufferData(msg);
return this;
case glBufferSubData:
glBufferSubData(msg);
return this;
case glDeleteBuffers:
glDeleteBuffers(msg);
return this;
case glDrawArrays:
if (msg.hasArg7())
processed = glDrawArrays(msg);
return this;
case glDrawElements:
if (msg.hasArg7())
processed = glDrawElements(msg);
return this;
case glDisableVertexAttribArray:
glDisableVertexAttribArray(msg);
return this;
case glEnableVertexAttribArray:
glEnableVertexAttribArray(msg);
return this;
case glGenBuffers:
glGenBuffers(msg);
return this;
case glVertexAttribPointer:
glVertexAttribPointer(msg);
return this;
case glVertexAttrib1f:
glVertexAttrib1f(msg);
return this;
case glVertexAttrib1fv:
glVertexAttrib1fv(msg);
return this;
case glVertexAttrib2f:
glVertexAttrib2f(msg);
return this;
case glVertexAttrib2fv:
glVertexAttrib2fv(msg);
return this;
case glVertexAttrib3f:
glVertexAttrib3f(msg);
return this;
case glVertexAttrib3fv:
glVertexAttrib3fv(msg);
return this;
case glVertexAttrib4f:
glVertexAttrib4f(msg);
return this;
case glVertexAttrib4fv:
glVertexAttrib4fv(msg);
return this;
default:
return null;
}
}
// void API_ENTRY(glBindBuffer)(GLenum target, GLuint buffer) // void API_ENTRY(glBindBuffer)(GLenum target, GLuint buffer)
public void glBindBuffer(Message msg) { public void glBindBuffer(Message msg) {
if (GLEnum.valueOf(msg.getArg0()) == GLEnum.GL_ARRAY_BUFFER) { if (GLEnum.valueOf(msg.getArg0()) == GLEnum.GL_ARRAY_BUFFER) {
@@ -141,32 +208,32 @@ public class GLServerVertex {
else if (GLEnum.GL_UNSIGNED_INT == type) else if (GLEnum.GL_UNSIGNED_INT == type)
if (normalized) if (normalized)
return (Integer.reverseBytes(src.getInt()) & 0xffffffffL) / (2e32f - 1); return (Integer.reverseBytes(src.getInt()) & 0xffffffffL) / (2e32f - 1);
else else
return Integer.reverseBytes(src.getInt()) & 0xffffffffL; return Integer.reverseBytes(src.getInt()) & 0xffffffffL;
else if (GLEnum.GL_INT == type) else if (GLEnum.GL_INT == type)
if (normalized) if (normalized)
return (Integer.reverseBytes(src.getInt()) * 2 + 1) / (2e32f - 1); return (Integer.reverseBytes(src.getInt()) * 2 + 1) / (2e32f - 1);
else else
return Integer.reverseBytes(src.getInt()); return Integer.reverseBytes(src.getInt());
else if (GLEnum.GL_UNSIGNED_SHORT == type) else if (GLEnum.GL_UNSIGNED_SHORT == type)
if (normalized) if (normalized)
return (Short.reverseBytes(src.getShort()) & 0xffff) / (2e16f - 1); return (Short.reverseBytes(src.getShort()) & 0xffff) / (2e16f - 1);
else else
return Short.reverseBytes(src.getShort()) & 0xffff; return Short.reverseBytes(src.getShort()) & 0xffff;
else if (GLEnum.GL_SHORT == type) else if (GLEnum.GL_SHORT == type)
if (normalized) if (normalized)
return (Short.reverseBytes(src.getShort()) * 2 + 1) / (2e16f - 1); return (Short.reverseBytes(src.getShort()) * 2 + 1) / (2e16f - 1);
else else
return Short.reverseBytes(src.getShort()); return Short.reverseBytes(src.getShort());
else if (GLEnum.GL_UNSIGNED_BYTE == type) else if (GLEnum.GL_UNSIGNED_BYTE == type)
if (normalized) if (normalized)
return (src.get() & 0xff) / (2e8f - 1); return (src.get() & 0xff) / (2e8f - 1);
else else
return src.get() & 0xff; return src.get() & 0xff;
else if (GLEnum.GL_BYTE == type) else if (GLEnum.GL_BYTE == type)
if (normalized) if (normalized)
return (src.get() * 2 + 1) / (2e8f - 1); return (src.get() * 2 + 1) / (2e8f - 1);
else else
return src.get(); return src.get();
else if (GLEnum.GL_FIXED == type) else if (GLEnum.GL_FIXED == type)
if (normalized) if (normalized)

View File

@@ -33,9 +33,11 @@ public class MessageData {
public float[] data; public float[] data;
public int maxAttrib; // used for formatting data public int maxAttrib; // used for formatting data
public GLEnum dataType; // could be float, int; mainly for formatting use public GLEnum dataType; // could be float, int; mainly for formatting use
Context context; // the context before this call
public MessageData(final Device device, final Message msg, final Context context) { public MessageData(final Device device, final Message msg, final Context context) {
this.msg = msg; this.msg = msg;
this.context = context;
image = null; image = null;
shader = null; shader = null;
data = null; data = null;

View File

@@ -38,6 +38,7 @@ import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.ListViewer; import org.eclipse.jface.viewers.ListViewer;
import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter; import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.jface.viewers.ViewerSorter; import org.eclipse.jface.viewers.ViewerSorter;
@@ -101,8 +102,10 @@ public class SampleView extends ViewPart implements Runnable {
public static final String ID = "glesv2debuggerclient.views.SampleView"; public static final String ID = "glesv2debuggerclient.views.SampleView";
TabFolder tabFolder; TabFolder tabFolder;
TabItem tabItemText, tabItemImage, tabItemBreakpointOption, tabItemShaderEditor; TabItem tabItemText, tabItemImage, tabItemBreakpointOption;
TabItem tabItemShaderEditor, tabContextViewer;
ListViewer viewer; ListViewer viewer;
TreeViewer contextViewer;
BreakpointOption breakpointOption; BreakpointOption breakpointOption;
ShaderEditor shaderEditor; ShaderEditor shaderEditor;
Canvas canvas; Canvas canvas;
@@ -141,6 +144,7 @@ public class SampleView extends ViewPart implements Runnable {
bar.setSelection(bar.getMaximum()); bar.setSelection(bar.getMaximum());
viewer.getList().setSelection( viewer.getList().setSelection(
entries.size() - 1); entries.size() - 1);
// MessageDataSelected(entries.get(entries.size() - 1));
} }
} }
}); });
@@ -228,6 +232,7 @@ public class SampleView extends ViewPart implements Runnable {
viewer.setFilters(new ViewerFilter[] { viewer.setFilters(new ViewerFilter[] {
new Filter() new Filter()
}); });
} }
/** /**
@@ -270,6 +275,14 @@ public class SampleView extends ViewPart implements Runnable {
tabItemShaderEditor.setText("Shader Editor"); tabItemShaderEditor.setText("Shader Editor");
tabItemShaderEditor.setControl(shaderEditor); tabItemShaderEditor.setControl(shaderEditor);
contextViewer = new TreeViewer(tabFolder);
ContextViewProvider contextViewProvider = new ContextViewProvider();
contextViewer.setContentProvider(contextViewProvider);
contextViewer.setLabelProvider(contextViewProvider);
tabContextViewer = new TabItem(tabFolder, SWT.NONE);
tabContextViewer.setText("Context Viewer");
tabContextViewer.setControl(contextViewer.getTree());
final ScrollBar hBar = canvas.getHorizontalBar(); final ScrollBar hBar = canvas.getHorizontalBar();
hBar.addListener(SWT.Selection, new Listener() { hBar.addListener(SWT.Selection, new Listener() {
@Override @Override
@@ -528,6 +541,33 @@ public class SampleView extends ViewPart implements Runnable {
}); });
} }
void MessageDataSelected(final MessageData msgData) {
if (null == msgData)
return;
contextViewer.setInput(msgData.context);
if (null != msgData.image) {
canvas.setBackgroundImage(msgData.image);
tabFolder.setSelection(tabItemImage);
canvas.redraw();
} else if (null != msgData.shader) {
text.setText(msgData.shader);
tabFolder.setSelection(tabItemText);
} else if (null != msgData.data) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < msgData.data.length; i++) {
builder.append(String.format("%.3g", msgData.data[i]));
if (i % (4 * msgData.maxAttrib) == (4 * msgData.maxAttrib - 1))
builder.append('\n');
else if (i % 4 == 3)
builder.append(" -");
if (i < msgData.data.length - 1)
builder.append(' ');
}
text.setText(builder.toString());
tabFolder.setSelection(tabItemText);
}
}
private void hookSelectionChanged() { private void hookSelectionChanged() {
viewer.addSelectionChangedListener(new ISelectionChangedListener() { viewer.addSelectionChangedListener(new ISelectionChangedListener() {
@Override @Override
@@ -537,39 +577,8 @@ public class SampleView extends ViewPart implements Runnable {
if (null == selection) if (null == selection)
return; return;
MessageData msgData = (MessageData) selection.getFirstElement(); MessageData msgData = (MessageData) selection.getFirstElement();
if (null == msgData) MessageDataSelected(msgData);
return;
if (null != msgData.image)
{
canvas.setBackgroundImage(msgData.image);
tabFolder.setSelection(tabItemImage);
}
else if (null != msgData.shader)
{
text.setText(msgData.shader);
text.setVisible(true);
canvas.setVisible(false);
text.getParent().layout();
}
else if (null != msgData.data)
{
StringBuilder builder = new StringBuilder();
for (int i = 0; i < msgData.data.length; i++)
{
builder.append(String.format("%.3g", msgData.data[i]));
if (i % (4 * msgData.maxAttrib) == (4 * msgData.maxAttrib - 1))
builder.append('\n');
else if (i % 4 == 3)
builder.append(" -");
if (i < msgData.data.length - 1)
builder.append(' ');
}
text.setText(builder.toString());
tabFolder.setSelection(tabItemText);
}
} }
}); });
} }
@@ -640,8 +649,13 @@ public class SampleView extends ViewPart implements Runnable {
context = new Context(msg.getContextId()); context = new Context(msg.getContextId());
contexts.put(msg.getContextId(), context); contexts.put(msg.getContextId(), context);
} }
msg = context.ProcessMessage(msg); Context newContext = context.ProcessMessage(msg);
shaderEditorUpdate |= context.serverShader.uiUpdate; // TODO: full cloning on change not implemented yet
if (newContext.processed != null)
msg = newContext.processed;
contexts.put(msg.getContextId(), newContext);
shaderEditorUpdate |= newContext.serverShader.uiUpdate;
newContext.serverShader.uiUpdate = false;
final MessageData msgData = new MessageData(this.getViewSite() final MessageData msgData = new MessageData(this.getViewSite()
.getShell().getDisplay(), msg, context); .getShell().getDisplay(), msg, context);

View File

@@ -107,7 +107,8 @@ public class ShaderEditor extends Composite implements SelectionListener, Extend
progs += context.serverShader.current.name + "(0x"; progs += context.serverShader.current.name + "(0x";
progs += Integer.toHexString(context.contextId) + ") "; progs += Integer.toHexString(context.contextId) + ") ";
} }
for (GLShader shader : context.serverShader.privateShaders.values()) { for (int i = 0; i < context.serverShader.shaders.size(); i++) {
GLShader shader = context.serverShader.shaders.valueAt(i);
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append(String.format("%08X", context.contextId)); builder.append(String.format("%08X", context.contextId));
builder.append(' '); builder.append(' ');
@@ -123,17 +124,17 @@ public class ShaderEditor extends Composite implements SelectionListener, Extend
builder.append(' '); builder.append(' ');
} }
builder.append(": "); builder.append(": ");
for (GLProgram program : shader.programs) { for (int program : shader.programs) {
builder.append(program.name); builder.append(program);
builder.append(" "); builder.append(" ");
} }
list.add(builder.toString()); list.add(builder.toString());
} }
} }
// if (!progs.equals(currentPrograms.getText())) {
currentPrograms.setText(progs);
// } currentPrograms.setText(progs);
toolbar.redraw();
toolbar.pack(true);
toolbar.update(); toolbar.update();
} }
@@ -169,11 +170,10 @@ public class ShaderEditor extends Composite implements SelectionListener, Extend
new Color(Display.getCurrent(), 255, 230, 230)); new Color(Display.getCurrent(), 255, 230, 230));
} }
if (infolog.length() > 0) { if (infolog.length() > 0) {
MessageDialog.openWarning(getShell(), if (!MessageDialog.openConfirm(getShell(),
"Shader Syntax Error, Upload Aborted", infolog); "Shader Syntax Error, Continue?", infolog))
return; return;
} }
} catch (IOException e) { } catch (IOException e) {
sampleView.showError(e); sampleView.showError(e);
} }
@@ -235,8 +235,7 @@ public class ShaderEditor extends Composite implements SelectionListener, Extend
matchingContext = true; matchingContext = true;
break; break;
} }
if (matchingContext) if (matchingContext) {
{
shadersToUpload.remove(i); shadersToUpload.remove(i);
break; break;
} }
@@ -270,7 +269,8 @@ public class ShaderEditor extends Composite implements SelectionListener, Extend
} }
}); });
} else } else
for (GLProgram program : shader.programs) { for (int programName : shader.programs) {
GLProgram program = shader.context.GetProgram(programName);
ExchangeMessage(contextId, queue, "glLinkProgram(%d)", program.name); ExchangeMessage(contextId, queue, "glLinkProgram(%d)", program.name);
rcv = ExchangeMessage(contextId, queue, rcv = ExchangeMessage(contextId, queue,
"glGetProgramiv(%d, GL_LINK_STATUS, [0])", program.name); "glGetProgramiv(%d, GL_LINK_STATUS, [0])", program.name);
@@ -336,7 +336,7 @@ public class ShaderEditor extends Composite implements SelectionListener, Extend
String[] details = list.getSelection()[0].split("\\s+"); String[] details = list.getSelection()[0].split("\\s+");
final int contextId = Integer.parseInt(details[0], 16); final int contextId = Integer.parseInt(details[0], 16);
int name = Integer.parseInt(details[2]); int name = Integer.parseInt(details[2]);
current = sampleView.contexts.get(contextId).serverShader.privateShaders.get(name); current = sampleView.contexts.get(contextId).serverShader.shaders.get(name);
styledText.setText(current.source); styledText.setText(current.source);
} }