Repository navigation
gamescope: take the payload from the APK when it ships one, and version it by date #2226
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
ed2617b
5e9d01b
6315279
f9be061
9982f7f
6b70851
e17c5f6
bb94486
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -11,7 +11,7 @@ import java.io.File | |||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| /** Versioned gamescope payload (gamescope, XWayland, scaling clients), fetched on the first gamescope launch. */ | ||||||||||||||||||||||||||||||||||||||||
| object GamescopePayload { | ||||||||||||||||||||||||||||||||||||||||
| const val VERSION = "20261022.13" | ||||||||||||||||||||||||||||||||||||||||
| const val VERSION = "20261023.3" | ||||||||||||||||||||||||||||||||||||||||
| const val ARCHIVE = "gamescope-gamenative-$VERSION.tzst" | ||||||||||||||||||||||||||||||||||||||||
| private const val STAMP = ".payload.version" | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
|
|
@@ -29,16 +29,39 @@ object GamescopePayload { | |||||||||||||||||||||||||||||||||||||||
| val archive = File(filesDir, ARCHIVE) | ||||||||||||||||||||||||||||||||||||||||
| if (!archive.isFile || archive.length() == 0L) { | ||||||||||||||||||||||||||||||||||||||||
| archive.delete() | ||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||
| SteamService.fetchFileWithFallback(ARCHIVE, archive, context, onProgress) | ||||||||||||||||||||||||||||||||||||||||
| } catch (e: Exception) { | ||||||||||||||||||||||||||||||||||||||||
| archive.delete() | ||||||||||||||||||||||||||||||||||||||||
| throw e | ||||||||||||||||||||||||||||||||||||||||
| // A payload shipped inside the APK wins over the download: it is the | ||||||||||||||||||||||||||||||||||||||||
| // build that was exercised with this app, and it needs no network. | ||||||||||||||||||||||||||||||||||||||||
| // Only when the asset is absent does the published archive get | ||||||||||||||||||||||||||||||||||||||||
| // fetched. | ||||||||||||||||||||||||||||||||||||||||
| if (copyFromAssets(context, archive)) { | ||||||||||||||||||||||||||||||||||||||||
| onProgress(1.0f) | ||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||
| SteamService.fetchFileWithFallback(ARCHIVE, archive, context, onProgress) | ||||||||||||||||||||||||||||||||||||||||
| } catch (e: Exception) { | ||||||||||||||||||||||||||||||||||||||||
| archive.delete() | ||||||||||||||||||||||||||||||||||||||||
| throw e | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| install(archive, filesDir) | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| /** Whether this APK carries the payload, and if so, copy it out to [dest]. */ | ||||||||||||||||||||||||||||||||||||||||
| private fun copyFromAssets(context: Context, dest: File): Boolean { | ||||||||||||||||||||||||||||||||||||||||
| val assets = context.assets | ||||||||||||||||||||||||||||||||||||||||
| val present = runCatching { assets.open(ARCHIVE).close() }.isSuccess | ||||||||||||||||||||||||||||||||||||||||
| if (!present) return false | ||||||||||||||||||||||||||||||||||||||||
| return runCatching { | ||||||||||||||||||||||||||||||||||||||||
| assets.open(ARCHIVE).use { input -> dest.outputStream().use { output -> input.copyTo(output) } } | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| .onFailure { | ||||||||||||||||||||||||||||||||||||||||
| Timber.w(it, "Failed to copy $ARCHIVE from assets") | ||||||||||||||||||||||||||||||||||||||||
| dest.delete() | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| .isSuccess | ||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+55
to
+62
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: The APK stream is copied directly to the final archive, so interruption can leave a non-empty partial file that the next launch tries to extract; zero-byte assets are also reported as success. Copy to a temporary file, require nonzero output, then atomically rename it. Prompt for AI agents
Suggested change
|
||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| @Synchronized | ||||||||||||||||||||||||||||||||||||||||
| internal fun install(archive: File, filesDir: File): File { | ||||||||||||||||||||||||||||||||||||||||
| val target = directory(filesDir) | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -98,6 +98,9 @@ object ContainerUtils { | |
| DefaultVersion.STEAM_TYPE = Container.STEAM_TYPE_HEADLESS | ||
| DefaultVersion.ASYNC_CACHE = "0" | ||
| } | ||
| DefaultVersion.DISPLAY_SERVER = Container.defaultDisplayServer( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: The Adreno display-server default is initialized only from Prompt for AI agents
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P3: The new display-server default checks Adreno through the GL renderer string, but Prompt for AI agents |
||
| GPUInformation.getRenderer(context).orEmpty().contains("adreno", ignoreCase = true), | ||
| ) | ||
| } | ||
|
|
||
| fun getGPUCards(context: Context): Map<Int, GpuInfo> { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -44,7 +44,6 @@ 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"; | ||
| public static final String DEFAULT_DISPLAY_SERVER = DISPLAY_SERVER_GAMESCOPE; | ||
| 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"; | ||
|
|
@@ -87,7 +86,7 @@ public enum XrControllerMapping { | |
| private String graphicsDriverConfig = DEFAULT_GRAPHICSDRIVERCONFIG; | ||
| private String rendererPresentMode = "fifo"; | ||
| private String displayRenderer = Container.DEFAULT_DISPLAY_RENDERER; | ||
| private String displayServer = Container.DEFAULT_DISPLAY_SERVER; | ||
| private String displayServer = DefaultVersion.DISPLAY_SERVER; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P1: This default is overwritten for new containers. Prompt for AI agents
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: Duplicating a container no longer preserves its display server because Prompt for AI agents |
||
| private int xrRefreshRate = 72; | ||
| private int xrRenderScale = 100; | ||
| private boolean sfCompatMode = true; | ||
|
|
@@ -309,6 +308,10 @@ 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; | ||
| } | ||
|
|
||
| public static boolean isX11Display(String containerVariant, String displayServer) { | ||
| return !BIONIC.equalsIgnoreCase(containerVariant) || !DISPLAY_SERVER_GAMESCOPE.equalsIgnoreCase(displayServer); | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P2:
copyFromAssetsruns only when the cached archive is missing or empty. A non-empty archive left by an interrupted prior launch can therefore bypass the APK asset and install a stale or downloaded payload. Check and copy the bundled asset before accepting the cached archive.Prompt for AI agents