Skip to content
This repository has been archived by the owner before Nov 9, 2022. It is now read-only.

8258754: Gracefully fallback to the OpenGL rendering pipeline if Metal rendering pipeline initialization fails #147

Closed
wants to merge 10 commits into from
@@ -76,9 +76,10 @@ public CGraphicsDevice(final int displayID) {
}

if (!metalPipelineEnabled && !oglPipelineEnabled) {
// Should never reach here, but still have to check this
// This indicates fallback to other rendering pipeline also failed.
// Should never reach here
System.out.println("Error - unable to initialize any rendering pipeline.");
// Throw exception????
throw new RuntimeException("Error - unable to initialize any rendering pipeline.");
}

// initializes default device state, might be redundant step since we
@@ -327,7 +328,9 @@ private void creatCGLGraphicsConfig(final int displayID) {
oglPipelineEnabled = true;
} else {
// Try falling back to Metal pipeline
System.out.println("OpenGL rendering pipeline initialization failed. Using Metal rendering pipeline.");
if (MacOSFlags.isOGLVerbose()) {
System.out.println("OpenGL rendering pipeline initialization failed. Using Metal rendering pipeline.");
}

this.config = MTLGraphicsConfig.getConfig(this, displayID, 0);

@@ -27,6 +27,7 @@

import java.security.PrivilegedAction;
import sun.java2d.metal.MTLGraphicsConfig;
import sun.java2d.opengl.CGLGraphicsConfig;


public class MacOSFlags {
@@ -37,33 +38,37 @@ public class MacOSFlags {
* metalEnabled: usage: "-Dsun.java2d.metal=[true|false]"
*/

private static boolean oglEnabled;
private static boolean oglVerbose;
private static boolean metalEnabled;
private static boolean metalVerbose;

private enum PropertyState {ENABLED, DISABLED, UNSPECIFIED};

static {
initJavaFlags();
initNativeFlags();
}

private static native boolean initNativeFlags();

private static boolean getBooleanProp(String p, boolean defaultVal) {
private static PropertyState getBooleanProp(String p, PropertyState defaultVal) {
String propString = System.getProperty(p);
boolean returnVal = defaultVal;
PropertyState returnVal = defaultVal;
aghaisas marked this conversation as resolved.
Show resolved Hide resolved
if (propString != null) {
if (propString.equals("true") ||
propString.equals("t") ||
propString.equals("True") ||
propString.equals("T") ||
propString.equals("")) // having the prop name alone
{ // is equivalent to true
returnVal = true;
returnVal = PropertyState.ENABLED;
} else if (propString.equals("false") ||
propString.equals("f") ||
propString.equals("False") ||
propString.equals("F"))
{
returnVal = false;
returnVal = PropertyState.DISABLED;
}
}
return returnVal;
@@ -90,19 +95,66 @@ private static boolean getPropertySet(String p) {
private static void initJavaFlags() {
java.security.AccessController.doPrivileged(
(PrivilegedAction<Object>) () -> {
metalEnabled = getBooleanProp("sun.java2d.metal", false);
if (metalEnabled) {
metalVerbose = isBooleanPropTrueVerbose("sun.java2d.metal");

// Check whether Metal framework is available on the system
if (!MTLGraphicsConfig.isMetalAvailable()) {
PropertyState oglState = getBooleanProp("sun.java2d.opengl", PropertyState.UNSPECIFIED);
PropertyState metalState = getBooleanProp("sun.java2d.metal", PropertyState.UNSPECIFIED);

Copy link
Collaborator

@prrace prrace Jan 14, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right here we could add
if (metalState == PropertyState.UNSPECIFIED && oglState == PropertyState.UNSPECIFIED) {
// change this line to set metalState to toggle the default pipeline.
oglState = PropertyState.ENABLED;
}
This makes it easier to set the default

Copy link
Collaborator Author

@aghaisas aghaisas Jan 15, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good suggestion.
We need to handle other invalid combinations here as well - I will update the code.

if (metalState == PropertyState.UNSPECIFIED) {
if (oglState == PropertyState.DISABLED) {
oglEnabled = false;
metalEnabled = true;
} else if (oglState == PropertyState.ENABLED || oglState == PropertyState.UNSPECIFIED) {
aghaisas marked this conversation as resolved.
Show resolved Hide resolved
oglEnabled = true;
metalEnabled = false;
}
} else if (metalState == PropertyState.ENABLED) {
if (oglState == PropertyState.DISABLED || oglState == PropertyState.UNSPECIFIED) {
aghaisas marked this conversation as resolved.
Show resolved Hide resolved
oglEnabled = false;
metalEnabled = true;
} else if (oglState == PropertyState.ENABLED) {
oglEnabled = true;
metalEnabled = false;
}
} else if (metalState == PropertyState.DISABLED) {
oglEnabled = true;
metalEnabled = false;
}

oglVerbose = isBooleanPropTrueVerbose("sun.java2d.opengl");
metalVerbose = isBooleanPropTrueVerbose("sun.java2d.metal");

boolean oglAvailable = CGLGraphicsConfig.isCGLAvailable();
boolean metalAvailable = MTLGraphicsConfig.isMetalAvailable();
aghaisas marked this conversation as resolved.
Show resolved Hide resolved

if (!oglAvailable && !metalAvailable) {
// Should never reach here
throw new RuntimeException("Error - Both, OpenGL and Metal frameworks not available.");
}

if (oglEnabled && !metalEnabled) {
// Check whether OGL is available
if (!oglAvailable) {
if (oglVerbose) {
System.out.println("Could not enable OpenGL pipeline (CGL not available)");
}
oglEnabled = false;
metalEnabled = metalAvailable;
}
} else if (metalEnabled && !oglEnabled) {
// Check whether Metal framework is available
if (!metalAvailable) {
if (metalVerbose) {
System.out.println("Could not enable Metal pipeline (Metal framework not available)");
}
metalEnabled = false;
oglEnabled = oglAvailable;
}
}

// At this point one of the rendering pipeline must be enabled.
if (!metalEnabled && !oglEnabled) {
throw new RuntimeException("Error - unable to initialize any rendering pipeline.");
}

return null;
});
}
@@ -114,4 +166,12 @@ public static boolean isMetalEnabled() {
public static boolean isMetalVerbose() {
return metalVerbose;
}

public static boolean isOGLEnabled() {
return oglEnabled;
}

public static boolean isOGLVerbose() {
return oglVerbose;
}
}