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>
|
<classifier>natives-linux-amd64</classifier>
|
||||||
<scope>runtime</scope>
|
<scope>runtime</scope>
|
||||||
</dependency>
|
</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>
|
<dependency>
|
||||||
<groupId>net.runelite.gluegen</groupId>
|
<groupId>net.runelite.gluegen</groupId>
|
||||||
<artifactId>gluegen-rt</artifactId>
|
<artifactId>gluegen-rt</artifactId>
|
||||||
@@ -143,6 +150,13 @@
|
|||||||
<classifier>natives-linux-amd64</classifier>
|
<classifier>natives-linux-amd64</classifier>
|
||||||
<scope>runtime</scope>
|
<scope>runtime</scope>
|
||||||
</dependency>
|
</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>
|
<dependency>
|
||||||
<groupId>net.runelite</groupId>
|
<groupId>net.runelite</groupId>
|
||||||
<artifactId>archive-patcher</artifactId>
|
<artifactId>archive-patcher</artifactId>
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import com.jogamp.opengl.GLContext;
|
|||||||
import com.jogamp.opengl.GLDrawable;
|
import com.jogamp.opengl.GLDrawable;
|
||||||
import com.jogamp.opengl.GLDrawableFactory;
|
import com.jogamp.opengl.GLDrawableFactory;
|
||||||
import com.jogamp.opengl.GLException;
|
import com.jogamp.opengl.GLException;
|
||||||
|
import com.jogamp.opengl.GLFBODrawable;
|
||||||
import com.jogamp.opengl.GLProfile;
|
import com.jogamp.opengl.GLProfile;
|
||||||
import java.awt.Canvas;
|
import java.awt.Canvas;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
@@ -51,6 +52,7 @@ import javax.inject.Inject;
|
|||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import jogamp.nativewindow.SurfaceScaleUtils;
|
import jogamp.nativewindow.SurfaceScaleUtils;
|
||||||
import jogamp.nativewindow.jawt.x11.X11JAWTWindow;
|
import jogamp.nativewindow.jawt.x11.X11JAWTWindow;
|
||||||
|
import jogamp.nativewindow.macosx.OSXUtil;
|
||||||
import jogamp.newt.awt.NewtFactoryAWT;
|
import jogamp.newt.awt.NewtFactoryAWT;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import net.runelite.api.BufferProvider;
|
import net.runelite.api.BufferProvider;
|
||||||
@@ -286,7 +288,8 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
|
|||||||
return false;
|
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);
|
canvas.setIgnoreRepaint(true);
|
||||||
|
|
||||||
@@ -304,55 +307,73 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
|
|||||||
|
|
||||||
GLProfile.initSingleton();
|
GLProfile.initSingleton();
|
||||||
|
|
||||||
GLProfile glProfile = GLProfile.get(GLProfile.GL4);
|
invokeOnMainThread(() ->
|
||||||
|
|
||||||
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())
|
|
||||||
{
|
{
|
||||||
// Debug config on context needs to be set before .makeCurrent call
|
GLProfile glProfile = GLProfile.get(GLProfile.GL4);
|
||||||
glContext.enableGLDebugMessage(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
int res = glContext.makeCurrent();
|
GLCapabilities glCaps = new GLCapabilities(glProfile);
|
||||||
if (res == GLContext.CONTEXT_NOT_CURRENT)
|
AWTGraphicsConfiguration config = AWTGraphicsConfiguration.create(canvas.getGraphicsConfiguration(), glCaps, glCaps);
|
||||||
{
|
|
||||||
throw new GLException("Unable to make context current");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Surface needs to be unlocked on X11 window otherwise input is blocked
|
jawtWindow = NewtFactoryAWT.getNativeWindow(canvas, config);
|
||||||
if (jawtWindow instanceof X11JAWTWindow && jawtWindow.getLock().isLocked())
|
canvas.setFocusable(true);
|
||||||
{
|
|
||||||
jawtWindow.unlockSurface();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.gl = glContext.getGL().getGL4();
|
GLDrawableFactory glDrawableFactory = GLDrawableFactory.getFactory(glProfile);
|
||||||
gl.setSwapInterval(0);
|
|
||||||
|
|
||||||
if (log.isDebugEnabled())
|
jawtWindow.lockSurface();
|
||||||
{
|
try
|
||||||
gl.glEnable(gl.GL_DEBUG_OUTPUT);
|
{
|
||||||
|
glDrawable = glDrawableFactory.createGLDrawable(jawtWindow);
|
||||||
|
glDrawable.setRealized(true);
|
||||||
|
|
||||||
// Suppress warning messages which flood the log on NVIDIA systems.
|
glContext = glDrawable.createContext(null);
|
||||||
gl.getContext().glDebugMessageControl(gl.GL_DEBUG_SOURCE_API, gl.GL_DEBUG_TYPE_OTHER,
|
if (log.isDebugEnabled())
|
||||||
gl.GL_DEBUG_SEVERITY_NOTIFICATION, 0, null, 0, false);
|
{
|
||||||
}
|
// Debug config on context needs to be set before .makeCurrent call
|
||||||
|
glContext.enableGLDebugMessage(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
jawtWindow.unlockSurface();
|
||||||
|
}
|
||||||
|
|
||||||
initVao();
|
int res = glContext.makeCurrent();
|
||||||
initProgram();
|
if (res == GLContext.CONTEXT_NOT_CURRENT)
|
||||||
initInterfaceTexture();
|
{
|
||||||
initUniformBuffer();
|
throw new GLException("Unable to make context current");
|
||||||
initBuffers();
|
}
|
||||||
|
|
||||||
|
// 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.setDrawCallbacks(this);
|
||||||
client.setGpu(true);
|
client.setGpu(true);
|
||||||
@@ -408,41 +429,51 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
|
|||||||
client.setGpu(false);
|
client.setGpu(false);
|
||||||
client.setDrawCallbacks(null);
|
client.setDrawCallbacks(null);
|
||||||
|
|
||||||
if (gl != null)
|
invokeOnMainThread(() ->
|
||||||
{
|
{
|
||||||
if (textureArrayId != -1)
|
if (gl != null)
|
||||||
{
|
{
|
||||||
textureManager.freeTextureArray(gl, textureArrayId);
|
if (textureArrayId != -1)
|
||||||
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);
|
if (!jawtWindow.getLock().isLocked())
|
||||||
uniformBufferId = -1;
|
{
|
||||||
|
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();
|
GLProfile.shutdown();
|
||||||
shutdownInterfaceTexture();
|
|
||||||
shutdownProgram();
|
|
||||||
shutdownVao();
|
|
||||||
shutdownAAFbo();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (jawtWindow != null)
|
|
||||||
{
|
|
||||||
if (!jawtWindow.getLock().isLocked())
|
|
||||||
{
|
|
||||||
jawtWindow.lockSurface();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (glContext != null)
|
|
||||||
{
|
|
||||||
glContext.destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
NewtFactoryAWT.destroyNativeWindow(jawtWindow);
|
|
||||||
}
|
|
||||||
|
|
||||||
jawtWindow = null;
|
jawtWindow = null;
|
||||||
gl = null;
|
gl = null;
|
||||||
@@ -839,6 +870,42 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw()
|
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())
|
if (jawtWindow.getAWTComponent() != client.getCanvas())
|
||||||
{
|
{
|
||||||
@@ -862,13 +929,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
|
|||||||
final int viewportHeight = client.getViewportHeight();
|
final int viewportHeight = client.getViewportHeight();
|
||||||
final int viewportWidth = client.getViewportWidth();
|
final int viewportWidth = client.getViewportWidth();
|
||||||
|
|
||||||
// If the viewport has changed, update the projection matrix
|
resize(canvasWidth, canvasHeight, viewportWidth, viewportHeight);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup anti-aliasing
|
// Setup anti-aliasing
|
||||||
final AntiAliasingMode antiAliasingMode = config.antiAliasingMode();
|
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.glBlendFunc(gl.GL_ONE, gl.GL_ONE_MINUS_SRC_ALPHA);
|
||||||
gl.glBindTexture(gl.GL_TEXTURE_2D, interfaceTexture);
|
gl.glBindTexture(gl.GL_TEXTURE_2D, interfaceTexture);
|
||||||
|
|
||||||
if (canvasWidth != lastCanvasWidth || canvasHeight != lastCanvasHeight)
|
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.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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use the texture bound in the first pass
|
// Use the texture bound in the first pass
|
||||||
final UIScalingMode uiScalingMode = config.uiScalingMode();
|
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)
|
private void glDpiAwareViewport(final int x, final int y, final int width, final int height)
|
||||||
{
|
{
|
||||||
final AffineTransform t = ((Graphics2D) canvas.getGraphics()).getTransform();
|
if (OSType.getOSType() == OSType.MacOS)
|
||||||
gl.glViewport(
|
{
|
||||||
getScaledValue(t.getScaleX(), x),
|
// JOGL seems to handle DPI scaling for us already
|
||||||
getScaledValue(t.getScaleY(), y),
|
gl.glViewport(x, y, width, height);
|
||||||
getScaledValue(t.getScaleX(), width),
|
}
|
||||||
getScaledValue(t.getScaleY(), 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()
|
private int getDrawDistance()
|
||||||
@@ -1539,4 +1599,16 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
|
|||||||
final int limit = useComputeShaders ? MAX_DISTANCE : DEFAULT_DISTANCE;
|
final int limit = useComputeShaders ? MAX_DISTANCE : DEFAULT_DISTANCE;
|
||||||
return Ints.constrainToRange(config.drawDistance(), 0, limit);
|
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