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