From 5b95f8a4b0e70a9ef5839be199f5274a94247f02 Mon Sep 17 00:00:00 2001 From: Kirill Vainer Date: Sat, 25 Apr 2015 16:57:24 -0400 Subject: [PATCH] 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. --- .../com/jme3/system/android/OGLESContext.java | 3 +- .../src/main/java/com/jme3/renderer/Caps.java | 14 +- .../java/com/jme3/renderer/opengl/GL.java | 1 - .../java/com/jme3/renderer/opengl/GL3.java | 10 +- .../jme3/renderer/opengl/GLDebugDesktop.java | 19 ++- .../com/jme3/renderer/opengl/GLDebugES.java | 10 +- .../java/com/jme3/renderer/opengl/GLExt.java | 4 +- .../java/com/jme3/renderer/opengl/GLFbo.java | 3 +- .../jme3/renderer/opengl/GLImageFormats.java | 38 +++-- .../com/jme3/renderer/opengl/GLRenderer.java | 160 ++++++++---------- .../com/jme3/renderer/opengl/GLTracer.java | 7 +- .../com/jme3/system/ios/IGLESContext.java | 5 +- .../java/com/jme3/renderer/lwjgl/LwjglGL.java | 12 +- .../com/jme3/renderer/lwjgl/LwjglGLExt.java | 68 +------- .../jme3/renderer/lwjgl/LwjglGLFboEXT.java | 98 +++++++++++ .../jme3/renderer/lwjgl/LwjglGLFboGL3.java | 96 +++++++++++ .../com/jme3/system/lwjgl/LwjglContext.java | 26 ++- 17 files changed, 383 insertions(+), 191 deletions(-) create mode 100644 jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGLFboEXT.java create mode 100644 jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGLFboGL3.java diff --git a/jme3-android/src/main/java/com/jme3/system/android/OGLESContext.java b/jme3-android/src/main/java/com/jme3/system/android/OGLESContext.java index 9472bff0b..991ad25c0 100644 --- a/jme3-android/src/main/java/com/jme3/system/android/OGLESContext.java +++ b/jme3-android/src/main/java/com/jme3/system/android/OGLESContext.java @@ -54,6 +54,7 @@ import com.jme3.input.dummy.DummyMouseInput; import com.jme3.renderer.android.AndroidGL; import com.jme3.renderer.opengl.GL; import com.jme3.renderer.opengl.GLExt; +import com.jme3.renderer.opengl.GLFbo; import com.jme3.renderer.opengl.GLRenderer; import com.jme3.system.*; import java.util.concurrent.atomic.AtomicBoolean; @@ -196,7 +197,7 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTex Object gl = new AndroidGL(); // gl = GLTracer.createGlesTracer((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(); JmeSystem.setSoftTextDialogInput(this); diff --git a/jme3-core/src/main/java/com/jme3/renderer/Caps.java b/jme3-core/src/main/java/com/jme3/renderer/Caps.java index f0d42c8f2..9387b687e 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/Caps.java +++ b/jme3-core/src/main/java/com/jme3/renderer/Caps.java @@ -337,7 +337,19 @@ public enum Caps { *

