Skip to content

Commit

Permalink
gdx-lwjgl3-angle extension to add rendering support through ANGLE (li…
Browse files Browse the repository at this point in the history
…bgdx#6672)

* Apply formatter

* Add support for ANGLE

libEGL and libGLESv2 shared libs need to be loadable, i.e. set DYLD_LIBRARY_PATH on macOS. Get prebuilt ANGLE here: https://github.com/xiaozhuai/angle_builds

Then config.setOpenGLVersion(Lwjgl3ApplicationConfiguration.GLVersion.GLES20, 0, 0); to enable the GLES backend.

Update LWJGL3 test starter to use ANGLE

Added gdx-lwjgl3-angle extension

When added to a project as a dependency, and if Lwjgl3ApplicationConfiguration.setOpenGLEmulation(GLEmulation.ANGLE_GLES20, 0, 0) is called, the backend will use ANGLE for rendering. Does not work on macOS yet, as dylib preloading doesn't work like on Windows and Linux. Need to change current working directory to the directory the dylibs have been extracted to, initialize GLFW, then reset the current working directory.

# Conflicts:
#	backends/gdx-backend-lwjgl3/pom.xml

Apply formatter

Apply formatter

Fix ANGLE loading on macOS.

Illustrative fix for multi-window framerate drop on macOS with ANGLE

* Apply formatter

* Fix gdx-lwjgl3-angle extension

Natives are now fetched from https://github.com/libgdx/gdx-angle-natives

* Removed Maven build file from gdx-lwjgl3-angle.

Co-authored-by: GitHub Action <[email protected]>
  • Loading branch information
badlogic and actions-user authored Jan 17, 2022
1 parent da31586 commit 53de67e
Show file tree
Hide file tree
Showing 15 changed files with 1,245 additions and 65 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ libgdx-*.zip.MD5
/extensions/gdx-bullet/libs/
/extensions/gdx-freetype/libs/
/extensions/gdx-image/libs/
/extensions/gdx-lwjgl3-angle/res
/extensions/gdx-setup/gdx-setup.jar
/extensions/gdx-setup/test/

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import java.io.File;
import java.io.PrintStream;
import java.lang.reflect.Method;
import java.nio.IntBuffer;

import com.badlogic.gdx.ApplicationLogger;
Expand All @@ -36,6 +37,8 @@
import org.lwjgl.opengl.GLCapabilities;
import org.lwjgl.opengl.GLUtil;
import org.lwjgl.opengl.KHRDebug;
import org.lwjgl.opengles.GLES;
import org.lwjgl.opengles.GLES20;
import org.lwjgl.system.Callback;

import com.badlogic.gdx.Application;
Expand Down Expand Up @@ -80,14 +83,40 @@ static void initializeGlfw () {
Lwjgl3NativesLoader.load();
errorCallback = GLFWErrorCallback.createPrint(System.err);
GLFW.glfwSetErrorCallback(errorCallback);
if (SharedLibraryLoader.isMac) GLFW.glfwInitHint(GLFW.GLFW_ANGLE_PLATFORM_TYPE, GLFW.GLFW_ANGLE_PLATFORM_TYPE_METAL);
GLFW.glfwInitHint(GLFW.GLFW_JOYSTICK_HAT_BUTTONS, GLFW.GLFW_FALSE);
if (!GLFW.glfwInit()) {
throw new GdxRuntimeException("Unable to initialize GLFW");
}
}
}

static void loadANGLE () {
try {
Class angleLoader = Class.forName("com.badlogic.gdx.backends.lwjgl3.angle.ANGLELoader");
Method load = angleLoader.getMethod("load");
load.invoke(angleLoader);
} catch (ClassNotFoundException t) {
return;
} catch (Throwable t) {
throw new GdxRuntimeException("Couldn't load ANGLE.", t);
}
}

static void postLoadANGLE () {
try {
Class angleLoader = Class.forName("com.badlogic.gdx.backends.lwjgl3.angle.ANGLELoader");
Method load = angleLoader.getMethod("postGlfwInit");
load.invoke(angleLoader);
} catch (ClassNotFoundException t) {
return;
} catch (Throwable t) {
throw new GdxRuntimeException("Couldn't load ANGLE.", t);
}
}

