xref: /aosp_15_r20/external/mesa3d/src/gallium/frontends/rusticl/mesa/pipe/device.rs (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 use crate::pipe::screen::*;
2 
3 use mesa_rust_gen::*;
4 use mesa_rust_util::ptr::ThreadSafeCPtr;
5 use mesa_rust_util::string::c_string_to_string;
6 
7 use std::collections::HashMap;
8 use std::{env, ptr};
9 
10 #[derive(PartialEq)]
11 pub(super) struct PipeLoaderDevice {
12     ldev: ThreadSafeCPtr<pipe_loader_device>,
13 }
14 
15 impl PipeLoaderDevice {
new(ldev: *mut pipe_loader_device) -> Option<Self>16     fn new(ldev: *mut pipe_loader_device) -> Option<Self> {
17         Some(Self {
18             // SAFETY: `pipe_loader_device` is considered to be thread-safe
19             ldev: unsafe { ThreadSafeCPtr::new(ldev)? },
20         })
21     }
22 
load_screen(self) -> Option<PipeScreen>23     fn load_screen(self) -> Option<PipeScreen> {
24         let s = unsafe { pipe_loader_create_screen(self.ldev.as_ptr(), false) };
25         PipeScreen::new(self, s)
26     }
27 
driver_name(&self) -> String28     pub fn driver_name(&self) -> String {
29         c_string_to_string(unsafe { self.ldev.as_ref() }.driver_name)
30     }
31 
device_type(&self) -> pipe_loader_device_type32     pub fn device_type(&self) -> pipe_loader_device_type {
33         unsafe { self.ldev.as_ref().type_ }
34     }
35 }
36 
37 impl Drop for PipeLoaderDevice {
drop(&mut self)38     fn drop(&mut self) {
39         unsafe {
40             pipe_loader_release(&mut self.ldev.as_ptr(), 1);
41         }
42     }
43 }
44 
load_devs() -> impl Iterator<Item = PipeLoaderDevice>45 fn load_devs() -> impl Iterator<Item = PipeLoaderDevice> {
46     let n = unsafe { pipe_loader_probe(ptr::null_mut(), 0, true) };
47     let mut devices: Vec<*mut pipe_loader_device> = vec![ptr::null_mut(); n as usize];
48     unsafe {
49         pipe_loader_probe(devices.as_mut_ptr(), n, true);
50     }
51 
52     devices.into_iter().filter_map(PipeLoaderDevice::new)
53 }
54 
get_enabled_devs() -> HashMap<String, u32>55 fn get_enabled_devs() -> HashMap<String, u32> {
56     let mut res = HashMap::new();
57 
58     if let Ok(enabled_devs) = env::var("RUSTICL_ENABLE") {
59         let mut last_driver = None;
60         for driver_str in enabled_devs.split(',') {
61             if driver_str.is_empty() {
62                 continue;
63             }
64 
65             // if the string parses to a number, just updated the device bitset
66             if let Ok(dev_id) = driver_str.parse::<u8>() {
67                 if let Some(last_driver) = last_driver {
68                     *res.get_mut(last_driver).unwrap() |= 1 << dev_id;
69                 }
70                 continue;
71             } else {
72                 let driver_str: Vec<_> = driver_str.split(':').collect();
73                 let mut devices = 0;
74 
75                 if driver_str.len() == 1 {
76                     devices = !0;
77                 } else if let Ok(dev_id) = driver_str[1].parse::<u8>() {
78                     devices |= 1 << dev_id;
79                 }
80 
81                 let driver_str = match driver_str[0] {
82                     "llvmpipe" | "lp" => "swrast",
83                     "freedreno" => "msm",
84                     a => a,
85                 };
86 
87                 res.insert(driver_str.to_owned(), devices);
88                 last_driver = Some(driver_str);
89             }
90         }
91 
92         if res.contains_key("panfrost") {
93             res.insert("panthor".to_owned(), res["panfrost"]);
94         }
95     }
96 
97     res
98 }
99 
load_screens() -> impl Iterator<Item = PipeScreen>100 pub fn load_screens() -> impl Iterator<Item = PipeScreen> {
101     let devs = load_devs();
102     let mut enabled_devs = get_enabled_devs();
103 
104     devs.filter(move |dev| {
105         let driver_name = unsafe { c_string_to_string(dev.ldev.as_ref().driver_name) };
106 
107         if let Some(enabled_devs) = enabled_devs.get_mut(&driver_name) {
108             let res = (*enabled_devs & 1) == 1;
109             *enabled_devs >>= 1;
110 
111             res
112         } else {
113             false
114         }
115     })
116     .filter_map(PipeLoaderDevice::load_screen)
117 }
118