Skip to main content

IOSurface

Struct IOSurface 

pub struct IOSurface(/* private fields */);
Expand description

Hardware-accelerated surface for efficient frame delivery

IOSurface is Apple’s cross-process framebuffer type. It provides:

  • Zero-copy sharing between processes
  • Direct GPU texture creation via Metal
  • Multi-planar format support (YCbCr, etc.)

§Memory Access Safety

The surface must be locked before accessing pixel data. Use lock to get a RAII guard that ensures proper locking/unlocking.

§Examples

use apple_cf::iosurface::{IOSurface, IOSurfaceLockOptions};

fn access_surface(surface: &IOSurface) -> Result<(), i32> {
    // Lock for read-only access
    let guard = surface.lock(IOSurfaceLockOptions::READ_ONLY)?;
     
    // Access pixel data through the guard
    let data = guard.as_slice();
    println!("Surface has {} bytes", data.len());
     
    // Surface automatically unlocked when guard drops
    Ok(())
}

Implementations§

§

impl IOSurface

pub fn create( width: usize, height: usize, pixel_format: u32, bytes_per_element: usize, ) -> Option<IOSurface>

Create a new IOSurface with the given dimensions and pixel format

§Arguments
  • width - Width in pixels
  • height - Height in pixels
  • pixel_format - Pixel format as a FourCC code (e.g., 0x42475241 for ‘BGRA’)
  • bytes_per_element - Bytes per pixel (e.g., 4 for BGRA)
§Returns

Some(IOSurface) if creation succeeded, None otherwise.

§Examples
use apple_cf::iosurface::IOSurface;

// Create a 100x100 BGRA IOSurface
let surface = IOSurface::create(100, 100, 0x42475241, 4)
    .expect("Failed to create IOSurface");
assert_eq!(surface.width(), 100);
assert_eq!(surface.height(), 100);

pub fn create_with_properties( width: usize, height: usize, pixel_format: u32, bytes_per_element: usize, bytes_per_row: usize, alloc_size: usize, planes: Option<&[PlaneProperties]>, ) -> Option<IOSurface>

Create an IOSurface with full properties including multi-planar support

This is the general API for creating IOSurfaces with any pixel format, including multi-planar formats like YCbCr 4:2:0.

§Arguments
  • width - Width in pixels
  • height - Height in pixels
  • pixel_format - Pixel format as FourCC (e.g., 0x42475241 for BGRA)
  • bytes_per_element - Bytes per pixel element
  • bytes_per_row - Bytes per row (should be 16-byte aligned for Metal)
  • alloc_size - Total allocation size in bytes
  • planes - Optional slice of plane info for multi-planar formats
§Examples
use apple_cf::iosurface::PlaneProperties;
use apple_cf::iosurface::IOSurface;

// Create a YCbCr 420v biplanar surface
let width = 1920usize;
let height = 1080usize;
let plane0_bpr = (width + 15) & !15;  // 16-byte aligned
let plane1_bpr = (width + 15) & !15;
let plane0_size = plane0_bpr * height;
let plane1_size = plane1_bpr * (height / 2);

let planes = [
    PlaneProperties {
        width,
        height,
        bytes_per_row: plane0_bpr,
        bytes_per_element: 1,
        offset: 0,
        size: plane0_size,
    },
    PlaneProperties {
        width: width / 2,
        height: height / 2,
        bytes_per_row: plane1_bpr,
        bytes_per_element: 2,
        offset: plane0_size,
        size: plane1_size,
    },
];

let surface = IOSurface::create_with_properties(
    width,
    height,
    0x34323076,  // '420v'
    1,
    plane0_bpr,
    plane0_size + plane1_size,
    Some(&planes),
);

pub fn from_raw(ptr: *mut c_void) -> Option<IOSurface>

Wraps a +1 retained IOSurfaceRef and returns None for null.

pub const unsafe fn from_ptr(ptr: *mut c_void) -> IOSurface

Wraps a raw IOSurfaceRef by taking ownership without retaining it.

§Safety

The caller must ensure ptr is a valid +1 retained IOSurfaceRef.

pub const fn as_ptr(&self) -> *mut c_void

Get the raw pointer

pub fn width(&self) -> usize

Get the width of the surface in pixels

pub fn height(&self) -> usize

Get the height of the surface in pixels

pub fn bytes_per_row(&self) -> usize

Get the bytes per row of the surface

pub fn alloc_size(&self) -> usize

Get the total allocation size of the surface in bytes

pub fn data_size(&self) -> usize

Get the data size of the surface in bytes (alias for alloc_size)

This method provides API parity with CVPixelBuffer::data_size().

pub fn pixel_format(&self) -> u32

Get the pixel format of the surface (OSType/FourCC)

pub fn id(&self) -> u32

Get the unique IOSurfaceID for this surface

pub fn seed(&self) -> u32

Get the modification seed value

This value changes each time the surface is modified, useful for detecting whether the surface contents have changed.

pub fn plane_count(&self) -> usize

Get the number of planes in this surface

Multi-planar formats like YCbCr 420 have multiple planes:

  • Plane 0: Y (luminance)
  • Plane 1: CbCr (chrominance)

Single-plane formats like BGRA return 0.

pub fn width_of_plane(&self, plane_index: usize) -> usize

Get the width of a specific plane

For YCbCr 4:2:0 formats, plane 1 (CbCr) is half the width of plane 0 (Y).

pub fn height_of_plane(&self, plane_index: usize) -> usize

Get the height of a specific plane

