diff --git a/app/src/main/java/app/gamenative/utils/ContainerUtils.kt b/app/src/main/java/app/gamenative/utils/ContainerUtils.kt index d3d3e363c5..c0a283099a 100644 --- a/app/src/main/java/app/gamenative/utils/ContainerUtils.kt +++ b/app/src/main/java/app/gamenative/utils/ContainerUtils.kt @@ -101,6 +101,7 @@ object ContainerUtils { } DefaultVersion.DISPLAY_SERVER = Container.defaultDisplayServer( GPUInformation.getRenderer(context).orEmpty().contains("adreno", ignoreCase = true), + Build.VERSION.SDK_INT, ) } diff --git a/app/src/main/java/com/winlator/container/Container.java b/app/src/main/java/com/winlator/container/Container.java index 8fda29fb66..cf86c9fd64 100644 --- a/app/src/main/java/com/winlator/container/Container.java +++ b/app/src/main/java/com/winlator/container/Container.java @@ -44,6 +44,8 @@ public enum XrControllerMapping { public static final String DEFAULT_DISPLAY_RENDERER = "vulkan"; public static final String DISPLAY_SERVER_X11 = "x11"; public static final String DISPLAY_SERVER_GAMESCOPE = "gamescope"; + /** Gamescope scans out through ASurfaceControl/ASurfaceTransaction, which libandroid only exports from API 29 (Android 10). */ + public static final int GAMESCOPE_MIN_SDK = 29; public static final String DEFAULT_DDRAWRAPPER = "none"; public static final String DEFAULT_DXWRAPPERCONFIG = "version=" + DefaultVersion.DXVK + ",framerate=0,maxDeviceMemory=0,async=" + DefaultVersion.ASYNC + ",asyncCache=" + DefaultVersion.ASYNC_CACHE + ",vkd3dVersion=" + DefaultVersion.VKD3D + ",vkd3dLevel=12_1" + ",ddrawrapper=" + Container.DEFAULT_DDRAWRAPPER + ",csmt=3" + ",gpuName=NVIDIA GeForce GTX 480" + ",videoMemorySize=2048" + ",strict_shader_math=1" + ",OffscreenRenderingMode=fbo" + ",renderer=gl";; public static final String DEFAULT_GRAPHICSDRIVERCONFIG = "vulkanVersion=1.3" + ",version=" + DefaultVersion.WRAPPER + ",blacklistedExtensions=" + ",maxDeviceMemory=0" + ",presentMode=mailbox" + ",syncFrame=0" + ",disablePresentWait=0" + ",resourceType=auto" + ",bcnEmulation=auto" + ",bcnEmulationType=compute" + ",bcnEmulationCache=0" + ",gpuName=Device"; @@ -308,8 +310,13 @@ public void setGraphicsDriverConfig(String graphicsDriverConfig) { public void setDisplayServer(String v) { this.displayServer = v; } - public static String defaultDisplayServer(boolean isAdreno) { - return isAdreno ? DISPLAY_SERVER_GAMESCOPE : DISPLAY_SERVER_X11; + /** Whether the gamescope display path can run on a device at this API level. */ + public static boolean isGamescopeSupported(int sdkInt) { + return sdkInt >= GAMESCOPE_MIN_SDK; + } + + public static String defaultDisplayServer(boolean isAdreno, int sdkInt) { + return isAdreno && isGamescopeSupported(sdkInt) ? DISPLAY_SERVER_GAMESCOPE : DISPLAY_SERVER_X11; } public static boolean isX11Display(String containerVariant, String displayServer) { diff --git a/app/src/test/java/com/winlator/container/ContainerDefaultDisplayServerTest.kt b/app/src/test/java/com/winlator/container/ContainerDefaultDisplayServerTest.kt new file mode 100644 index 0000000000..9eb206bc1d --- /dev/null +++ b/app/src/test/java/com/winlator/container/ContainerDefaultDisplayServerTest.kt @@ -0,0 +1,36 @@ +package com.winlator.container + +import org.junit.Assert.assertEquals +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner + +@RunWith(RobolectricTestRunner::class) +class ContainerDefaultDisplayServerTest { + + @Test + fun `adreno on API 29 or newer defaults to gamescope`() { + assertEquals(Container.DISPLAY_SERVER_GAMESCOPE, Container.defaultDisplayServer(true, 29)) + assertEquals(Container.DISPLAY_SERVER_GAMESCOPE, Container.defaultDisplayServer(true, 36)) + } + + @Test + fun `adreno below API 29 defaults to x11 because ASurfaceControl is missing`() { + assertEquals(Container.DISPLAY_SERVER_X11, Container.defaultDisplayServer(true, 28)) + assertEquals(Container.DISPLAY_SERVER_X11, Container.defaultDisplayServer(true, 26)) + } + + @Test + fun `non-adreno defaults to x11 at every API level`() { + assertEquals(Container.DISPLAY_SERVER_X11, Container.defaultDisplayServer(false, 28)) + assertEquals(Container.DISPLAY_SERVER_X11, Container.defaultDisplayServer(false, 36)) + } + + @Test + fun `gamescope support follows the ASurfaceControl API floor`() { + assertFalse(Container.isGamescopeSupported(28)) + assertTrue(Container.isGamescopeSupported(29)) + } +}