core_video/
opengl_buffer.rs

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