1#![crate_name = "io_surface"]
11#![crate_type = "rlib"]
12
13use cgl::{kCGLNoError, CGLErrorString, CGLGetCurrentContext, CGLTexImageIOSurface2D, GLenum};
16use core_foundation::base::{CFRelease, CFRetain, CFType, CFTypeID, CFTypeRef, TCFType};
17use core_foundation::dictionary::{CFDictionary, CFDictionaryRef};
18use core_foundation::string::{CFString, CFStringRef};
19use core_foundation_sys::base::mach_port_t;
20use leaky_cow::LeakyCow;
21use libc::{c_int, size_t};
22use std::ffi::CStr;
23use std::os::raw::c_void;
24use std::slice;
25
26const BGRA: GLenum = 0x80E1;
27const RGBA: GLenum = 0x1908;
28const RGB: GLenum = 0x1907;
29const TEXTURE_RECTANGLE_ARB: GLenum = 0x84F5;
30const UNSIGNED_INT_8_8_8_8_REV: GLenum = 0x8367;
31
32#[allow(non_snake_case, non_upper_case_globals)]
33pub mod IOSurfaceLockOptions {
34 pub const kIOSurfaceLockReadOnly: u32 = 0x00000001;
35 pub const kIOSurfaceLockAvoidSync: u32 = 0x00000002;
36}
37
38type IOReturn = c_int;
39
40#[repr(C)]
41pub struct __IOSurface(c_void);
42
43pub type IOSurfaceRef = *const __IOSurface;
44
45pub struct IOSurface {
46 pub obj: IOSurfaceRef,
47}
48
49impl Drop for IOSurface {
50 fn drop(&mut self) {
51 unsafe { CFRelease(self.as_CFTypeRef()) }
52 }
53}
54
55pub type IOSurfaceID = u32;
56
57impl Clone for IOSurface {
58 #[inline]
59 fn clone(&self) -> IOSurface {
60 unsafe { TCFType::wrap_under_get_rule(self.obj) }
61 }
62}
63
64impl TCFType for IOSurface {
65 type Ref = IOSurfaceRef;
66
67 #[inline]
68 fn as_concrete_TypeRef(&self) -> IOSurfaceRef {
69 self.obj
70 }
71
72 #[inline]
73 unsafe fn wrap_under_create_rule(obj: IOSurfaceRef) -> IOSurface {
74 assert!(!obj.is_null(), "Attempted to create a NULL object.");
75 IOSurface { obj }
76 }
77
78 #[inline]
79 fn type_id() -> CFTypeID {
80 unsafe { IOSurfaceGetTypeID() }
81 }
82
83 #[inline]
84 fn as_CFTypeRef(&self) -> CFTypeRef {
85 self.as_concrete_TypeRef() as CFTypeRef
86 }
87
88 #[inline]
89 unsafe fn wrap_under_get_rule(reference: IOSurfaceRef) -> IOSurface {
90 assert!(!reference.is_null(), "Attempted to create a NULL object.");
91 let reference = CFRetain(reference as *const c_void) as IOSurfaceRef;
92 TCFType::wrap_under_create_rule(reference)
93 }
94}
95
96pub fn new(properties: &CFDictionary<CFString, CFType>) -> IOSurface {
97 unsafe { TCFType::wrap_under_create_rule(IOSurfaceCreate(properties.as_concrete_TypeRef())) }
98}
99
100pub fn lookup(csid: IOSurfaceID) -> IOSurface {
104 unsafe { TCFType::wrap_under_create_rule(IOSurfaceLookup(csid)) }
105}
106
107impl IOSurface {
108 pub fn get_id(&self) -> IOSurfaceID {
109 unsafe { IOSurfaceGetID(self.as_concrete_TypeRef()) }
110 }
111
112 pub fn bind_to_gl_texture(&self, width: i32, height: i32, has_alpha: bool) {
114 unsafe {
115 let context = CGLGetCurrentContext();
116 let gl_error = CGLTexImageIOSurface2D(
117 context,
118 TEXTURE_RECTANGLE_ARB,
119 if has_alpha {
120 RGBA as GLenum
121 } else {
122 RGB as GLenum
123 },
124 width,
125 height,
126 BGRA as GLenum,
127 UNSIGNED_INT_8_8_8_8_REV,
128 self.as_concrete_TypeRef() as *mut libc::c_void,
129 0,
130 );
131
132 if gl_error != kCGLNoError {
133 let error_msg = CStr::from_ptr(CGLErrorString(gl_error));
134 let error_msg = error_msg.to_string_lossy();
135 panic!("{}", error_msg.leak());
138 }
139 }
140 }
141
142 pub fn upload(&self, data: &[u8]) {
143 unsafe {
144 let surface = self.as_concrete_TypeRef();
145 let mut seed = 0;
146
147 IOSurfaceLock(surface, 0, &mut seed);
148
149 let height = IOSurfaceGetHeight(surface);
150 let stride = IOSurfaceGetBytesPerRow(surface);
151 let size = height * stride;
152 let address = IOSurfaceGetBaseAddress(surface) as *mut u8;
153 let dest: &mut [u8] = slice::from_raw_parts_mut(address, size);
154 dest.clone_from_slice(data);
155
156 IOSurfaceUnlock(surface, 0, &mut seed);
158 }
159 }
160}
161
162#[cfg_attr(feature = "link", link(name = "IOSurface", kind = "framework"))]
163extern "C" {
164 pub static kIOSurfaceAllocSize: CFStringRef;
165 pub static kIOSurfaceWidth: CFStringRef;
166 pub static kIOSurfaceHeight: CFStringRef;
167 pub static kIOSurfaceBytesPerRow: CFStringRef;
168 pub static kIOSurfaceBytesPerElement: CFStringRef;
169 pub static kIOSurfaceElementWidth: CFStringRef;
170 pub static kIOSurfaceElementHeight: CFStringRef;
171 pub static kIOSurfaceOffset: CFStringRef;
172
173 pub static kIOSurfacePlaneInfo: CFStringRef;
174 pub static kIOSurfacePlaneWidth: CFStringRef;
175 pub static kIOSurfacePlaneHeight: CFStringRef;
176 pub static kIOSurfacePlaneBytesPerRow: CFStringRef;
177 pub static kIOSurfacePlaneOffset: CFStringRef;
178 pub static kIOSurfacePlaneSize: CFStringRef;
179
180 pub static kIOSurfacePlaneBase: CFStringRef;
181 pub static kIOSurfacePlaneBytesPerElement: CFStringRef;
182 pub static kIOSurfacePlaneElementWidth: CFStringRef;
183 pub static kIOSurfacePlaneElementHeight: CFStringRef;
184
185 pub static kIOSurfaceCacheMode: CFStringRef;
186 pub static kIOSurfaceIsGlobal: CFStringRef;
187 pub static kIOSurfacePixelFormat: CFStringRef;
188
189 pub fn IOSurfaceCreate(properties: CFDictionaryRef) -> IOSurfaceRef;
190 pub fn IOSurfaceLookup(csid: IOSurfaceID) -> IOSurfaceRef;
191 pub fn IOSurfaceGetID(buffer: IOSurfaceRef) -> IOSurfaceID;
192
193 pub fn IOSurfaceGetTypeID() -> CFTypeID;
194
195 pub fn IOSurfaceLock(buffer: IOSurfaceRef, options: u32, seed: *mut u32) -> IOReturn;
196 pub fn IOSurfaceUnlock(buffer: IOSurfaceRef, options: u32, seed: *mut u32) -> IOReturn;
197 pub fn IOSurfaceGetSeed(buffer: IOSurfaceRef) -> u32;
198
199 pub fn IOSurfaceGetHeight(buffer: IOSurfaceRef) -> size_t;
200 pub fn IOSurfaceGetWidth(buffer: IOSurfaceRef) -> usize;
201 pub fn IOSurfaceGetBytesPerRow(buffer: IOSurfaceRef) -> size_t;
202 pub fn IOSurfaceGetBaseAddress(buffer: IOSurfaceRef) -> *mut c_void;
203 pub fn IOSurfaceGetElementHeight(buffer: IOSurfaceRef) -> usize;
204 pub fn IOSurfaceGetElementWidth(buffer: IOSurfaceRef) -> usize;
205 pub fn IOSurfaceGetBytesPerElement(buffer: IOSurfaceRef) -> usize;
206 pub fn IOSurfaceGetAllocSize(buffer: IOSurfaceRef) -> usize;
207
208 pub fn IOSurfaceGetPixelFormat(buffer: IOSurfaceRef) -> i32;
209
210 pub fn IOSurfaceGetUseCount(buffer: IOSurfaceRef) -> i32;
211 pub fn IOSurfaceIncrementUseCount(buffer: IOSurfaceRef);
212 pub fn IOSurfaceDecrementUseCount(buffer: IOSurfaceRef);
213 pub fn IOSurfaceIsInUse(buffer: IOSurfaceRef) -> bool;
214
215 pub fn IOSurfaceCreateMachPort(buffer: IOSurfaceRef) -> mach_port_t;
216 pub fn IOSurfaceLookupFromMachPort(port: mach_port_t) -> IOSurfaceRef;
217
218 pub fn IOSurfaceGetPropertyAlignment(property: CFStringRef) -> usize;
219 pub fn IOSurfaceGetPropertyMaximum(property: CFStringRef) -> usize;
220
221 pub fn IOSurfaceCopyValue(buffer: IOSurfaceRef, key: CFStringRef) -> CFTypeRef;
222 pub fn IOSurfaceRemoveValue(buffer: IOSurfaceRef, key: CFStringRef);
223 pub fn IOSurfaceSetValue(buffer: IOSurfaceRef, key: CFStringRef, value: CFTypeRef);
224
225 pub fn IOSurfaceGetBaseAddressOfPlane(buffer: IOSurfaceRef, plane_index: usize) -> *mut c_void;
226 pub fn IOSurfaceGetBytesPerElementOfPlane(buffer: IOSurfaceRef, plane_index: usize) -> usize;
227 pub fn IOSurfaceGetBytesPerRowOfPlane(buffer: IOSurfaceRef, plane_index: usize) -> usize;
228 pub fn IOSurfaceGetElementHeightOfPlane(buffer: IOSurfaceRef, plane_index: usize) -> usize;
229 pub fn IOSurfaceGetElementWidthOfPlane(buffer: IOSurfaceRef, plane_index: usize) -> usize;
230 pub fn IOSurfaceGetHeightOfPlane(buffer: IOSurfaceRef, plane_index: usize) -> usize;
231 pub fn IOSurfaceGetWidthOfPlane(buffer: IOSurfaceRef, plane_index: usize) -> usize;
232}