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"?>
<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);
}