1use std::ffi::CStr;
9
10use super::*;
11use block::{Block, RcBlock};
12
13#[cfg(feature = "dispatch")]
14use dispatch;
15
16type MTLSharedEventNotificationBlock<'a> = RcBlock<(&'a SharedEventRef, u64), ()>;
18
19pub enum MTLEvent {}
21
22foreign_obj_type! {
23 type CType = MTLEvent;
24 pub struct Event;
25}
26
27impl EventRef {
28 pub fn device(&self) -> &DeviceRef {
29 unsafe { msg_send![self, device] }
30 }
31}
32
33pub enum MTLSharedEvent {}
35
36foreign_obj_type! {
37 type CType = MTLSharedEvent;
38 pub struct SharedEvent;
39 type ParentType = Event;
40}
41
42impl SharedEventRef {
43 pub fn signaled_value(&self) -> u64 {
44 unsafe { msg_send![self, signaledValue] }
45 }
46
47 pub fn set_signaled_value(&self, new_value: u64) {
48 unsafe { msg_send![self, setSignaledValue: new_value] }
49 }
50
51 pub fn notify(
54 &self,
55 listener: &SharedEventListenerRef,
56 value: u64,
57 block: MTLSharedEventNotificationBlock,
58 ) {
59 unsafe {
60 let block = mem::transmute::<
63 MTLSharedEventNotificationBlock,
64 *mut BlockBase<(&SharedEventRef, u64), ()>,
65 >(block);
66 (*block).flags |= BLOCK_HAS_SIGNATURE | BLOCK_HAS_COPY_DISPOSE;
67 (*block).extra = &raw const BLOCK_EXTRA;
68 let () = msg_send![self, notifyListener:listener atValue:value block:block];
69 }
70
71 extern "C" fn dtor(_: *mut BlockBase<(&SharedEventRef, u64), ()>) {}
72
73 const SIGNATURE: &CStr = c"v16@?0Q8";
74 const SIGNATURE_PTR: *const i8 = SIGNATURE.as_ptr().cast();
75 static mut BLOCK_EXTRA: BlockExtra<(&SharedEventRef, u64), ()> = BlockExtra {
76 unknown0: std::ptr::null_mut(),
77 unknown1: std::ptr::null_mut(),
78 unknown2: std::ptr::null_mut(),
79 dtor,
80 signature: &SIGNATURE_PTR,
81 };
82 }
83}
84
85pub enum MTLSharedEventListener {}
87
88foreign_obj_type! {
89 type CType = MTLSharedEventListener;
90 pub struct SharedEventListener;
91}
92
93impl SharedEventListener {
94 pub unsafe fn from_queue_handle(queue: dispatch_queue_t) -> Self {
95 let listener: SharedEventListener = msg_send![class!(MTLSharedEventListener), alloc];
96 let ptr: *mut Object = msg_send![listener.as_ref(), initWithDispatchQueue: queue];
97 if ptr.is_null() {
98 panic!("[MTLSharedEventListener alloc] initWithDispatchQueue failed");
99 }
100 listener
101 }
102
103 #[cfg(feature = "dispatch")]
104 pub fn from_queue(queue: &dispatch::Queue) -> Self {
105 unsafe {
106 let raw_queue = std::mem::transmute::<&dispatch::Queue, *const dispatch_queue_t>(queue);
107 Self::from_queue_handle(*raw_queue)
108 }
109 }
110}
111
112pub enum MTLFence {}
114
115foreign_obj_type! {
116 type CType = MTLFence;
117 pub struct Fence;
118}
119
120impl FenceRef {
121 pub fn device(&self) -> &DeviceRef {
122 unsafe { msg_send![self, device] }
123 }
124
125 pub fn label(&self) -> &str {
126 unsafe {
127 let label = msg_send![self, label];
128 crate::nsstring_as_str(label)
129 }
130 }
131
132 pub fn set_label(&self, label: &str) {
133 unsafe {
134 let nslabel = crate::nsstring_from_str(label);
135 let () = msg_send![self, setLabel: nslabel];
136 }
137 }
138}
139
140bitflags::bitflags! {
141 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
148 pub struct MTLRenderStages: NSUInteger {
149 const Vertex = 1 << 0;
151 const Fragment = 1 << 1;
153 const Tile = 1 << 2;
155 }
156}
157
158const BLOCK_HAS_COPY_DISPOSE: i32 = 0x02000000;
159const BLOCK_HAS_SIGNATURE: i32 = 0x40000000;
160
161#[repr(C)]
162struct BlockBase<A, R> {
163 isa: *const std::ffi::c_void, flags: i32, _reserved: i32, invoke: unsafe extern "C" fn(*mut Block<A, R>, ...) -> R, extra: *const BlockExtra<A, R>, }
169
170type BlockExtraDtor<A, R> = extern "C" fn(*mut BlockBase<A, R>);
171
172#[repr(C)]
173struct BlockExtra<A, R> {
174 unknown0: *mut i32, unknown1: *mut i32, unknown2: *mut i32, dtor: BlockExtraDtor<A, R>, signature: *const *const i8, }