gpu: add support for osx
Compute shaders must be forced off due to macos not supporting opengl 4.3
This commit is contained in:
@@ -117,6 +117,13 @@
|
||||
<classifier>natives-linux-amd64</classifier>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.runelite.jogl</groupId>
|
||||
<artifactId>jogl-all</artifactId>
|
||||
<version>${jogl.version}</version>
|
||||
<classifier>natives-macosx-universal</classifier>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.runelite.gluegen</groupId>
|
||||
<artifactId>gluegen-rt</artifactId>
|
||||
@@ -143,6 +150,13 @@
|
||||
<classifier>natives-linux-amd64</classifier>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.runelite.gluegen</groupId>
|
||||
<artifactId>gluegen-rt</artifactId>
|
||||
<version>${jogl.version}</version>
|
||||
<classifier>natives-macosx-universal</classifier>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.runelite</groupId>
|
||||
<artifactId>archive-patcher</artifactId>
|
||||
|
||||
@@ -35,6 +35,7 @@ import com.jogamp.opengl.GLContext;
|
||||
import com.jogamp.opengl.GLDrawable;
|
||||
import com.jogamp.opengl.GLDrawableFactory;
|
||||
import com.jogamp.opengl.GLException;
|
||||
import com.jogamp.opengl.GLFBODrawable;
|
||||
import com.jogamp.opengl.GLProfile;
|
||||
import java.awt.Canvas;
|
||||
import java.awt.Dimension;
|
||||
@@ -51,6 +52,7 @@ import javax.inject.Inject;
|
||||
import javax.swing.SwingUtilities;
|
||||
import jogamp.nativewindow.SurfaceScaleUtils;
|
||||
import jogamp.nativewindow.jawt.x11.X11JAWTWindow;
|
||||
import jogamp.nativewindow.macosx.OSXUtil;
|
||||
import jogamp.newt.awt.NewtFactoryAWT;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.BufferProvider;
|
||||
@@ -286,7 +288,8 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
|
||||
return false;
|
||||
}
|
||||
|
||||
useComputeShaders = config.useComputeShaders();
|
||||
// OSX supports up to OpenGL 4.1, however 4.3 is required for compute shaders
|
||||
useComputeShaders = config.useComputeShaders() && OSType.getOSType() != OSType.MacOS;
|
||||
|
||||
canvas.setIgnoreRepaint(true);
|
||||
|
||||
@@ -304,55 +307,73 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
|
||||
|
||||
GLProfile.initSingleton();
|
||||
|
||||
GLProfile glProfile = GLProfile.get(GLProfile.GL4);
|
||||
|
||||
GLCapabilities glCaps = new GLCapabilities(glProfile);
|
||||
AWTGraphicsConfiguration config = AWTGraphicsConfiguration.create(canvas.getGraphicsConfiguration(), glCaps, glCaps);
|
||||
|
||||
jawtWindow = NewtFactoryAWT.getNativeWindow(canvas, config);
|
||||
canvas.setFocusable(true);
|
||||
|
||||
GLDrawableFactory glDrawableFactory = GLDrawableFactory.getFactory(glProfile);
|
||||
|
||||
glDrawable = glDrawableFactory.createGLDrawable(jawtWindow);
|
||||
glDrawable.setRealized(true);
|
||||
|
||||
glContext = glDrawable.createContext(null);
|
||||
if (log.isDebugEnabled())
|
||||
invokeOnMainThread(() ->
|
||||
{
|
||||
// Debug config on context needs to be set before .makeCurrent call
|
||||
glContext.enableGLDebugMessage(true);
|
||||
}
|
||||
GLProfile glProfile = GLProfile.get(GLProfile.GL4);
|
||||
|
||||
int res = glContext.makeCurrent();
|
||||
if (res == GLContext.CONTEXT_NOT_CURRENT)
|
||||
{
|
||||
throw new GLException("Unable to make context current");
|
||||
}
|
||||
GLCapabilities glCaps = new GLCapabilities(glProfile);
|
||||
AWTGraphicsConfiguration config = AWTGraphicsConfiguration.create(canvas.getGraphicsConfiguration(), glCaps, glCaps);
|
||||
|
||||
// Surface needs to be unlocked on X11 window otherwise input is blocked
|
||||
if (jawtWindow instanceof X11JAWTWindow && jawtWindow.getLock().isLocked())
|
||||
{
|
||||
jawtWindow.unlockSurface();
|
||||
}
|
||||
jawtWindow = NewtFactoryAWT.getNativeWindow(canvas, config);
|
||||
canvas.setFocusable(true);
|
||||
|
||||
this.gl = glContext.getGL().getGL4();
|
||||
gl.setSwapInterval(0);
|
||||
GLDrawableFactory glDrawableFactory = GLDrawableFactory.getFactory(glProfile);
|
||||
|
||||
if (log.isDebugEnabled())
|
||||
{
|
||||
gl.glEnable(gl.GL_DEBUG_OUTPUT);
|
||||
jawtWindow.lockSurface();
|
||||
try
|
||||
{
|
||||
glDrawable = glDrawableFactory.createGLDrawable(jawtWindow);
|
||||
glDrawable.setRealized(true);
|
||||
|
||||
// Suppress warning messages which flood the log on NVIDIA systems.
|
||||
gl.getContext().glDebugMessageControl(gl.GL_DEBUG_SOURCE_API, gl.GL_DEBUG_TYPE_OTHER,
|
||||
gl.GL_DEBUG_SEVERITY_NOTIFICATION, 0, null, 0, false);
|
||||
}
|
||||
glContext = glDrawable.createContext(null);
|
||||
if (log.isDebugEnabled())
|
||||
{
|
||||
// Debug config on context needs to be set before .makeCurrent call
|
||||
glContext.enableGLDebugMessage(true);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
jawtWindow.unlockSurface();
|
||||
}
|
||||
|
||||
initVao();
|
||||
initProgram();
|
||||
initInterfaceTexture();
|
||||
initUniformBuffer();
|
||||
initBuffers();
|
||||
int res = glContext.makeCurrent();
|
||||
if (res == GLContext.CONTEXT_NOT_CURRENT)
|
||||
{
|
||||
throw new GLException("Unable to make context current");
|
||||
}
|
||||
|
||||
// Surface needs to be unlocked on X11 window otherwise input is blocked
|
||||
if (jawtWindow instanceof X11JAWTWindow && jawtWindow.getLock().isLocked())
|
||||
{
|
||||
jawtWindow.unlockSurface();
|
||||
}
|
||||
|
||||
this.gl = glContext.getGL().getGL4();
|
||||
gl.setSwapInterval(0);
|
||||
|
||||
if (log.isDebugEnabled())
|
||||
{
|
||||
gl.glEnable(gl.GL_DEBUG_OUTPUT);
|
||||
|
||||
// Suppress warning messages which flood the log on NVIDIA systems.
|
||||
gl.getContext().glDebugMessageControl(gl.GL_DEBUG_SOURCE_API, gl.GL_DEBUG_TYPE_OTHER,
|
||||
gl.GL_DEBUG_SEVERITY_NOTIFICATION, 0, null, 0, false);
|
||||
}
|
||||
|
||||
initVao();
|
||||
try
|
||||
{
|
||||
initProgram();
|
||||
}
|
||||
catch (ShaderException ex)
|
||||
{
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
initInterfaceTexture();
|
||||
initUniformBuffer();
|
||||
initBuffers();
|
||||
});
|
||||
|
||||
client.setDrawCallbacks(this);
|
||||
client.setGpu(true);
|
||||
@@ -408,41 +429,51 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
|
||||
client.setGpu(false);
|
||||
client.setDrawCallbacks(null);
|
||||
|
||||
if (gl != null)
|
||||
invokeOnMainThread(() ->
|
||||
{
|
||||
if (textureArrayId != -1)
|
||||
if (gl != null)
|
||||
{
|
||||
textureManager.freeTextureArray(gl, textureArrayId);
|
||||
textureArrayId = -1;
|
||||
if (textureArrayId != -1)
|
||||
{
|
||||
textureManager.freeTextureArray(gl, textureArrayId);
|
||||
textureArrayId = -1;
|
||||
}
|
||||
|
||||
if (uniformBufferId != -1)
|
||||
{
|
||||
GLUtil.glDeleteBuffer(gl, uniformBufferId);
|
||||
uniformBufferId = -1;
|
||||
}
|
||||
|
||||
shutdownBuffers();
|
||||
shutdownInterfaceTexture();
|
||||
shutdownProgram();
|
||||
shutdownVao();
|
||||
shutdownAAFbo();
|
||||
}
|
||||
|
||||
if (uniformBufferId != -1)
|
||||
if (jawtWindow != null)
|
||||
{
|
||||
GLUtil.glDeleteBuffer(gl, uniformBufferId);
|
||||
uniformBufferId = -1;
|
||||
if (!jawtWindow.getLock().isLocked())
|
||||
{
|
||||
jawtWindow.lockSurface();
|
||||
}
|
||||
|
||||
if (glContext != null)
|
||||
{
|
||||
glContext.destroy();
|
||||
}
|
||||
|
||||
// this crashes on osx when the plugin is turned back on, don't know why
|
||||
// we'll just leak the window...
|
||||
if (OSType.getOSType() != OSType.MacOS)
|
||||
{
|
||||
NewtFactoryAWT.destroyNativeWindow(jawtWindow);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
shutdownBuffers();
|
||||
shutdownInterfaceTexture();
|
||||
shutdownProgram();
|
||||
shutdownVao();
|
||||
shutdownAAFbo();
|
||||
}
|
||||
|
||||
if (jawtWindow != null)
|
||||
{
|
||||
if (!jawtWindow.getLock().isLocked())
|
||||
{
|
||||
jawtWindow.lockSurface();
|
||||
}
|
||||
|
||||
if (glContext != null)
|
||||
{
|
||||
glContext.destroy();
|
||||
}
|
||||
|
||||
NewtFactoryAWT.destroyNativeWindow(jawtWindow);
|
||||
}
|
||||
GLProfile.shutdown();
|
||||
|
||||
jawtWindow = null;
|
||||
gl = null;
|
||||
@@ -839,6 +870,42 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
|
||||
|
||||
@Override
|
||||
public void draw()
|
||||
{
|
||||
invokeOnMainThread(this::drawFrame);
|
||||
}
|
||||
|
||||
private void resize(int canvasWidth, int canvasHeight, int viewportWidth, int viewportHeight)
|
||||
{
|
||||
// If the viewport has changed, update the projection matrix
|
||||
if (viewportWidth > 0 && viewportHeight > 0 && (viewportWidth != lastViewportWidth || viewportHeight != lastViewportHeight))
|
||||
{
|
||||
lastViewportWidth = viewportWidth;
|
||||
lastViewportHeight = viewportHeight;
|
||||
createProjectionMatrix(0, viewportWidth, viewportHeight, 0, 0, Constants.SCENE_SIZE * Perspective.LOCAL_TILE_SIZE);
|
||||
}
|
||||
|
||||
if (canvasWidth != lastCanvasWidth || canvasHeight != lastCanvasHeight)
|
||||
{
|
||||
lastCanvasWidth = canvasWidth;
|
||||
lastCanvasHeight = canvasHeight;
|
||||
|
||||
gl.glBindTexture(gl.GL_TEXTURE_2D, interfaceTexture);
|
||||
gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGBA, canvasWidth, canvasHeight, 0, gl.GL_BGRA, gl.GL_UNSIGNED_INT_8_8_8_8_REV, null);
|
||||
gl.glBindTexture(gl.GL_TEXTURE_2D, 0);
|
||||
|
||||
if (OSType.getOSType() == OSType.MacOS && glDrawable instanceof GLFBODrawable)
|
||||
{
|
||||
// GLDrawables created with createGLDrawable() do not have a resize listener
|
||||
// I don't know why this works with Windows/Linux, but on OSX
|
||||
// it prevents JOGL from resizing its FBOs and underlying GL textures. So,
|
||||
// we manually trigger a resize here.
|
||||
GLFBODrawable glfboDrawable = (GLFBODrawable) glDrawable;
|
||||
glfboDrawable.resetSize(gl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void drawFrame()
|
||||
{
|
||||
if (jawtWindow.getAWTComponent() != client.getCanvas())
|
||||
{
|
||||
@@ -862,13 +929,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
|
||||
final int viewportHeight = client.getViewportHeight();
|
||||
final int viewportWidth = client.getViewportWidth();
|
||||
|
||||
// If the viewport has changed, update the projection matrix
|
||||
if (viewportWidth > 0 && viewportHeight > 0 && (viewportWidth != lastViewportWidth || viewportHeight != lastViewportHeight))
|
||||
{
|
||||
createProjectionMatrix(0, viewportWidth, viewportHeight, 0, 0, Constants.SCENE_SIZE * Perspective.LOCAL_TILE_SIZE);
|
||||
lastViewportWidth = viewportWidth;
|
||||
lastViewportHeight = viewportHeight;
|
||||
}
|
||||
resize(canvasWidth, canvasHeight, viewportWidth, viewportHeight);
|
||||
|
||||
// Setup anti-aliasing
|
||||
final AntiAliasingMode antiAliasingMode = config.antiAliasingMode();
|
||||
@@ -1176,16 +1237,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
|
||||
gl.glBlendFunc(gl.GL_ONE, gl.GL_ONE_MINUS_SRC_ALPHA);
|
||||
gl.glBindTexture(gl.GL_TEXTURE_2D, interfaceTexture);
|
||||
|
||||
if (canvasWidth != lastCanvasWidth || canvasHeight != lastCanvasHeight)
|
||||
{
|
||||
gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGBA, width, height, 0, gl.GL_BGRA, gl.GL_UNSIGNED_INT_8_8_8_8_REV, interfaceBuffer);
|
||||
lastCanvasWidth = canvasWidth;
|
||||
lastCanvasHeight = canvasHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
gl.glTexSubImage2D(gl.GL_TEXTURE_2D, 0, 0, 0, width, height, gl.GL_BGRA, gl.GL_UNSIGNED_INT_8_8_8_8_REV, interfaceBuffer);
|
||||
}
|
||||
gl.glTexSubImage2D(gl.GL_TEXTURE_2D, 0, 0, 0, width, height, gl.GL_BGRA, gl.GL_UNSIGNED_INT_8_8_8_8_REV, interfaceBuffer);
|
||||
|
||||
// Use the texture bound in the first pass
|
||||
final UIScalingMode uiScalingMode = config.uiScalingMode();
|
||||
@@ -1526,12 +1578,20 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
|
||||
|
||||
private void glDpiAwareViewport(final int x, final int y, final int width, final int height)
|
||||
{
|
||||
final AffineTransform t = ((Graphics2D) canvas.getGraphics()).getTransform();
|
||||
gl.glViewport(
|
||||
getScaledValue(t.getScaleX(), x),
|
||||
getScaledValue(t.getScaleY(), y),
|
||||
getScaledValue(t.getScaleX(), width),
|
||||
getScaledValue(t.getScaleY(), height));
|
||||
if (OSType.getOSType() == OSType.MacOS)
|
||||
{
|
||||
// JOGL seems to handle DPI scaling for us already
|
||||
gl.glViewport(x, y, width, height);
|
||||
}
|
||||
else
|
||||
{
|
||||
final AffineTransform t = ((Graphics2D) canvas.getGraphics()).getTransform();
|
||||
gl.glViewport(
|
||||
getScaledValue(t.getScaleX(), x),
|
||||
getScaledValue(t.getScaleY(), y),
|
||||
getScaledValue(t.getScaleX(), width),
|
||||
getScaledValue(t.getScaleY(), height));
|
||||
}
|
||||
}
|
||||
|
||||
private int getDrawDistance()
|
||||
@@ -1539,4 +1599,16 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
|
||||
final int limit = useComputeShaders ? MAX_DISTANCE : DEFAULT_DISTANCE;
|
||||
return Ints.constrainToRange(config.drawDistance(), 0, limit);
|
||||
}
|
||||
|
||||
private static void invokeOnMainThread(Runnable runnable)
|
||||
{
|
||||
if (OSType.getOSType() == OSType.MacOS)
|
||||
{
|
||||
OSXUtil.RunOnMainThread(true, false, runnable);
|
||||
}
|
||||
else
|
||||
{
|
||||
runnable.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user