* 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 diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java index 9c73838e2..21ca7a7fa 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java @@ -32,7 +32,6 @@ package com.jme3.renderer.opengl; import java.nio.ByteBuffer; -import java.nio.DoubleBuffer; import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.nio.ShortBuffer; diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL3.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GL3.java index 50eb065ab..190ed4547 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL3.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GL3.java @@ -35,14 +35,18 @@ import java.nio.IntBuffer; /** * GL functions only available on vanilla desktop OpenGL 3.0. - * + * * @author Kirill Vainer */ public interface GL3 extends GL2 { - + 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 glBindVertexArray(int param1); /// GL3+ + public void glDeleteVertexArrays(IntBuffer arrays); /// GL3+ public void glGenVertexArrays(IntBuffer param1); /// GL3+ + public String glGetString(int param1, int param2); /// GL3+ } diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugDesktop.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugDesktop.java index e13402bd5..5fbaaaa52 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugDesktop.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugDesktop.java @@ -3,13 +3,13 @@ package com.jme3.renderer.opengl; import java.nio.ByteBuffer; 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 GL3 gl3; - public GLDebugDesktop(GL gl, GLFbo glfbo) { - super(gl, glfbo); + public GLDebugDesktop(GL gl, GLExt glext, GLFbo glfbo) { + super(gl, glext, glfbo); this.gl2 = gl instanceof GL2 ? (GL2) 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); 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(); + } } 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 index 259c56406..3e8850589 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugES.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugES.java @@ -10,12 +10,10 @@ public class GLDebugES extends GLDebug implements GL, GLFbo, GLExt { private final GLFbo glfbo; private final GLExt glext; - public GLDebugES(GL gl, GLFbo glfbo) { + public GLDebugES(GL gl, GLExt glext, GLFbo glfbo) { this.gl = gl; -// this.gl2 = gl instanceof GL2 ? (GL2) gl : null; -// this.gl3 = gl instanceof GL3 ? (GL3) gl : null; + this.glext = glext; this.glfbo = glfbo; - this.glext = glfbo instanceof GLExt ? (GLExt) glfbo : null; } 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) { - 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(); } @@ -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) { - glext.glRenderbufferStorageMultisampleEXT(target, samples, internalformat, width, height); + glfbo.glRenderbufferStorageMultisampleEXT(target, samples, internalformat, width, height); checkError(); } diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLExt.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLExt.java index b0e0b5f78..27f0eb8bd 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLExt.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLExt.java @@ -41,7 +41,7 @@ import java.nio.IntBuffer; * * @author Kirill Vainer */ -public interface GLExt extends GLFbo { +public interface GLExt { public static final int GL_ALREADY_SIGNALED = 0x911A; 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_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 glBufferSubData(int target, long offset, IntBuffer data); 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 Object glFenceSync(int condition, int flags); 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 glVertexAttribDivisorARB(int index, int divisor); } diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLFbo.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLFbo.java index 252619db8..737019ce2 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLFbo.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLFbo.java @@ -83,6 +83,7 @@ public interface GLFbo { public void glBindFramebufferEXT(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 void glDeleteFramebuffersEXT(IntBuffer param1); public void glDeleteRenderbuffersEXT(IntBuffer param1); @@ -92,5 +93,5 @@ public interface GLFbo { public void glGenRenderbuffersEXT(IntBuffer param1); public void glGenerateMipmapEXT(int param1); public void glRenderbufferStorageEXT(int param1, int param2, int param3, int param4); - + public void glRenderbufferStorageMultisampleEXT(int target, int samples, int internalformat, int width, int height); } diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLImageFormats.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLImageFormats.java index 423ae909e..a7ef9f52d 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLImageFormats.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLImageFormats.java @@ -89,9 +89,11 @@ public final class GLImageFormats { GLImageFormat[][] formatToGL = new GLImageFormat[2][Image.Format.values().length]; if (caps.contains(Caps.OpenGL20)) { - format(formatToGL, Format.Alpha8, GL2.GL_ALPHA8, GL.GL_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); + if (!caps.contains(Caps.CoreProfile)) { + format(formatToGL, Format.Alpha8, GL2.GL_ALPHA8, GL.GL_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.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); @@ -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.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.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); + if (!caps.contains(Caps.CoreProfile)) { + 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.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); @@ -124,16 +128,20 @@ public final class GLImageFormats { } } else if (caps.contains(Caps.Rgba8)) { // 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); - 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); + if (!caps.contains(Caps.CoreProfile)) { + format(formatToGL, Format.Alpha8, GLExt.GL_RGBA8, GL.GL_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.RGBA8, GLExt.GL_RGBA8, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE); } else { // 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); - 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); + if (!caps.contains(Caps.CoreProfile)) { + format(formatToGL, Format.Alpha8, GL.GL_RGBA4, GL.GL_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.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); if (caps.contains(Caps.FloatTexture)) { - format(formatToGL, Format.Luminance16F, GLExt.GL_LUMINANCE16F_ARB, GL.GL_LUMINANCE, 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); + if (!caps.contains(Caps.CoreProfile)) { + format(formatToGL, Format.Luminance16F, GLExt.GL_LUMINANCE16F_ARB, GL.GL_LUMINANCE, 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.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); diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java index 32d8e6b24..7b928202f 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java @@ -112,13 +112,13 @@ public class GLRenderer implements Renderer { private final GLFbo glfbo; private final TextureUtil texUtil; - public GLRenderer(GL gl, GLFbo glfbo) { + public GLRenderer(GL gl, GLExt glext, GLFbo glfbo) { this.gl = gl; this.gl2 = gl instanceof GL2 ? (GL2)gl : null; this.gl3 = gl instanceof GL3 ? (GL3)gl : null; this.gl4 = gl instanceof GL4 ? (GL4)gl : null; this.glfbo = glfbo; - this.glext = glfbo instanceof GLExt ? (GLExt)glfbo : null; + this.glext = glext; this.texUtil = new TextureUtil(gl, gl2, glext, context); } @@ -137,10 +137,19 @@ public class GLRenderer implements Renderer { return limits; } - private static HashSet loadExtensions(String extensions) { + private HashSet loadExtensions() { HashSet extensionSet = new HashSet(64); - for (String extension : extensions.split(" ")) { - extensionSet.add(extension); + if (gl3 != null) { + // 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; } @@ -185,10 +194,12 @@ public class GLRenderer implements Renderer { caps.add(Caps.OpenGL31); if (oglVer >= 320) { caps.add(Caps.OpenGL32); - }if(oglVer>=330){ + } + if (oglVer >= 330) { caps.add(Caps.OpenGL33); caps.add(Caps.GeometryShader); - }if(oglVer>=400){ + } + if (oglVer >= 400) { caps.add(Caps.OpenGL40); caps.add(Caps.TesselationShader); } @@ -243,7 +254,7 @@ public class GLRenderer implements Renderer { } private void loadCapabilitiesCommon() { - extensions = loadExtensions(gl.glGetString(GL.GL_EXTENSIONS)); + extensions = loadExtensions(); limits.put(Limits.VertexTextureUnits, getInteger(GL.GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS)); 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)); - + // gl.glGetInteger(GL.GL_MAX_VERTEX_UNIFORM_COMPONENTS, intBuf16); // vertexUniforms = intBuf16.get(0); // logger.log(Level.FINER, "Vertex Uniforms: {0}", vertexUniforms); @@ -279,7 +290,7 @@ public class GLRenderer implements Renderer { // == texture format extensions == - boolean hasFloatTexture = false; + boolean hasFloatTexture; hasFloatTexture = hasExtension("GL_OES_texture_half_float") && hasExtension("GL_OES_texture_float"); @@ -375,11 +386,11 @@ public class GLRenderer implements Renderer { caps.add(Caps.TextureFilterAnisotropic); } - if (hasExtension("GL_EXT_framebuffer_object")) { + if (hasExtension("GL_EXT_framebuffer_object") || gl3 != null) { caps.add(Caps.FrameBuffer); - limits.put(Limits.RenderBufferSize, getInteger(GLExt.GL_MAX_RENDERBUFFER_SIZE_EXT)); - limits.put(Limits.FrameBufferAttachments, getInteger(GLExt.GL_MAX_COLOR_ATTACHMENTS_EXT)); + limits.put(Limits.RenderBufferSize, getInteger(GLFbo.GL_MAX_RENDERBUFFER_SIZE_EXT)); + limits.put(Limits.FrameBufferAttachments, getInteger(GLFbo.GL_MAX_COLOR_ATTACHMENTS_EXT)); if (hasExtension("GL_EXT_framebuffer_blit")) { caps.add(Caps.FrameBufferBlit); @@ -434,21 +445,30 @@ public class GLRenderer implements Renderer { caps.add(Caps.SeamlessCubemap); } -// if (hasExtension("GL_ARB_get_program_binary")) { -// int binaryFormats = getInteger(GLExt.GL_NUM_PROGRAM_BINARY_FORMATS); -// } + if (caps.contains(Caps.OpenGL32) && !hasExtension("GL_ARB_compatibility")) { + 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 logger.log(Level.INFO, "OpenGL Renderer Information\n" + " * Vendor: {0}\n" + " * Renderer: {1}\n" + " * OpenGL Version: {2}\n" + - " * GLSL Version: {3}", + " * GLSL Version: {3}\n" + + " * Profile: {4}", new Object[]{ gl.glGetString(GL.GL_VENDOR), gl.glGetString(GL.GL_RENDERER), 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) @@ -491,6 +511,20 @@ public class GLRenderer implements Renderer { // Initialize default state.. 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() { @@ -610,31 +644,6 @@ public class GLRenderer implements Renderer { 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 (!context.polyOffsetEnabled) { gl.glEnable(GL.GL_POLYGON_OFFSET_FILL); @@ -1288,24 +1297,24 @@ public class GLRenderer implements Renderer { } if (src == null) { - glfbo.glBindFramebufferEXT(GLExt.GL_READ_FRAMEBUFFER_EXT, 0); + glfbo.glBindFramebufferEXT(GLFbo.GL_READ_FRAMEBUFFER_EXT, 0); srcX0 = vpX; srcY0 = vpY; srcX1 = vpX + vpW; srcY1 = vpY + vpH; } else { - glfbo.glBindFramebufferEXT(GLExt.GL_READ_FRAMEBUFFER_EXT, src.getId()); + glfbo.glBindFramebufferEXT(GLFbo.GL_READ_FRAMEBUFFER_EXT, src.getId()); srcX1 = src.getWidth(); srcY1 = src.getHeight(); } if (dst == null) { - glfbo.glBindFramebufferEXT(GLExt.GL_DRAW_FRAMEBUFFER_EXT, 0); + glfbo.glBindFramebufferEXT(GLFbo.GL_DRAW_FRAMEBUFFER_EXT, 0); dstX0 = vpX; dstY0 = vpY; dstX1 = vpX + vpW; dstY1 = vpY + vpH; } else { - glfbo.glBindFramebufferEXT(GLExt.GL_DRAW_FRAMEBUFFER_EXT, dst.getId()); + glfbo.glBindFramebufferEXT(GLFbo.GL_DRAW_FRAMEBUFFER_EXT, dst.getId()); dstX1 = dst.getWidth(); dstY1 = dst.getHeight(); } @@ -1313,12 +1322,12 @@ public class GLRenderer implements Renderer { if (copyDepth) { mask |= GL.GL_DEPTH_BUFFER_BIT; } - glext.glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, + glfbo.glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, GL.GL_NEAREST); - glfbo.glBindFramebufferEXT(GLExt.GL_FRAMEBUFFER_EXT, prevFBO); + glfbo.glBindFramebufferEXT(GLFbo.GL_FRAMEBUFFER_EXT, prevFBO); } else { throw new RendererException("Framebuffer blitting not supported by the video hardware"); } @@ -1364,7 +1373,7 @@ public class GLRenderer implements Renderer { } if (context.boundRB != id) { - glfbo.glBindRenderbufferEXT(GLExt.GL_RENDERBUFFER_EXT, id); + glfbo.glBindRenderbufferEXT(GLFbo.GL_RENDERBUFFER_EXT, id); context.boundRB = id; } @@ -1382,13 +1391,13 @@ public class GLRenderer implements Renderer { if (maxSamples < samples) { samples = maxSamples; } - glext.glRenderbufferStorageMultisampleEXT(GLExt.GL_RENDERBUFFER_EXT, + glfbo.glRenderbufferStorageMultisampleEXT(GLFbo.GL_RENDERBUFFER_EXT, samples, glFmt.internalFormat, fb.getWidth(), fb.getHeight()); } else { - glfbo.glRenderbufferStorageEXT(GLExt.GL_RENDERBUFFER_EXT, + glfbo.glRenderbufferStorageEXT(GLFbo.GL_RENDERBUFFER_EXT, glFmt.internalFormat, fb.getWidth(), fb.getHeight()); @@ -1398,7 +1407,7 @@ public class GLRenderer implements Renderer { private int convertAttachmentSlot(int attachmentSlot) { // can also add support for stencil here if (attachmentSlot == FrameBuffer.SLOT_DEPTH) { - return GLExt.GL_DEPTH_ATTACHMENT_EXT; + return GLFbo.GL_DEPTH_ATTACHMENT_EXT; } else if (attachmentSlot == FrameBuffer.SLOT_DEPTH_STENCIL) { // NOTE: Using depth stencil format requires GL3, this is already // checked via render caps. @@ -1407,7 +1416,7 @@ public class GLRenderer implements Renderer { 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) { @@ -1425,7 +1434,7 @@ public class GLRenderer implements Renderer { setupTextureParams(tex); } - glfbo.glFramebufferTexture2DEXT(GLExt.GL_FRAMEBUFFER_EXT, + glfbo.glFramebufferTexture2DEXT(GLFbo.GL_FRAMEBUFFER_EXT, convertAttachmentSlot(rb.getSlot()), convertTextureType(tex.getType(), image.getMultiSamples(), rb.getFace()), image.getId(), @@ -1443,9 +1452,9 @@ public class GLRenderer implements Renderer { updateRenderTexture(fb, rb); } if (needAttach) { - glfbo.glFramebufferRenderbufferEXT(GLExt.GL_FRAMEBUFFER_EXT, + glfbo.glFramebufferRenderbufferEXT(GLFbo.GL_FRAMEBUFFER_EXT, convertAttachmentSlot(rb.getSlot()), - GLExt.GL_RENDERBUFFER_EXT, + GLFbo.GL_RENDERBUFFER_EXT, rb.getId()); } } @@ -1463,7 +1472,7 @@ public class GLRenderer implements Renderer { } 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 context.boundDrawBuf = 0; context.boundFBO = id; @@ -1543,7 +1552,7 @@ public class GLRenderer implements Renderer { if (fb == null) { // unbind any fbos if (context.boundFBO != 0) { - glfbo.glBindFramebufferEXT(GLExt.GL_FRAMEBUFFER_EXT, 0); + glfbo.glBindFramebufferEXT(GLFbo.GL_FRAMEBUFFER_EXT, 0); statistics.onFrameBufferUse(null, true); context.boundFBO = 0; @@ -1575,7 +1584,7 @@ public class GLRenderer implements Renderer { setViewPort(0, 0, fb.getWidth(), fb.getHeight()); 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); context.boundFBO = fb.getId(); @@ -1615,7 +1624,7 @@ public class GLRenderer implements Renderer { if (context.boundDrawBuf != 100 + fb.getNumColorBuffers()) { intBuf16.clear(); 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(); @@ -1627,7 +1636,7 @@ public class GLRenderer implements Renderer { // select this draw buffer if (gl2 != null) { 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(); } } @@ -1656,7 +1665,7 @@ public class GLRenderer implements Renderer { setFrameBuffer(fb); if (gl2 != null) { 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(); } } @@ -1680,7 +1689,7 @@ public class GLRenderer implements Renderer { public void deleteFrameBuffer(FrameBuffer fb) { if (fb.getId() != -1) { if (context.boundFBO == fb.getId()) { - glfbo.glBindFramebufferEXT(GLExt.GL_FRAMEBUFFER_EXT, 0); + glfbo.glBindFramebufferEXT(GLFbo.GL_FRAMEBUFFER_EXT, 0); context.boundFBO = 0; } @@ -2618,32 +2627,13 @@ public class GLRenderer implements Renderer { 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()) { gl.glLineWidth(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()); } statistics.onMeshDrawn(mesh, lod, count); 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 b69d524b4..1b0d70749 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 @@ -64,6 +64,7 @@ public final class GLTracer implements InvocationHandler { noEnumArgs("glScissor", 0, 1, 2, 3); noEnumArgs("glClear", 0); noEnumArgs("glGetInteger", 1); + noEnumArgs("glGetString", 1); noEnumArgs("glBindTexture", 1); noEnumArgs("glPixelStorei", 1); @@ -95,8 +96,6 @@ public final class GLTracer implements InvocationHandler { noEnumArgs("glFramebufferTexture2DEXT", 3, 4); noEnumArgs("glBlitFramebufferEXT", 0, 1, 2, 3, 4, 5, 6, 7, 8); - - noEnumArgs("glCreateProgram", -1); noEnumArgs("glCreateShader", -1); noEnumArgs("glShaderSource", 0); @@ -155,7 +154,7 @@ public final class GLTracer implements InvocationHandler { * @return A tracer that implements the given interface */ public static Object createGlesTracer(Object glInterface, Class glInterfaceClass) { - IntMap constMap = generateConstantMap(GL.class, GLExt.class); + IntMap constMap = generateConstantMap(GL.class, GLFbo.class, GLExt.class); return Proxy.newProxyInstance(glInterface.getClass().getClassLoader(), new Class[] { glInterfaceClass }, new GLTracer(glInterface, constMap)); @@ -169,7 +168,7 @@ public final class GLTracer implements InvocationHandler { * @return A tracer that implements the given interface */ public static Object createDesktopGlTracer(Object glInterface, Class ... glInterfaceClasses) { - IntMap constMap = generateConstantMap(GL2.class, GLExt.class); + IntMap constMap = generateConstantMap(GL2.class, GL3.class, GL4.class, GLFbo.class, GLExt.class); return Proxy.newProxyInstance(glInterface.getClass().getClassLoader(), glInterfaceClasses, new GLTracer(glInterface, constMap)); diff --git a/jme3-ios/src/main/java/com/jme3/system/ios/IGLESContext.java b/jme3-ios/src/main/java/com/jme3/system/ios/IGLESContext.java index 7feaeae5b..2d046550e 100644 --- a/jme3-ios/src/main/java/com/jme3/system/ios/IGLESContext.java +++ b/jme3-ios/src/main/java/com/jme3/system/ios/IGLESContext.java @@ -40,6 +40,7 @@ import com.jme3.renderer.ios.IosGL; import com.jme3.renderer.opengl.GL; import com.jme3.renderer.opengl.GLDebugES; import com.jme3.renderer.opengl.GLExt; +import com.jme3.renderer.opengl.GLFbo; import com.jme3.renderer.opengl.GLRenderer; import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Level; @@ -158,11 +159,11 @@ public class IGLESContext implements JmeContext { GLExt glext = (GLExt) gl; // if (settings.getBoolean("GraphicsDebug")) { - gl = new GLDebugES(gl, glext); + gl = new GLDebugES(gl, glext, (GLFbo) glext); glext = (GLExt) gl; // } - renderer = new GLRenderer(gl, glext); + renderer = new GLRenderer(gl, glext, (GLFbo) glext); renderer.initialize(); input = new IosInputHandler(); diff --git a/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java b/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java index 82b8ee72b..0b55a3a40 100644 --- a/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java +++ b/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java @@ -13,7 +13,7 @@ import java.nio.ShortBuffer; import com.jme3.renderer.opengl.GL4; 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) { if (buffer == null) { @@ -237,6 +237,10 @@ public class LwjglGL implements GL, GL2, GL3,GL4 { public String glGetString(int param1) { return GL11.glGetString(param1); } + + public String glGetString(int param1, int param2) { + return GL30.glGetStringi(param1, param2); + } public boolean glIsEnabled(int param1) { return GL11.glIsEnabled(param1); @@ -444,4 +448,10 @@ public class LwjglGL implements GL, GL2, GL3,GL4 { public void glPatchParameter(int count) { GL40.glPatchParameteri(GL40.GL_PATCH_VERTICES,count); } + + @Override + public void glDeleteVertexArrays(IntBuffer arrays) { + checkLimit(arrays); + ARBVertexArrayObject.glDeleteVertexArrays(arrays); + } } diff --git a/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGLExt.java b/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGLExt.java index 89139282a..2c6a63fd7 100644 --- a/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGLExt.java +++ b/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGLExt.java @@ -7,12 +7,8 @@ import java.nio.FloatBuffer; import java.nio.IntBuffer; import org.lwjgl.opengl.ARBDrawInstanced; import org.lwjgl.opengl.ARBInstancedArrays; -import org.lwjgl.opengl.ARBPixelBufferObject; import org.lwjgl.opengl.ARBSync; 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.GL20; 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"); } } - - 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) { checkLimit(data); GL15.glBufferData(target, data, usage); } + @Override public void glBufferSubData(int target, long offset, IntBuffer data) { checkLimit(data); GL15.glBufferSubData(target, offset, data); } + @Override public void glDrawArraysInstancedARB(int mode, int first, int count, int primcount) { ARBDrawInstanced.glDrawArraysInstancedARB(mode, first, count, primcount); } + @Override public void glDrawBuffers(IntBuffer bufs) { checkLimit(bufs); GL20.glDrawBuffers(bufs); } + @Override 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); } + @Override public void glGetMultisample(int pname, int index, FloatBuffer val) { checkLimit(val); ARBTextureMultisample.glGetMultisample(pname, index, val); } - public void glRenderbufferStorageMultisampleEXT(int target, int samples, int internalformat, int width, int height) { - EXTFramebufferMultisample.glRenderbufferStorageMultisampleEXT(target, samples, internalformat, width, height); - } - + @Override public void glTexImage2DMultisample(int target, int samples, int internalformat, int width, int height, boolean fixedsamplelocations) { ARBTextureMultisample.glTexImage2DMultisample(target, samples, internalformat, width, height, fixedsamplelocations); } + @Override public void glVertexAttribDivisorARB(int index, int 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 public Object glFenceSync(int condition, int flags) { return ARBSync.glFenceSync(condition, flags); diff --git a/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGLFboEXT.java b/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGLFboEXT.java new file mode 100644 index 000000000..159000a6c --- /dev/null +++ b/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGLFboEXT.java @@ -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); + } +} diff --git a/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGLFboGL3.java b/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGLFboGL3.java new file mode 100644 index 000000000..acc540273 --- /dev/null +++ b/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGLFboGL3.java @@ -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); + } +} diff --git a/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglContext.java b/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglContext.java index 1286323ef..57ef81c0a 100644 --- a/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglContext.java +++ b/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglContext.java @@ -39,13 +39,18 @@ import com.jme3.renderer.Renderer; import com.jme3.renderer.RendererException; import com.jme3.renderer.lwjgl.LwjglGL; 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.GL2; import com.jme3.renderer.opengl.GL3; +import com.jme3.renderer.opengl.GL4; import com.jme3.renderer.opengl.GLDebugDesktop; import com.jme3.renderer.opengl.GLExt; import com.jme3.renderer.opengl.GLFbo; 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.system.AppSettings; import com.jme3.system.JmeContext; @@ -203,21 +208,30 @@ public abstract class LwjglContext implements JmeContext { } if (settings.getRenderer().equals(AppSettings.LWJGL_OPENGL2) - || settings.getRenderer().equals(AppSettings.LWJGL_OPENGL3)) { + || settings.getRenderer().equals(AppSettings.LWJGL_OPENGL3)) { 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")) { - gl = new GLDebugDesktop(gl, glfbo); + gl = new GLDebugDesktop(gl, glext, glfbo); + glext = (GLExt) gl; glfbo = (GLFbo) gl; } if (settings.getBoolean("GraphicsTrace")) { - gl = (GL) GLTracer.createDesktopGlTracer(gl, GL.class, GL2.class, GL3.class); - glfbo = (GLFbo) GLTracer.createDesktopGlTracer(glfbo, GLExt.class); + gl = (GL) GLTracer.createDesktopGlTracer(gl, GL.class, GL2.class, GL3.class, GL4.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(); } else { throw new UnsupportedOperationException("Unsupported renderer: " + settings.getRenderer());