-
Notifications
You must be signed in to change notification settings - Fork 79
Expand file tree
/
Copy pathbuffer.rs
More file actions
92 lines (83 loc) · 2.72 KB
/
buffer.rs
File metadata and controls
92 lines (83 loc) · 2.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
use core_foundation::{
base::TCFType, boolean::CFBoolean, dictionary::CFDictionary, number::CFNumber, string::CFString,
};
use io_surface::{
kIOSurfaceBytesPerElement, kIOSurfaceBytesPerRow, kIOSurfaceHeight, kIOSurfacePixelFormat,
kIOSurfaceWidth, IOSurface, IOSurfaceRef,
};
use std::{ffi::c_int, slice};
#[link(name = "IOSurface", kind = "framework")]
extern "C" {
fn IOSurfaceGetBaseAddress(buffer: IOSurfaceRef) -> *mut u8;
fn IOSurfaceGetBytesPerRow(buffer: IOSurfaceRef) -> usize;
fn IOSurfaceLock(buffer: IOSurfaceRef, options: u32, seed: *mut u32) -> c_int;
fn IOSurfaceUnlock(buffer: IOSurfaceRef, options: u32, seed: *mut u32) -> c_int;
}
pub struct Buffer {
io_surface: IOSurface,
ptr: *mut u32,
stride: usize,
len: usize,
}
impl Buffer {
pub fn new(width: i32, height: i32) -> Self {
let properties = unsafe {
CFDictionary::from_CFType_pairs(&[
(
CFString::wrap_under_get_rule(kIOSurfaceWidth),
CFNumber::from(width).as_CFType(),
),
(
CFString::wrap_under_get_rule(kIOSurfaceHeight),
CFNumber::from(height).as_CFType(),
),
(
CFString::wrap_under_get_rule(kIOSurfaceBytesPerElement),
CFNumber::from(4).as_CFType(),
),
(
CFString::wrap_under_get_rule(kIOSurfacePixelFormat),
CFNumber::from(i32::from_be_bytes(*b"BGRA")).as_CFType(),
),
])
};
let io_surface = io_surface::new(&properties);
let ptr = unsafe { IOSurfaceGetBaseAddress(io_surface.obj) } as *mut u32;
let stride = unsafe { IOSurfaceGetBytesPerRow(io_surface.obj) } / 4;
let len = stride * height as usize;
Self {
io_surface,
ptr,
stride,
len,
}
}
pub fn as_ptr(&self) -> IOSurfaceRef {
self.io_surface.obj
}
#[inline]
pub fn stride(&self) -> usize {
self.stride
}
pub unsafe fn lock(&mut self) {
let mut seed = 0;
unsafe {
IOSurfaceLock(self.io_surface.obj, 0, &mut seed);
}
}
pub unsafe fn unlock(&mut self) {
let mut seed = 0;
unsafe {
IOSurfaceUnlock(self.io_surface.obj, 0, &mut seed);
}
}
// TODO: We can assume alignment, right?
#[inline]
pub unsafe fn pixels_ref(&self) -> &[u32] {
unsafe { slice::from_raw_parts(self.ptr, self.len) }
}
#[inline]
pub unsafe fn pixels_mut(&self) -> &mut [u32] {
unsafe { slice::from_raw_parts_mut(self.ptr, self.len) }
}
}