io_surface/
lib.rs

1// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution.
3//
4// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7// option. This file may not be copied, modified, or distributed
8// except according to those terms.
9
10//! This crate has been deprecated in favour of the `objc2-io-surface` crate.
11#![deprecated = "use the objc2-io-surface crate instead"]
12#![crate_name = "io_surface"]
13#![crate_type = "rlib"]
14
15// Rust bindings to the IOSurface framework on macOS.
16
17use cgl::{kCGLNoError, CGLErrorString, CGLGetCurrentContext, CGLTexImageIOSurface2D, GLenum};
18use core::ffi::{c_int, c_void};
19use core_foundation::base::{CFRelease, CFRetain, CFType, CFTypeID, CFTypeRef, TCFType};
20use core_foundation::dictionary::{CFDictionary, CFDictionaryRef};
21use core_foundation::string::{CFString, CFStringRef};
22use core_foundation_sys::base::mach_port_t;
23use leaky_cow::LeakyCow;
24use std::ffi::CStr;
25use std::slice;
26
27const BGRA: GLenum = 0x80E1;
28const RGBA: GLenum = 0x1908;
29const RGB: GLenum = 0x1907;
30const TEXTURE_RECTANGLE_ARB: GLenum = 0x84F5;
31const UNSIGNED_INT_8_8_8_8_REV: GLenum = 0x8367;
32
33#[allow(non_snake_case, non_upper_case_globals)]
34pub mod IOSurfaceLockOptions {
35    pub const kIOSurfaceLockReadOnly: u32 = 0x00000001;
36    pub const kIOSurfaceLockAvoidSync: u32 = 0x00000002;
37}
38
39type IOReturn = c_int;
40
41#[repr(C)]
42pub struct __IOSurface(c_void);
43
44pub type IOSurfaceRef = *const __IOSurface;
45
46pub struct IOSurface {
47    pub obj: IOSurfaceRef,
48}
49
50impl Drop for IOSurface {
51    fn drop(&mut self) {
52        unsafe { CFRelease(self.as_CFTypeRef()) }
53    }
54}
55
56pub type IOSurfaceID = u32;
57
58impl Clone for IOSurface {
59    #[inline]
60    fn clone(&self) -> IOSurface {
61        unsafe { TCFType::wrap_under_get_rule(self.obj) }
62    }
63}
64
65impl TCFType for IOSurface {
66    type Ref = IOSurfaceRef;
67
68    #[inline]
69    fn as_concrete_TypeRef(&self) -> IOSurfaceRef {
70        self.obj
71    }
72
73    #[inline]
74    unsafe fn wrap_under_create_rule(obj: IOSurfaceRef) -> IOSurface {
75        assert!(!obj.is_null(), "Attempted to create a NULL object.");
76        IOSurface { obj }
77    }
78
79    #[inline]
80    fn type_id() -> CFTypeID {
81        unsafe { IOSurfaceGetTypeID() }
82    }
83
84    #[inline]
85    fn as_CFTypeRef(&self) -> CFTypeRef {
86        self.as_concrete_TypeRef() as CFTypeRef
87    }
88
89    #[inline]
90    unsafe fn wrap_under_get_rule(reference: IOSurfaceRef) -> IOSurface {
91        assert!(!reference.is_null(), "Attempted to create a NULL object.");
92        let reference = CFRetain(reference as *const c_void) as IOSurfaceRef;
93        TCFType::wrap_under_create_rule(reference)
94    }
95}
96
97pub fn new(properties: &CFDictionary<CFString, CFType>) -> IOSurface {
98    unsafe { TCFType::wrap_under_create_rule(IOSurfaceCreate(properties.as_concrete_TypeRef())) }
99}
100
101/// Looks up an `IOSurface` by its global ID.
102///
103/// FIXME(pcwalton): This should return an `Option`.
104pub fn lookup(csid: IOSurfaceID) -> IOSurface {
105    unsafe { TCFType::wrap_under_create_rule(IOSurfaceLookup(csid)) }
106}
107
108impl IOSurface {
109    pub fn get_id(&self) -> IOSurfaceID {
110        unsafe { IOSurfaceGetID(self.as_concrete_TypeRef()) }
111    }
112
113    /// Binds to the current GL texture.
114    pub fn bind_to_gl_texture(&self, width: i32, height: i32, has_alpha: bool) {
115        unsafe {
116            let context = CGLGetCurrentContext();
117            let gl_error = CGLTexImageIOSurface2D(
118                context,
119                TEXTURE_RECTANGLE_ARB,
120                if has_alpha {
121                    RGBA as GLenum
122                } else {
123                    RGB as GLenum
124                },
125                width,
126                height,
127                BGRA as GLenum,
128                UNSIGNED_INT_8_8_8_8_REV,
129                self.as_concrete_TypeRef() as *mut c_void,
130                0,
131            );
132
133            if gl_error != kCGLNoError {
134                let error_msg = CStr::from_ptr(CGLErrorString(gl_error));
135                let error_msg = error_msg.to_string_lossy();
136                // This will only actually leak memory if error_msg is a `Cow::Owned`, which
137                // will only happen if the platform gives us invalid unicode.
138                panic!("{}", error_msg.leak());
139            }
140        }
141    }
142
143    pub fn upload(&self, data: &[u8]) {
144        unsafe {
145            let surface = self.as_concrete_TypeRef();
146            let mut seed = 0;
147
148            IOSurfaceLock(surface, 0, &mut seed);
149
150            let height = IOSurfaceGetHeight(surface);
151            let stride = IOSurfaceGetBytesPerRow(surface);
152            let size = height * stride;
153            let address = IOSurfaceGetBaseAddress(surface) as *mut u8;
154            let dest: &mut [u8] = slice::from_raw_parts_mut(address, size);
155            dest.clone_from_slice(data);
156
157            // FIXME(pcwalton): RAII
158            IOSurfaceUnlock(surface, 0, &mut seed);
159        }
160    }
161}
162
163#[cfg_attr(feature = "link", link(name = "IOSurface", kind = "framework"))]
164extern "C" {
165    pub static kIOSurfaceAllocSize: CFStringRef;
166    pub static kIOSurfaceWidth: CFStringRef;
167    pub static kIOSurfaceHeight: CFStringRef;
168    pub static kIOSurfaceBytesPerRow: CFStringRef;
169    pub static kIOSurfaceBytesPerElement: CFStringRef;
170    pub static kIOSurfaceElementWidth: CFStringRef;
171    pub static kIOSurfaceElementHeight: CFStringRef;
172    pub static kIOSurfaceOffset: CFStringRef;
173
174    pub static kIOSurfacePlaneInfo: CFStringRef;
175    pub static kIOSurfacePlaneWidth: CFStringRef;
176    pub static kIOSurfacePlaneHeight: CFStringRef;
177    pub static kIOSurfacePlaneBytesPerRow: CFStringRef;
178    pub static kIOSurfacePlaneOffset: CFStringRef;
179    pub static kIOSurfacePlaneSize: CFStringRef;
180
181    pub static kIOSurfacePlaneBase: CFStringRef;
182    pub static kIOSurfacePlaneBytesPerElement: CFStringRef;
183    pub static kIOSurfacePlaneElementWidth: CFStringRef;
184    pub static kIOSurfacePlaneElementHeight: CFStringRef;
185
186    pub static kIOSurfaceCacheMode: CFStringRef;
187    pub static kIOSurfaceIsGlobal: CFStringRef;
188    pub static kIOSurfacePixelFormat: CFStringRef;
189
190    pub fn IOSurfaceCreate(properties: CFDictionaryRef) -> IOSurfaceRef;
191    pub fn IOSurfaceLookup(csid: IOSurfaceID) -> IOSurfaceRef;
192    pub fn IOSurfaceGetID(buffer: IOSurfaceRef) -> IOSurfaceID;
193
194    pub fn IOSurfaceGetTypeID() -> CFTypeID;
195
196    pub fn IOSurfaceLock(buffer: IOSurfaceRef, options: u32, seed: *mut u32) -> IOReturn;
197    pub fn IOSurfaceUnlock(buffer: IOSurfaceRef, options: u32, seed: *mut u32) -> IOReturn;
198    pub fn IOSurfaceGetSeed(buffer: IOSurfaceRef) -> u32;
199
200    pub fn IOSurfaceGetHeight(buffer: IOSurfaceRef) -> usize;
201    pub fn IOSurfaceGetWidth(buffer: IOSurfaceRef) -> usize;
202    pub fn IOSurfaceGetBytesPerRow(buffer: IOSurfaceRef) -> usize;
203    pub fn IOSurfaceGetBaseAddress(buffer: IOSurfaceRef) -> *mut c_void;
204    pub fn IOSurfaceGetElementHeight(buffer: IOSurfaceRef) -> usize;
205    pub fn IOSurfaceGetElementWidth(buffer: IOSurfaceRef) -> usize;
206    pub fn IOSurfaceGetBytesPerElement(buffer: IOSurfaceRef) -> usize;
207    pub fn IOSurfaceGetAllocSize(buffer: IOSurfaceRef) -> usize;
208
209    pub fn IOSurfaceGetPixelFormat(buffer: IOSurfaceRef) -> i32;
210
211    pub fn IOSurfaceGetUseCount(buffer: IOSurfaceRef) -> i32;
212    pub fn IOSurfaceIncrementUseCount(buffer: IOSurfaceRef);
213    pub fn IOSurfaceDecrementUseCount(buffer: IOSurfaceRef);
214    pub fn IOSurfaceIsInUse(buffer: IOSurfaceRef) -> bool;
215
216    pub fn IOSurfaceCreateMachPort(buffer: IOSurfaceRef) -> mach_port_t;
217    pub fn IOSurfaceLookupFromMachPort(port: mach_port_t) -> IOSurfaceRef;
218
219    pub fn IOSurfaceGetPropertyAlignment(property: CFStringRef) -> usize;
220    pub fn IOSurfaceGetPropertyMaximum(property: CFStringRef) -> usize;
221
222    pub fn IOSurfaceCopyValue(buffer: IOSurfaceRef, key: CFStringRef) -> CFTypeRef;
223    pub fn IOSurfaceRemoveValue(buffer: IOSurfaceRef, key: CFStringRef);
224    pub fn IOSurfaceSetValue(buffer: IOSurfaceRef, key: CFStringRef, value: CFTypeRef);
225
226    pub fn IOSurfaceGetBaseAddressOfPlane(buffer: IOSurfaceRef, plane_index: usize) -> *mut c_void;
227    pub fn IOSurfaceGetBytesPerElementOfPlane(buffer: IOSurfaceRef, plane_index: usize) -> usize;
228    pub fn IOSurfaceGetBytesPerRowOfPlane(buffer: IOSurfaceRef, plane_index: usize) -> usize;
229    pub fn IOSurfaceGetElementHeightOfPlane(buffer: IOSurfaceRef, plane_index: usize) -> usize;
230    pub fn IOSurfaceGetElementWidthOfPlane(buffer: IOSurfaceRef, plane_index: usize) -> usize;
231    pub fn IOSurfaceGetHeightOfPlane(buffer: IOSurfaceRef, plane_index: usize) -> usize;
232    pub fn IOSurfaceGetWidthOfPlane(buffer: IOSurfaceRef, plane_index: usize) -> usize;
233}