From eeff5437b53c9ed5508418ef86672cd96a5dea3c Mon Sep 17 00:00:00 2001 From: James Seibel Date: Fri, 1 Oct 2021 23:25:51 -0500 Subject: [PATCH] Hopefully add Mac and Linux support --- .../bufferBuilding/LodBufferBuilder.java | 4 +- .../com/seibel/lod/enums/GlProxyContext.java | 16 ++ .../java/com/seibel/lod/proxy/GlProxy.java | 231 ++++++++++++++---- 3 files changed, 196 insertions(+), 55 deletions(-) create mode 100644 src/main/java/com/seibel/lod/enums/GlProxyContext.java diff --git a/src/main/java/com/seibel/lod/builders/bufferBuilding/LodBufferBuilder.java b/src/main/java/com/seibel/lod/builders/bufferBuilding/LodBufferBuilder.java index 9e79784a7..e08ad746c 100644 --- a/src/main/java/com/seibel/lod/builders/bufferBuilding/LodBufferBuilder.java +++ b/src/main/java/com/seibel/lod/builders/bufferBuilding/LodBufferBuilder.java @@ -35,13 +35,13 @@ import org.lwjgl.opengl.GL15C; import com.google.common.util.concurrent.ThreadFactoryBuilder; import com.seibel.lod.builders.bufferBuilding.lodTemplates.Box; import com.seibel.lod.config.LodConfig; +import com.seibel.lod.enums.GlProxyContext; import com.seibel.lod.objects.LodDimension; import com.seibel.lod.objects.LodRegion; import com.seibel.lod.objects.PosToRenderContainer; import com.seibel.lod.objects.RegionPos; import com.seibel.lod.proxy.ClientProxy; import com.seibel.lod.proxy.GlProxy; -import com.seibel.lod.proxy.GlProxy.GlProxyContext; import com.seibel.lod.render.LodRenderer; import com.seibel.lod.util.DataPointUtil; import com.seibel.lod.util.DetailDistanceUtil; @@ -555,7 +555,7 @@ public class LodBufferBuilder if (glProxy.getGlContext() != GlProxyContext.LOD_BUILDER) { glProxy.setGlContext(GlProxyContext.LOD_BUILDER); - ClientProxy.LOGGER.info(Thread.currentThread().getName() + ": setting OpenGL context to: [" + GlProxyContext.LOD_BUILDER + "]"); + ClientProxy.LOGGER.debug(Thread.currentThread().getName() + ": setting OpenGL context to: [" + GlProxyContext.LOD_BUILDER + "]"); } diff --git a/src/main/java/com/seibel/lod/enums/GlProxyContext.java b/src/main/java/com/seibel/lod/enums/GlProxyContext.java new file mode 100644 index 000000000..52f0b16b9 --- /dev/null +++ b/src/main/java/com/seibel/lod/enums/GlProxyContext.java @@ -0,0 +1,16 @@ +package com.seibel.lod.enums; + +/** + * Minecraft, Lod_Builder, None + * + * @author James Seibel + * @version 10-1-2021 + */ +public enum GlProxyContext +{ + MINECRAFT, + LOD_BUILDER, + + /** used to un-bind threads */ + NONE, +} \ No newline at end of file diff --git a/src/main/java/com/seibel/lod/proxy/GlProxy.java b/src/main/java/com/seibel/lod/proxy/GlProxy.java index 24355fef7..afc82266d 100644 --- a/src/main/java/com/seibel/lod/proxy/GlProxy.java +++ b/src/main/java/com/seibel/lod/proxy/GlProxy.java @@ -1,10 +1,18 @@ package com.seibel.lod.proxy; +import org.apache.commons.lang3.SystemUtils; +import org.lwjgl.PointerBuffer; +import org.lwjgl.opengl.CGL; import org.lwjgl.opengl.GL; import org.lwjgl.opengl.GLCapabilities; +import org.lwjgl.opengl.GLX; +import org.lwjgl.opengl.GLX14; import org.lwjgl.opengl.WGL; +import org.lwjgl.system.linux.X11; +import org.lwjgl.system.linux.XVisualInfo; import com.mojang.blaze3d.systems.RenderSystem; +import com.seibel.lod.enums.GlProxyContext; /** * A singleton that holds references to different openGL contexts @@ -19,26 +27,41 @@ import com.mojang.blaze3d.systems.RenderSystem; * * * @author James Seibel - * @version 9-15-2021 + * @version 10-1-2021 */ public class GlProxy { private static GlProxy instance = null; - public final long deviceContext; - public long minecraftGlContext; - public GLCapabilities minecraftGlCapabilities; + // windows context variables + private long windowsDeviceContext; + + // mac context variables + private long macPixelFormat; + + // linux context variables + long linuxDisplayID; + + long linuxMcDrawable; + long linuxMcReadDrawable; + + long linuxLodBuilderDrawable; + long linuxLodBuilderReadDrawable; + + + + public final long minecraftGlContext; + public final GLCapabilities minecraftGlCapabilities; + + public final long lodBuilderGlContext; + public final GLCapabilities lodBuilderGlCapabilities; - public long lodBuilderGlContext; - public GLCapabilities lodBuilderGlCapabilities; /** This is just used for debugging, hopefuly it can be removed once * the context switching is more stable. */ public Thread lodBuilderOwnerThread = null; - /** - * Does this computer's GPU support fancy fog? - */ + /** Does this computer's GPU support fancy fog? */ public final boolean fancyFogAvailable; @@ -57,22 +80,81 @@ public class GlProxy // create the builder context // //============================// - minecraftGlContext = WGL.wglGetCurrentContext(); - minecraftGlCapabilities = GL.getCapabilities(); - deviceContext = WGL.wglGetCurrentDC(); - lodBuilderGlContext = WGL.wglCreateContext(deviceContext); - if (!WGL.wglShareLists(minecraftGlContext, lodBuilderGlContext)) - throw new IllegalStateException("Unable to share lists between Minecraft and builder contexts."); - if (!WGL.wglMakeCurrent(deviceContext, lodBuilderGlContext)) - throw new IllegalStateException("Unable to change OpenGL contexts! tried to change to [" + GlProxyContext.LOD_BUILDER.toString() + "] from [" + GlProxyContext.MINECRAFT.toString() + "]"); - lodBuilderGlCapabilities = GL.createCapabilities(); - WGL.wglMakeCurrent(deviceContext, 0L); + minecraftGlCapabilities = GL.getCapabilities(); + + // run OS specific context creation code + if (SystemUtils.IS_OS_WINDOWS) + { + ClientProxy.LOGGER.info(GlProxy.class.getSimpleName() + " Running Windows setup."); + + // get Minecraft variables + minecraftGlContext = WGL.wglGetCurrentContext(); + windowsDeviceContext = WGL.wglGetCurrentDC(); + + // setup the lodBuilder variables + lodBuilderGlContext = WGL.wglCreateContext(windowsDeviceContext); + if (!WGL.wglShareLists(minecraftGlContext, lodBuilderGlContext)) + throw new IllegalStateException("Unable to share lists between Minecraft and builder contexts."); + if (!WGL.wglMakeCurrent(windowsDeviceContext, lodBuilderGlContext)) + throw new IllegalStateException("Unable to change OpenGL contexts! tried to change to [" + GlProxyContext.LOD_BUILDER.toString() + "] from [" + GlProxyContext.MINECRAFT.toString() + "]"); + lodBuilderGlCapabilities = GL.createCapabilities(); + } + else if (SystemUtils.IS_OS_MAC) + { + ClientProxy.LOGGER.info(GlProxy.class.getSimpleName() + " Running Mac setup."); + + // get Minecraft variables + minecraftGlContext = CGL.CGLGetCurrentContext(); + macPixelFormat = CGL.CGLGetPixelFormat(minecraftGlContext); + + // setup the lodBuilder variables + lodBuilderGlContext = CGL.CGLCreateContext(macPixelFormat, minecraftGlContext, null); + lodBuilderGlCapabilities = GL.createCapabilities(); + } + else + { + // if we can't determine the OS, default to linux + if (SystemUtils.IS_OS_LINUX) + ClientProxy.LOGGER.info(GlProxy.class.getSimpleName() + " Running Linux setup."); + else + ClientProxy.LOGGER.info(GlProxy.class.getSimpleName() + " Unkown OS: [" + SystemUtils.OS_NAME + "] Running Linux setup."); + + + // get Minecraft variables // + + minecraftGlContext = GLX14.glXGetCurrentContext(); + linuxDisplayID = GLX14.glXGetCurrentDisplay(); + + + // setup the lodBuilder variables // + + linuxMcDrawable = GLX14.glXGetCurrentDrawable(); + linuxMcReadDrawable = GLX14.glXGetCurrentReadDrawable(); + + // single buffered example config +// int attributeList[] = { GLX.GLX_RGBA, +// GLX.GLX_RED_SIZE, 1, +// GLX.GLX_GREEN_SIZE, 1, +// GLX.GLX_BLUE_SIZE, 1, +// GLX.GLX_DEPTH_SIZE, 12, +// X11.None }; + + // use the defaults for all config options + int attributeList[] = { X11.None }; + + PointerBuffer config = GLX14.glXChooseFBConfig(linuxDisplayID, 0, attributeList); + XVisualInfo visualInfo = GLX14.glXGetVisualFromFBConfig(linuxDisplayID, config.address()); + lodBuilderGlContext = GLX14.glXCreateContext(linuxDisplayID, visualInfo, minecraftGlContext, false); + lodBuilderGlCapabilities = GL.createCapabilities(); + + linuxLodBuilderDrawable = GLX14.glXGetCurrentDrawable(); + linuxLodBuilderReadDrawable = GLX14.glXGetCurrentReadDrawable(); + } // Since this is called on the render thread, make sure the Minecraft context is used in the end - WGL.wglMakeCurrent(deviceContext, minecraftGlContext); - + setGlContext(GlProxyContext.MINECRAFT); @@ -90,11 +172,14 @@ public class GlProxy } + + /** - * A simple wrapper function to make switching contexts easier + * A wrapper function to make switching contexts easier.
+ * Does nothing if the calling thread is already using newContext. * * @throws IllegalStateException if unable to change to newContext.
- * This expection should never be thrown if + * This exception should never be thrown if * switching to GlProxyContext.NONE */ public void setGlContext(GlProxyContext newContext) @@ -107,70 +192,101 @@ public class GlProxy long contextPointer = 0L; + long linuxDrawable = 0L; + long linuxReadDrawable = 0L; GLCapabilities newGlCapabilities = null; + + // get the pointer(s) for this context switch(newContext) { case LOD_BUILDER: + linuxDrawable = linuxLodBuilderDrawable; + linuxReadDrawable = linuxLodBuilderReadDrawable; + contextPointer = lodBuilderGlContext; newGlCapabilities = lodBuilderGlCapabilities; break; + case MINECRAFT: + linuxDrawable = linuxMcDrawable; + linuxReadDrawable = linuxMcReadDrawable; + contextPointer = minecraftGlContext; newGlCapabilities = minecraftGlCapabilities; break; + + default: // default should never happen, it is just here to make the compiler happy case NONE: - contextPointer = 0L; // equivalent to null + // 0L is equivalent to null + linuxDrawable = 0L; + linuxReadDrawable = 0L; + + contextPointer = 0L; newGlCapabilities = null; break; - - default: - // should never happen, here to make the compiler happy } - if (!WGL.wglMakeCurrent(deviceContext, contextPointer)) - throw new IllegalStateException("Unable to change OpenGL contexts! tried to change to [" + newContext.toString() + "] from [" + currentContext.toString() + "] on thread: [" + Thread.currentThread().getName() + "] lod builder owner thread: " + (lodBuilderOwnerThread != null ? lodBuilderOwnerThread.getName() : "null")); - if (newContext == GlProxyContext.LOD_BUILDER) + String contextSwitchError = "Unable to change OpenGL contexts! tried to change to [" + newContext.toString() + "] from [" + currentContext.toString() + "] on thread: [" + Thread.currentThread().getName() + "] lod builder owner thread: " + (lodBuilderOwnerThread != null ? lodBuilderOwnerThread.getName() : "null"); + + // run the OS specific context switching code + if (SystemUtils.IS_OS_WINDOWS) { - lodBuilderOwnerThread = Thread.currentThread(); + if (!WGL.wglMakeCurrent(windowsDeviceContext, contextPointer)) + throw new IllegalStateException(contextSwitchError); } - else if (newContext == GlProxyContext.NONE && currentContext == GlProxyContext.LOD_BUILDER) + else if (SystemUtils.IS_OS_MAC) { - lodBuilderOwnerThread = null; + if (CGL.CGLSetCurrentContext(contextPointer) != CGL.kCGLNoError) + throw new IllegalStateException(contextSwitchError); + } + else //if (SystemUtils.IS_OS_LINUX) + { + // default to linux + if (!GLX14.glXMakeContextCurrent(linuxDisplayID, linuxDrawable, linuxReadDrawable, contextPointer)) + throw new IllegalStateException(contextSwitchError); } GL.setCapabilities(newGlCapabilities); + + + + // used for debugging + if (newContext == GlProxyContext.LOD_BUILDER) + lodBuilderOwnerThread = Thread.currentThread(); + else if (newContext == GlProxyContext.NONE && currentContext == GlProxyContext.LOD_BUILDER) + lodBuilderOwnerThread = null; } - /** - * Returns this thread's OpenGL context. - */ + + + + + /** Returns this thread's OpenGL context. */ public GlProxyContext getGlContext() { - long currentContext = WGL.wglGetCurrentContext(); + long currentContext; + + if (SystemUtils.IS_OS_WINDOWS) + currentContext = WGL.wglGetCurrentContext(); + else if (SystemUtils.IS_OS_MAC) + currentContext = CGL.CGLGetCurrentContext(); + else //if (SystemUtils.IS_OS_LINUX) // default to Linux + currentContext = GLX.glXGetCurrentContext(); + + if(currentContext == lodBuilderGlContext) - { return GlProxyContext.LOD_BUILDER; - } else if(currentContext == minecraftGlContext) - { return GlProxyContext.MINECRAFT; - } - else - { + else if (currentContext == 0L) return GlProxyContext.NONE; - } + else + // hopefully this shouldn't happen, but + // at least now we will be notified if it does happen + throw new IllegalStateException(Thread.currentThread().getName() + " has a unkown OpenGl context: [" + currentContext + "]. Minecraft context [" + minecraftGlContext + "], LodBuilder context [" + lodBuilderGlContext + "], no context [0]."); } - /** Minecraft, Alpha, Beta, None */ - public enum GlProxyContext - { - MINECRAFT, - LOD_BUILDER, - - /** used to un-bind threads */ - NONE, - } public static GlProxy getInstance() { @@ -185,4 +301,13 @@ public class GlProxy return instance; } + + + + + + + + + }