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

Use TreeView and Reflection to display the states per GL call.
Need to implement more state cloning and tacking.
Prepare to group calls by frame, and clone the context for each frame.

Change-Id: Ib1e5c175da779610204003e352cc1fcf66af969b
Signed-off-by: David Li <davidxli@google.com>
This commit is contained in:
David Li
2011-03-30 15:14:36 -07:00
parent c93109f059
commit 55fee09e0c
10 changed files with 681 additions and 184 deletions

View File

@@ -1,9 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<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="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="src" path="src"/>
<classpathentry kind="lib" path="lib/liblzf.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

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

View File

@@ -6,4 +6,5 @@ bin.includes = plugin.xml,\
icons/,\
contexts.xml,\
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;
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.Collection;
import java.util.Map;
import java.util.Set;
public class Context {
public class Context implements Cloneable {
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 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) {
this.contextId = contextId;
shares.add(this);
}
public Message ProcessMessage(Message msg) {
switch (msg.getFunction()) {
case glBindBuffer:
serverVertex.glBindBuffer(msg);
break;
case glBufferData:
serverVertex.glBufferData(msg);
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;
// returns instance TODO: return new instance if changed
public Context ProcessMessage(Message msg) {
GLServerVertex newVertex = serverVertex.Process(msg);
if (newVertex != null) {
processed = newVertex.processed;
assert newVertex == serverVertex;
return this;
}
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;
import com.android.glesv2debugger.DebuggerMessage.Message;
import com.android.sdklib.util.SparseArray;
import java.util.ArrayList;
import java.util.HashMap;
class GLShader {
final int name;
class GLShader implements Cloneable {
public final int name;
final GLServerShader context; // the context this was created in
final GLEnum type;
boolean delete;
ArrayList<GLProgram> programs = new ArrayList<GLProgram>();
String source, originalSource;
public final GLEnum type;
public boolean delete;
public ArrayList<Integer> programs = new ArrayList<Integer>();
public String source, originalSource;
GLShader(final int name, final GLServerShader context, final GLEnum type) {
this.name = name;
this.context = context;
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 {
final int name;
class GLProgram implements Cloneable {
public final int name;
final GLServerShader context; // the context this was created in
boolean delete;
GLShader vert, frag;
public boolean delete;
public int vert, frag;
GLProgram(final int name, final GLServerShader context) {
this.name = name;
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 {
final Context context;
HashMap<Integer, GLShader> privateShaders = new HashMap<Integer, GLShader>();
HashMap<Integer, GLProgram> privatePrograms = new HashMap<Integer, GLProgram>();
GLProgram current = null;
public boolean uiUpdate = false;
public class GLServerShader implements Cloneable {
Context context;
public SparseArray<GLShader> shaders = new SparseArray<GLShader>();
public SparseArray<GLProgram> programs = new SparseArray<GLProgram>();
public GLProgram current = null;
boolean uiUpdate = false;
GLServerShader(final Context context) {
GLServerShader(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;
uiUpdate = true;
switch (msg.getFunction()) {
case glAttachShader:
glAttachShader(msg);
break;
return this;
case glCreateProgram:
glCreateProgram(msg);
break;
return this;
case glCreateShader:
glCreateShader(msg);
break;
return this;
case glDeleteProgram:
glDeleteProgram(msg);
break;
return this;
case glDeleteShader:
glDeleteShader(msg);
break;
return this;
case glDetachShader:
glDetachShader(msg);
break;
return this;
case glShaderSource:
glShaderSource(msg);
break;
return this;
case glUseProgram:
glUseProgram(msg);
break;
return this;
default:
uiUpdate = oldUiUpdate;
break;
return null;
}
}
@@ -97,7 +148,7 @@ public class GLServerShader {
if (name == 0)
return null;
for (Context ctx : context.shares) {
GLShader shader = ctx.serverShader.privateShaders.get(name);
GLShader shader = ctx.serverShader.shaders.get(name);
if (shader != null)
return shader;
}
@@ -109,7 +160,7 @@ public class GLServerShader {
if (name == 0)
return null;
for (Context ctx : context.shares) {
GLProgram program = ctx.serverShader.privatePrograms.get(name);
GLProgram program = ctx.serverShader.programs.get(name);
if (program != null)
return program;
}
@@ -122,20 +173,20 @@ public class GLServerShader {
GLProgram program = GetProgram(msg.getArg0());
GLShader shader = GetShader(msg.getArg1());
if (GLEnum.GL_VERTEX_SHADER == shader.type)
program.vert = shader;
program.vert = shader.name;
else
program.frag = shader;
shader.programs.add(program);
program.frag = shader.name;
shader.programs.add(program.name);
}
// GLuint API_ENTRY(glCreateProgram)(void)
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)
void glCreateShader(final Message msg) {
privateShaders.put(msg.getRet(),
shaders.put(msg.getRet(),
new GLShader(msg.getRet(), this, GLEnum.valueOf(msg.getArg0())));
}
@@ -148,9 +199,9 @@ public class GLServerShader {
for (Context ctx : context.shares)
if (ctx.serverShader.current == program)
return;
glDetachShader(program, program.vert);
glDetachShader(program, program.frag);
privatePrograms.remove(program.name);
glDetachShader(program, GetShader(program.vert));
glDetachShader(program, GetShader(program.frag));
programs.remove(program.name);
}
// void API_ENTRY(glDeleteShader)(GLuint shader)
@@ -160,7 +211,7 @@ public class GLServerShader {
GLShader shader = GetShader(msg.getArg0());
shader.delete = true;
if (shader.programs.size() == 0)
privateShaders.remove(shader.name);
shaders.remove(shader.name);
}
// void API_ENTRY(glDetachShader)(GLuint program, GLuint shader)
@@ -171,15 +222,15 @@ public class GLServerShader {
void glDetachShader(final GLProgram program, final GLShader shader) {
if (program == null)
return;
if (program.vert == shader)
program.vert = null;
else if (program.frag == shader)
program.frag = null;
if (program.vert == shader.name)
program.vert = 0;
else if (program.frag == shader.name)
program.frag = 0;
else
return;
shader.programs.remove(program);
shader.programs.remove(program.name);
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
@@ -195,12 +246,11 @@ public class GLServerShader {
void glUseProgram(final Message msg) {
GLProgram oldCurrent = current;
current = GetProgram(msg.getArg0());
if (null != oldCurrent && oldCurrent.delete && oldCurrent != current)
{
if (null != oldCurrent && oldCurrent.delete && oldCurrent != current) {
for (Context ctx : context.shares)
if (ctx.serverShader.current == oldCurrent)
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;
class GLBuffer {
GLEnum usage;
GLEnum target;
ByteBuffer data;
public GLEnum usage;
public GLEnum target;
public ByteBuffer data;
}
class GLAttribPointer {
int size; // number of values per vertex
GLEnum type; // data type
int stride; // bytes
int ptr; // pointer in debugger server or byte offset into buffer
GLBuffer buffer;
boolean normalized;
boolean enabled;
public int size; // number of values per vertex
public GLEnum type; // data type
public int stride; // bytes
public int ptr; // pointer in debugger server or byte offset into buffer
public GLBuffer buffer;
public boolean normalized;
public boolean enabled;
}
public class GLServerVertex {
HashMap<Integer, GLBuffer> buffers;
GLBuffer attribBuffer, indexBuffer; // current binding
GLAttribPointer attribPointers[];
float defaultAttribs[][];
public HashMap<Integer, GLBuffer> buffers;
public GLBuffer attribBuffer, indexBuffer; // current binding
public GLAttribPointer attribPointers[];
public float defaultAttribs[][];
int maxAttrib;
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)
public void glBindBuffer(Message msg) {
if (GLEnum.valueOf(msg.getArg0()) == GLEnum.GL_ARRAY_BUFFER) {

View File

@@ -33,9 +33,11 @@ public class MessageData {
public float[] data;
public int maxAttrib; // used for formatting data
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) {
this.msg = msg;
this.context = context;
image = null;
shader = 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.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
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";
TabFolder tabFolder;
TabItem tabItemText, tabItemImage, tabItemBreakpointOption, tabItemShaderEditor;
TabItem tabItemText, tabItemImage, tabItemBreakpointOption;
TabItem tabItemShaderEditor, tabContextViewer;
ListViewer viewer;
TreeViewer contextViewer;
BreakpointOption breakpointOption;
ShaderEditor shaderEditor;
Canvas canvas;
@@ -141,6 +144,7 @@ public class SampleView extends ViewPart implements Runnable {
bar.setSelection(bar.getMaximum());
viewer.getList().setSelection(
entries.size() - 1);
// MessageDataSelected(entries.get(entries.size() - 1));
}
}
});
@@ -228,6 +232,7 @@ public class SampleView extends ViewPart implements Runnable {
viewer.setFilters(new ViewerFilter[] {
new Filter()
});
}
/**
@@ -270,6 +275,14 @@ public class SampleView extends ViewPart implements Runnable {
tabItemShaderEditor.setText("Shader Editor");
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();
hBar.addListener(SWT.Selection, new Listener() {
@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() {
viewer.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
@@ -537,39 +577,8 @@ public class SampleView extends ViewPart implements Runnable {
if (null == selection)
return;
MessageData msgData = (MessageData) selection.getFirstElement();
if (null == msgData)
return;
if (null != msgData.image)
{
canvas.setBackgroundImage(msgData.image);
tabFolder.setSelection(tabItemImage);
MessageDataSelected(msgData);
}
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());
contexts.put(msg.getContextId(), context);
}
msg = context.ProcessMessage(msg);
shaderEditorUpdate |= context.serverShader.uiUpdate;
Context newContext = context.ProcessMessage(msg);
// 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()
.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 += 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();
builder.append(String.format("%08X", context.contextId));
builder.append(' ');
@@ -123,17 +124,17 @@ public class ShaderEditor extends Composite implements SelectionListener, Extend
builder.append(' ');
}
builder.append(": ");
for (GLProgram program : shader.programs) {
builder.append(program.name);
for (int program : shader.programs) {
builder.append(program);
builder.append(" ");
}
list.add(builder.toString());
}
}
// if (!progs.equals(currentPrograms.getText())) {
currentPrograms.setText(progs);
// }
currentPrograms.setText(progs);
toolbar.redraw();
toolbar.pack(true);
toolbar.update();
}
@@ -169,11 +170,10 @@ public class ShaderEditor extends Composite implements SelectionListener, Extend
new Color(Display.getCurrent(), 255, 230, 230));
}
if (infolog.length() > 0) {
MessageDialog.openWarning(getShell(),
"Shader Syntax Error, Upload Aborted", infolog);
if (!MessageDialog.openConfirm(getShell(),
"Shader Syntax Error, Continue?", infolog))
return;
}
} catch (IOException e) {
sampleView.showError(e);
}
@@ -235,8 +235,7 @@ public class ShaderEditor extends Composite implements SelectionListener, Extend
matchingContext = true;
break;
}
if (matchingContext)
{
if (matchingContext) {
shadersToUpload.remove(i);
break;
}
@@ -270,7 +269,8 @@ public class ShaderEditor extends Composite implements SelectionListener, Extend
}
});
} else
for (GLProgram program : shader.programs) {
for (int programName : shader.programs) {
GLProgram program = shader.context.GetProgram(programName);
ExchangeMessage(contextId, queue, "glLinkProgram(%d)", program.name);
rcv = ExchangeMessage(contextId, queue,
"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+");
final int contextId = Integer.parseInt(details[0], 16);
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);
}