GLRenderer: Improve compatibility with OpenGL 3.2 core profile

* Separate GLFbo and GLExt implementations. GLFbo can now be implemented either via vanilla OpenGL3 calls or GL_EXT_framebuffer_*** extensions (OpenGL2.1- only).
 * Use modern way of getting supported extensions in core profile.
 * Luminance and Alpha formats are not available when running in core profile.
 * Bind a dummy vertex array object (VAO) when running in core profile.
 * Point sprite mode is always enabled. Since both OpenGL ES 2.0 and OpenGL 3.2 core require it, jME3 is no longer capable of rendering regular points.
experimental
Kirill Vainer 10 years ago
parent 389b117fb6
commit 5b95f8a4b0
  1. 3
      jme3-android/src/main/java/com/jme3/system/android/OGLESContext.java
  2. 14
      jme3-core/src/main/java/com/jme3/renderer/Caps.java
  3. 1
      jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java
  4. 10
      jme3-core/src/main/java/com/jme3/renderer/opengl/GL3.java
  5. 19
      jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugDesktop.java
  6. 10
      jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugES.java
  7. 4
      jme3-core/src/main/java/com/jme3/renderer/opengl/GLExt.java
  8. 3
      jme3-core/src/main/java/com/jme3/renderer/opengl/GLFbo.java
  9. 38
      jme3-core/src/main/java/com/jme3/renderer/opengl/GLImageFormats.java
  10. 160
      jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java
  11. 7
      jme3-core/src/main/java/com/jme3/renderer/opengl/GLTracer.java
  12. 5
      jme3-ios/src/main/java/com/jme3/system/ios/IGLESContext.java
  13. 12
      jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java
  14. 68
      jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGLExt.java
  15. 98
      jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGLFboEXT.java
  16. 96
      jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGLFboGL3.java
  17. 26
      jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglContext.java

@ -54,6 +54,7 @@ import com.jme3.input.dummy.DummyMouseInput;
import com.jme3.renderer.android.AndroidGL; import com.jme3.renderer.android.AndroidGL;
import com.jme3.renderer.opengl.GL; import com.jme3.renderer.opengl.GL;
import com.jme3.renderer.opengl.GLExt; import com.jme3.renderer.opengl.GLExt;
import com.jme3.renderer.opengl.GLFbo;
import com.jme3.renderer.opengl.GLRenderer; import com.jme3.renderer.opengl.GLRenderer;
import com.jme3.system.*; import com.jme3.system.*;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
@ -196,7 +197,7 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTex
Object gl = new AndroidGL(); Object gl = new AndroidGL();
// gl = GLTracer.createGlesTracer((GL)gl, (GLExt)gl); // gl = GLTracer.createGlesTracer((GL)gl, (GLExt)gl);
// gl = new GLDebugES((GL)gl, (GLExt)gl); // gl = new GLDebugES((GL)gl, (GLExt)gl);
renderer = new GLRenderer((GL)gl, (GLExt)gl); renderer = new GLRenderer((GL)gl, (GLExt)gl, (GLFbo)gl);
renderer.initialize(); renderer.initialize();
JmeSystem.setSoftTextDialogInput(this); JmeSystem.setSoftTextDialogInput(this);

@ -337,7 +337,19 @@ public enum Caps {
* <p> * <p>
* Improves the quality of environment mapping. * Improves the quality of environment mapping.
*/ */
SeamlessCubemap; SeamlessCubemap,
/**
* Running with OpenGL 3.2+ core profile.
*
* Compatibility features will not be available.
*/
CoreProfile,
/**
* GPU can provide and accept binary shaders.
*/
BinaryShader;
/** /**
* Returns true if given the renderer capabilities, the texture * Returns true if given the renderer capabilities, the texture

@ -32,7 +32,6 @@
package com.jme3.renderer.opengl; package com.jme3.renderer.opengl;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer; import java.nio.FloatBuffer;
import java.nio.IntBuffer; import java.nio.IntBuffer;
import java.nio.ShortBuffer; import java.nio.ShortBuffer;

@ -35,14 +35,18 @@ import java.nio.IntBuffer;
/** /**
* GL functions only available on vanilla desktop OpenGL 3.0. * GL functions only available on vanilla desktop OpenGL 3.0.
* *
* @author Kirill Vainer * @author Kirill Vainer
*/ */
public interface GL3 extends GL2 { public interface GL3 extends GL2 {
public static final int GL_DEPTH_STENCIL_ATTACHMENT = 0x821A; public static final int GL_DEPTH_STENCIL_ATTACHMENT = 0x821A;
public static final int GL_GEOMETRY_SHADER=0x8DD9; public static final int GL_GEOMETRY_SHADER = 0x8DD9;
public static final int GL_NUM_EXTENSIONS = 0x821D;
public void glBindFragDataLocation(int param1, int param2, String param3); /// GL3+ public void glBindFragDataLocation(int param1, int param2, String param3); /// GL3+
public void glBindVertexArray(int param1); /// GL3+ public void glBindVertexArray(int param1); /// GL3+
public void glDeleteVertexArrays(IntBuffer arrays); /// GL3+
public void glGenVertexArrays(IntBuffer param1); /// GL3+ public void glGenVertexArrays(IntBuffer param1); /// GL3+
public String glGetString(int param1, int param2); /// GL3+
} }

@ -3,13 +3,13 @@ package com.jme3.renderer.opengl;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.IntBuffer; import java.nio.IntBuffer;
public class GLDebugDesktop extends GLDebugES implements GL2, GL3 { public class GLDebugDesktop extends GLDebugES implements GL2, GL3, GL4 {
private final GL2 gl2; private final GL2 gl2;
private final GL3 gl3; private final GL3 gl3;
public GLDebugDesktop(GL gl, GLFbo glfbo) { public GLDebugDesktop(GL gl, GLExt glext, GLFbo glfbo) {
super(gl, glfbo); super(gl, glext, glfbo);
this.gl2 = gl instanceof GL2 ? (GL2) gl : null; this.gl2 = gl instanceof GL2 ? (GL2) gl : null;
this.gl3 = gl instanceof GL3 ? (GL3) gl : null; this.gl3 = gl instanceof GL3 ? (GL3) gl : null;
} }
@ -73,5 +73,18 @@ public class GLDebugDesktop extends GLDebugES implements GL2, GL3 {
gl3.glGenVertexArrays(param1); gl3.glGenVertexArrays(param1);
checkError(); checkError();
} }
@Override
public String glGetString(int param1, int param2) {
String result = gl3.glGetString(param1, param2);
checkError();
return result;
}
@Override
public void glDeleteVertexArrays(IntBuffer arrays) {
gl3.glDeleteVertexArrays(arrays);
checkError();
}
} }

@ -10,12 +10,10 @@ public class GLDebugES extends GLDebug implements GL, GLFbo, GLExt {
private final GLFbo glfbo; private final GLFbo glfbo;
private final GLExt glext; private final GLExt glext;
public GLDebugES(GL gl, GLFbo glfbo) { public GLDebugES(GL gl, GLExt glext, GLFbo glfbo) {
this.gl = gl; this.gl = gl;
// this.gl2 = gl instanceof GL2 ? (GL2) gl : null; this.glext = glext;
// this.gl3 = gl instanceof GL3 ? (GL3) gl : null;
this.glfbo = glfbo; this.glfbo = glfbo;
this.glext = glfbo instanceof GLExt ? (GLExt) glfbo : null;
} }
public void glActiveTexture(int texture) { public void glActiveTexture(int texture) {
@ -478,7 +476,7 @@ public class GLDebugES extends GLDebug implements GL, GLFbo, GLExt {
} }
public void glBlitFramebufferEXT(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, int mask, int filter) { 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); glfbo.glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
checkError(); checkError();
} }
@ -525,7 +523,7 @@ public class GLDebugES extends GLDebug implements GL, GLFbo, GLExt {
} }
public void glRenderbufferStorageMultisampleEXT(int target, int samples, int internalformat, int width, int height) { public void glRenderbufferStorageMultisampleEXT(int target, int samples, int internalformat, int width, int height) {
glext.glRenderbufferStorageMultisampleEXT(target, samples, internalformat, width, height); glfbo.glRenderbufferStorageMultisampleEXT(target, samples, internalformat, width, height);
checkError(); checkError();
} }

