diff --git a/jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGLExt.java b/jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGLExt.java index 83836aa3da..38d66b7f23 100644 --- a/jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGLExt.java +++ b/jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGLExt.java @@ -38,7 +38,14 @@ import java.nio.IntBuffer; /** - * The LWJGL implementation og {@link GLExt}. + * The LWJGL implementation of {@link GLExt}. + * + *
Each method prefers the equivalent core OpenGL function (available since + * the GL version that promoted the feature to core) and falls back to the + * corresponding ARB extension only when the core entry point is unavailable. + * This avoids JVM crashes on macOS Core Profile drivers that strip legacy ARB + * extension pointers even when the underlying functionality is exposed through + * the core profile. */ public class LwjglGLExt extends LwjglRender implements GLExt { @@ -56,7 +63,12 @@ public void glBufferSubData(final int target, final long offset, final IntBuffer @Override public void glDrawArraysInstancedARB(final int mode, final int first, final int count, final int primCount) { - ARBDrawInstanced.glDrawArraysInstancedARB(mode, first, count, primCount); + // glDrawArraysInstanced is core since OpenGL 3.1 + if (GL.getCapabilities().OpenGL31) { + GL31.glDrawArraysInstanced(mode, first, count, primCount); + } else { + ARBDrawInstanced.glDrawArraysInstancedARB(mode, first, count, primCount); + } } @Override @@ -68,64 +80,124 @@ public void glDrawBuffers(final IntBuffer bufs) { @Override public void glDrawElementsInstancedARB(final int mode, final int indicesCount, final int type, final long indicesBufferOffset, final int primCount) { - ARBDrawInstanced.glDrawElementsInstancedARB(mode, indicesCount, type, indicesBufferOffset, primCount); + // glDrawElementsInstanced is core since OpenGL 3.1 + if (GL.getCapabilities().OpenGL31) { + GL31.glDrawElementsInstanced(mode, indicesCount, type, indicesBufferOffset, primCount); + } else { + ARBDrawInstanced.glDrawElementsInstancedARB(mode, indicesCount, type, indicesBufferOffset, primCount); + } } @Override public void glGetMultisample(final int pname, final int index, final FloatBuffer val) { checkLimit(val); - ARBTextureMultisample.glGetMultisamplefv(pname, index, val); + // glGetMultisamplefv is core since OpenGL 3.2 + if (GL.getCapabilities().OpenGL32) { + GL32.glGetMultisamplefv(pname, index, val); + } else { + ARBTextureMultisample.glGetMultisamplefv(pname, index, val); + } } @Override public void glTexImage2DMultisample(final int target, final int samples, final int internalFormat, final int width, final int height, final boolean fixedSampleLocations) { - ARBTextureMultisample.glTexImage2DMultisample(target, samples, internalFormat, width, height, fixedSampleLocations); + // glTexImage2DMultisample is core since OpenGL 3.2 + if (GL.getCapabilities().OpenGL32) { + GL32.glTexImage2DMultisample(target, samples, internalFormat, width, height, fixedSampleLocations); + } else { + ARBTextureMultisample.glTexImage2DMultisample(target, samples, internalFormat, width, height, fixedSampleLocations); + } } @Override public void glVertexAttribDivisorARB(final int index, final int divisor) { - ARBInstancedArrays.glVertexAttribDivisorARB(index, divisor); + // glVertexAttribDivisor is core since OpenGL 3.3 + if (GL.getCapabilities().OpenGL33) { + GL33.glVertexAttribDivisor(index, divisor); + } else { + ARBInstancedArrays.glVertexAttribDivisorARB(index, divisor); + } } @Override public int glGetUniformBlockIndex(final int program, final String uniformBlockName) { - return ARBUniformBufferObject.glGetUniformBlockIndex(program, uniformBlockName); + // glGetUniformBlockIndex is core since OpenGL 3.1 + if (GL.getCapabilities().OpenGL31) { + return GL31.glGetUniformBlockIndex(program, uniformBlockName); + } else { + return ARBUniformBufferObject.glGetUniformBlockIndex(program, uniformBlockName); + } } @Override public void glBindBufferBase(final int target, final int index, final int buffer) { - ARBUniformBufferObject.glBindBufferBase(target, index, buffer); + // glBindBufferBase is core since OpenGL 3.0 + if (GL.getCapabilities().OpenGL30) { + GL30.glBindBufferBase(target, index, buffer); + } else { + ARBUniformBufferObject.glBindBufferBase(target, index, buffer); + } } @Override public void glUniformBlockBinding(final int program, final int uniformBlockIndex, final int uniformBlockBinding) { - ARBUniformBufferObject.glUniformBlockBinding(program, uniformBlockIndex, uniformBlockBinding); + // glUniformBlockBinding is core since OpenGL 3.1 + if (GL.getCapabilities().OpenGL31) { + GL31.glUniformBlockBinding(program, uniformBlockIndex, uniformBlockBinding); + } else { + ARBUniformBufferObject.glUniformBlockBinding(program, uniformBlockIndex, uniformBlockBinding); + } } @Override public int glGetProgramResourceIndex(final int program, final int programInterface, final String name) { - return ARBProgramInterfaceQuery.glGetProgramResourceIndex(program, programInterface, name); + // glGetProgramResourceIndex is core since OpenGL 4.3 + if (GL.getCapabilities().OpenGL43) { + return GL43.glGetProgramResourceIndex(program, programInterface, name); + } else { + return ARBProgramInterfaceQuery.glGetProgramResourceIndex(program, programInterface, name); + } } @Override public void glShaderStorageBlockBinding(final int program, final int storageBlockIndex, final int storageBlockBinding) { - ARBShaderStorageBufferObject.glShaderStorageBlockBinding(program, storageBlockIndex, storageBlockBinding); + // glShaderStorageBlockBinding is core since OpenGL 4.3 + if (GL.getCapabilities().OpenGL43) { + GL43.glShaderStorageBlockBinding(program, storageBlockIndex, storageBlockBinding); + } else { + ARBShaderStorageBufferObject.glShaderStorageBlockBinding(program, storageBlockIndex, storageBlockBinding); + } } @Override public Object glFenceSync(final int condition, final int flags) { - return ARBSync.glFenceSync(condition, flags); + // glFenceSync is core since OpenGL 3.2 + if (GL.getCapabilities().OpenGL32) { + return GL32.glFenceSync(condition, flags); + } else { + return ARBSync.glFenceSync(condition, flags); + } } - + @Override public int glClientWaitSync(final Object sync, final int flags, final long timeout) { - return ARBSync.glClientWaitSync((Long) sync, flags, timeout); + // glClientWaitSync is core since OpenGL 3.2 + if (GL.getCapabilities().OpenGL32) { + return GL32.glClientWaitSync((Long) sync, flags, timeout); + } else { + return ARBSync.glClientWaitSync((Long) sync, flags, timeout); + } } @Override public void glDeleteSync(final Object sync) { - ARBSync.glDeleteSync((Long) sync); + // glDeleteSync is core since OpenGL 3.2 + if (GL.getCapabilities().OpenGL32) { + GL32.glDeleteSync((Long) sync); + } else { + ARBSync.glDeleteSync((Long) sync); + } } @Override