For YCbCr 4:2:0 formats, plane 1 (CbCr) is half the height of plane 0 (Y).

pub fn bytes_per_row_of_plane(&self, plane_index: usize) -> usize

Get the bytes per row of a specific plane

pub fn bytes_per_element(&self) -> usize

Get the bytes per element of the surface

pub fn element_width(&self) -> usize

Get the element width of the surface

pub fn element_height(&self) -> usize

Get the element height of the surface

pub fn is_in_use(&self) -> bool

Check if the surface is currently in use

pub fn increment_use_count(&self)

Increment the use count of the surface

pub fn decrement_use_count(&self)

Decrement the use count of the surface

pub fn lock_raw(&self, options: IOSurfaceLockOptions) -> Result<u32, i32>

Lock the surface for CPU access (low-level API)

Prefer using lock for RAII-style access.

§Arguments
  • options - Lock options (e.g., IOSurfaceLockOptions::READ_ONLY)
§Errors

Returns kern_return_t error code if the lock fails.

pub fn unlock_raw(&self, options: IOSurfaceLockOptions) -> Result<u32, i32>

Unlock the surface after CPU access (low-level API)

§Arguments
  • options - Must match the options used in the corresponding lock_raw() call
§Errors

Returns kern_return_t error code if the unlock fails.

pub fn lock( &self, options: IOSurfaceLockOptions, ) -> Result<IOSurfaceLockGuard<'_>, i32>

Lock the surface and return a guard for RAII-style access

This is the recommended way to access surface memory. The guard ensures the surface is properly unlocked when it goes out of scope.

§Arguments
  • options - Lock options (e.g., IOSurfaceLockOptions::READ_ONLY)
§Errors

Returns kern_return_t error code if the lock fails.

§Examples
use apple_cf::iosurface::{IOSurface, IOSurfaceLockOptions};

fn read_surface(surface: &IOSurface) -> Result<(), i32> {
    let guard = surface.lock(IOSurfaceLockOptions::READ_ONLY)?;
    let data = guard.as_slice();
    println!("Read {} bytes", data.len());
    Ok(())
}

pub fn lock_read_only(&self) -> Result<IOSurfaceLockGuard<'_>, i32>

Lock the surface for read-only access

This is a convenience method equivalent to lock(IOSurfaceLockOptions::READ_ONLY).

§Errors

Returns kern_return_t error code if the lock fails.

pub fn lock_read_write(&self) -> Result<IOSurfaceLockGuard<'_>, i32>

Lock the surface for read-write access

This is a convenience method equivalent to lock(IOSurfaceLockOptions::NONE).

§Errors

Returns kern_return_t error code if the lock fails.

Trait Implementations§

§

impl Clone for IOSurface

§

fn clone(&self) -> IOSurface

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
§

impl Debug for IOSurface

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
§

impl Display for IOSurface

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
§

impl Drop for IOSurface

§

fn drop(&mut self)

Executes the destructor for this type. Read more
§

impl Hash for IOSurface

§

fn hash<H>(&self, state: &mut H)
where H: Hasher,

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl IOSurfaceMetalExt for IOSurface

Source§

fn info(&self) -> IOSurfaceInfo

Get detailed information about this IOSurface for Metal texture creation

Source§

fn is_ycbcr_biplanar(&self) -> bool

Check if this IOSurface uses a YCbCr biplanar format

Source§

fn texture_params(&self) -> Vec<TextureParams>

Get texture parameters for creating Metal textures from this IOSurface

Returns texture parameters for each plane needed to render this surface.

  • Single-plane formats (BGRA, L10R): Returns 1 texture param
  • YCbCr biplanar formats: Returns 2 texture params (Y and CbCr planes)
Source§

fn metal_textures<T, F>(&self, create_texture: F) -> Option<CapturedTextures<T>>

Create Metal textures from this IOSurface using a closure

This is a zero-copy operation - the textures share memory with the IOSurface.

The closure receives TextureParams and the raw IOSurfaceRef pointer, and should return the created texture.

§Example
use screencapturekit::cm::IOSurface;
use screencapturekit::metal::IOSurfaceMetalExt;
use std::ffi::c_void;

fn example(surface: &IOSurface) {
    let textures = surface.metal_textures(|params, _iosurface_ptr| {
        // Create Metal texture using params.width, params.height, params.format
        // Return Some(texture) or None
        Some(()) // placeholder
    });

    if let Some(textures) = textures {
        if textures.is_ycbcr() {
            // Use YCbCr shader with plane0 (Y) and plane1 (CbCr)
        }
    }
}
§Safety

The closure receives a raw IOSurfaceRef pointer. The pointer is valid for the duration of the closure call.

Source§

fn create_metal_textures( &self, device: &MetalDevice, ) -> Option<MetalCapturedTextures>

Create Metal textures from this IOSurface using the provided device

This is a zero-copy operation - the textures share memory with the IOSurface.

§Example
use screencapturekit::metal::{IOSurfaceMetalExt, MetalDevice};
use screencapturekit::cm::IOSurface;

fn example(surface: &IOSurface) {
    let device = MetalDevice::system_default().expect("No Metal device");
    if let Some(textures) = surface.create_metal_textures(&device) {
        if textures.is_ycbcr() {
            // Use YCbCr shader with plane0 (Y) and plane1 (CbCr)
        }
    }
}
§

impl PartialEq for IOSurface

§

fn eq(&self, other: &IOSurface) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
§

impl Eq for IOSurface

§

impl Send for IOSurface

§

impl Sync for IOSurface

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.