1 // Copyright 2017 GFX developers
2 //
3 // Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4 // http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5 // http://opensource.org/licenses/MIT>, at your option. This file may not be
6 // copied, modified, or distributed except according to those terms.
7 
8 #![allow(non_snake_case)]
9 #![allow(non_upper_case_globals)]
10 
11 #[macro_use]
12 extern crate bitflags;
13 #[macro_use]
14 extern crate log;
15 #[macro_use]
16 extern crate objc;
17 #[macro_use]
18 extern crate foreign_types;
19 
20 use std::borrow::{Borrow, ToOwned};
21 use std::marker::PhantomData;
22 use std::mem;
23 use std::ops::Deref;
24 use std::os::raw::c_void;
25 
26 use core_graphics::base::CGFloat;
27 use core_graphics::geometry::CGSize;
28 use foreign_types::ForeignType;
29 use objc::runtime::{Object, NO, YES};
30 use cocoa::foundation::NSUInteger;
31 
nsstring_as_str(nsstr: &objc::runtime::Object) -> &str32 fn nsstring_as_str(nsstr: &objc::runtime::Object) -> &str {
33     let bytes = unsafe {
34         let bytes: *const std::os::raw::c_char = msg_send![nsstr, UTF8String];
35         bytes as *const u8
36     };
37     let len: NSUInteger = unsafe { msg_send![nsstr, length] };
38     unsafe {
39         let bytes = std::slice::from_raw_parts(bytes, len as usize);
40         std::str::from_utf8(bytes).unwrap()
41     }
42 }
43 
nsstring_from_str(string: &str) -> *mut objc::runtime::Object44 fn nsstring_from_str(string: &str) -> *mut objc::runtime::Object {
45     const UTF8_ENCODING: usize = 4;
46 
47     let cls = class!(NSString);
48     let bytes = string.as_ptr() as *const c_void;
49     unsafe {
50         let obj: *mut objc::runtime::Object = msg_send![cls, alloc];
51         let obj: *mut objc::runtime::Object = msg_send![
52             obj,
53             initWithBytes:bytes
54             length:string.len()
55             encoding:UTF8_ENCODING
56         ];
57         let _: *mut c_void = msg_send![obj, autorelease];
58         obj
59     }
60 }
61 
62 macro_rules! foreign_obj_type {
63     {type CType = $raw_ident:ident;
64     pub struct $owned_ident:ident;
65     pub struct $ref_ident:ident;
66     type ParentType = $parent_ref:ident;
67     } => {
68         foreign_obj_type! {
69             type CType = $raw_ident;
70             pub struct $owned_ident;
71             pub struct $ref_ident;
72         }
73 
74         impl ::std::ops::Deref for $ref_ident {
75             type Target = $parent_ref;
76 
77             fn deref(&self) -> &$parent_ref {
78                 unsafe { &*(self as *const $ref_ident as *const $parent_ref)  }
79             }
80         }
81     };
82     {type CType = $raw_ident:ident;
83     pub struct $owned_ident:ident;
84     pub struct $ref_ident:ident;
85     } => {
86         foreign_type! {
87             type CType = $raw_ident;
88             fn drop = crate::obj_drop;
89             fn clone = crate::obj_clone;
90             pub struct $owned_ident;
91             pub struct $ref_ident;
92         }
93 
94         unsafe impl ::objc::Message for $raw_ident {
95         }
96         unsafe impl ::objc::Message for $ref_ident {
97         }
98 
99         impl ::std::fmt::Debug for $ref_ident {
100             fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
101                 unsafe {
102                     let string: *mut ::objc::runtime::Object = msg_send![self, debugDescription];
103                     write!(f, "{}", crate::nsstring_as_str(&*string))
104                 }
105             }
106         }
107 
108         impl ::std::fmt::Debug for $owned_ident {
109             fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
110                 ::std::ops::Deref::deref(self).fmt(f)
111             }
112         }
113     };
114 }
115 
116 macro_rules! try_objc {
117     {
118         $err_name: ident => $body:expr
119     } => {
120         {
121             let mut $err_name: *mut ::objc::runtime::Object = ::std::ptr::null_mut();
122             let value = $body;
123             if !$err_name.is_null() {
124                 let desc: *mut Object = msg_send![$err_name, localizedDescription];
125                 let compile_error: *const std::os::raw::c_char = msg_send![desc, UTF8String];
126                 let message = CStr::from_ptr(compile_error).to_string_lossy().into_owned();
127                 let () = msg_send![$err_name, release];
128                 return Err(message);
129             }
130             value
131         }
132     };
133 }
134 
135 pub struct NSArray<T> {
136     _phantom: PhantomData<T>,
137 }
138 
139 pub struct Array<T>(*mut NSArray<T>)
140 where
141     T: ForeignType + 'static,
142     T::Ref: objc::Message + 'static;
143 pub struct ArrayRef<T>(foreign_types::Opaque, PhantomData<T>)
144 where
145     T: ForeignType + 'static,
146     T::Ref: objc::Message + 'static;
147 
148 impl<T> Drop for Array<T>
149 where
150     T: ForeignType + 'static,
151     T::Ref: objc::Message + 'static,
152 {
drop(&mut self)153     fn drop(&mut self) {
154         unsafe {
155             let () = msg_send![self.0, release];
156         }
157     }
158 }
159 
160 impl<T> Clone for Array<T>
161 where
162     T: ForeignType + 'static,
163     T::Ref: objc::Message + 'static,
164 {
clone(&self) -> Self165     fn clone(&self) -> Self {
166         unsafe { Array(msg_send![self.0, retain]) }
167     }
168 }
169 
170 unsafe impl<T> objc::Message for NSArray<T>
171 where
172     T: ForeignType + 'static,
173     T::Ref: objc::Message + 'static,
174 {
175 }
176 unsafe impl<T> objc::Message for ArrayRef<T>
177 where
178     T: ForeignType + 'static,
179     T::Ref: objc::Message + 'static,
180 {
181 }
182 
183 impl<T> Array<T>
184 where
185     T: ForeignType + 'static,
186     T::Ref: objc::Message + 'static,
187 {
from_slice<'a>(s: &[&T::Ref]) -> &'a ArrayRef<T>188     pub fn from_slice<'a>(s: &[&T::Ref]) -> &'a ArrayRef<T> {
189         unsafe {
190             let class = class!(NSArray);
191             msg_send![class, arrayWithObjects: s.as_ptr() count: s.len()]
192         }
193     }
194 
from_owned_slice<'a>(s: &[T]) -> &'a ArrayRef<T>195     pub fn from_owned_slice<'a>(s: &[T]) -> &'a ArrayRef<T> {
196         unsafe {
197             let class = class!(NSArray);
198             msg_send![class, arrayWithObjects: s.as_ptr() count: s.len()]
199         }
200     }
201 }
202 
203 impl<T> foreign_types::ForeignType for Array<T>
204 where
205     T: ForeignType + 'static,
206     T::Ref: objc::Message + 'static,
207 {
208     type CType = NSArray<T>;
209     type Ref = ArrayRef<T>;
210 
from_ptr(p: *mut NSArray<T>) -> Self211     unsafe fn from_ptr(p: *mut NSArray<T>) -> Self {
212         Array(p)
213     }
214 
as_ptr(&self) -> *mut NSArray<T>215     fn as_ptr(&self) -> *mut NSArray<T> {
216         self.0
217     }
218 }
219 
220 impl<T> foreign_types::ForeignTypeRef for ArrayRef<T>
221 where
222     T: ForeignType + 'static,
223     T::Ref: objc::Message + 'static,
224 {
225     type CType = NSArray<T>;
226 }
227 
228 impl<T> Deref for Array<T>
229 where
230     T: ForeignType + 'static,
231     T::Ref: objc::Message + 'static,
232 {
233     type Target = ArrayRef<T>;
234 
deref(&self) -> &ArrayRef<T>235     fn deref(&self) -> &ArrayRef<T> {
236         unsafe { mem::transmute(self.as_ptr()) }
237     }
238 }
239 
240 impl<T> Borrow<ArrayRef<T>> for Array<T>
241 where
242     T: ForeignType + 'static,
243     T::Ref: objc::Message + 'static,
244 {
borrow(&self) -> &ArrayRef<T>245     fn borrow(&self) -> &ArrayRef<T> {
246         unsafe { mem::transmute(self.as_ptr()) }
247     }
248 }
249 
250 impl<T> ToOwned for ArrayRef<T>
251 where
252     T: ForeignType + 'static,
253     T::Ref: objc::Message + 'static,
254 {
255     type Owned = Array<T>;
256 
to_owned(&self) -> Array<T>257     fn to_owned(&self) -> Array<T> {
258         unsafe { Array::from_ptr(msg_send![self, retain]) }
259     }
260 }
261 
262 pub enum CAMetalDrawable {}
263 
264 foreign_obj_type! {
265     type CType = CAMetalDrawable;
266     pub struct CoreAnimationDrawable;
267     pub struct CoreAnimationDrawableRef;
268     type ParentType = DrawableRef;
269 }
270 
271 impl CoreAnimationDrawableRef {
texture(&self) -> &TextureRef272     pub fn texture(&self) -> &TextureRef {
273         unsafe { msg_send![self, texture] }
274     }
275 }
276 
277 pub enum CAMetalLayer {}
278 
279 foreign_obj_type! {
280     type CType = CAMetalLayer;
281     pub struct CoreAnimationLayer;
282     pub struct CoreAnimationLayerRef;
283 }
284 
285 impl CoreAnimationLayer {
new() -> Self286     pub fn new() -> Self {
287         unsafe {
288             let class = class!(CAMetalLayer);
289             msg_send![class, new]
290         }
291     }
292 }
293 
294 impl CoreAnimationLayerRef {
set_device(&self, device: &DeviceRef)295     pub fn set_device(&self, device: &DeviceRef) {
296         unsafe { msg_send![self, setDevice: device] }
297     }
298 
pixel_format(&self) -> MTLPixelFormat299     pub fn pixel_format(&self) -> MTLPixelFormat {
300         unsafe { msg_send![self, pixelFormat] }
301     }
302 
set_pixel_format(&self, pixel_format: MTLPixelFormat)303     pub fn set_pixel_format(&self, pixel_format: MTLPixelFormat) {
304         unsafe { msg_send![self, setPixelFormat: pixel_format] }
305     }
306 
drawable_size(&self) -> CGSize307     pub fn drawable_size(&self) -> CGSize {
308         unsafe { msg_send![self, drawableSize] }
309     }
310 
set_drawable_size(&self, size: CGSize)311     pub fn set_drawable_size(&self, size: CGSize) {
312         unsafe { msg_send![self, setDrawableSize: size] }
313     }
314 
presents_with_transaction(&self) -> bool315     pub fn presents_with_transaction(&self) -> bool {
316         unsafe {
317             match msg_send![self, presentsWithTransaction] {
318                 YES => true,
319                 NO => false,
320                 _ => unreachable!(),
321             }
322         }
323     }
324 
set_presents_with_transaction(&self, transaction: bool)325     pub fn set_presents_with_transaction(&self, transaction: bool) {
326         unsafe { msg_send![self, setPresentsWithTransaction: transaction] }
327     }
328 
set_edge_antialiasing_mask(&self, mask: u64)329     pub fn set_edge_antialiasing_mask(&self, mask: u64) {
330         unsafe { msg_send![self, setEdgeAntialiasingMask: mask] }
331     }
332 
set_masks_to_bounds(&self, masks: bool)333     pub fn set_masks_to_bounds(&self, masks: bool) {
334         unsafe { msg_send![self, setMasksToBounds: masks] }
335     }
336 
remove_all_animations(&self)337     pub fn remove_all_animations(&self) {
338         unsafe { msg_send![self, removeAllAnimations] }
339     }
340 
next_drawable(&self) -> Option<&CoreAnimationDrawableRef>341     pub fn next_drawable(&self) -> Option<&CoreAnimationDrawableRef> {
342         unsafe { msg_send![self, nextDrawable] }
343     }
344 
set_contents_scale(&self, scale: CGFloat)345     pub fn set_contents_scale(&self, scale: CGFloat) {
346         unsafe { msg_send![self, setContentsScale: scale] }
347     }
348 }
349 
350 mod argument;
351 mod buffer;
352 mod capturemanager;
353 mod commandbuffer;
354 mod commandqueue;
355 mod constants;
356 mod depthstencil;
357 mod device;
358 mod drawable;
359 mod encoder;
360 mod heap;
361 mod library;
362 mod pipeline;
363 mod renderpass;
364 mod resource;
365 mod sampler;
366 mod texture;
367 mod types;
368 mod vertexdescriptor;
369 
370 pub use argument::*;
371 pub use buffer::*;
372 pub use capturemanager::*;
373 pub use commandbuffer::*;
374 pub use commandqueue::*;
375 pub use constants::*;
376 pub use depthstencil::*;
377 pub use device::*;
378 pub use drawable::*;
379 pub use encoder::*;
380 pub use heap::*;
381 pub use library::*;
382 pub use pipeline::*;
383 pub use renderpass::*;
384 pub use resource::*;
385 pub use sampler::*;
386 pub use texture::*;
387 pub use types::*;
388 pub use vertexdescriptor::*;
389 
390 #[inline]
obj_drop<T>(p: *mut T)391 unsafe fn obj_drop<T>(p: *mut T) {
392     msg_send![(p as *mut Object), release]
393 }
394 
395 #[inline]
obj_clone<T: 'static>(p: *mut T) -> *mut T396 unsafe fn obj_clone<T: 'static>(p: *mut T) -> *mut T {
397     msg_send![(p as *mut Object), retain]
398 }
399 
400 #[allow(non_camel_case_types)]
401 type c_size_t = usize;
402