public Lwjgl3Application (ApplicationListener listener, Lwjgl3ApplicationConfiguration config) {
if (config.glEmulation == Lwjgl3ApplicationConfiguration.GLEmulation.ANGLE_GLES20) loadANGLE();
initializeGlfw();
setApplicationLogger(new Lwjgl3ApplicationLogger());
if (config.title == null) config.title = listener.getClass().getSimpleName();
Expand All @@ -111,6 +140,7 @@ public Lwjgl3Application (ApplicationListener listener, Lwjgl3ApplicationConfigu
this.sync = new Sync();

Lwjgl3Window window = createWindow(config, listener, 0);
if (config.glEmulation == Lwjgl3ApplicationConfiguration.GLEmulation.ANGLE_GLES20) postLoadANGLE();
windows.add(window);
try {
loop();
Expand Down Expand Up @@ -435,7 +465,7 @@ static long createGlfwWindow (Lwjgl3ApplicationConfiguration config, long shared
GLFW.glfwWindowHint(GLFW.GLFW_DEPTH_BITS, config.depth);
GLFW.glfwWindowHint(GLFW.GLFW_SAMPLES, config.samples);

if (config.useGL30) {
if (config.glEmulation == Lwjgl3ApplicationConfiguration.GLEmulation.GL30) {
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, config.gles30ContextMajorVersion);
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, config.gles30ContextMinorVersion);
if (SharedLibraryLoader.isMac) {
Expand All @@ -445,6 +475,13 @@ static long createGlfwWindow (Lwjgl3ApplicationConfiguration config, long shared
GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_FORWARD_COMPAT, GLFW.GLFW_TRUE);
GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_PROFILE, GLFW.GLFW_OPENGL_CORE_PROFILE);
}
} else {
if (config.glEmulation == Lwjgl3ApplicationConfiguration.GLEmulation.ANGLE_GLES20) {
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_CREATION_API, GLFW.GLFW_EGL_CONTEXT_API);
GLFW.glfwWindowHint(GLFW.GLFW_CLIENT_API, GLFW.GLFW_OPENGL_ES_API);
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, 2);
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, 0);
}
}

