use std::ptr::{null, null_mut};
use core_foundation::{
base::{kCFAllocatorDefault, CFAllocatorRef, CFType, TCFType},
dictionary::{CFDictionary, CFDictionaryRef},
string::CFStringRef,
};
use io_surface::IOSurface;
use crate::{
io_surface::IOSurfaceRef,
pixel_buffer::{CVPixelBuffer, CVPixelBufferRef},
return_::{kCVReturnSuccess, CVReturn},
};
extern "C" {
pub static kCVPixelBufferIOSurfaceOpenGLTextureCompatibilityKey: CFStringRef;
pub static kCVPixelBufferIOSurfaceOpenGLFBOCompatibilityKey: CFStringRef;
pub static kCVPixelBufferIOSurfaceCoreAnimationCompatibilityKey: CFStringRef;
pub static kCVPixelBufferIOSurfaceOpenGLESTextureCompatibilityKey: CFStringRef;
pub static kCVPixelBufferIOSurfaceOpenGLESFBOCompatibilityKey: CFStringRef;
pub fn CVPixelBufferGetIOSurface(pixelBuffer: CVPixelBufferRef) -> IOSurfaceRef;
pub fn CVPixelBufferCreateWithIOSurface(
allocator: CFAllocatorRef,
surface: IOSurfaceRef,
pixelBufferAttributes: CFDictionaryRef,
pixelBufferOut: *mut CVPixelBufferRef,
) -> CVReturn;
}
impl CVPixelBuffer {
pub fn from_io_surface(io_surface: &IOSurface, options: Option<&CFDictionary<CFType, CFType>>) -> Result<CVPixelBuffer, CVReturn> {
let mut pixel_buffer: CVPixelBufferRef = null_mut();
let status = unsafe {
CVPixelBufferCreateWithIOSurface(
kCFAllocatorDefault,
io_surface.as_concrete_TypeRef(),
options.map_or(null(), |options| options.as_concrete_TypeRef()),
&mut pixel_buffer,
)
};
if status == kCVReturnSuccess {
Ok(unsafe { TCFType::wrap_under_create_rule(pixel_buffer) })
} else {
Err(status)
}
}
pub fn get_io_surface(&self) -> Option<IOSurface> {
unsafe {
let surface = CVPixelBufferGetIOSurface(self.as_concrete_TypeRef());
if surface.is_null() {
None
} else {
Some(TCFType::wrap_under_create_rule(surface))
}
}
}
}