Skip to main content

core_video/
opengl_buffer.rs

1use std::ptr::{null, null_mut};
2
3use core_foundation::{
4    base::{kCFAllocatorDefault, CFAllocatorRef, CFType, CFTypeID, TCFType},
5    declare_TCFType,
6    dictionary::{CFDictionary, CFDictionaryRef},
7    impl_CFTypeDescription, impl_TCFType,
8    string::{CFString, CFStringRef},
9};
10use libc::size_t;
11
12use crate::{
13    buffer::TCVBuffer,
14    image_buffer::{CVImageBufferRef, TCVImageBuffer},
15    r#return::{kCVReturnSuccess, CVReturn},
16    CGLContextObj, GLenum, GLint,
17};
18
19pub type CVOpenGLBufferRef = CVImageBufferRef;
20
21extern "C" {
22    pub static kCVOpenGLBufferWidth: CFStringRef;
23    pub static kCVOpenGLBufferHeight: CFStringRef;
24    pub static kCVOpenGLBufferTarget: CFStringRef;
25    pub static kCVOpenGLBufferInternalFormat: CFStringRef;
26    pub static kCVOpenGLBufferMaximumMipmapLevel: CFStringRef;
27
28    pub fn CVOpenGLBufferGetTypeID() -> CFTypeID;
29    pub fn CVOpenGLBufferRetain(buffer: CVOpenGLBufferRef) -> CVOpenGLBufferRef;
30    pub fn CVOpenGLBufferRelease(buffer: CVOpenGLBufferRef);
31    pub fn CVOpenGLBufferCreate(
32        allocator: CFAllocatorRef,
33        width: size_t,
34        height: size_t,
35        attributes: CFDictionaryRef,
36        bufferOut: *mut CVOpenGLBufferRef,
37    ) -> CVReturn;
38    pub fn CVOpenGLBufferGetAttributes(openGLBuffer: CVOpenGLBufferRef) -> CFDictionaryRef;
39    pub fn CVOpenGLBufferAttach(openGLBuffer: CVOpenGLBufferRef, cglContext: CGLContextObj, face: GLenum, level: GLint, screen: GLint) -> CVReturn;
40}
41
42pub enum CVOpenGLBufferKeys {
43    Width,
44    Height,
45    Target,
46    InternalFormat,
47    MaximumMipmapLevel,
48}
49
50impl From<CVOpenGLBufferKeys> for CFStringRef {
51    fn from(key: CVOpenGLBufferKeys) -> Self {
52        unsafe {
53            match key {
54                CVOpenGLBufferKeys::Width => kCVOpenGLBufferWidth,
55                CVOpenGLBufferKeys::Height => kCVOpenGLBufferHeight,
56                CVOpenGLBufferKeys::Target => kCVOpenGLBufferTarget,
57                CVOpenGLBufferKeys::InternalFormat => kCVOpenGLBufferInternalFormat,
58                CVOpenGLBufferKeys::MaximumMipmapLevel => kCVOpenGLBufferMaximumMipmapLevel,
59            }
60        }
61    }
62}
63
64impl From<CVOpenGLBufferKeys> for CFString {
65    fn from(key: CVOpenGLBufferKeys) -> Self {
66        unsafe { CFString::wrap_under_get_rule(CFStringRef::from(key)) }
67    }
68}
69
70declare_TCFType!(CVOpenGLBuffer, CVOpenGLBufferRef);
71impl_TCFType!(CVOpenGLBuffer, CVOpenGLBufferRef, CVOpenGLBufferGetTypeID);
72impl_CFTypeDescription!(CVOpenGLBuffer);
73
74impl TCVBuffer for CVOpenGLBuffer {}
75impl TCVImageBuffer for CVOpenGLBuffer {}
76
77impl CVOpenGLBuffer {
78    #[inline]
79    pub fn new(width: size_t, height: size_t, attributes: Option<&CFDictionary<CFString, CFType>>) -> Result<CVOpenGLBuffer, CVReturn> {
80        let mut buffer: CVOpenGLBufferRef = null_mut();
81        let status = unsafe {
82            CVOpenGLBufferCreate(kCFAllocatorDefault, width, height, attributes.map_or(null(), |attrs| attrs.as_concrete_TypeRef()), &mut buffer)
83        };
84        if status == kCVReturnSuccess {
85            Ok(unsafe { TCFType::wrap_under_create_rule(buffer) })
86        } else {
87            Err(status)
88        }
89    }
90
91    #[inline]
92    pub fn get_attributes(&self) -> Option<CFDictionary<CFString, CFType>> {
93        unsafe {
94            let attributes = CVOpenGLBufferGetAttributes(self.as_concrete_TypeRef());
95            if attributes.is_null() {
96                None
97            } else {
98                Some(TCFType::wrap_under_create_rule(attributes))
99            }
100        }
101    }
102
103    #[inline]
104    pub unsafe fn attach(&self, cgl_context: CGLContextObj, face: GLenum, level: GLint, screen: GLint) -> Result<(), CVReturn> {
105        let status = unsafe { CVOpenGLBufferAttach(self.as_concrete_TypeRef(), cgl_context, face, level, screen) };
106        if status == kCVReturnSuccess {
107            Ok(())
108        } else {
109            Err(status)
110        }
111    }
112}