if (config.transparentFramebuffer) {
Expand Down Expand Up @@ -503,14 +540,18 @@ static long createGlfwWindow (Lwjgl3ApplicationConfiguration config, long shared
}
GLFW.glfwMakeContextCurrent(windowHandle);
GLFW.glfwSwapInterval(config.vSyncEnabled ? 1 : 0);
GL.createCapabilities();
if (config.glEmulation == Lwjgl3ApplicationConfiguration.GLEmulation.ANGLE_GLES20) {
GLES.createCapabilities();
} else {
GL.createCapabilities();
}

initiateGL();
initiateGL(config.glEmulation == Lwjgl3ApplicationConfiguration.GLEmulation.ANGLE_GLES20);
if (!glVersion.isVersionEqualToOrHigher(2, 0))
throw new GdxRuntimeException("OpenGL 2.0 or higher with the FBO extension is required. OpenGL version: "
+ GL11.glGetString(GL11.GL_VERSION) + "\n" + glVersion.getDebugVersionString());

if (!supportsFBO()) {
if (config.glEmulation != Lwjgl3ApplicationConfiguration.GLEmulation.ANGLE_GLES20 && !supportsFBO()) {
throw new GdxRuntimeException("OpenGL 2.0 or higher with the FBO extension is required. OpenGL version: "
+ GL11.glGetString(GL11.GL_VERSION) + ", FBO extension: false\n" + glVersion.getDebugVersionString());
}
Expand All @@ -523,11 +564,18 @@ static long createGlfwWindow (Lwjgl3ApplicationConfiguration config, long shared
return windowHandle;
}

private static void initiateGL () {
String versionString = GL11.glGetString(GL11.GL_VERSION);
String vendorString = GL11.glGetString(GL11.GL_VENDOR);
String rendererString = GL11.glGetString(GL11.GL_RENDERER);
glVersion = new GLVersion(Application.ApplicationType.Desktop, versionString, vendorString, rendererString);
private static void initiateGL (boolean useGLES20) {
if (!useGLES20) {
String versionString = GL11.glGetString(GL11.GL_VERSION);
String vendorString = GL11.glGetString(GL11.GL_VENDOR);
String rendererString = GL11.glGetString(GL11.GL_RENDERER);
glVersion = new GLVersion(Application.ApplicationType.Desktop, versionString, vendorString, rendererString);
} else {
String versionString = GLES20.glGetString(GL11.GL_VERSION);
String vendorString = GLES20.glGetString(GL11.GL_VENDOR);
String rendererString = GLES20.glGetString(GL11.GL_RENDERER);
glVersion = new GLVersion(Application.ApplicationType.Desktop, versionString, vendorString, rendererString);
}
}

private static boolean supportsFBO () {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,11 @@ public class Lwjgl3ApplicationConfiguration extends Lwjgl3WindowConfiguration {
int audioDeviceBufferSize = 512;
int audioDeviceBufferCount = 9;

boolean useGL30 = false;
public enum GLEmulation {
ANGLE_GLES20, GL20, GL30
}

GLEmulation glEmulation = GLEmulation.GL20;
int gles30ContextMajorVersion = 3;
int gles30ContextMinorVersion = 2;

Expand Down Expand Up @@ -79,7 +83,7 @@ void set (Lwjgl3ApplicationConfiguration config) {
audioDeviceSimultaneousSources = config.audioDeviceSimultaneousSources;
audioDeviceBufferSize = config.audioDeviceBufferSize;
audioDeviceBufferCount = config.audioDeviceBufferCount;
useGL30 = config.useGL30;
glEmulation = config.glEmulation;
gles30ContextMajorVersion = config.gles30ContextMajorVersion;
gles30ContextMinorVersion = config.gles30ContextMinorVersion;
r = config.r;
Expand Down Expand Up @@ -126,18 +130,18 @@ public void setAudioConfig (int simultaniousSources, int bufferSize, int bufferC
this.audioDeviceBufferCount = bufferCount;
}

/** Sets whether to use OpenGL ES 3.0 emulation. If the given major/minor version is not supported, the backend falls back to
* OpenGL ES 2.0 emulation. The default parameters for major and minor should be 3 and 2 respectively to be compatible with Mac
* OS X. Specifying major version 4 and minor version 2 will ensure that all OpenGL ES 3.0 features are supported. Note however
* that Mac OS X does only support 3.2.
/** Sets which OpenGL version to use to emulate OpenGL ES. If the given major/minor version is not supported, the backend falls
* back to OpenGL ES 2.0 emulation through OpenGL 2.0. The default parameters for major and minor should be 3 and 2
* respectively to be compatible with Mac OS X. Specifying major version 4 and minor version 2 will ensure that all OpenGL ES
* 3.0 features are supported. Note however that Mac OS X does only support 3.2.
*
* @see <a href= "http://legacy.lwjgl.org/javadoc/org/lwjgl/opengl/ContextAttribs.html"> LWJGL OSX ContextAttribs note</a>
*
* @param useGL30 whether to use OpenGL ES 3.0
* @param glVersion which OpenGL ES emulation version to use
* @param gles3MajorVersion OpenGL ES major version, use 3 as default
* @param gles3MinorVersion OpenGL ES minor version, use 2 as default */
public void useOpenGL3 (boolean useGL30, int gles3MajorVersion, int gles3MinorVersion) {
this.useGL30 = useGL30;
public void setOpenGLEmulation (GLEmulation glVersion, int gles3MajorVersion, int gles3MinorVersion) {
this.glEmulation = glVersion;
this.gles30ContextMajorVersion = gles3MajorVersion;
this.gles30ContextMinorVersion = gles3MinorVersion;
}
Expand Down
Loading

0 comments on commit 53de67e

Please sign in to comment.