From 4633d9e54629f908b91df8c6e54cf32c9d30d8ad Mon Sep 17 00:00:00 2001 From: shadowislord Date: Mon, 19 Jan 2015 18:20:54 -0500 Subject: [PATCH] Add GL wrappers for debugging and tracing --- .../com/jme3/renderer/opengl/GLDebug.java | 49 ++ .../com/jme3/renderer/opengl/GLDebugES.java | 524 ++++++++++++++++++ .../com/jme3/renderer/opengl/GLDebugGL2.java | 77 +++ .../com/jme3/renderer/opengl/GLTracer.java | 31 +- 4 files changed, 680 insertions(+), 1 deletion(-) create mode 100644 jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebug.java create mode 100644 jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugES.java create mode 100644 jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugGL2.java diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebug.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebug.java new file mode 100644 index 000000000..5b9c94d44 --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebug.java @@ -0,0 +1,49 @@ +package com.jme3.renderer.opengl; + +import com.jme3.renderer.RendererException; + +public abstract class GLDebug { + + protected GL gl; + + protected String decodeError(int err) { + String errMsg; + switch (err) { + case GL.GL_NO_ERROR: + errMsg = "No Error"; + break; + case GL.GL_INVALID_ENUM: + errMsg = "Invalid enum argument"; + break; + case GL.GL_INVALID_OPERATION: + errMsg = "Invalid operation"; + break; + case GL.GL_INVALID_VALUE: + errMsg = "Invalid numeric argument"; + break; + case GL.GL_OUT_OF_MEMORY: + errMsg = "Out of memory"; + break; + case GLFbo.GL_INVALID_FRAMEBUFFER_OPERATION_EXT: + errMsg = "Framebuffer is not complete"; + break; + case GL2.GL_STACK_OVERFLOW: + errMsg = "Internal stack overflow"; + break; + case GL2.GL_STACK_UNDERFLOW: + errMsg = "Internal stack underflow"; + break; + default: + errMsg = "Unknown"; + break; + } + return errMsg + " (Error Code: " + err + ")"; + } + + protected void checkError() { + int err = gl.glGetError(); + if (err != 0) { + throw new RendererException("An OpenGL error occurred - " + decodeError(err)); + } + } +} diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugES.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugES.java new file mode 100644 index 000000000..3d5f0dc81 --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugES.java @@ -0,0 +1,524 @@ +package com.jme3.renderer.opengl; + +import java.nio.ByteBuffer; +import java.nio.FloatBuffer; +import java.nio.IntBuffer; +import java.nio.ShortBuffer; + +public class GLDebugES extends GLDebug implements GL, GLFbo, GLExt { + + private final GLFbo glfbo; + private final GLExt glext; + + public GLDebugES(GL gl, GLFbo glfbo) { + this.gl = gl; +// this.gl2 = gl instanceof GL2 ? (GL2) gl : null; +// this.gl3 = gl instanceof GL3 ? (GL3) gl : null; + this.glfbo = glfbo; + this.glext = glfbo instanceof GLExt ? (GLExt) glfbo : null; + } + + public void glActiveTexture(int texture) { + gl.glActiveTexture(texture); + checkError(); + } + + public void glAttachShader(int program, int shader) { + gl.glAttachShader(program, shader); + checkError(); + } + + public void glBindBuffer(int target, int buffer) { + gl.glBindBuffer(target, buffer); + checkError(); + } + + public void glBindTexture(int target, int texture) { + gl.glBindTexture(target, texture); + checkError(); + } + + public void glBlendFunc(int sfactor, int dfactor) { + gl.glBlendFunc(sfactor, dfactor); + checkError(); + } + + public void glBufferData(int target, FloatBuffer data, int usage) { + gl.glBufferData(target, data, usage); + checkError(); + } + + public void glBufferData(int target, ShortBuffer data, int usage) { + gl.glBufferData(target, data, usage); + checkError(); + } + + public void glBufferData(int target, ByteBuffer data, int usage) { + gl.glBufferData(target, data, usage); + checkError(); + } + + public void glBufferSubData(int target, long offset, FloatBuffer data) { + gl.glBufferSubData(target, offset, data); + checkError(); + } + + public void glBufferSubData(int target, long offset, ShortBuffer data) { + gl.glBufferSubData(target, offset, data); + checkError(); + } + + public void glBufferSubData(int target, long offset, ByteBuffer data) { + gl.glBufferSubData(target, offset, data); + checkError(); + } + + public void glClear(int mask) { + gl.glClear(mask); + checkError(); + } + + public void glClearColor(float red, float green, float blue, float alpha) { + gl.glClearColor(red, green, blue, alpha); + checkError(); + } + + public void glColorMask(boolean red, boolean green, boolean blue, boolean alpha) { + gl.glColorMask(red, green, blue, alpha); + checkError(); + } + + public void glCompileShader(int shader) { + gl.glCompileShader(shader); + checkError(); + } + + public void glCompressedTexImage2D(int target, int level, int internalformat, int width, int height, int border, ByteBuffer data) { + gl.glCompressedTexImage2D(target, level, internalformat, width, height, border, data); + checkError(); + } + + public void glCompressedTexSubImage2D(int target, int level, int xoffset, int yoffset, int width, int height, int format, ByteBuffer data) { + gl.glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, data); + checkError(); + } + + public int glCreateProgram() { + int program = gl.glCreateProgram(); + checkError(); + return program; + } + + public int glCreateShader(int shaderType) { + int shader = gl.glCreateShader(shaderType); + checkError(); + return shader; + } + + public void glCullFace(int mode) { + gl.glCullFace(mode); + checkError(); + } + + public void glDeleteBuffers(IntBuffer buffers) { + gl.glDeleteBuffers(buffers); + checkError(); + } + + public void glDeleteProgram(int program) { + gl.glDeleteProgram(program); + checkError(); + } + + public void glDeleteShader(int shader) { + gl.glDeleteShader(shader); + checkError(); + } + + public void glDeleteTextures(IntBuffer textures) { + gl.glDeleteTextures(textures); + checkError(); + } + + public void glDepthFunc(int func) { + gl.glDepthFunc(func); + checkError(); + } + + public void glDepthMask(boolean flag) { + gl.glDepthMask(flag); + checkError(); + } + + public void glDepthRange(double nearVal, double farVal) { + gl.glDepthRange(nearVal, farVal); + checkError(); + } + + public void glDetachShader(int program, int shader) { + gl.glDetachShader(program, shader); + checkError(); + } + + public void glDisable(int cap) { + gl.glDisable(cap); + checkError(); + } + + public void glDisableVertexAttribArray(int index) { + gl.glDisableVertexAttribArray(index); + checkError(); + } + + public void glDrawArrays(int mode, int first, int count) { + gl.glDrawArrays(mode, first, count); + checkError(); + } + + public void glDrawRangeElements(int mode, int start, int end, int count, int type, long indices) { + gl.glDrawRangeElements(mode, start, end, count, type, indices); + checkError(); + } + + public void glEnable(int cap) { + gl.glEnable(cap); + checkError(); + } + + public void glEnableVertexAttribArray(int index) { + gl.glEnableVertexAttribArray(index); + checkError(); + } + + public void glGenBuffers(IntBuffer buffers) { + gl.glGenBuffers(buffers); + checkError(); + } + + public void glGenTextures(IntBuffer textures) { + gl.glGenTextures(textures); + checkError(); + } + + public int glGetAttribLocation(int program, String name) { + int location = gl.glGetAttribLocation(program, name); + checkError(); + return location; + } + + public void glGetBoolean(int pname, ByteBuffer params) { + gl.glGetBoolean(pname, params); + checkError(); + } + + public int glGetError() { + // No need to check for error here? Haha + return gl.glGetError(); + } + + public void glGetInteger(int pname, IntBuffer params) { + gl.glGetInteger(pname, params); + checkError(); + } + + public void glGetProgram(int program, int pname, IntBuffer params) { + gl.glGetProgram(program, pname, params); + checkError(); + } + + public String glGetProgramInfoLog(int program, int maxSize) { + String infoLog = gl.glGetProgramInfoLog(program, maxSize); + checkError(); + return infoLog; + } + + public void glGetShader(int shader, int pname, IntBuffer params) { + gl.glGetShader(shader, pname, params); + checkError(); + } + + public String glGetShaderInfoLog(int shader, int maxSize) { + String infoLog = gl.glGetShaderInfoLog(shader, maxSize); + checkError(); + return infoLog; + } + + public String glGetString(int name) { + String string = gl.glGetString(name); + checkError(); + return string; + } + + public int glGetUniformLocation(int program, String name) { + int location = gl.glGetUniformLocation(program, name); + checkError(); + return location; + } + + public boolean glIsEnabled(int cap) { + boolean enabled = gl.glIsEnabled(cap); + checkError(); + return enabled; + } + + public void glLineWidth(float width) { + gl.glLineWidth(width); + checkError(); + } + + public void glLinkProgram(int program) { + gl.glLinkProgram(program); + checkError(); + } + + public void glPixelStorei(int pname, int param) { + gl.glPixelStorei(pname, param); + checkError(); + } + + public void glPolygonOffset(float factor, float units) { + gl.glPolygonOffset(factor, units); + checkError(); + } + + public void glReadPixels(int x, int y, int width, int height, int format, int type, ByteBuffer data) { + gl.glReadPixels(x, y, width, height, format, type, data); + checkError(); + } + + public void glScissor(int x, int y, int width, int height) { + gl.glScissor(x, y, width, height); + checkError(); + } + + public void glShaderSource(int shader, String[] string, IntBuffer length) { + gl.glShaderSource(shader, string, length); + checkError(); + } + + public void glStencilFuncSeparate(int face, int func, int ref, int mask) { + gl.glStencilFuncSeparate(face, func, ref, mask); + checkError(); + } + + public void glStencilOpSeparate(int face, int sfail, int dpfail, int dppass) { + gl.glStencilOpSeparate(face, sfail, dpfail, dppass); + checkError(); + } + + public void glTexImage2D(int target, int level, int internalFormat, int width, int height, int border, int format, int type, ByteBuffer data) { + gl.glTexImage2D(target, level, internalFormat, width, height, border, format, type, data); + checkError(); + } + + public void glTexParameterf(int target, int pname, float param) { + gl.glTexParameterf(target, pname, param); + checkError(); + } + + public void glTexParameteri(int target, int pname, int param) { + gl.glTexParameteri(target, pname, param); + checkError(); + } + + public void glTexSubImage2D(int target, int level, int xoffset, int yoffset, int width, int height, int format, int type, ByteBuffer data) { + gl.glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, data); + checkError(); + } + + public void glUniform1(int location, FloatBuffer value) { + gl.glUniform1(location, value); + checkError(); + } + + public void glUniform1(int location, IntBuffer value) { + gl.glUniform1(location, value); + checkError(); + } + + public void glUniform1f(int location, float v0) { + gl.glUniform1f(location, v0); + checkError(); + } + + public void glUniform1i(int location, int v0) { + gl.glUniform1i(location, v0); + checkError(); + } + + public void glUniform2(int location, IntBuffer value) { + gl.glUniform2(location, value); + checkError(); + } + + public void glUniform2(int location, FloatBuffer value) { + gl.glUniform2(location, value); + checkError(); + } + + public void glUniform2f(int location, float v0, float v1) { + gl.glUniform2f(location, v0, v1); + checkError(); + } + + public void glUniform3(int location, IntBuffer value) { + gl.glUniform3(location, value); + checkError(); + } + + public void glUniform3(int location, FloatBuffer value) { + gl.glUniform3(location, value); + checkError(); + } + + public void glUniform3f(int location, float v0, float v1, float v2) { + gl.glUniform3f(location, v0, v1, v2); + checkError(); + } + + public void glUniform4(int location, FloatBuffer value) { + gl.glUniform4(location, value); + checkError(); + } + + public void glUniform4(int location, IntBuffer value) { + gl.glUniform4(location, value); + checkError(); + } + + public void glUniform4f(int location, float v0, float v1, float v2, float v3) { + gl.glUniform4f(location, v0, v1, v2, v3); + checkError(); + } + + public void glUniformMatrix3(int location, boolean transpose, FloatBuffer value) { + gl.glUniformMatrix3(location, transpose, value); + checkError(); + } + + public void glUniformMatrix4(int location, boolean transpose, FloatBuffer value) { + gl.glUniformMatrix4(location, transpose, value); + checkError(); + } + + public void glUseProgram(int program) { + gl.glUseProgram(program); + checkError(); + } + + public void glVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, long pointer) { + gl.glVertexAttribPointer(index, size, type, normalized, stride, pointer); + checkError(); + } + + public void glViewport(int x, int y, int width, int height) { + gl.glViewport(x, y, width, height); + checkError(); + } + + public void glBindFramebufferEXT(int param1, int param2) { + glfbo.glBindFramebufferEXT(param1, param2); + checkError(); + } + + public void glBindRenderbufferEXT(int param1, int param2) { + glfbo.glBindRenderbufferEXT(param1, param2); + checkError(); + } + + public int glCheckFramebufferStatusEXT(int param1) { + int result = glfbo.glCheckFramebufferStatusEXT(param1); + checkError(); + return result; + } + + public void glDeleteFramebuffersEXT(IntBuffer param1) { + glfbo.glDeleteFramebuffersEXT(param1); + checkError(); + } + + public void glDeleteRenderbuffersEXT(IntBuffer param1) { + glfbo.glDeleteRenderbuffersEXT(param1); + checkError(); + } + + public void glFramebufferRenderbufferEXT(int param1, int param2, int param3, int param4) { + glfbo.glFramebufferRenderbufferEXT(param1, param2, param3, param4); + checkError(); + } + + public void glFramebufferTexture2DEXT(int param1, int param2, int param3, int param4, int param5) { + glfbo.glFramebufferTexture2DEXT(param1, param2, param3, param4, param5); + checkError(); + } + + public void glGenFramebuffersEXT(IntBuffer param1) { + glfbo.glGenFramebuffersEXT(param1); + checkError(); + } + + public void glGenRenderbuffersEXT(IntBuffer param1) { + glfbo.glGenRenderbuffersEXT(param1); + checkError(); + } + + public void glGenerateMipmapEXT(int param1) { + glfbo.glGenerateMipmapEXT(param1); + checkError(); + } + + public void glRenderbufferStorageEXT(int param1, int param2, int param3, int param4) { + glfbo.glRenderbufferStorageEXT(param1, param2, param3, param4); + checkError(); + } + + public void glBlitFramebufferEXT(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, int mask, int filter) { + glext.glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); + checkError(); + } + + public void glBufferData(int target, IntBuffer data, int usage) { + glext.glBufferData(target, data, usage); + checkError(); + } + + public void glBufferSubData(int target, long offset, IntBuffer data) { + glext.glBufferSubData(target, offset, data); + checkError(); + } + + public void glDrawArraysInstancedARB(int mode, int first, int count, int primcount) { + glext.glDrawArraysInstancedARB(mode, first, count, primcount); + checkError(); + } + + public void glDrawBuffers(IntBuffer bufs) { + glext.glDrawBuffers(bufs); + checkError(); + } + + public void glDrawElementsInstancedARB(int mode, int indices_count, int type, long indices_buffer_offset, int primcount) { + glext.glDrawElementsInstancedARB(mode, indices_count, type, indices_buffer_offset, primcount); + checkError(); + } + + public void glGetMultisample(int pname, int index, FloatBuffer val) { + glext.glGetMultisample(pname, index, val); + checkError(); + } + + public void glRenderbufferStorageMultisampleEXT(int target, int samples, int internalformat, int width, int height) { + glext.glRenderbufferStorageMultisampleEXT(target, samples, internalformat, width, height); + checkError(); + } + + public void glTexImage2DMultisample(int target, int samples, int internalformat, int width, int height, boolean fixedsamplelocations) { + glext.glTexImage2DMultisample(target, samples, internalformat, width, height, fixedsamplelocations); + checkError(); + } + + public void glVertexAttribDivisorARB(int index, int divisor) { + glext.glVertexAttribDivisorARB(index, divisor); + checkError(); + } +} diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugGL2.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugGL2.java new file mode 100644 index 000000000..f71b15aae --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugGL2.java @@ -0,0 +1,77 @@ +package com.jme3.renderer.opengl; + +import java.nio.ByteBuffer; +import java.nio.IntBuffer; + +public class GLDebugGL2 extends GLDebugES { + + private final GL2 gl2; + private final GL3 gl3; + + public GLDebugGL2(GL gl, GLFbo glfbo) { + super(gl, glfbo); + this.gl2 = gl instanceof GL2 ? (GL2) gl : null; + this.gl3 = gl instanceof GL3 ? (GL3) gl : null; + } + + public void glAlphaFunc(int func, float ref) { + gl2.glAlphaFunc(func, ref); + checkError(); + } + + public void glPointSize(float size) { + gl2.glPointSize(size); + checkError(); + } + + public void glPolygonMode(int face, int mode) { + gl2.glPolygonMode(face, mode); + checkError(); + } + + public void glDrawBuffer(int mode) { + gl2.glDrawBuffer(mode); + checkError(); + } + + public void glReadBuffer(int mode) { + gl2.glReadBuffer(mode); + checkError(); + } + + public void glCompressedTexImage3D(int target, int level, int internalformat, int width, int height, int depth, int border, ByteBuffer data) { + gl2.glCompressedTexImage3D(target, level, internalformat, width, height, depth, border, data); + checkError(); + } + + public void glCompressedTexSubImage3D(int target, int level, int xoffset, int yoffset, int zoffset, int width, int height, int depth, int format, ByteBuffer data) { + gl2.glCompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, data); + checkError(); + } + + public void glTexImage3D(int target, int level, int internalFormat, int width, int height, int depth, int border, int format, int type, ByteBuffer data) { + gl2.glTexImage3D(target, level, internalFormat, width, height, depth, border, format, type, data); + checkError(); + } + + public void glTexSubImage3D(int target, int level, int xoffset, int yoffset, int zoffset, int width, int height, int depth, int format, int type, ByteBuffer data) { + gl2.glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data); + checkError(); + } + + public void glBindFragDataLocation(int param1, int param2, String param3) { + gl3.glBindFragDataLocation(param1, param2, param3); + checkError(); + } + + public void glBindVertexArray(int param1) { + gl3.glBindVertexArray(param1); + checkError(); + } + + public void glGenVertexArrays(IntBuffer param1) { + gl3.glGenVertexArrays(param1); + checkError(); + } + +} diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLTracer.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLTracer.java index 86593f442..4127ca803 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLTracer.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLTracer.java @@ -35,6 +35,7 @@ import com.jme3.util.IntMap; import java.lang.reflect.Field; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; +import java.lang.reflect.Proxy; import java.nio.ByteBuffer; import java.nio.IntBuffer; import java.util.HashMap; @@ -112,7 +113,7 @@ public final class GLTracer implements InvocationHandler { this.constMap = constMap; } - public static IntMap generateConstantMap(Class ... classes) { + private static IntMap generateConstantMap(Class ... classes) { IntMap constMap = new IntMap(); for (Class clazz : classes) { for (Field field : clazz.getFields()) { @@ -129,7 +130,35 @@ public final class GLTracer implements InvocationHandler { } return constMap; } + + /** + * Creates a tracer implementation that wraps OpenGL ES 2. + * + * @param gl OGL interface + * @param glext OGL extension interface + * @return A tracer that implements GL, GLFbo, and GLExt. + */ + public static GL createGlesTracer(GL gl, GLExt glext) { + IntMap constMap = generateConstantMap(GL.class, GLExt.class); + return (GL) Proxy.newProxyInstance(glext.getClass().getClassLoader(), + new Class[] { GL.class, GLExt.class }, + new GLTracer(gl, glext, constMap)); + } + /** + * Creates a tracer implementation that wraps OpenGL 2+. + * + * @param gl OGL interface + * @param glext OGL extension interface + * @return A tracer that implements GL, GL2, GL3, GLFbo, and GLExt. + */ + public static GL createDesktopGlTracer(GL3 gl, GLExt glext) { + IntMap constMap = generateConstantMap(GL3.class, GLExt.class); + return (GL) Proxy.newProxyInstance(glext.getClass().getClassLoader(), + new Class[] { GL3.class, GLExt.class }, + new GLTracer(gl, glext, constMap)); + } + private String translateInteger(String method, int value, int argIndex) { IntMap argSlotMap = nonEnumArgMap.get(method); if (argSlotMap != null && argSlotMap.containsKey(argIndex)) {