GLES2Dbg: implemented shader tracking and editing
Next commit is improving the protocol and checking errors after shader upload Change-Id: I6afe3b63a68e00cd395885fd26cd6fcb311cfbec Signed-off-by: David Li <davidxli@google.com>
This commit is contained in:
@@ -21,7 +21,6 @@ import com.android.glesv2debugger.DebuggerMessage.Message.Function;
|
|||||||
import com.android.glesv2debugger.DebuggerMessage.Message.Prop;
|
import com.android.glesv2debugger.DebuggerMessage.Message.Prop;
|
||||||
import com.android.glesv2debugger.DebuggerMessage.Message.Type;
|
import com.android.glesv2debugger.DebuggerMessage.Message.Type;
|
||||||
import org.eclipse.jface.dialogs.InputDialog;
|
import org.eclipse.jface.dialogs.InputDialog;
|
||||||
import org.eclipse.jface.dialogs.MessageDialog;
|
|
||||||
import org.eclipse.jface.window.Window;
|
import org.eclipse.jface.window.Window;
|
||||||
import org.eclipse.swt.SWT;
|
import org.eclipse.swt.SWT;
|
||||||
import org.eclipse.swt.custom.ScrolledComposite;
|
import org.eclipse.swt.custom.ScrolledComposite;
|
||||||
@@ -42,7 +41,6 @@ public class BreakpointOption extends ScrolledComposite implements SelectionList
|
|||||||
|
|
||||||
SampleView sampleView;
|
SampleView sampleView;
|
||||||
HashMap<Function, Button> buttonsBreak = new HashMap<Function, Button>();
|
HashMap<Function, Button> buttonsBreak = new HashMap<Function, Button>();
|
||||||
MessageParserEx messageParserEx = new MessageParserEx();
|
|
||||||
|
|
||||||
BreakpointOption(SampleView sampleView, Composite parent) {
|
BreakpointOption(SampleView sampleView, Composite parent) {
|
||||||
super(parent, SWT.NO_BACKGROUND | SWT.V_SCROLL | SWT.H_SCROLL);
|
super(parent, SWT.NO_BACKGROUND | SWT.V_SCROLL | SWT.H_SCROLL);
|
||||||
@@ -72,7 +70,6 @@ public class BreakpointOption extends ScrolledComposite implements SelectionList
|
|||||||
this.setExpandVertical(true);
|
this.setExpandVertical(true);
|
||||||
this.setMinSize(size);
|
this.setMinSize(size);
|
||||||
this.layout();
|
this.layout();
|
||||||
// this.pack(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetBreakpoint(Function function, boolean enabled) {
|
void SetBreakpoint(Function function, boolean enabled) {
|
||||||
@@ -140,7 +137,8 @@ public class BreakpointOption extends ScrolledComposite implements SelectionList
|
|||||||
SetBreakpoint(msg.getFunction(), false);
|
SetBreakpoint(msg.getFunction(), false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
messageParserEx.Parse(builder, inputDialog.getValue());
|
MessageParserEx.instance.Parse(builder, inputDialog.getValue());
|
||||||
|
builder.setExpectResponse(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -18,13 +18,21 @@ package com.android.glesv2debugger;
|
|||||||
|
|
||||||
import com.android.glesv2debugger.DebuggerMessage.Message;
|
import com.android.glesv2debugger.DebuggerMessage.Message;
|
||||||
|
|
||||||
public class Context {
|
import java.util.ArrayList;
|
||||||
public int contextId;
|
|
||||||
public GLServerVertex serverVertex = new GLServerVertex();
|
|
||||||
public byte [] readPixelRef = new byte [0];
|
|
||||||
|
|
||||||
public Message ProcessMessage(Message msg)
|
public class Context {
|
||||||
{
|
public final int contextId;
|
||||||
|
ArrayList<Context> shares = new ArrayList<Context>(); // includes self
|
||||||
|
public GLServerVertex serverVertex = new GLServerVertex();
|
||||||
|
public GLServerShader serverShader = new GLServerShader(this);
|
||||||
|
public byte[] readPixelRef = new byte[0];
|
||||||
|
|
||||||
|
public Context(int contextId) {
|
||||||
|
this.contextId = contextId;
|
||||||
|
shares.add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Message ProcessMessage(Message msg) {
|
||||||
switch (msg.getFunction()) {
|
switch (msg.getFunction()) {
|
||||||
case glBindBuffer:
|
case glBindBuffer:
|
||||||
serverVertex.glBindBuffer(msg);
|
serverVertex.glBindBuffer(msg);
|
||||||
@@ -83,6 +91,7 @@ public class Context {
|
|||||||
serverVertex.glVertexAttrib4fv(msg);
|
serverVertex.glVertexAttrib4fv(msg);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
serverShader.ProcessMessage(msg);
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -446,7 +446,8 @@ public final class DebuggerMessage {
|
|||||||
implements com.google.protobuf.Internal.EnumLite {
|
implements com.google.protobuf.Internal.EnumLite {
|
||||||
BeforeCall(0, 0),
|
BeforeCall(0, 0),
|
||||||
AfterCall(1, 1),
|
AfterCall(1, 1),
|
||||||
Response(2, 2),
|
AfterGeneratedCall(2, 2),
|
||||||
|
Response(3, 3),
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
@@ -456,7 +457,8 @@ public final class DebuggerMessage {
|
|||||||
switch (value) {
|
switch (value) {
|
||||||
case 0: return BeforeCall;
|
case 0: return BeforeCall;
|
||||||
case 1: return AfterCall;
|
case 1: return AfterCall;
|
||||||
case 2: return Response;
|
case 2: return AfterGeneratedCall;
|
||||||
|
case 3: return Response;
|
||||||
default: return null;
|
default: return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,206 @@
|
|||||||
|
/*
|
||||||
|
** 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 java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
class GLShader {
|
||||||
|
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;
|
||||||
|
|
||||||
|
GLShader(final int name, final GLServerShader context, final GLEnum type) {
|
||||||
|
this.name = name;
|
||||||
|
this.context = context;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GLProgram {
|
||||||
|
final int name;
|
||||||
|
final GLServerShader context; // the context this was created in
|
||||||
|
boolean delete;
|
||||||
|
GLShader vert, frag;
|
||||||
|
|
||||||
|
GLProgram(final int name, final GLServerShader context) {
|
||||||
|
this.name = name;
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
GLServerShader(final Context context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ProcessMessage(final Message msg) {
|
||||||
|
boolean oldUiUpdate = uiUpdate;
|
||||||
|
uiUpdate = true;
|
||||||
|
switch (msg.getFunction()) {
|
||||||
|
case glAttachShader:
|
||||||
|
glAttachShader(msg);
|
||||||
|
break;
|
||||||
|
case glCreateProgram:
|
||||||
|
glCreateProgram(msg);
|
||||||
|
break;
|
||||||
|
case glCreateShader:
|
||||||
|
glCreateShader(msg);
|
||||||
|
break;
|
||||||
|
case glDeleteProgram:
|
||||||
|
glDeleteProgram(msg);
|
||||||
|
break;
|
||||||
|
case glDeleteShader:
|
||||||
|
glDeleteShader(msg);
|
||||||
|
break;
|
||||||
|
case glDetachShader:
|
||||||
|
glDetachShader(msg);
|
||||||
|
break;
|
||||||
|
case glShaderSource:
|
||||||
|
glShaderSource(msg);
|
||||||
|
break;
|
||||||
|
case glUseProgram:
|
||||||
|
glUseProgram(msg);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
uiUpdate = oldUiUpdate;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GLShader GetShader(int name) {
|
||||||
|
if (name == 0)
|
||||||
|
return null;
|
||||||
|
for (Context ctx : context.shares) {
|
||||||
|
GLShader shader = ctx.serverShader.privateShaders.get(name);
|
||||||
|
if (shader != null)
|
||||||
|
return shader;
|
||||||
|
}
|
||||||
|
assert false;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLProgram GetProgram(int name) {
|
||||||
|
if (name == 0)
|
||||||
|
return null;
|
||||||
|
for (Context ctx : context.shares) {
|
||||||
|
GLProgram program = ctx.serverShader.privatePrograms.get(name);
|
||||||
|
if (program != null)
|
||||||
|
return program;
|
||||||
|
}
|
||||||
|
assert false;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// void API_ENTRY(glAttachShader)(GLuint program, GLuint shader)
|
||||||
|
void glAttachShader(final Message msg) {
|
||||||
|
GLProgram program = GetProgram(msg.getArg0());
|
||||||
|
GLShader shader = GetShader(msg.getArg1());
|
||||||
|
if (GLEnum.GL_VERTEX_SHADER == shader.type)
|
||||||
|
program.vert = shader;
|
||||||
|
else
|
||||||
|
program.frag = shader;
|
||||||
|
shader.programs.add(program);
|
||||||
|
}
|
||||||
|
|
||||||
|
// GLuint API_ENTRY(glCreateProgram)(void)
|
||||||
|
void glCreateProgram(final Message msg) {
|
||||||
|
privatePrograms.put(msg.getRet(), new GLProgram(msg.getRet(), this));
|
||||||
|
}
|
||||||
|
|
||||||
|
// GLuint API_ENTRY(glCreateShader)(GLenum type)
|
||||||
|
void glCreateShader(final Message msg) {
|
||||||
|
privateShaders.put(msg.getRet(),
|
||||||
|
new GLShader(msg.getRet(), this, GLEnum.valueOf(msg.getArg0())));
|
||||||
|
}
|
||||||
|
|
||||||
|
// void API_ENTRY(glDeleteProgram)
|
||||||
|
void glDeleteProgram(final Message msg) {
|
||||||
|
if (msg.getArg0() == 0)
|
||||||
|
return;
|
||||||
|
GLProgram program = GetProgram(msg.getArg0());
|
||||||
|
program.delete = true;
|
||||||
|
for (Context ctx : context.shares)
|
||||||
|
if (ctx.serverShader.current == program)
|
||||||
|
return;
|
||||||
|
glDetachShader(program, program.vert);
|
||||||
|
glDetachShader(program, program.frag);
|
||||||
|
privatePrograms.remove(program.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// void API_ENTRY(glDeleteShader)(GLuint shader)
|
||||||
|
void glDeleteShader(final Message msg) {
|
||||||
|
if (msg.getArg0() == 0)
|
||||||
|
return;
|
||||||
|
GLShader shader = GetShader(msg.getArg0());
|
||||||
|
shader.delete = true;
|
||||||
|
if (shader.programs.size() == 0)
|
||||||
|
privateShaders.remove(shader.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// void API_ENTRY(glDetachShader)(GLuint program, GLuint shader)
|
||||||
|
void glDetachShader(final Message msg) {
|
||||||
|
glDetachShader(GetProgram(msg.getArg0()), GetShader(msg.getArg1()));
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
shader.programs.remove(program);
|
||||||
|
if (shader.delete && shader.programs.size() == 0)
|
||||||
|
shader.context.privateShaders.remove(shader.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// void API_ENTRY(glShaderSource)(GLuint shader, GLsizei count, const
|
||||||
|
// GLchar** string, const GLint* length)
|
||||||
|
void glShaderSource(final Message msg) {
|
||||||
|
if (!msg.hasData())
|
||||||
|
return; // TODO: distinguish between generated calls
|
||||||
|
GLShader shader = GetShader(msg.getArg0());
|
||||||
|
shader.source = shader.originalSource = msg.getData().toStringUtf8();
|
||||||
|
}
|
||||||
|
|
||||||
|
// void API_ENTRY(glUseProgram)(GLuint program)
|
||||||
|
void glUseProgram(final Message msg) {
|
||||||
|
GLProgram oldCurrent = current;
|
||||||
|
current = GetProgram(msg.getArg0());
|
||||||
|
if (null != oldCurrent && oldCurrent.delete && oldCurrent != current)
|
||||||
|
{
|
||||||
|
for (Context ctx : context.shares)
|
||||||
|
if (ctx.serverShader.current == oldCurrent)
|
||||||
|
return;
|
||||||
|
oldCurrent.context.privatePrograms.remove(oldCurrent.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,6 +19,7 @@ package com.android.glesv2debugger;
|
|||||||
import com.android.glesv2debugger.DebuggerMessage.Message;
|
import com.android.glesv2debugger.DebuggerMessage.Message;
|
||||||
import com.android.glesv2debugger.DebuggerMessage.Message.DataType;
|
import com.android.glesv2debugger.DebuggerMessage.Message.DataType;
|
||||||
import com.android.glesv2debugger.DebuggerMessage.Message.Function;
|
import com.android.glesv2debugger.DebuggerMessage.Message.Function;
|
||||||
|
import com.android.glesv2debugger.DebuggerMessage.Message.Type;
|
||||||
|
|
||||||
import org.eclipse.swt.graphics.Device;
|
import org.eclipse.swt.graphics.Device;
|
||||||
import org.eclipse.swt.graphics.Image;
|
import org.eclipse.swt.graphics.Image;
|
||||||
@@ -51,11 +52,16 @@ public class MessageData {
|
|||||||
builder.append(String.format(":%.3f", msg.getClock()));
|
builder.append(String.format(":%.3f", msg.getClock()));
|
||||||
builder.append(String.format(" 0x%08X", msg.getContextId()));
|
builder.append(String.format(" 0x%08X", msg.getContextId()));
|
||||||
builder.append(" ");
|
builder.append(" ");
|
||||||
|
if (msg.getType() == Type.BeforeCall) // incomplete call, client SKIPPED
|
||||||
|
builder.append("[BeforeCall(AfterCall missing)] ");
|
||||||
|
else if (msg.getType() == Type.AfterGeneratedCall)
|
||||||
|
builder.append("[AfterGeneratedCall] ");
|
||||||
|
else
|
||||||
|
assert msg.getType() == Type.AfterCall;
|
||||||
builder.append(MessageFormatter.Format(msg));
|
builder.append(MessageFormatter.Format(msg));
|
||||||
switch (function) {
|
switch (function) {
|
||||||
case glDrawArrays: // msg was modified by GLServerVertex
|
case glDrawArrays: // msg was modified by GLServerVertex
|
||||||
case glDrawElements:
|
case glDrawElements:
|
||||||
assert msg.hasData();
|
|
||||||
if (!msg.hasArg8() || !msg.hasData())
|
if (!msg.hasArg8() || !msg.hasData())
|
||||||
break;
|
break;
|
||||||
dataType = GLEnum.valueOf(msg.getArg8());
|
dataType = GLEnum.valueOf(msg.getArg8());
|
||||||
|
|||||||
@@ -301,4 +301,5 @@ public class MessageParserEx extends MessageParser {
|
|||||||
// TODO: GLvoid* ptr
|
// TODO: GLvoid* ptr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final static MessageParserEx instance = new MessageParserEx();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,10 +20,6 @@ import com.android.glesv2debugger.DebuggerMessage.Message;
|
|||||||
import com.android.glesv2debugger.DebuggerMessage.Message.Function;
|
import com.android.glesv2debugger.DebuggerMessage.Message.Function;
|
||||||
import com.android.glesv2debugger.DebuggerMessage.Message.Type;
|
import com.android.glesv2debugger.DebuggerMessage.Message.Type;
|
||||||
|
|
||||||
import org.eclipse.jface.dialogs.MessageDialog;
|
|
||||||
import org.eclipse.swt.SWT;
|
|
||||||
import org.eclipse.swt.widgets.Shell;
|
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.EOFException;
|
import java.io.EOFException;
|
||||||
@@ -85,6 +81,12 @@ public class MessageQueue implements Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void AddCommands(ArrayList<Message> cmds) {
|
||||||
|
synchronized (commands) {
|
||||||
|
commands.addAll(cmds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
Socket socket = new Socket();
|
Socket socket = new Socket();
|
||||||
@@ -101,7 +103,6 @@ public class MessageQueue implements Runnable {
|
|||||||
Error(e);
|
Error(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
// try {
|
|
||||||
while (running) {
|
while (running) {
|
||||||
Message msg = null;
|
Message msg = null;
|
||||||
if (incoming.size() > 0) { // find queued incoming
|
if (incoming.size() > 0) { // find queued incoming
|
||||||
@@ -126,8 +127,10 @@ public class MessageQueue implements Runnable {
|
|||||||
|
|
||||||
int contextId = msg.getContextId();
|
int contextId = msg.getContextId();
|
||||||
if (!incoming.containsKey(contextId))
|
if (!incoming.containsKey(contextId))
|
||||||
incoming.put(contextId,
|
incoming.put(contextId, new ArrayList<Message>());
|
||||||
new ArrayList<Message>());
|
|
||||||
|
if (msg.getType() == Type.AfterGeneratedCall)
|
||||||
|
continue; // TODO: for now, don't care
|
||||||
|
|
||||||
// FIXME: the expected sequence will change for interactive mode
|
// FIXME: the expected sequence will change for interactive mode
|
||||||
while (msg.getType() == Type.BeforeCall) {
|
while (msg.getType() == Type.BeforeCall) {
|
||||||
@@ -149,6 +152,9 @@ public class MessageQueue implements Runnable {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (next.getType() == Type.AfterGeneratedCall)
|
||||||
|
continue; // TODO: for now, don't care
|
||||||
|
|
||||||
if (next.getContextId() != contextId) {
|
if (next.getContextId() != contextId) {
|
||||||
// message part not for this context
|
// message part not for this context
|
||||||
if (!incoming.containsKey(next.getContextId()))
|
if (!incoming.containsKey(next.getContextId()))
|
||||||
@@ -176,13 +182,14 @@ public class MessageQueue implements Runnable {
|
|||||||
Error(e);
|
Error(e);
|
||||||
running = false;
|
running = false;
|
||||||
}
|
}
|
||||||
// } catch (Exception e) {
|
|
||||||
// Error(e);
|
|
||||||
// running = false;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Message RemoveMessage(int contextId) {
|
Message GetMessage(int contextId) {
|
||||||
|
// ReadMessage and filter by contextId
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Message RemoveCompleteMessage(int contextId) {
|
||||||
synchronized (complete) {
|
synchronized (complete) {
|
||||||
if (complete.size() == 0)
|
if (complete.size() == 0)
|
||||||
return null;
|
return null;
|
||||||
@@ -244,10 +251,12 @@ public class MessageQueue implements Runnable {
|
|||||||
builder.setFunction(Function.CONTINUE);
|
builder.setFunction(Function.CONTINUE);
|
||||||
else if (msg.getType() == Type.AfterCall)
|
else if (msg.getType() == Type.AfterCall)
|
||||||
builder.setFunction(Function.SKIP);
|
builder.setFunction(Function.SKIP);
|
||||||
|
else if (msg.getType() == Type.AfterGeneratedCall)
|
||||||
|
builder.setFunction(Function.SKIP);
|
||||||
else
|
else
|
||||||
assert false;
|
assert false;
|
||||||
builder.setType(Type.Response);
|
builder.setType(Type.Response);
|
||||||
builder.setExpectResponse(false);
|
builder.setExpectResponse(msg.getExpectResponse());
|
||||||
if (msg.getExpectResponse())
|
if (msg.getExpectResponse())
|
||||||
sampleView.breakpointOption.BreakpointReached(builder, msg);
|
sampleView.breakpointOption.BreakpointReached(builder, msg);
|
||||||
if (SendCommands(dos, 0) || msg.getExpectResponse())
|
if (SendCommands(dos, 0) || msg.getExpectResponse())
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ public class SampleView extends ViewPart implements Runnable {
|
|||||||
LayoutComposite layoutComposite;
|
LayoutComposite layoutComposite;
|
||||||
ListViewer viewer;
|
ListViewer viewer;
|
||||||
BreakpointOption breakpointOption;
|
BreakpointOption breakpointOption;
|
||||||
|
ShaderEditor shaderEditor;
|
||||||
org.eclipse.swt.widgets.Canvas canvas;
|
org.eclipse.swt.widgets.Canvas canvas;
|
||||||
Text text;
|
Text text;
|
||||||
Action actionConnect; // connect / disconnect
|
Action actionConnect; // connect / disconnect
|
||||||
@@ -239,11 +240,6 @@ public class SampleView extends ViewPart implements Runnable {
|
|||||||
// Create the help context id for the viewer's control
|
// Create the help context id for the viewer's control
|
||||||
PlatformUI.getWorkbench().getHelpSystem()
|
PlatformUI.getWorkbench().getHelpSystem()
|
||||||
.setHelp(viewer.getControl(), "GLESv2DebuggerClient.viewer");
|
.setHelp(viewer.getControl(), "GLESv2DebuggerClient.viewer");
|
||||||
makeActions();
|
|
||||||
hookContextMenu();
|
|
||||||
hookDoubleClickAction();
|
|
||||||
hookSelectionChanged();
|
|
||||||
contributeToActionBars();
|
|
||||||
|
|
||||||
layoutComposite = new LayoutComposite(parent, 0);
|
layoutComposite = new LayoutComposite(parent, 0);
|
||||||
layoutComposite.setLayout(new FillLayout());
|
layoutComposite.setLayout(new FillLayout());
|
||||||
@@ -257,6 +253,7 @@ public class SampleView extends ViewPart implements Runnable {
|
|||||||
canvas.setVisible(false);
|
canvas.setVisible(false);
|
||||||
|
|
||||||
breakpointOption = new BreakpointOption(this, layoutComposite);
|
breakpointOption = new BreakpointOption(this, layoutComposite);
|
||||||
|
shaderEditor = new ShaderEditor(this, layoutComposite);
|
||||||
|
|
||||||
final ScrollBar hBar = canvas.getHorizontalBar();
|
final ScrollBar hBar = canvas.getHorizontalBar();
|
||||||
hBar.addListener(SWT.Selection, new Listener() {
|
hBar.addListener(SWT.Selection, new Listener() {
|
||||||
@@ -335,6 +332,12 @@ public class SampleView extends ViewPart implements Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
makeActions();
|
||||||
|
hookContextMenu();
|
||||||
|
hookDoubleClickAction();
|
||||||
|
hookSelectionChanged();
|
||||||
|
contributeToActionBars();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void hookContextMenu() {
|
private void hookContextMenu() {
|
||||||
@@ -465,7 +468,18 @@ public class SampleView extends ViewPart implements Runnable {
|
|||||||
{
|
{
|
||||||
breakpointOption.setVisible(!breakpointOption.isVisible());
|
breakpointOption.setVisible(!breakpointOption.isVisible());
|
||||||
layoutComposite.layout(true);
|
layoutComposite.layout(true);
|
||||||
manager.update(true);
|
}
|
||||||
|
};
|
||||||
|
action.setChecked(true);
|
||||||
|
manager.add(action);
|
||||||
|
|
||||||
|
action = new Action("Shaders", Action.AS_CHECK_BOX)
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
shaderEditor.setVisible(!shaderEditor.isVisible());
|
||||||
|
layoutComposite.layout(true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
action.setChecked(true);
|
action.setChecked(true);
|
||||||
@@ -606,14 +620,24 @@ public class SampleView extends ViewPart implements Runnable {
|
|||||||
showError(e1);
|
showError(e1);
|
||||||
}
|
}
|
||||||
ArrayList<MessageData> msgs = new ArrayList<MessageData>();
|
ArrayList<MessageData> msgs = new ArrayList<MessageData>();
|
||||||
|
boolean shaderEditorUpdate = false;
|
||||||
while (running) {
|
while (running) {
|
||||||
if (!messageQueue.IsRunning())
|
if (!messageQueue.IsRunning())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
Message msg = messageQueue.RemoveMessage(0);
|
Message msg = messageQueue.RemoveCompleteMessage(0);
|
||||||
if (msgs.size() > 60 || (msgs.size() > 0 && null == msg)) {
|
if (msgs.size() > 60 || (msgs.size() > 0 && null == msg)) {
|
||||||
viewContentProvider.add(msgs);
|
viewContentProvider.add(msgs);
|
||||||
msgs.clear();
|
msgs.clear();
|
||||||
|
|
||||||
|
if (shaderEditorUpdate)
|
||||||
|
this.getSite().getShell().getDisplay().syncExec(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
shaderEditor.Update();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
shaderEditorUpdate = false;
|
||||||
}
|
}
|
||||||
if (null == msg) {
|
if (null == msg) {
|
||||||
try {
|
try {
|
||||||
@@ -626,10 +650,11 @@ public class SampleView extends ViewPart implements Runnable {
|
|||||||
|
|
||||||
Context context = contexts.get(msg.getContextId());
|
Context context = contexts.get(msg.getContextId());
|
||||||
if (null == context) {
|
if (null == context) {
|
||||||
context = new Context();
|
context = new Context(msg.getContextId());
|
||||||
contexts.put(msg.getContextId(), context);
|
contexts.put(msg.getContextId(), context);
|
||||||
}
|
}
|
||||||
msg = context.ProcessMessage(msg);
|
msg = context.ProcessMessage(msg);
|
||||||
|
shaderEditorUpdate |= context.serverShader.uiUpdate;
|
||||||
|
|
||||||
final MessageData msgData = new MessageData(this.getViewSite()
|
final MessageData msgData = new MessageData(this.getViewSite()
|
||||||
.getShell().getDisplay(), msg, context);
|
.getShell().getDisplay(), msg, context);
|
||||||
|
|||||||
@@ -0,0 +1,240 @@
|
|||||||
|
/*
|
||||||
|
** 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.Type;
|
||||||
|
|
||||||
|
import org.eclipse.jface.dialogs.MessageDialog;
|
||||||
|
import org.eclipse.swt.SWT;
|
||||||
|
import org.eclipse.swt.custom.ExtendedModifyEvent;
|
||||||
|
import org.eclipse.swt.custom.ExtendedModifyListener;
|
||||||
|
import org.eclipse.swt.custom.StyleRange;
|
||||||
|
import org.eclipse.swt.custom.StyledText;
|
||||||
|
import org.eclipse.swt.events.SelectionEvent;
|
||||||
|
import org.eclipse.swt.events.SelectionListener;
|
||||||
|
import org.eclipse.swt.graphics.Font;
|
||||||
|
import org.eclipse.swt.layout.GridData;
|
||||||
|
import org.eclipse.swt.layout.GridLayout;
|
||||||
|
import org.eclipse.swt.widgets.Composite;
|
||||||
|
import org.eclipse.swt.widgets.List;
|
||||||
|
import org.eclipse.swt.widgets.ToolBar;
|
||||||
|
import org.eclipse.swt.widgets.ToolItem;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class ShaderEditor extends Composite implements SelectionListener, ExtendedModifyListener {
|
||||||
|
SampleView sampleView;
|
||||||
|
|
||||||
|
ToolBar toolbar;
|
||||||
|
ToolItem uploadShader, restoreShader;
|
||||||
|
List list;
|
||||||
|
StyledText styledText;
|
||||||
|
|
||||||
|
GLShader current;
|
||||||
|
|
||||||
|
ArrayList<Message> cmds = new ArrayList<Message>();
|
||||||
|
|
||||||
|
ShaderEditor(SampleView sampleView, Composite parent) {
|
||||||
|
super(parent, 0);
|
||||||
|
this.sampleView = sampleView;
|
||||||
|
|
||||||
|
GridLayout gridLayout = new GridLayout();
|
||||||
|
gridLayout.numColumns = 1;
|
||||||
|
this.setLayout(gridLayout);
|
||||||
|
|
||||||
|
toolbar = new ToolBar(this, SWT.BORDER);
|
||||||
|
|
||||||
|
uploadShader = new ToolItem(toolbar, SWT.PUSH);
|
||||||
|
uploadShader.setText("Upload Shader");
|
||||||
|
uploadShader.addSelectionListener(this);
|
||||||
|
|
||||||
|
restoreShader = new ToolItem(toolbar, SWT.PUSH);
|
||||||
|
restoreShader.setText("Original Shader");
|
||||||
|
restoreShader.addSelectionListener(this);
|
||||||
|
|
||||||
|
list = new List(this, SWT.V_SCROLL);
|
||||||
|
list.setFont(new Font(parent.getDisplay(), "Courier", 10, 0));
|
||||||
|
list.addSelectionListener(this);
|
||||||
|
GridData gridData = new GridData();
|
||||||
|
gridData.horizontalAlignment = SWT.FILL;
|
||||||
|
gridData.grabExcessHorizontalSpace = true;
|
||||||
|
gridData.verticalAlignment = SWT.FILL;
|
||||||
|
gridData.grabExcessVerticalSpace = true;
|
||||||
|
list.setLayoutData(gridData);
|
||||||
|
|
||||||
|
styledText = new StyledText(this, SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI);
|
||||||
|
gridData = new GridData();
|
||||||
|
gridData.horizontalAlignment = SWT.FILL;
|
||||||
|
gridData.grabExcessHorizontalSpace = true;
|
||||||
|
gridData.verticalAlignment = SWT.FILL;
|
||||||
|
gridData.grabExcessVerticalSpace = true;
|
||||||
|
styledText.setLayoutData(gridData);
|
||||||
|
styledText.addExtendedModifyListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update() {
|
||||||
|
list.removeAll();
|
||||||
|
for (Context context : sampleView.contexts.values()) {
|
||||||
|
for (GLShader shader : context.serverShader.privateShaders.values()) {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
builder.append(String.format("%08X", context.contextId));
|
||||||
|
builder.append(' ');
|
||||||
|
builder.append(shader.type);
|
||||||
|
while (builder.length() < 30)
|
||||||
|
builder.append(" ");
|
||||||
|
builder.append(shader.name);
|
||||||
|
while (builder.length() < 40)
|
||||||
|
builder.append(" ");
|
||||||
|
builder.append(':');
|
||||||
|
for (Context ctx : context.shares) {
|
||||||
|
builder.append(String.format("%08X", ctx.contextId));
|
||||||
|
builder.append(' ');
|
||||||
|
}
|
||||||
|
builder.append(':');
|
||||||
|
for (GLProgram program : shader.programs) {
|
||||||
|
builder.append(program.name);
|
||||||
|
builder.append(" ");
|
||||||
|
}
|
||||||
|
list.add(builder.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UploadShader() {
|
||||||
|
current.source = styledText.getText();
|
||||||
|
|
||||||
|
ArrayList<Message> cmds = new ArrayList<Message>();
|
||||||
|
final int contextId = current.context.context.contextId;
|
||||||
|
|
||||||
|
Message.Builder builder = GetBuilder(contextId);
|
||||||
|
MessageParserEx.instance.Parse(builder,
|
||||||
|
String.format("glShaderSource(%d,1,\"%s\",0)", current.name, current.source));
|
||||||
|
cmds.add(builder.build());
|
||||||
|
|
||||||
|
builder = GetBuilder(contextId);
|
||||||
|
MessageParserEx.instance.Parse(builder,
|
||||||
|
String.format("glCompileShader(%d)", current.name));
|
||||||
|
cmds.add(builder.build());
|
||||||
|
|
||||||
|
for (GLProgram program : current.programs) {
|
||||||
|
builder = GetBuilder(contextId);
|
||||||
|
MessageParserEx.instance.Parse(builder,
|
||||||
|
String.format("glLinkProgram(%d)", program.name));
|
||||||
|
cmds.add(builder.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
sampleView.messageQueue.AddCommands(cmds);
|
||||||
|
}
|
||||||
|
|
||||||
|
Message.Builder GetBuilder(int contextId) {
|
||||||
|
Message.Builder builder = Message.newBuilder();
|
||||||
|
builder.setContextId(contextId);
|
||||||
|
builder.setType(Type.Response);
|
||||||
|
builder.setExpectResponse(false);
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void widgetSelected(SelectionEvent e) {
|
||||||
|
if (e.getSource() == uploadShader && null != current) {
|
||||||
|
UploadShader();
|
||||||
|
return;
|
||||||
|
} else if (e.getSource() == restoreShader && null != current) {
|
||||||
|
current.source = styledText.getText();
|
||||||
|
styledText.setText(current.originalSource);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (list.getSelectionCount() < 1)
|
||||||
|
return;
|
||||||
|
if (null != current && !current.source.equals(styledText.getText())) {
|
||||||
|
String[] btns = {
|
||||||
|
"&Upload", "&Save", "&Discard"
|
||||||
|
};
|
||||||
|
MessageDialog dialog = new MessageDialog(this.getShell(), "Shader Edited",
|
||||||
|
null, "Shader source has been edited", MessageDialog.QUESTION, btns, 0);
|
||||||
|
int rc = dialog.open();
|
||||||
|
if (rc == SWT.DEFAULT || rc == 0)
|
||||||
|
UploadShader();
|
||||||
|
else if (rc == 1)
|
||||||
|
current.source = styledText.getText();
|
||||||
|
// else if (rc == 2) do nothing; selection is changing
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
styledText.setText(current.source);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void widgetDefaultSelected(SelectionEvent e) {
|
||||||
|
widgetSelected(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void modifyText(ExtendedModifyEvent event) {
|
||||||
|
final String[] keywords = {
|
||||||
|
"gl_Position", "gl_FragColor"
|
||||||
|
};
|
||||||
|
// FIXME: proper scanner for syntax highlighting
|
||||||
|
String text = styledText.getText();
|
||||||
|
int start = event.start;
|
||||||
|
int end = event.start + event.length;
|
||||||
|
start -= 20; // deleting chars from keyword causes rescan
|
||||||
|
end += 20;
|
||||||
|
if (start < 0)
|
||||||
|
start = 0;
|
||||||
|
if (end > text.length())
|
||||||
|
end = text.length();
|
||||||
|
if (null != styledText.getStyleRangeAtOffset(event.start)) {
|
||||||
|
StyleRange clearStyleRange = new StyleRange();
|
||||||
|
clearStyleRange.start = start;
|
||||||
|
clearStyleRange.length = end - start;
|
||||||
|
clearStyleRange.foreground = event.display.getSystemColor(SWT.COLOR_BLACK);
|
||||||
|
styledText.setStyleRange(clearStyleRange);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (start < end) {
|
||||||
|
for (final String keyword : keywords) {
|
||||||
|
if (!text.substring(start).startsWith(keyword))
|
||||||
|
continue;
|
||||||
|
if (start > 0) {
|
||||||
|
final char before = text.charAt(start - 1);
|
||||||
|
if (Character.isLetterOrDigit(before))
|
||||||
|
continue;
|
||||||
|
else if (before == '_')
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (start + keyword.length() < text.length()) {
|
||||||
|
final char after = text.charAt(start + keyword.length());
|
||||||
|
if (Character.isLetterOrDigit(after))
|
||||||
|
continue;
|
||||||
|
else if (after == '_')
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
StyleRange style1 = new StyleRange();
|
||||||
|
style1.start = start;
|
||||||
|
style1.length = keyword.length();
|
||||||
|
style1.foreground = event.display.getSystemColor(SWT.COLOR_BLUE);
|
||||||
|
styledText.setStyleRange(style1);
|
||||||
|
}
|
||||||
|
start++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user