1use magma::{
6 MAGMA_STATUS_OK, magma_buffer_get_handle, magma_buffer_id_t, magma_buffer_t,
7 magma_command_descriptor_t, magma_connection_create_buffer, magma_connection_create_context2,
8 magma_connection_create_semaphore, magma_connection_execute_command,
9 magma_connection_map_buffer, magma_connection_release, magma_connection_release_buffer,
10 magma_connection_release_context, magma_connection_release_semaphore, magma_connection_t,
11 magma_device_create_connection, magma_device_import, magma_device_query, magma_device_release,
12 magma_device_t, magma_handle_t, magma_initialize_logging, magma_priority_t, magma_query_t,
13 magma_semaphore_id_t, magma_semaphore_reset, magma_semaphore_signal, magma_semaphore_t,
14 magma_status_t,
15};
16use starnix_logging::log_error;
17use std::panic::Location;
18use std::sync::Arc;
19use zx::HandleBased;
20
21fn magma_result(status: magma_status_t) -> Result<(), magma_status_t> {
22 if status == MAGMA_STATUS_OK { Ok(()) } else { Err(status) }
23}
24
25trait KgslErrorLogger {
26 #[track_caller]
27 fn kgsl_log_error(self) -> Self;
28}
29
30impl<T> KgslErrorLogger for Result<T, magma_status_t> {
31 #[track_caller]
32 fn kgsl_log_error(self) -> Self {
33 match self {
34 Ok(v) => Ok(v),
35 Err(status) => {
36 let caller = Location::caller();
37 log_error!("kgsl: {}({}): {}", caller.file(), caller.line(), status);
38 Err(status)
39 }
40 }
41 }
42}
43
44pub fn initialize_logging(channel: zx::Channel) -> Result<(), ()> {
45 let result = unsafe { magma_initialize_logging(channel.into_raw()) };
47 if result == MAGMA_STATUS_OK { Ok(()) } else { Err(()) }
48}
49
50#[derive(Debug)]
51pub enum QueryOutput {
52 Value(u64),
53 Buffer(zx::Vmo),
54}
55
56#[derive(Debug, Clone)]
57pub struct Device {
58 inner: Arc<DeviceInternal>,
59}
60
61#[derive(Debug)]
62struct DeviceInternal {
63 magma_device: magma_device_t,
64}
65
66impl Drop for DeviceInternal {
67 fn drop(&mut self) {
68 unsafe { magma_device_release(self.magma_device) };
70 }
71}
72
73impl Device {
74 pub fn from_channel(channel: zx::Channel) -> Result<Self, magma_status_t> {
75 let mut magma_device: magma_device_t = 0;
76 let result = unsafe { magma_device_import(channel.into_raw(), &mut magma_device) };
79 magma_result(result).kgsl_log_error()?;
80 Ok(Device { inner: Arc::new(DeviceInternal { magma_device }) })
81 }
82
83 pub fn query(&self, id: magma_query_t) -> Result<QueryOutput, magma_status_t> {
84 let mut result_out: u64 = 0;
85 let mut result_buffer_out: magma_handle_t = 0;
86 let result = unsafe {
89 magma_device_query(self.inner.magma_device, id, &mut result_buffer_out, &mut result_out)
90 };
91 magma_result(result).kgsl_log_error()?;
92 if result_buffer_out != 0 {
93 return Ok(QueryOutput::Buffer(zx::Vmo::from_handle(unsafe {
95 zx::NullableHandle::from_raw(result_buffer_out)
96 })));
97 }
98 Ok(QueryOutput::Value(result_out))
99 }
100
101 pub fn create_connection(&self) -> Result<Connection, magma_status_t> {
102 let mut magma_connection: magma_connection_t = 0;
103 let result = unsafe {
106 magma_device_create_connection(self.inner.magma_device, &mut magma_connection)
107 };
108 magma_result(result).kgsl_log_error()?;
109 Ok(Connection { inner: Arc::new(ConnectionInternal { magma_connection }) })
110 }
111}
112
113#[derive(Debug, Clone)]
114pub struct Connection {
115 inner: Arc<ConnectionInternal>,
116}
117
118#[derive(Debug)]
119struct ConnectionInternal {
120 magma_connection: magma_connection_t,
121}
122
123impl Drop for ConnectionInternal {
124 fn drop(&mut self) {
125 unsafe { magma_connection_release(self.magma_connection) };
127 }
128}
129
130impl Connection {
131 pub fn create_context(&self, priority: magma_priority_t) -> Result<Context, magma_status_t> {
132 let mut magma_context_id: u32 = 0;
133 let result = unsafe {
136 magma_connection_create_context2(
137 self.inner.magma_connection,
138 priority,
139 &mut magma_context_id,
140 )
141 };
142 magma_result(result).kgsl_log_error()?;
143 Ok(Context {
144 inner: Arc::new(ContextInternal { connection: self.inner.clone(), magma_context_id }),
145 })
146 }
147
148 pub fn create_semaphore(&self) -> Result<Semaphore, magma_status_t> {
149 let mut magma_semaphore: magma_semaphore_t = 0;
150 let mut magma_semaphore_id: magma_semaphore_id_t = 0;
151 let result = unsafe {
154 magma_connection_create_semaphore(
155 self.inner.magma_connection,
156 &mut magma_semaphore,
157 &mut magma_semaphore_id,
158 )
159 };
160 magma_result(result).kgsl_log_error()?;
161 Ok(Semaphore {
162 inner: Arc::new(SemaphoreInternal {
163 connection: self.inner.clone(),
164 magma_semaphore,
165 magma_semaphore_id,
166 }),
167 })
168 }
169
170 pub fn create_buffer(&self, size: u64) -> Result<Buffer, magma_status_t> {
171 let mut size_out: u64 = 0;
172 let mut magma_buffer: magma_buffer_t = 0;
173 let mut magma_buffer_id: magma_buffer_id_t = 0;
174 let result = unsafe {
177 magma_connection_create_buffer(
178 self.inner.magma_connection,
179 size,
180 &mut size_out,
181 &mut magma_buffer,
182 &mut magma_buffer_id,
183 )
184 };
185 magma_result(result).kgsl_log_error()?;
186 Ok(Buffer {
187 inner: Arc::new(BufferInternal {
188 connection: self.inner.clone(),
189 magma_buffer,
190 magma_buffer_id,
191 size: size_out,
192 }),
193 })
194 }
195}
196
197#[derive(Debug, Clone)]
198pub struct Context {
199 inner: Arc<ContextInternal>,
200}
201
202#[derive(Debug)]
203struct ContextInternal {
204 connection: Arc<ConnectionInternal>,
205 magma_context_id: u32,
206}
207
208impl Drop for ContextInternal {
209 fn drop(&mut self) {
210 unsafe {
213 magma_connection_release_context(
214 self.connection.magma_connection,
215 self.magma_context_id,
216 )
217 };
218 }
219}
220
221pub struct ExecResource {
222 pub buffer: Buffer,
223 pub offset: u64,
224 pub length: u64,
225}
226
227impl Context {
228 pub fn execute_command(
229 &self,
230 command_buffers: Vec<ExecResource>,
231 resources: Vec<ExecResource>,
232 wait_semaphores: Vec<Semaphore>,
233 signal_semaphores: Vec<Semaphore>,
234 flags: u64,
235 ) -> Result<(), magma_status_t> {
236 let mut magma_resources: Vec<magma::magma_exec_resource> = resources
238 .iter()
239 .chain(command_buffers.iter())
240 .map(|r| magma::magma_exec_resource {
241 buffer_id: r.buffer.id(),
242 offset: r.offset,
243 length: r.length,
244 })
245 .collect();
246
247 let mut magma_command_buffers: Vec<magma::magma_exec_command_buffer> = command_buffers
249 .iter()
250 .enumerate()
251 .map(|(i, _)| magma::magma_exec_command_buffer {
252 resource_index: (resources.len() + i) as u32,
253 unused: 0,
254 start_offset: 0,
255 })
256 .collect();
257
258 let mut semaphore_ids: Vec<u64> = wait_semaphores
260 .iter()
261 .map(|s| s.id())
262 .chain(signal_semaphores.iter().map(|s| s.id()))
263 .collect();
264
265 let mut descriptor = magma_command_descriptor_t {
266 resource_count: magma_resources.len() as u32,
267 command_buffer_count: magma_command_buffers.len() as u32,
268 wait_semaphore_count: wait_semaphores.len() as u32,
269 signal_semaphore_count: signal_semaphores.len() as u32,
270 resources: magma_resources.as_mut_ptr(),
271 command_buffers: magma_command_buffers.as_mut_ptr(),
272 semaphore_ids: semaphore_ids.as_mut_ptr(),
273 flags,
274 };
275
276 let result = unsafe {
278 magma_connection_execute_command(
279 self.inner.connection.magma_connection,
280 self.inner.magma_context_id,
281 &mut descriptor,
282 )
283 };
284 magma_result(result).kgsl_log_error()?;
285 Ok(())
286 }
287}
288
289#[derive(Debug, Clone)]
290pub struct Semaphore {
291 inner: Arc<SemaphoreInternal>,
292}
293
294impl Semaphore {
295 pub fn id(&self) -> magma_semaphore_id_t {
296 self.inner.magma_semaphore_id
297 }
298
299 pub fn signal(&self) {
300 unsafe { magma_semaphore_signal(self.inner.magma_semaphore) }
302 }
303
304 pub fn reset(&self) {
305 unsafe { magma_semaphore_reset(self.inner.magma_semaphore) }
307 }
308}
309
310#[derive(Debug)]
311struct SemaphoreInternal {
312 connection: Arc<ConnectionInternal>,
313 magma_semaphore: magma_semaphore_t,
314 magma_semaphore_id: magma_semaphore_id_t,
315}
316
317impl Drop for SemaphoreInternal {
318 fn drop(&mut self) {
319 unsafe {
322 magma_connection_release_semaphore(
323 self.connection.magma_connection,
324 self.magma_semaphore,
325 )
326 };
327 }
328}
329
330#[derive(Debug, Clone)]
331pub struct Buffer {
332 inner: Arc<BufferInternal>,
333}
334
335impl Buffer {
336 pub fn id(&self) -> magma_buffer_id_t {
337 self.inner.magma_buffer_id
338 }
339
340 pub fn size(&self) -> u64 {
341 self.inner.size
342 }
343
344 pub fn get_handle(&self) -> Result<zx::NullableHandle, magma_status_t> {
345 let mut handle: magma_handle_t = 0;
346 let result = unsafe { magma_buffer_get_handle(self.inner.magma_buffer, &mut handle) };
348 magma_result(result).kgsl_log_error()?;
349 let handle = unsafe { zx::NullableHandle::from_raw(handle) };
351 Ok(handle)
352 }
353
354 pub fn map(
355 &self,
356 hw_va: u64,
357 offset: u64,
358 length: u64,
359 flags: u64,
360 ) -> Result<(), magma_status_t> {
361 let result = unsafe {
363 magma_connection_map_buffer(
364 self.inner.connection.magma_connection,
365 hw_va,
366 self.inner.magma_buffer,
367 offset,
368 length,
369 flags,
370 )
371 };
372 magma_result(result).kgsl_log_error()?;
373 Ok(())
374 }
375}
376
377#[derive(Debug)]
378struct BufferInternal {
379 connection: Arc<ConnectionInternal>,
380 magma_buffer: magma_buffer_t,
381 magma_buffer_id: magma_buffer_id_t,
382 size: u64,
383}
384
385impl Drop for BufferInternal {
386 fn drop(&mut self) {
387 unsafe {
390 magma_connection_release_buffer(self.connection.magma_connection, self.magma_buffer)
391 };
392 }
393}