diff --git a/app/src/main/assets/container_pattern_common.tzst b/app/src/main/assets/container_pattern_common.tzst index 05e4f7c35..b85846a01 100644 Binary files a/app/src/main/assets/container_pattern_common.tzst and b/app/src/main/assets/container_pattern_common.tzst differ diff --git a/app/src/main/assets/wnsteam/bionic/steam.exe b/app/src/main/assets/wnsteam/bionic/steam.exe index 7260a95f5..4893ee1eb 100755 Binary files a/app/src/main/assets/wnsteam/bionic/steam.exe and b/app/src/main/assets/wnsteam/bionic/steam.exe differ diff --git a/app/src/main/cpp/wn-steam-launcher/src/main.cpp b/app/src/main/cpp/wn-steam-launcher/src/main.cpp index e452cf14a..a5eb5be86 100644 --- a/app/src/main/cpp/wn-steam-launcher/src/main.cpp +++ b/app/src/main/cpp/wn-steam-launcher/src/main.cpp @@ -757,7 +757,8 @@ int main(int argc, char** argv) { const char* user = getenv("WN_STEAM_USERNAME"); const char* token = getenv("WN_STEAM_TOKEN"); uint64_t steamId = env_u64("WN_STEAM_STEAMID"); - const char* gameExe = (argc > 1) ? argv[1] : NULL; + const char* gameExe = getenv("WN_STEAM_GAME_EXE"); + if (!gameExe || !*gameExe) gameExe = (argc > 1) ? argv[1] : NULL; uint32_t appId = appIdStr ? (uint32_t) strtoul(appIdStr, NULL, 10) : 0; log_line("[wn-launcher] env appId=%u steamId=%llu user=%s exe=%s", @@ -775,8 +776,8 @@ int main(int argc, char** argv) { } else { log_line("[wn-launcher] token missing"); } - if (argc <= 1 || !gameExe || !*gameExe) { - log_line("[wn-launcher] no game exe passed on argv[1]"); + if (!gameExe || !*gameExe) { + log_line("[wn-launcher] no game exe passed (env WN_STEAM_GAME_EXE or argv[1])"); return 1; } diff --git a/app/src/main/runtime/display/XServerDisplayActivity.java b/app/src/main/runtime/display/XServerDisplayActivity.java index cf4a7d7f4..05129665d 100644 --- a/app/src/main/runtime/display/XServerDisplayActivity.java +++ b/app/src/main/runtime/display/XServerDisplayActivity.java @@ -292,6 +292,7 @@ public class XServerDisplayActivity extends FixedFontScaleAppCompatActivity { private final EnvVars envVars = new EnvVars(); // True when the chosen launch exe differs from Steam's configured entry: launcher skips Steam LaunchApp and CreateProcess'es the selected exe directly. Recomputed per launch. private boolean wnSteamDirectExeOverride = false; + private String wnSteamPlanWGameExe = null; private boolean firstTimeBoot = false; private SharedPreferences preferences; private boolean isMouseDisabled = false; @@ -6736,6 +6737,9 @@ private void setupXEnvironment() throws PackageManager.NameNotFoundException { envVars.put("WN_STEAM_STEAMID", planWSid); envVars.put("WN_STEAM_TOKEN", planWTok); envVars.put("WN_STEAM_APPID", String.valueOf(bsAppId)); + if (wnSteamPlanWGameExe != null && !wnSteamPlanWGameExe.isEmpty()) { + envVars.put("WN_STEAM_GAME_EXE", wnSteamPlanWGameExe); + } if (wnSteamDirectExeOverride) { envVars.put("WN_STEAM_DIRECT_EXE", "1"); Log.i("XServerDisplayActivity", @@ -8171,6 +8175,7 @@ private String getWineStartCommand(GuestProgramLauncherComponent launcherCompone int appId = Integer.parseInt(shortcut.getExtra("app_id")); // Reset per launch; set below once the launch exe is resolved. wnSteamDirectExeOverride = false; + wnSteamPlanWGameExe = null; String steamExtraArgs = appendSteamJoinConnect( com.winlator.cmod.feature.stores.steam.utils.SteamLaunchOptions .gameArgs(shortcut.getSettingExtra("execArgs", container.getExecArgs()))); @@ -8254,8 +8259,14 @@ private String getWineStartCommand(GuestProgramLauncherComponent launcherCompone .PrefManager.INSTANCE.getWnPlanW(); String wrapperExe = planW ? "steam.exe" : "wn-steam-helper.exe"; - args = "\"C:\\Program Files (x86)\\Steam\\" + wrapperExe - + "\" \"" + steamGameExe + "\"" + steamExtraArgs; + if (planW) { + wnSteamPlanWGameExe = steamGameExe; + args = "\"C:\\Program Files (x86)\\Steam\\" + wrapperExe + + "\"" + steamExtraArgs; + } else { + args = "\"C:\\Program Files (x86)\\Steam\\" + wrapperExe + + "\" \"" + steamGameExe + "\"" + steamExtraArgs; + } Log.d("XServerDisplayActivity", "Bionic Steam launch via " + wrapperExe + " (planW=" + planW + "): " + steamGameExe); @@ -8398,8 +8409,15 @@ && new File(storeInstallPath).exists()) { } } - if (!args.isEmpty() && !args.startsWith("winhandler.exe") && !args.startsWith("explorer")) { - return "winhandler.exe " + args; + if (!args.isEmpty() + && !args.startsWith("winhandler.exe") + && !args.startsWith("winlauncher.exe") + && !args.startsWith("explorer")) { + String affinityArg = + taskAffinityMask != 0 + ? "/affinity " + Integer.toHexString(taskAffinityMask & 0xFFFF) + " " + : ""; + return "winlauncher.exe " + affinityArg + args; } else { return args; } diff --git a/app/src/main/runtime/display/environment/components/GuestProgramLauncherComponent.java b/app/src/main/runtime/display/environment/components/GuestProgramLauncherComponent.java index 58ac5f6ae..30d003cd1 100644 --- a/app/src/main/runtime/display/environment/components/GuestProgramLauncherComponent.java +++ b/app/src/main/runtime/display/environment/components/GuestProgramLauncherComponent.java @@ -1160,6 +1160,12 @@ private int execGuestProgram() { + "MESA_VK_WSI_DEBUG=" + envVars.get("MESA_VK_WSI_DEBUG")); + String winhandlerCmd = + wineInfo.isArm64EC() + ? winePath + "/wine winhandler.exe" + : imageFs.getBinDir() + "/box64 wine winhandler.exe"; + ProcessHelper.exec(winhandlerCmd, envVars.toStringArray(), rootDir, null); + return ProcessHelper.exec( command, envVars.toStringArray(), diff --git a/app/src/main/runtime/display/renderer/VulkanRenderer.java b/app/src/main/runtime/display/renderer/VulkanRenderer.java index 058986a45..fb02a736f 100644 --- a/app/src/main/runtime/display/renderer/VulkanRenderer.java +++ b/app/src/main/runtime/display/renderer/VulkanRenderer.java @@ -475,10 +475,16 @@ private void buildAndSubmitFrame() { if (textureSrc != drawable) { float invW = 1.0f / Math.max(1, textureSrc.width); float invH = 1.0f / Math.max(1, textureSrc.height); + int spanW = drawable.hasPresentedSourceSize() + ? Short.toUnsignedInt(drawable.getPresentedSourceWidth()) + : drawable.width; + int spanH = drawable.hasPresentedSourceSize() + ? Short.toUnsignedInt(drawable.getPresentedSourceHeight()) + : drawable.height; buf.putFloat(uvOff, -scanoutX * invW); buf.putFloat(uvOff + 4, -scanoutY * invH); - buf.putFloat(uvOff + 8, (drawable.width - scanoutX) * invW); - buf.putFloat(uvOff + 12, (drawable.height - scanoutY) * invH); + buf.putFloat(uvOff + 8, (spanW - scanoutX) * invW); + buf.putFloat(uvOff + 12, (spanH - scanoutY) * invH); } else { buf.putFloat(uvOff, 0.0f); buf.putFloat(uvOff + 4, 0.0f); diff --git a/app/src/main/runtime/display/xserver/extensions/PresentExtension.java b/app/src/main/runtime/display/xserver/extensions/PresentExtension.java index d8b36919a..38cb8d139 100644 --- a/app/src/main/runtime/display/xserver/extensions/PresentExtension.java +++ b/app/src/main/runtime/display/xserver/extensions/PresentExtension.java @@ -294,9 +294,7 @@ private boolean canDirectScanout(Drawable content, Drawable pixmap, short xOff, return pixmap.isDirectScanout() && texture != null && xOff <= 0 - && yOff <= 0 - && pixmap.width + xOff >= content.width - && pixmap.height + yOff >= content.height; + && yOff <= 0; } private static void copyPresentedRegion(