@ -41,7 +41,7 @@ import java.nio.IntBuffer;
* *
* @author Kirill Vainer * @author Kirill Vainer
*/ */
public interface GLExt extends GLFbo { public interface GLExt {
public static final int GL_ALREADY_SIGNALED = 0x911A; public static final int GL_ALREADY_SIGNALED = 0x911A;
public static final int GL_COMPRESSED_RGB8_ETC2 = 0x9274; public static final int GL_COMPRESSED_RGB8_ETC2 = 0x9274;
@ -100,7 +100,6 @@ public interface GLExt extends GLFbo {
public static final int GL_UNSIGNED_INT_5_9_9_9_REV_EXT = 0x8C3E; public static final int GL_UNSIGNED_INT_5_9_9_9_REV_EXT = 0x8C3E;
public static final int GL_WAIT_FAILED = 0x911D; public static final int GL_WAIT_FAILED = 0x911D;
public void glBlitFramebufferEXT(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, int mask, int filter);
public void glBufferData(int target, IntBuffer data, int usage); public void glBufferData(int target, IntBuffer data, int usage);
public void glBufferSubData(int target, long offset, IntBuffer data); public void glBufferSubData(int target, long offset, IntBuffer data);
public int glClientWaitSync(Object sync, int flags, long timeout); public int glClientWaitSync(Object sync, int flags, long timeout);
@ -110,7 +109,6 @@ public interface GLExt extends GLFbo {
public void glDrawElementsInstancedARB(int mode, int indices_count, int type, long indices_buffer_offset, int primcount); public void glDrawElementsInstancedARB(int mode, int indices_count, int type, long indices_buffer_offset, int primcount);
public Object glFenceSync(int condition, int flags); public Object glFenceSync(int condition, int flags);
public void glGetMultisample(int pname, int index, FloatBuffer val); public void glGetMultisample(int pname, int index, FloatBuffer val);
public void glRenderbufferStorageMultisampleEXT(int target, int samples, int internalformat, int width, int height);
public void glTexImage2DMultisample(int target, int samples, int internalformat, int width, int height, boolean fixedsamplelocations); public void glTexImage2DMultisample(int target, int samples, int internalformat, int width, int height, boolean fixedsamplelocations);
public void glVertexAttribDivisorARB(int index, int divisor); public void glVertexAttribDivisorARB(int index, int divisor);
} }

@ -83,6 +83,7 @@ public interface GLFbo {
public void glBindFramebufferEXT(int param1, int param2); public void glBindFramebufferEXT(int param1, int param2);
public void glBindRenderbufferEXT(int param1, int param2); public void glBindRenderbufferEXT(int param1, int param2);
public void glBlitFramebufferEXT(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, int mask, int filter);
public int glCheckFramebufferStatusEXT(int param1); public int glCheckFramebufferStatusEXT(int param1);
public void glDeleteFramebuffersEXT(IntBuffer param1); public void glDeleteFramebuffersEXT(IntBuffer param1);
public void glDeleteRenderbuffersEXT(IntBuffer param1); public void glDeleteRenderbuffersEXT(IntBuffer param1);
@ -92,5 +93,5 @@ public interface GLFbo {
public void glGenRenderbuffersEXT(IntBuffer param1); public void glGenRenderbuffersEXT(IntBuffer param1);
public void glGenerateMipmapEXT(int param1); public void glGenerateMipmapEXT(int param1);
public void glRenderbufferStorageEXT(int param1, int param2, int param3, int param4); public void glRenderbufferStorageEXT(int param1, int param2, int param3, int param4);
public void glRenderbufferStorageMultisampleEXT(int target, int samples, int internalformat, int width, int height);
} }

@ -89,9 +89,11 @@ public final class GLImageFormats {
GLImageFormat[][] formatToGL = new GLImageFormat[2][Image.Format.values().length]; GLImageFormat[][] formatToGL = new GLImageFormat[2][Image.Format.values().length];
if (caps.contains(Caps.OpenGL20)) { if (caps.contains(Caps.OpenGL20)) {
format(formatToGL, Format.Alpha8, GL2.GL_ALPHA8, GL.GL_ALPHA, GL.GL_UNSIGNED_BYTE); if (!caps.contains(Caps.CoreProfile)) {
format(formatToGL, Format.Luminance8, GL2.GL_LUMINANCE8, GL.GL_LUMINANCE, GL.GL_UNSIGNED_BYTE); format(formatToGL, Format.Alpha8, GL2.GL_ALPHA8, GL.GL_ALPHA, GL.GL_UNSIGNED_BYTE);
format(formatToGL, Format.Luminance8Alpha8, GL2.GL_LUMINANCE8_ALPHA8, GL.GL_LUMINANCE_ALPHA, GL.GL_UNSIGNED_BYTE); format(formatToGL, Format.Luminance8, GL2.GL_LUMINANCE8, GL.GL_LUMINANCE, GL.GL_UNSIGNED_BYTE);
format(formatToGL, Format.Luminance8Alpha8, GL2.GL_LUMINANCE8_ALPHA8, GL.GL_LUMINANCE_ALPHA, GL.GL_UNSIGNED_BYTE);
}
format(formatToGL, Format.RGB8, GL2.GL_RGB8, GL.GL_RGB, GL.GL_UNSIGNED_BYTE); format(formatToGL, Format.RGB8, GL2.GL_RGB8, GL.GL_RGB, GL.GL_UNSIGNED_BYTE);
format(formatToGL, Format.RGBA8, GLExt.GL_RGBA8, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE); format(formatToGL, Format.RGBA8, GLExt.GL_RGBA8, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE);
format(formatToGL, Format.RGB565, GL2.GL_RGB8, GL.GL_RGB, GL.GL_UNSIGNED_SHORT_5_6_5); format(formatToGL, Format.RGB565, GL2.GL_RGB8, GL.GL_RGB, GL.GL_UNSIGNED_SHORT_5_6_5);
@ -108,8 +110,10 @@ public final class GLImageFormats {
formatSrgb(formatToGL, Format.RGB565, GLExt.GL_SRGB8_EXT, GL.GL_RGB, GL.GL_UNSIGNED_SHORT_5_6_5); formatSrgb(formatToGL, Format.RGB565, GLExt.GL_SRGB8_EXT, GL.GL_RGB, GL.GL_UNSIGNED_SHORT_5_6_5);
formatSrgb(formatToGL, Format.RGB5A1, GLExt.GL_SRGB8_ALPHA8_EXT, GL.GL_RGBA, GL.GL_UNSIGNED_SHORT_5_5_5_1); formatSrgb(formatToGL, Format.RGB5A1, GLExt.GL_SRGB8_ALPHA8_EXT, GL.GL_RGBA, GL.GL_UNSIGNED_SHORT_5_5_5_1);
formatSrgb(formatToGL, Format.RGBA8, GLExt.GL_SRGB8_ALPHA8_EXT, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE); formatSrgb(formatToGL, Format.RGBA8, GLExt.GL_SRGB8_ALPHA8_EXT, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE);
formatSrgb(formatToGL, Format.Luminance8, GLExt.GL_SLUMINANCE8_EXT, GL.GL_LUMINANCE, GL.GL_UNSIGNED_BYTE); if (!caps.contains(Caps.CoreProfile)) {
formatSrgb(formatToGL, Format.Luminance8Alpha8, GLExt.GL_SLUMINANCE8_ALPHA8_EXT, GL.GL_LUMINANCE_ALPHA, GL.GL_UNSIGNED_BYTE); formatSrgb(formatToGL, Format.Luminance8, GLExt.GL_SLUMINANCE8_EXT, GL.GL_LUMINANCE, GL.GL_UNSIGNED_BYTE);
formatSrgb(formatToGL, Format.Luminance8Alpha8, GLExt.GL_SLUMINANCE8_ALPHA8_EXT, GL.GL_LUMINANCE_ALPHA, GL.GL_UNSIGNED_BYTE);
}
formatSrgb(formatToGL, Format.BGR8, GLExt.GL_SRGB8_EXT, GL2.GL_BGR, GL.GL_UNSIGNED_BYTE); formatSrgb(formatToGL, Format.BGR8, GLExt.GL_SRGB8_EXT, GL2.GL_BGR, GL.GL_UNSIGNED_BYTE);
formatSrgb(formatToGL, Format.ABGR8, GLExt.GL_SRGB8_ALPHA8_EXT, GL.GL_RGBA, GL2.GL_UNSIGNED_INT_8_8_8_8); formatSrgb(formatToGL, Format.ABGR8, GLExt.GL_SRGB8_ALPHA8_EXT, GL.GL_RGBA, GL2.GL_UNSIGNED_INT_8_8_8_8);
formatSrgb(formatToGL, Format.ARGB8, GLExt.GL_SRGB8_ALPHA8_EXT, GL2.GL_BGRA, GL2.GL_UNSIGNED_INT_8_8_8_8); formatSrgb(formatToGL, Format.ARGB8, GLExt.GL_SRGB8_ALPHA8_EXT, GL2.GL_BGRA, GL2.GL_UNSIGNED_INT_8_8_8_8);
@ -124,16 +128,20 @@ public final class GLImageFormats {
} }
} else if (caps.contains(Caps.Rgba8)) { } else if (caps.contains(Caps.Rgba8)) {
// A more limited form of 32-bit RGBA. Only GL_RGBA8 is available. // A more limited form of 32-bit RGBA. Only GL_RGBA8 is available.
format(formatToGL, Format.Alpha8, GLExt.GL_RGBA8, GL.GL_ALPHA, GL.GL_UNSIGNED_BYTE); if (!caps.contains(Caps.CoreProfile)) {
format(formatToGL, Format.Luminance8, GLExt.GL_RGBA8, GL.GL_LUMINANCE, GL.GL_UNSIGNED_BYTE); format(formatToGL, Format.Alpha8, GLExt.GL_RGBA8, GL.GL_ALPHA, GL.GL_UNSIGNED_BYTE);
format(formatToGL, Format.Luminance8Alpha8, GLExt.GL_RGBA8, GL.GL_LUMINANCE_ALPHA, GL.GL_UNSIGNED_BYTE); format(formatToGL, Format.Luminance8, GLExt.GL_RGBA8, GL.GL_LUMINANCE, GL.GL_UNSIGNED_BYTE);
format(formatToGL, Format.Luminance8Alpha8, GLExt.GL_RGBA8, GL.GL_LUMINANCE_ALPHA, GL.GL_UNSIGNED_BYTE);
}
format(formatToGL, Format.RGB8, GLExt.GL_RGBA8, GL.GL_RGB, GL.GL_UNSIGNED_BYTE); format(formatToGL, Format.RGB8, GLExt.GL_RGBA8, GL.GL_RGB, GL.GL_UNSIGNED_BYTE);
format(formatToGL, Format.RGBA8, GLExt.GL_RGBA8, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE); format(formatToGL, Format.RGBA8, GLExt.GL_RGBA8, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE);
} else { } else {
// Actually, the internal format isn't used for OpenGL ES 2! This is the same as the above.. // Actually, the internal format isn't used for OpenGL ES 2! This is the same as the above..
format(formatToGL, Format.Alpha8, GL.GL_RGBA4, GL.GL_ALPHA, GL.GL_UNSIGNED_BYTE); if (!caps.contains(Caps.CoreProfile)) {
format(formatToGL, Format.Luminance8, GL.GL_RGB565, GL.GL_LUMINANCE, GL.GL_UNSIGNED_BYTE); format(formatToGL, Format.Alpha8, GL.GL_RGBA4, GL.GL_ALPHA, GL.GL_UNSIGNED_BYTE);
format(formatToGL, Format.Luminance8Alpha8, GL.GL_RGBA4, GL.GL_LUMINANCE_ALPHA, GL.GL_UNSIGNED_BYTE); format(formatToGL, Format.Luminance8, GL.GL_RGB565, GL.GL_LUMINANCE, GL.GL_UNSIGNED_BYTE);
format(formatToGL, Format.Luminance8Alpha8, GL.GL_RGBA4, GL.GL_LUMINANCE_ALPHA, GL.GL_UNSIGNED_BYTE);
}
format(formatToGL, Format.RGB8, GL.GL_RGB565, GL.GL_RGB, GL.GL_UNSIGNED_BYTE); format(formatToGL, Format.RGB8, GL.GL_RGB565, GL.GL_RGB, GL.GL_UNSIGNED_BYTE);
format(formatToGL, Format.RGBA8, GL.GL_RGBA4, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE); format(formatToGL, Format.RGBA8, GL.GL_RGBA4, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE);
} }
@ -145,9 +153,11 @@ public final class GLImageFormats {
format(formatToGL, Format.RGB5A1, GL.GL_RGB5_A1, GL.GL_RGBA, GL.GL_UNSIGNED_SHORT_5_5_5_1); format(formatToGL, Format.RGB5A1, GL.GL_RGB5_A1, GL.GL_RGBA, GL.GL_UNSIGNED_SHORT_5_5_5_1);
if (caps.contains(Caps.FloatTexture)) { if (caps.contains(Caps.FloatTexture)) {
format(formatToGL, Format.Luminance16F, GLExt.GL_LUMINANCE16F_ARB, GL.GL_LUMINANCE, GLExt.GL_HALF_FLOAT_ARB); if (!caps.contains(Caps.CoreProfile)) {
format(formatToGL, Format.Luminance32F, GLExt.GL_LUMINANCE32F_ARB, GL.GL_LUMINANCE, GL.GL_FLOAT); format(formatToGL, Format.Luminance16F, GLExt.GL_LUMINANCE16F_ARB, GL.GL_LUMINANCE, GLExt.GL_HALF_FLOAT_ARB);
format(formatToGL, Format.Luminance16FAlpha16F, GLExt.GL_LUMINANCE_ALPHA16F_ARB, GL.GL_LUMINANCE_ALPHA, GLExt.GL_HALF_FLOAT_ARB); format(formatToGL, Format.Luminance32F, GLExt.GL_LUMINANCE32F_ARB, GL.GL_LUMINANCE, GL.GL_FLOAT);
format(formatToGL, Format.Luminance16FAlpha16F, GLExt.GL_LUMINANCE_ALPHA16F_ARB, GL.GL_LUMINANCE_ALPHA, GLExt.GL_HALF_FLOAT_ARB);
}
format(formatToGL, Format.RGB16F, GLExt.GL_RGB16F_ARB, GL.GL_RGB, GLExt.GL_HALF_FLOAT_ARB); format(formatToGL, Format.RGB16F, GLExt.GL_RGB16F_ARB, GL.GL_RGB, GLExt.GL_HALF_FLOAT_ARB);
format(formatToGL, Format.RGB32F, GLExt.GL_RGB32F_ARB, GL.GL_RGB, GL.GL_FLOAT); format(formatToGL, Format.RGB32F, GLExt.GL_RGB32F_ARB, GL.GL_RGB, GL.GL_FLOAT);
format(formatToGL, Format.RGBA16F, GLExt.GL_RGBA16F_ARB, GL.GL_RGBA, GLExt.GL_HALF_FLOAT_ARB); format(formatToGL, Format.RGBA16F, GLExt.GL_RGBA16F_ARB, GL.GL_RGBA, GLExt.GL_HALF_FLOAT_ARB);

@ -112,13 +112,13 @@ public class GLRenderer implements Renderer {
private final GLFbo glfbo; private final GLFbo glfbo;
private final TextureUtil texUtil; private final TextureUtil texUtil;
public GLRenderer(GL gl, GLFbo glfbo) { public GLRenderer(GL gl, GLExt glext, GLFbo glfbo) {
this.gl = gl; this.gl = gl;
this.gl2 = gl instanceof GL2 ? (GL2)gl : null; this.gl2 = gl instanceof GL2 ? (GL2)gl : null;
this.gl3 = gl instanceof GL3 ? (GL3)gl : null; this.gl3 = gl instanceof GL3 ? (GL3)gl : null;
this.gl4 = gl instanceof GL4 ? (GL4)gl : null; this.gl4 = gl instanceof GL4 ? (GL4)gl : null;
this.glfbo = glfbo; this.glfbo = glfbo;
this.glext = glfbo instanceof GLExt ? (GLExt)glfbo : null; this.glext = glext;
this.texUtil = new TextureUtil(gl, gl2, glext, context); this.texUtil = new TextureUtil(gl, gl2, glext, context);
} }
@ -137,10 +137,19 @@ public class GLRenderer implements Renderer {
return limits; return limits;
} }
private static HashSet<String> loadExtensions(String extensions) { private HashSet<String> loadExtensions() {
HashSet<String> extensionSet = new HashSet<String>(64); HashSet<String> extensionSet = new HashSet<String>(64);
for (String extension : extensions.split(" ")) { if (gl3 != null) {
extensionSet.add(extension); // If OpenGL3+ is available, use the non-deprecated way
// of getting supported extensions.
gl3.glGetInteger(GL3.GL_NUM_EXTENSIONS, intBuf16);
int extensionCount = intBuf16.get(0);
for (int i = 0; i < extensionCount; i++) {
String extension = gl3.glGetString(GL.GL_EXTENSIONS, i);
extensionSet.add(extension);
}
} else {
extensionSet.addAll(Arrays.asList(gl.glGetString(GL.GL_EXTENSIONS).split(" ")));
} }
return extensionSet; return extensionSet;
} }
@ -185,10 +194,12 @@ public class GLRenderer implements Renderer {
caps.add(Caps.OpenGL31); caps.add(Caps.OpenGL31);
if (oglVer >= 320) { if (oglVer >= 320) {
caps.add(Caps.OpenGL32); caps.add(Caps.OpenGL32);
}if(oglVer>=330){ }
if (oglVer >= 330) {
caps.add(Caps.OpenGL33); caps.add(Caps.OpenGL33);
caps.add(Caps.GeometryShader); caps.add(Caps.GeometryShader);
}if(oglVer>=400){ }
if (oglVer >= 400) {
caps.add(Caps.OpenGL40); caps.add(Caps.OpenGL40);
caps.add(Caps.TesselationShader); caps.add(Caps.TesselationShader);
} }
@ -243,7 +254,7 @@ public class GLRenderer implements Renderer {
} }
private void loadCapabilitiesCommon() { private void loadCapabilitiesCommon() {
extensions = loadExtensions(gl.glGetString(GL.GL_EXTENSIONS)); extensions = loadExtensions();
limits.put(Limits.VertexTextureUnits, getInteger(GL.GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS)); limits.put(Limits.VertexTextureUnits, getInteger(GL.GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS));
if (limits.get(Limits.VertexTextureUnits) > 0) { if (limits.get(Limits.VertexTextureUnits) > 0) {
@ -251,7 +262,7 @@ public class GLRenderer implements Renderer {
} }
limits.put(Limits.FragmentTextureUnits, getInteger(GL.GL_MAX_TEXTURE_IMAGE_UNITS)); limits.put(Limits.FragmentTextureUnits, getInteger(GL.GL_MAX_TEXTURE_IMAGE_UNITS));
// gl.glGetInteger(GL.GL_MAX_VERTEX_UNIFORM_COMPONENTS, intBuf16); // gl.glGetInteger(GL.GL_MAX_VERTEX_UNIFORM_COMPONENTS, intBuf16);
// vertexUniforms = intBuf16.get(0); // vertexUniforms = intBuf16.get(0);
// logger.log(Level.FINER, "Vertex Uniforms: {0}", vertexUniforms); // logger.log(Level.FINER, "Vertex Uniforms: {0}", vertexUniforms);
@ -279,7 +290,7 @@ public class GLRenderer implements Renderer {
// == texture format extensions == // == texture format extensions ==
boolean hasFloatTexture = false; boolean hasFloatTexture;
hasFloatTexture = hasExtension("GL_OES_texture_half_float") && hasFloatTexture = hasExtension("GL_OES_texture_half_float") &&
hasExtension("GL_OES_texture_float"); hasExtension("GL_OES_texture_float");
@ -375,11 +386,11 @@ public class GLRenderer implements Renderer {
caps.add(Caps.TextureFilterAnisotropic); caps.add(Caps.TextureFilterAnisotropic);
} }
if (hasExtension("GL_EXT_framebuffer_object")) { if (hasExtension("GL_EXT_framebuffer_object") || gl3 != null) {
caps.add(Caps.FrameBuffer); caps.add(Caps.FrameBuffer);
limits.put(Limits.RenderBufferSize, getInteger(GLExt.GL_MAX_RENDERBUFFER_SIZE_EXT)); limits.put(Limits.RenderBufferSize, getInteger(GLFbo.GL_MAX_RENDERBUFFER_SIZE_EXT));
limits.put(Limits.FrameBufferAttachments, getInteger(GLExt.GL_MAX_COLOR_ATTACHMENTS_EXT)); limits.put(Limits.FrameBufferAttachments, getInteger(GLFbo.GL_MAX_COLOR_ATTACHMENTS_EXT));
if (hasExtension("GL_EXT_framebuffer_blit")) { if (hasExtension("GL_EXT_framebuffer_blit")) {
caps.add(Caps.FrameBufferBlit); caps.add(Caps.FrameBufferBlit);
@ -434,21 +445,30 @@ public class GLRenderer implements Renderer {
caps.add(Caps.SeamlessCubemap); caps.add(Caps.SeamlessCubemap);
} }
// if (hasExtension("GL_ARB_get_program_binary")) { if (caps.contains(Caps.OpenGL32) && !hasExtension("GL_ARB_compatibility")) {
// int binaryFormats = getInteger(GLExt.GL_NUM_PROGRAM_BINARY_FORMATS); caps.add(Caps.CoreProfile);
// } }
if (hasExtension("GL_ARB_get_program_binary")) {
int binaryFormats = getInteger(GLExt.GL_NUM_PROGRAM_BINARY_FORMATS);
if (binaryFormats > 0) {
caps.add(Caps.BinaryShader);
}
}
// Print context information // Print context information
logger.log(Level.INFO, "OpenGL Renderer Information\n" + logger.log(Level.INFO, "OpenGL Renderer Information\n" +
" * Vendor: {0}\n" + " * Vendor: {0}\n" +
" * Renderer: {1}\n" + " * Renderer: {1}\n" +
" * OpenGL Version: {2}\n" + " * OpenGL Version: {2}\n" +
" * GLSL Version: {3}", " * GLSL Version: {3}\n" +
" * Profile: {4}",
new Object[]{ new Object[]{
gl.glGetString(GL.GL_VENDOR), gl.glGetString(GL.GL_VENDOR),
gl.glGetString(GL.GL_RENDERER), gl.glGetString(GL.GL_RENDERER),
gl.glGetString(GL.GL_VERSION), gl.glGetString(GL.GL_VERSION),
gl.glGetString(GL.GL_SHADING_LANGUAGE_VERSION) gl.glGetString(GL.GL_SHADING_LANGUAGE_VERSION),
caps.contains(Caps.CoreProfile) ? "Core" : "Compatibility"
}); });
// Print capabilities (if fine logging is enabled) // Print capabilities (if fine logging is enabled)
@ -491,6 +511,20 @@ public class GLRenderer implements Renderer {
// Initialize default state.. // Initialize default state..
gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1); gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1);
if (caps.contains(Caps.CoreProfile)) {
// Core Profile requires VAO to be bound.
gl3.glGenVertexArrays(intBuf16);
int vaoId = intBuf16.get(0);
gl3.glBindVertexArray(vaoId);
}
if (gl2 != null) {
gl2.glEnable(GL2.GL_VERTEX_PROGRAM_POINT_SIZE);
if (!caps.contains(Caps.CoreProfile)) {
gl2.glEnable(GL2.GL_POINT_SPRITE);
context.pointSprite = true;
}
}
} }
public void invalidateState() { public void invalidateState() {
@ -610,31 +644,6 @@ public class GLRenderer implements Renderer {
context.colorWriteEnabled = false; context.colorWriteEnabled = false;
} }
if (gl2 != null) {
if (state.isPointSprite() && !context.pointSprite) {
// Only enable/disable sprite
if (context.boundTextures[0] != null) {
if (context.boundTextureUnit != 0) {
gl.glActiveTexture(GL.GL_TEXTURE0);
context.boundTextureUnit = 0;
}
gl2.glEnable(GL2.GL_POINT_SPRITE);
gl2.glEnable(GL2.GL_VERTEX_PROGRAM_POINT_SIZE);
}
context.pointSprite = true;
} else if (!state.isPointSprite() && context.pointSprite) {
if (context.boundTextures[0] != null) {
if (context.boundTextureUnit != 0) {
gl.glActiveTexture(GL.GL_TEXTURE0);
context.boundTextureUnit = 0;
}
gl2.glDisable(GL2.GL_POINT_SPRITE);
gl2.glDisable(GL2.GL_VERTEX_PROGRAM_POINT_SIZE);
context.pointSprite = false;
}
}
}
if (state.isPolyOffset()) { if (state.isPolyOffset()) {
if (!context.polyOffsetEnabled) { if (!context.polyOffsetEnabled) {
gl.glEnable(GL.GL_POLYGON_OFFSET_FILL); gl.glEnable(GL.GL_POLYGON_OFFSET_FILL);
@ -1288,24 +1297,24 @@ public class GLRenderer implements Renderer {
} }
if (src == null) { if (src == null) {
glfbo.glBindFramebufferEXT(GLExt.GL_READ_FRAMEBUFFER_EXT, 0); glfbo.glBindFramebufferEXT(GLFbo.GL_READ_FRAMEBUFFER_EXT, 0);
srcX0 = vpX; srcX0 = vpX;
srcY0 = vpY; srcY0 = vpY;
srcX1 = vpX + vpW; srcX1 = vpX + vpW;
srcY1 = vpY + vpH; srcY1 = vpY + vpH;
} else { } else {
glfbo.glBindFramebufferEXT(GLExt.GL_READ_FRAMEBUFFER_EXT, src.getId()); glfbo.glBindFramebufferEXT(GLFbo.GL_READ_FRAMEBUFFER_EXT, src.getId());
srcX1 = src.getWidth(); srcX1 = src.getWidth();
srcY1 = src.getHeight(); srcY1 = src.getHeight();
} }
if (dst == null) { if (dst == null) {
glfbo.glBindFramebufferEXT(GLExt.GL_DRAW_FRAMEBUFFER_EXT, 0); glfbo.glBindFramebufferEXT(GLFbo.GL_DRAW_FRAMEBUFFER_EXT, 0);
dstX0 = vpX; dstX0 = vpX;
dstY0 = vpY; dstY0 = vpY;
dstX1 = vpX + vpW; dstX1 = vpX + vpW;
dstY1 = vpY + vpH; dstY1 = vpY + vpH;
} else { } else {
glfbo.glBindFramebufferEXT(GLExt.GL_DRAW_FRAMEBUFFER_EXT, dst.getId()); glfbo.glBindFramebufferEXT(GLFbo.GL_DRAW_FRAMEBUFFER_EXT, dst.getId());
dstX1 = dst.getWidth(); dstX1 = dst.getWidth();
dstY1 = dst.getHeight(); dstY1 = dst.getHeight();
} }
@ -1313,12 +1322,12 @@ public class GLRenderer implements Renderer {
if (copyDepth) { if (copyDepth) {
mask |= GL.GL_DEPTH_BUFFER_BIT; mask |= GL.GL_DEPTH_BUFFER_BIT;
} }
glext.glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, glfbo.glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1,
dstX0, dstY0, dstX1, dstY1, mask, dstX0, dstY0, dstX1, dstY1, mask,
GL.GL_NEAREST); GL.GL_NEAREST);
glfbo.glBindFramebufferEXT(GLExt.GL_FRAMEBUFFER_EXT, prevFBO); glfbo.glBindFramebufferEXT(GLFbo.GL_FRAMEBUFFER_EXT, prevFBO);
} else { } else {
throw new RendererException("Framebuffer blitting not supported by the video hardware"); throw new RendererException("Framebuffer blitting not supported by the video hardware");
} }
@ -1364,7 +1373,7 @@ public class GLRenderer implements Renderer {
} }
if (context.boundRB != id) { if (context.boundRB != id) {
glfbo.glBindRenderbufferEXT(GLExt.GL_RENDERBUFFER_EXT, id); glfbo.glBindRenderbufferEXT(GLFbo.GL_RENDERBUFFER_EXT, id);
context.boundRB = id; context.boundRB = id;
} }
@ -1382,13 +1391,13 @@ public class GLRenderer implements Renderer {
if (maxSamples < samples) { if (maxSamples < samples) {
samples = maxSamples; samples = maxSamples;
} }
glext.glRenderbufferStorageMultisampleEXT(GLExt.GL_RENDERBUFFER_EXT, glfbo.glRenderbufferStorageMultisampleEXT(GLFbo.GL_RENDERBUFFER_EXT,
samples, samples,
glFmt.internalFormat, glFmt.internalFormat,
fb.getWidth(), fb.getWidth(),
fb.getHeight()); fb.getHeight());
} else { } else {
glfbo.glRenderbufferStorageEXT(GLExt.GL_RENDERBUFFER_EXT, glfbo.glRenderbufferStorageEXT(GLFbo.GL_RENDERBUFFER_EXT,
glFmt.internalFormat, glFmt.internalFormat,
fb.getWidth(), fb.getWidth(),
fb.getHeight()); fb.getHeight());
@ -1398,7 +1407,7 @@ public class GLRenderer implements Renderer {
private int convertAttachmentSlot(int attachmentSlot) { private int convertAttachmentSlot(int attachmentSlot) {
// can also add support for stencil here // can also add support for stencil here
if (attachmentSlot == FrameBuffer.SLOT_DEPTH) { if (attachmentSlot == FrameBuffer.SLOT_DEPTH) {
return GLExt.GL_DEPTH_ATTACHMENT_EXT; return GLFbo.GL_DEPTH_ATTACHMENT_EXT;
} else if (attachmentSlot == FrameBuffer.SLOT_DEPTH_STENCIL) { } else if (attachmentSlot == FrameBuffer.SLOT_DEPTH_STENCIL) {
// NOTE: Using depth stencil format requires GL3, this is already // NOTE: Using depth stencil format requires GL3, this is already
// checked via render caps. // checked via render caps.
@ -1407,7 +1416,7 @@ public class GLRenderer implements Renderer {
throw new UnsupportedOperationException("Invalid FBO attachment slot: " + attachmentSlot); throw new UnsupportedOperationException("Invalid FBO attachment slot: " + attachmentSlot);
} }
return GLExt.GL_COLOR_ATTACHMENT0_EXT + attachmentSlot; return GLFbo.GL_COLOR_ATTACHMENT0_EXT + attachmentSlot;
} }
public void updateRenderTexture(FrameBuffer fb, RenderBuffer rb) { public void updateRenderTexture(FrameBuffer fb, RenderBuffer rb) {
@ -1425,7 +1434,7 @@ public class GLRenderer implements Renderer {
setupTextureParams(tex); setupTextureParams(tex);
} }
glfbo.glFramebufferTexture2DEXT(GLExt.GL_FRAMEBUFFER_EXT, glfbo.glFramebufferTexture2DEXT(GLFbo.GL_FRAMEBUFFER_EXT,
convertAttachmentSlot(rb.getSlot()), convertAttachmentSlot(rb.getSlot()),
convertTextureType(tex.getType(), image.getMultiSamples(), rb.getFace()), convertTextureType(tex.getType(), image.getMultiSamples(), rb.getFace()),
image.getId(), image.getId(),
@ -1443,9 +1452,9 @@ public class GLRenderer implements Renderer {
updateRenderTexture(fb, rb); updateRenderTexture(fb, rb);
} }
if (needAttach) { if (needAttach) {
glfbo.glFramebufferRenderbufferEXT(GLExt.GL_FRAMEBUFFER_EXT, glfbo.glFramebufferRenderbufferEXT(GLFbo.GL_FRAMEBUFFER_EXT,
convertAttachmentSlot(rb.getSlot()), convertAttachmentSlot(rb.getSlot()),
GLExt.GL_RENDERBUFFER_EXT, GLFbo.GL_RENDERBUFFER_EXT,
rb.getId()); rb.getId());
} }
} }
@ -1463,7 +1472,7 @@ public class GLRenderer implements Renderer {
} }
if (context.boundFBO != id) { if (context.boundFBO != id) {
glfbo.glBindFramebufferEXT(GLExt.GL_FRAMEBUFFER_EXT, id); glfbo.glBindFramebufferEXT(GLFbo.GL_FRAMEBUFFER_EXT, id);
// binding an FBO automatically sets draw buf to GL_COLOR_ATTACHMENT0 // binding an FBO automatically sets draw buf to GL_COLOR_ATTACHMENT0
context.boundDrawBuf = 0; context.boundDrawBuf = 0;
context.boundFBO = id; context.boundFBO = id;
@ -1543,7 +1552,7 @@ public class GLRenderer implements Renderer {
if (fb == null) { if (fb == null) {
// unbind any fbos // unbind any fbos
if (context.boundFBO != 0) { if (context.boundFBO != 0) {
glfbo.glBindFramebufferEXT(GLExt.GL_FRAMEBUFFER_EXT, 0); glfbo.glBindFramebufferEXT(GLFbo.GL_FRAMEBUFFER_EXT, 0);
statistics.onFrameBufferUse(null, true); statistics.onFrameBufferUse(null, true);
context.boundFBO = 0; context.boundFBO = 0;
@ -1575,7 +1584,7 @@ public class GLRenderer implements Renderer {
setViewPort(0, 0, fb.getWidth(), fb.getHeight()); setViewPort(0, 0, fb.getWidth(), fb.getHeight());
if (context.boundFBO != fb.getId()) { if (context.boundFBO != fb.getId()) {
glfbo.glBindFramebufferEXT(GLExt.GL_FRAMEBUFFER_EXT, fb.getId()); glfbo.glBindFramebufferEXT(GLFbo.GL_FRAMEBUFFER_EXT, fb.getId());
statistics.onFrameBufferUse(fb, true); statistics.onFrameBufferUse(fb, true);
context.boundFBO = fb.getId(); context.boundFBO = fb.getId();
@ -1615,7 +1624,7 @@ public class GLRenderer implements Renderer {
if (context.boundDrawBuf != 100 + fb.getNumColorBuffers()) { if (context.boundDrawBuf != 100 + fb.getNumColorBuffers()) {
intBuf16.clear(); intBuf16.clear();
for (int i = 0; i < fb.getNumColorBuffers(); i++) { for (int i = 0; i < fb.getNumColorBuffers(); i++) {
intBuf16.put(GLExt.GL_COLOR_ATTACHMENT0_EXT + i); intBuf16.put(GLFbo.GL_COLOR_ATTACHMENT0_EXT + i);
} }
intBuf16.flip(); intBuf16.flip();
@ -1627,7 +1636,7 @@ public class GLRenderer implements Renderer {
// select this draw buffer // select this draw buffer
if (gl2 != null) { if (gl2 != null) {
if (context.boundDrawBuf != rb.getSlot()) { if (context.boundDrawBuf != rb.getSlot()) {
gl2.glDrawBuffer(GLExt.GL_COLOR_ATTACHMENT0_EXT + rb.getSlot()); gl2.glDrawBuffer(GLFbo.GL_COLOR_ATTACHMENT0_EXT + rb.getSlot());
context.boundDrawBuf = rb.getSlot(); context.boundDrawBuf = rb.getSlot();
} }
} }
@ -1656,7 +1665,7 @@ public class GLRenderer implements Renderer {
setFrameBuffer(fb); setFrameBuffer(fb);
if (gl2 != null) { if (gl2 != null) {
if (context.boundReadBuf != rb.getSlot()) { if (context.boundReadBuf != rb.getSlot()) {
gl2.glReadBuffer(GLExt.GL_COLOR_ATTACHMENT0_EXT + rb.getSlot()); gl2.glReadBuffer(GLFbo.GL_COLOR_ATTACHMENT0_EXT + rb.getSlot());
context.boundReadBuf = rb.getSlot(); context.boundReadBuf = rb.getSlot();
} }
} }
@ -1680,7 +1689,7 @@ public class GLRenderer implements Renderer {
public void deleteFrameBuffer(FrameBuffer fb) { public void deleteFrameBuffer(FrameBuffer fb) {
if (fb.getId() != -1) { if (fb.getId() != -1) {
if (context.boundFBO == fb.getId()) { if (context.boundFBO == fb.getId()) {
glfbo.glBindFramebufferEXT(GLExt.GL_FRAMEBUFFER_EXT, 0); glfbo.glBindFramebufferEXT(GLFbo.GL_FRAMEBUFFER_EXT, 0);
context.boundFBO = 0; context.boundFBO = 0;
} }
@ -2618,32 +2627,13 @@ public class GLRenderer implements Renderer {
return; return;
} }
if (context.pointSprite && mesh.getMode() != Mode.Points) {
// XXX: Hack, disable point sprite mode if mesh not in point mode
if (context.boundTextures[0] != null) {
if (context.boundTextureUnit != 0) {
gl.glActiveTexture(GL.GL_TEXTURE0);
context.boundTextureUnit = 0;
}
if (gl2 != null) {
gl2.glDisable(GL2.GL_POINT_SPRITE);
gl2.glDisable(GL2.GL_VERTEX_PROGRAM_POINT_SIZE);
}
context.pointSprite = false;
}
}
if (gl2 != null) {
if (context.pointSize != mesh.getPointSize()) {
gl2.glPointSize(mesh.getPointSize());
context.pointSize = mesh.getPointSize();
}
}
if (context.lineWidth != mesh.getLineWidth()) { if (context.lineWidth != mesh.getLineWidth()) {
gl.glLineWidth(mesh.getLineWidth()); gl.glLineWidth(mesh.getLineWidth());
context.lineWidth = mesh.getLineWidth(); context.lineWidth = mesh.getLineWidth();
} }
if(gl4!=null && mesh.getMode().equals(Mode.Patch)){
if (gl4 != null && mesh.getMode().equals(Mode.Patch)) {
gl4.glPatchParameter(mesh.getPatchVertexCount()); gl4.glPatchParameter(mesh.getPatchVertexCount());
} }
statistics.onMeshDrawn(mesh, lod, count); statistics.onMeshDrawn(mesh, lod, count);

@ -64,6 +64,7 @@ public final class GLTracer implements InvocationHandler {
noEnumArgs("glScissor", 0, 1, 2, 3); noEnumArgs("glScissor", 0, 1, 2, 3);
noEnumArgs("glClear", 0); noEnumArgs("glClear", 0);
noEnumArgs("glGetInteger", 1); noEnumArgs("glGetInteger", 1);
noEnumArgs("glGetString", 1);
noEnumArgs("glBindTexture", 1); noEnumArgs("glBindTexture", 1);
noEnumArgs("glPixelStorei", 1); noEnumArgs("glPixelStorei", 1);
@ -95,8 +96,6 @@ public final class GLTracer implements InvocationHandler {
noEnumArgs("glFramebufferTexture2DEXT", 3, 4); noEnumArgs("glFramebufferTexture2DEXT", 3, 4);
noEnumArgs("glBlitFramebufferEXT", 0, 1, 2, 3, 4, 5, 6, 7, 8); noEnumArgs("glBlitFramebufferEXT", 0, 1, 2, 3, 4, 5, 6, 7, 8);
noEnumArgs("glCreateProgram", -1); noEnumArgs("glCreateProgram", -1);
noEnumArgs("glCreateShader", -1); noEnumArgs("glCreateShader", -1);
noEnumArgs("glShaderSource", 0); noEnumArgs("glShaderSource", 0);
@ -155,7 +154,7 @@ public final class GLTracer implements InvocationHandler {
* @return A tracer that implements the given interface * @return A tracer that implements the given interface
*/ */
public static Object createGlesTracer(Object glInterface, Class<?> glInterfaceClass) { public static Object createGlesTracer(Object glInterface, Class<?> glInterfaceClass) {
IntMap<String> constMap = generateConstantMap(GL.class, GLExt.class); IntMap<String> constMap = generateConstantMap(GL.class, GLFbo.class, GLExt.class);
return Proxy.newProxyInstance(glInterface.getClass().getClassLoader(), return Proxy.newProxyInstance(glInterface.getClass().getClassLoader(),
new Class<?>[] { glInterfaceClass }, new Class<?>[] { glInterfaceClass },
new GLTracer(glInterface, constMap)); new GLTracer(glInterface, constMap));
@ -169,7 +168,7 @@ public final class GLTracer implements InvocationHandler {
* @return A tracer that implements the given interface * @return A tracer that implements the given interface
*/ */
public static Object createDesktopGlTracer(Object glInterface, Class<?> ... glInterfaceClasses) { public static Object createDesktopGlTracer(Object glInterface, Class<?> ... glInterfaceClasses) {
IntMap<String> constMap = generateConstantMap(GL2.class, GLExt.class); IntMap<String> constMap = generateConstantMap(GL2.class, GL3.class, GL4.class, GLFbo.class, GLExt.class);
return Proxy.newProxyInstance(glInterface.getClass().getClassLoader(), return Proxy.newProxyInstance(glInterface.getClass().getClassLoader(),
glInterfaceClasses, glInterfaceClasses,
new GLTracer(glInterface, constMap)); new GLTracer(glInterface, constMap));

@ -40,6 +40,7 @@ import com.jme3.renderer.ios.IosGL;
import com.jme3.renderer.opengl.GL; import com.jme3.renderer.opengl.GL;
import com.jme3.renderer.opengl.GLDebugES; import com.jme3.renderer.opengl.GLDebugES;
import com.jme3.renderer.opengl.GLExt; import com.jme3.renderer.opengl.GLExt;
import com.jme3.renderer.opengl.GLFbo;
import com.jme3.renderer.opengl.GLRenderer; import com.jme3.renderer.opengl.GLRenderer;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level; import java.util.logging.Level;
@ -158,11 +159,11 @@ public class IGLESContext implements JmeContext {
GLExt glext = (GLExt) gl; GLExt glext = (GLExt) gl;
// if (settings.getBoolean("GraphicsDebug")) { // if (settings.getBoolean("GraphicsDebug")) {
gl = new GLDebugES(gl, glext); gl = new GLDebugES(gl, glext, (GLFbo) glext);
glext = (GLExt) gl; glext = (GLExt) gl;
// } // }
renderer = new GLRenderer(gl, glext); renderer = new GLRenderer(gl, glext, (GLFbo) glext);
renderer.initialize(); renderer.initialize();
input = new IosInputHandler(); input = new IosInputHandler();

@ -13,7 +13,7 @@ import java.nio.ShortBuffer;
import com.jme3.renderer.opengl.GL4; import com.jme3.renderer.opengl.GL4;
import org.lwjgl.opengl.*; import org.lwjgl.opengl.*;
public class LwjglGL implements GL, GL2, GL3,GL4 { public class LwjglGL implements GL, GL2, GL3, GL4 {
private static void checkLimit(Buffer buffer) { private static void checkLimit(Buffer buffer) {
if (buffer == null) { if (buffer == null) {
@ -237,6 +237,10 @@ public class LwjglGL implements GL, GL2, GL3,GL4 {
public String glGetString(int param1) { public String glGetString(int param1) {
return GL11.glGetString(param1); return GL11.glGetString(param1);
} }
public String glGetString(int param1, int param2) {
return GL30.glGetStringi(param1, param2);
}
public boolean glIsEnabled(int param1) { public boolean glIsEnabled(int param1) {
return GL11.glIsEnabled(param1); return GL11.glIsEnabled(param1);
@ -444,4 +448,10 @@ public class LwjglGL implements GL, GL2, GL3,GL4 {
public void glPatchParameter(int count) { public void glPatchParameter(int count) {
GL40.glPatchParameteri(GL40.GL_PATCH_VERTICES,count); GL40.glPatchParameteri(GL40.GL_PATCH_VERTICES,count);
} }
@Override
public void glDeleteVertexArrays(IntBuffer arrays) {
checkLimit(arrays);
ARBVertexArrayObject.glDeleteVertexArrays(arrays);
}
} }

@ -7,12 +7,8 @@ import java.nio.FloatBuffer;
import java.nio.IntBuffer; import java.nio.IntBuffer;
import org.lwjgl.opengl.ARBDrawInstanced; import org.lwjgl.opengl.ARBDrawInstanced;
import org.lwjgl.opengl.ARBInstancedArrays; import org.lwjgl.opengl.ARBInstancedArrays;
import org.lwjgl.opengl.ARBPixelBufferObject;
import org.lwjgl.opengl.ARBSync; import org.lwjgl.opengl.ARBSync;
import org.lwjgl.opengl.ARBTextureMultisample; import org.lwjgl.opengl.ARBTextureMultisample;
import org.lwjgl.opengl.EXTFramebufferBlit;
import org.lwjgl.opengl.EXTFramebufferMultisample;
import org.lwjgl.opengl.EXTFramebufferObject;
import org.lwjgl.opengl.GL15; import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20; import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GLSync; import org.lwjgl.opengl.GLSync;
@ -30,99 +26,51 @@ public class LwjglGLExt implements GLExt {
throw new RendererException("Attempting to upload empty buffer (remaining = 0), that's an error"); throw new RendererException("Attempting to upload empty buffer (remaining = 0), that's an error");
} }
} }
public void glBlitFramebufferEXT(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, int mask, int filter) {
EXTFramebufferBlit.glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
}
@Override
public void glBufferData(int target, IntBuffer data, int usage) { public void glBufferData(int target, IntBuffer data, int usage) {
checkLimit(data); checkLimit(data);
GL15.glBufferData(target, data, usage); GL15.glBufferData(target, data, usage);
} }
@Override
public void glBufferSubData(int target, long offset, IntBuffer data) { public void glBufferSubData(int target, long offset, IntBuffer data) {
checkLimit(data); checkLimit(data);
GL15.glBufferSubData(target, offset, data); GL15.glBufferSubData(target, offset, data);
} }
@Override
public void glDrawArraysInstancedARB(int mode, int first, int count, int primcount) { public void glDrawArraysInstancedARB(int mode, int first, int count, int primcount) {
ARBDrawInstanced.glDrawArraysInstancedARB(mode, first, count, primcount); ARBDrawInstanced.glDrawArraysInstancedARB(mode, first, count, primcount);
} }
@Override
public void glDrawBuffers(IntBuffer bufs) { public void glDrawBuffers(IntBuffer bufs) {
checkLimit(bufs); checkLimit(bufs);
GL20.glDrawBuffers(bufs); GL20.glDrawBuffers(bufs);
} }
@Override
public void glDrawElementsInstancedARB(int mode, int indices_count, int type, long indices_buffer_offset, int primcount) { public void glDrawElementsInstancedARB(int mode, int indices_count, int type, long indices_buffer_offset, int primcount) {
ARBDrawInstanced.glDrawElementsInstancedARB(mode, indices_count, type, indices_buffer_offset, primcount); ARBDrawInstanced.glDrawElementsInstancedARB(mode, indices_count, type, indices_buffer_offset, primcount);
} }
@Override
public void glGetMultisample(int pname, int index, FloatBuffer val) { public void glGetMultisample(int pname, int index, FloatBuffer val) {
checkLimit(val); checkLimit(val);
ARBTextureMultisample.glGetMultisample(pname, index, val); ARBTextureMultisample.glGetMultisample(pname, index, val);
} }
public void glRenderbufferStorageMultisampleEXT(int target, int samples, int internalformat, int width, int height) { @Override
EXTFramebufferMultisample.glRenderbufferStorageMultisampleEXT(target, samples, internalformat, width, height);
}
public void glTexImage2DMultisample(int target, int samples, int internalformat, int width, int height, boolean fixedsamplelocations) { public void glTexImage2DMultisample(int target, int samples, int internalformat, int width, int height, boolean fixedsamplelocations) {
ARBTextureMultisample.glTexImage2DMultisample(target, samples, internalformat, width, height, fixedsamplelocations); ARBTextureMultisample.glTexImage2DMultisample(target, samples, internalformat, width, height, fixedsamplelocations);
} }
@Override
public void glVertexAttribDivisorARB(int index, int divisor) { public void glVertexAttribDivisorARB(int index, int divisor) {
ARBInstancedArrays.glVertexAttribDivisorARB(index, divisor); ARBInstancedArrays.glVertexAttribDivisorARB(index, divisor);
} }
public void glBindFramebufferEXT(int param1, int param2) {
EXTFramebufferObject.glBindFramebufferEXT(param1, param2);
}
public void glBindRenderbufferEXT(int param1, int param2) {
EXTFramebufferObject.glBindRenderbufferEXT(param1, param2);
}
public int glCheckFramebufferStatusEXT(int param1) {
return EXTFramebufferObject.glCheckFramebufferStatusEXT(param1);
}
public void glDeleteFramebuffersEXT(IntBuffer param1) {
checkLimit(param1);
EXTFramebufferObject.glDeleteFramebuffersEXT(param1);
}
public void glDeleteRenderbuffersEXT(IntBuffer param1) {
checkLimit(param1);
EXTFramebufferObject.glDeleteRenderbuffersEXT(param1);
}
public void glFramebufferRenderbufferEXT(int param1, int param2, int param3, int param4) {
EXTFramebufferObject.glFramebufferRenderbufferEXT(param1, param2, param3, param4);
}
public void glFramebufferTexture2DEXT(int param1, int param2, int param3, int param4, int param5) {
EXTFramebufferObject.glFramebufferTexture2DEXT(param1, param2, param3, param4, param5);
}
public void glGenFramebuffersEXT(IntBuffer param1) {
checkLimit(param1);
EXTFramebufferObject.glGenFramebuffersEXT(param1);
}
public void glGenRenderbuffersEXT(IntBuffer param1) {
checkLimit(param1);
EXTFramebufferObject.glGenRenderbuffersEXT(param1);
}
public void glGenerateMipmapEXT(int param1) {
EXTFramebufferObject.glGenerateMipmapEXT(param1);
}
public void glRenderbufferStorageEXT(int param1, int param2, int param3, int param4) {
EXTFramebufferObject.glRenderbufferStorageEXT(param1, param2, param3, param4);
}
@Override @Override
public Object glFenceSync(int condition, int flags) { public Object glFenceSync(int condition, int flags) {
return ARBSync.glFenceSync(condition, flags); return ARBSync.glFenceSync(condition, flags);

@ -0,0 +1,98 @@
package com.jme3.renderer.lwjgl;
import com.jme3.renderer.RendererException;
import com.jme3.renderer.opengl.GLFbo;
import java.nio.Buffer;
import java.nio.IntBuffer;
import org.lwjgl.opengl.EXTFramebufferBlit;
import org.lwjgl.opengl.EXTFramebufferMultisample;
import org.lwjgl.opengl.EXTFramebufferObject;
/**
* Implements GLFbo via GL_EXT_framebuffer_object.
*
* @author Kirill Vainer
*/
public class LwjglGLFboEXT implements GLFbo {
private static void checkLimit(Buffer buffer) {
if (buffer == null) {
return;
}
if (buffer.limit() == 0) {
throw new RendererException("Attempting to upload empty buffer (limit = 0), that's an error");
}
if (buffer.remaining() == 0) {
throw new RendererException("Attempting to upload empty buffer (remaining = 0), that's an error");
}
}
@Override
public void glBlitFramebufferEXT(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, int mask, int filter) {
EXTFramebufferBlit.glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
}
@Override
public void glRenderbufferStorageMultisampleEXT(int target, int samples, int internalformat, int width, int height) {
EXTFramebufferMultisample.glRenderbufferStorageMultisampleEXT(target, samples, internalformat, width, height);
}
@Override
public void glBindFramebufferEXT(int param1, int param2) {
EXTFramebufferObject.glBindFramebufferEXT(param1, param2);
}
@Override
public void glBindRenderbufferEXT(int param1, int param2) {
EXTFramebufferObject.glBindRenderbufferEXT(param1, param2);
}
@Override
public int glCheckFramebufferStatusEXT(int param1) {
return EXTFramebufferObject.glCheckFramebufferStatusEXT(param1);
}
@Override
public void glDeleteFramebuffersEXT(IntBuffer param1) {
checkLimit(param1);
EXTFramebufferObject.glDeleteFramebuffersEXT(param1);
}
@Override
public void glDeleteRenderbuffersEXT(IntBuffer param1) {
checkLimit(param1);
EXTFramebufferObject.glDeleteRenderbuffersEXT(param1);
}
@Override
public void glFramebufferRenderbufferEXT(int param1, int param2, int param3, int param4) {
EXTFramebufferObject.glFramebufferRenderbufferEXT(param1, param2, param3, param4);
}
@Override
public void glFramebufferTexture2DEXT(int param1, int param2, int param3, int param4, int param5) {
EXTFramebufferObject.glFramebufferTexture2DEXT(param1, param2, param3, param4, param5);
}
@Override
public void glGenFramebuffersEXT(IntBuffer param1) {
checkLimit(param1);
EXTFramebufferObject.glGenFramebuffersEXT(param1);
}
@Override
public void glGenRenderbuffersEXT(IntBuffer param1) {
checkLimit(param1);
EXTFramebufferObject.glGenRenderbuffersEXT(param1);
}
@Override
public void glGenerateMipmapEXT(int param1) {
EXTFramebufferObject.glGenerateMipmapEXT(param1);
}
@Override
public void glRenderbufferStorageEXT(int param1, int param2, int param3, int param4) {
EXTFramebufferObject.glRenderbufferStorageEXT(param1, param2, param3, param4);
}
}

@ -0,0 +1,96 @@
package com.jme3.renderer.lwjgl;
import com.jme3.renderer.RendererException;
import com.jme3.renderer.opengl.GLFbo;
import java.nio.Buffer;
import java.nio.IntBuffer;
import org.lwjgl.opengl.GL30;
/**
* Implements GLFbo via OpenGL3+.
*
* @author Kirill Vainer
*/
public class LwjglGLFboGL3 implements GLFbo {
private static void checkLimit(Buffer buffer) {
if (buffer == null) {
return;
}
if (buffer.limit() == 0) {
throw new RendererException("Attempting to upload empty buffer (limit = 0), that's an error");
}
if (buffer.remaining() == 0) {
throw new RendererException("Attempting to upload empty buffer (remaining = 0), that's an error");
}
}
@Override
public void glBlitFramebufferEXT(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, int mask, int filter) {
GL30.glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
}
@Override
public void glRenderbufferStorageMultisampleEXT(int target, int samples, int internalformat, int width, int height) {
GL30.glRenderbufferStorageMultisample(target, samples, internalformat, width, height);
}
@Override
public void glBindFramebufferEXT(int param1, int param2) {
GL30.glBindFramebuffer(param1, param2);
}
@Override
public void glBindRenderbufferEXT(int param1, int param2) {
GL30.glBindRenderbuffer(param1, param2);
}
@Override
public int glCheckFramebufferStatusEXT(int param1) {
return GL30.glCheckFramebufferStatus(param1);
}
@Override
public void glDeleteFramebuffersEXT(IntBuffer param1) {
checkLimit(param1);
GL30.glDeleteFramebuffers(param1);
}
@Override
public void glDeleteRenderbuffersEXT(IntBuffer param1) {
checkLimit(param1);
GL30.glDeleteRenderbuffers(param1);
}
@Override
public void glFramebufferRenderbufferEXT(int param1, int param2, int param3, int param4) {
GL30.glFramebufferRenderbuffer(param1, param2, param3, param4);
}
@Override
public void glFramebufferTexture2DEXT(int param1, int param2, int param3, int param4, int param5) {
GL30.glFramebufferTexture2D(param1, param2, param3, param4, param5);
}
@Override
public void glGenFramebuffersEXT(IntBuffer param1) {
checkLimit(param1);
GL30.glGenFramebuffers(param1);
}
@Override
public void glGenRenderbuffersEXT(IntBuffer param1) {
checkLimit(param1);
GL30.glGenRenderbuffers(param1);
}
@Override
public void glGenerateMipmapEXT(int param1) {
GL30.glGenerateMipmap(param1);
}
@Override
public void glRenderbufferStorageEXT(int param1, int param2, int param3, int param4) {
GL30.glRenderbufferStorage(param1, param2, param3, param4);
}
}

@ -39,13 +39,18 @@ import com.jme3.renderer.Renderer;
import com.jme3.renderer.RendererException; import com.jme3.renderer.RendererException;
import com.jme3.renderer.lwjgl.LwjglGL; import com.jme3.renderer.lwjgl.LwjglGL;
import com.jme3.renderer.lwjgl.LwjglGLExt; import com.jme3.renderer.lwjgl.LwjglGLExt;
import com.jme3.renderer.lwjgl.LwjglGLFboEXT;
import com.jme3.renderer.lwjgl.LwjglGLFboGL3;
import com.jme3.renderer.opengl.GL; import com.jme3.renderer.opengl.GL;
import com.jme3.renderer.opengl.GL2; import com.jme3.renderer.opengl.GL2;
import com.jme3.renderer.opengl.GL3; import com.jme3.renderer.opengl.GL3;
import com.jme3.renderer.opengl.GL4;
import com.jme3.renderer.opengl.GLDebugDesktop; import com.jme3.renderer.opengl.GLDebugDesktop;
import com.jme3.renderer.opengl.GLExt; import com.jme3.renderer.opengl.GLExt;
import com.jme3.renderer.opengl.GLFbo; import com.jme3.renderer.opengl.GLFbo;
import com.jme3.renderer.opengl.GLRenderer; import com.jme3.renderer.opengl.GLRenderer;
import com.jme3.renderer.opengl.GLTiming;
import com.jme3.renderer.opengl.GLTimingState;
import com.jme3.renderer.opengl.GLTracer; import com.jme3.renderer.opengl.GLTracer;
import com.jme3.system.AppSettings; import com.jme3.system.AppSettings;
import com.jme3.system.JmeContext; import com.jme3.system.JmeContext;
@ -203,21 +208,30 @@ public abstract class LwjglContext implements JmeContext {
} }
if (settings.getRenderer().equals(AppSettings.LWJGL_OPENGL2) if (settings.getRenderer().equals(AppSettings.LWJGL_OPENGL2)
|| settings.getRenderer().equals(AppSettings.LWJGL_OPENGL3)) { || settings.getRenderer().equals(AppSettings.LWJGL_OPENGL3)) {
GL gl = new LwjglGL(); GL gl = new LwjglGL();
GLFbo glfbo = new LwjglGLExt(); GLExt glext = new LwjglGLExt();
GLFbo glfbo;
if (GLContext.getCapabilities().OpenGL30) {
glfbo = new LwjglGLFboGL3();
} else {
glfbo = new LwjglGLFboEXT();
}
if (settings.getBoolean("GraphicsDebug")) { if (settings.getBoolean("GraphicsDebug")) {
gl = new GLDebugDesktop(gl, glfbo); gl = new GLDebugDesktop(gl, glext, glfbo);
glext = (GLExt) gl;
glfbo = (GLFbo) gl; glfbo = (GLFbo) gl;
} }
if (settings.getBoolean("GraphicsTrace")) { if (settings.getBoolean("GraphicsTrace")) {
gl = (GL) GLTracer.createDesktopGlTracer(gl, GL.class, GL2.class, GL3.class); gl = (GL) GLTracer.createDesktopGlTracer(gl, GL.class, GL2.class, GL3.class, GL4.class);
glfbo = (GLFbo) GLTracer.createDesktopGlTracer(glfbo, GLExt.class); glext = (GLExt) GLTracer.createDesktopGlTracer(glext, GLExt.class);
glfbo = (GLFbo) GLTracer.createDesktopGlTracer(glfbo, GLFbo.class);
} }
renderer = new GLRenderer(gl, glfbo); renderer = new GLRenderer(gl, glext, glfbo);
renderer.initialize(); renderer.initialize();
} else { } else {
throw new UnsupportedOperationException("Unsupported renderer: " + settings.getRenderer()); throw new UnsupportedOperationException("Unsupported renderer: " + settings.getRenderer());

Loading…
Cancel
Save