Skip to main content

compatdb_core/
runtime.rs

1//! What `compatdb.so` needs to apply a [`Resolution`] inside a process.
2//!
3//! That is the process's arch, its image path, command line and environment
4//! block as Wine hands them over in UTF-16, the reader of an image's version
5//! resource, and the values the library hands to Wine.
6//!
7//! A launcher does not need this module. It builds rules, writes the table
8//! into [`ENV_VAR`](crate::ENV_VAR) and, to show what a program would get,
9//! uses [`Table::preview`](crate::Table::preview) with a [`VersionInfo`] it
10//! fills in itself.
11//!
12//! [`Resolution`]: crate::Resolution
13//! [`VersionInfo`]: crate::VersionInfo
14
15mod process;
16mod version;
17
18pub use self::{
19    process::{
20        Arch, IMAGE_FILE_MACHINE_ARM64, append_cmdline, append_cmdline_each, basename_of,
21        env_value, merge_env,
22    },
23    version::version_info,
24};
25use crate::{D3d9, Dxgi, OpenGl, Wined3d};
26
27/// The DXGI-family implementation a process loads when no rule names one.
28///
29/// That is wined3d, as in upstream Wine, for every arch. Its tree has no
30/// D3D12. Either tree serves every arch: the 64-bit modules of both are
31/// ARM64X, so a native ARM64 program loads their ARM64 half and an x64
32/// program, which runs as ARM64EC, their ARM64EC half; an i386 program gets
33/// their i386 builds under emulation.
34#[must_use]
35pub const fn default_dxgi(_arch: Arch) -> Dxgi {
36    Dxgi::Wined3d
37}
38
39/// The DXGI-family implementation a process loads: the requested one, or
40/// [`default_dxgi`] for the arch when nothing was requested.
41#[must_use]
42pub const fn effective_dxgi(requested: Option<Dxgi>, arch: Arch) -> Dxgi {
43    match requested {
44        Some(want) => want,
45        None => default_dxgi(arch),
46    }
47}
48
49/// The D3D9 implementation a process loads when no rule names one.
50///
51/// That is wined3d, as in upstream Wine, for every arch. Either tree serves
52/// every arch: the 64-bit modules of both, mtld3d's release build and Wine's
53/// own `d3d9.dll`, are ARM64X, so a native ARM64 program loads their ARM64
54/// half and an x64 program, which runs as ARM64EC, their ARM64EC half; an
55/// i386 program gets their i386 builds under emulation.
56#[must_use]
57pub const fn default_d3d9(_arch: Arch) -> D3d9 {
58    D3d9::Wined3d
59}
60
61/// The D3D9 implementation a process loads: the requested one, or
62/// [`default_d3d9`] for the arch when nothing was requested.
63#[must_use]
64pub const fn effective_d3d9(requested: Option<D3d9>, arch: Arch) -> D3d9 {
65    match requested {
66        Some(want) => want,
67        None => default_d3d9(arch),
68    }
69}
70
71/// The value ntdll's `set_compat_opengl` takes for `opengl`: 1 for Mesa's
72/// EGL, 0 for Apple's OpenGL.
73#[must_use]
74pub const fn opengl_hook_value(opengl: OpenGl) -> i32 {
75    match opengl {
76        OpenGl::Egl => 1,
77        OpenGl::Cgl => 0,
78    }
79}
80
81/// The `WINE_D3D_CONFIG` value for the renderer `wined3d` on top of
82/// `config`.
83///
84/// `config` is the value the rules' own `env` entries leave the variable at
85/// (`None` when they do not set it, or remove it). The renderer comes first
86/// and the other options of `config` are kept, while a `renderer` option
87/// there is dropped: the setting decides the renderer. OpenGL is set as
88/// explicitly as Vulkan, so a process that asks for it does not inherit
89/// Vulkan from the process that started it.
90#[must_use]
91pub fn wined3d_config(wined3d: Wined3d, config: Option<&str>) -> String {
92    let mut options = vec![format!("renderer={}", wined3d.as_str())];
93    options.extend(
94        config
95            .unwrap_or("")
96            .split([',', ';'])
97            .filter(|o| !o.is_empty())
98            .filter(|o| o.split('=').next() != Some("renderer"))
99            .map(String::from),
100    );
101    options.join(",")
102}
103
104/// The `renderer` option of a `WINE_D3D_CONFIG` value, the first one as
105/// wined3d reads it, or `None` when the value has none.
106#[must_use]
107pub fn wined3d_renderer_in(config: &str) -> Option<&str> {
108    config
109        .split([',', ';'])
110        .find_map(|o| o.strip_prefix("renderer="))
111}
112
113#[cfg(test)]
114mod tests;