core_video/
opengl_buffer.rs1use 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}