Skip to main content

core_video/
opengl_texture_cache.rs

1use std::ptr::{null, null_mut};
2
3use core_foundation::{
4    base::{kCFAllocatorDefault, CFAllocatorRef, CFType, CFTypeID, TCFType},
5    dictionary::{CFDictionary, CFDictionaryRef},
6    impl_CFTypeDescription, impl_TCFType,
7    string::{CFString, CFStringRef},
8};
9use libc::c_void;
10
11use crate::{
12    base::CVOptionFlags,
13    image_buffer::{CVImageBuffer, CVImageBufferRef},
14    opengl_texture::{CVOpenGLTexture, CVOpenGLTextureRef},
15    r#return::{kCVReturnSuccess, CVReturn},
16    CGLContextObj, CGLPixelFormatObj,
17};
18
19#[repr(C)]
20pub struct __CVOpenGLTextureCache(c_void);
21
22pub type CVOpenGLTextureCacheRef = *mut __CVOpenGLTextureCache;
23
24extern "C" {
25    pub static kCVOpenGLTextureCacheChromaSamplingModeKey: CFStringRef;
26    pub static kCVOpenGLTextureCacheChromaSamplingModeAutomatic: CFStringRef;
27    pub static kCVOpenGLTextureCacheChromaSamplingModeHighestQuality: CFStringRef;
28    pub static kCVOpenGLTextureCacheChromaSamplingModeBestPerformance: CFStringRef;
29
30    pub fn CVOpenGLTextureCacheGetTypeID() -> CFTypeID;
31    pub fn CVOpenGLTextureCacheRetain(textureCache: CVOpenGLTextureCacheRef) -> CVOpenGLTextureCacheRef;
32    pub fn CVOpenGLTextureCacheRelease(textureCache: CVOpenGLTextureCacheRef);
33    pub fn CVOpenGLTextureCacheCreate(
34        allocator: CFAllocatorRef,
35        cacheAttributes: CFDictionaryRef,
36        cglContext: CGLContextObj,
37        cglPixelFormat: CGLPixelFormatObj,
38        textureAttributes: CFDictionaryRef,
39        cacheOut: *mut CVOpenGLTextureCacheRef,
40    ) -> CVReturn;
41    pub fn CVOpenGLTextureCacheCreateTextureFromImage(
42        allocator: CFAllocatorRef,
43        textureCache: CVOpenGLTextureCacheRef,
44        sourceImage: CVImageBufferRef,
45        attributes: CFDictionaryRef,
46        textureOut: *mut CVOpenGLTextureRef,
47    ) -> CVReturn;
48    pub fn CVOpenGLTextureCacheFlush(textureCache: CVOpenGLTextureCacheRef, options: CVOptionFlags);
49}
50
51pub enum CVOpenGLTextureCacheKeys {
52    ChromaSamplingMode,
53}
54
55impl From<CVOpenGLTextureCacheKeys> for CFStringRef {
56    fn from(key: CVOpenGLTextureCacheKeys) -> Self {
57        unsafe {
58            match key {
59                CVOpenGLTextureCacheKeys::ChromaSamplingMode => kCVOpenGLTextureCacheChromaSamplingModeKey,
60            }
61        }
62    }
63}
64
65impl From<CVOpenGLTextureCacheKeys> for CFString {
66    fn from(key: CVOpenGLTextureCacheKeys) -> Self {
67        unsafe { CFString::wrap_under_get_rule(CFStringRef::from(key)) }
68    }
69}
70
71pub enum CVOpenGLTextureCacheChromaSamplingMode {
72    Automatic,
73    HighestQuality,
74    BestPerformance,
75}
76
77impl From<CVOpenGLTextureCacheChromaSamplingMode> for CFStringRef {
78    fn from(mode: CVOpenGLTextureCacheChromaSamplingMode) -> Self {
79        unsafe {
80            match mode {
81                CVOpenGLTextureCacheChromaSamplingMode::Automatic => kCVOpenGLTextureCacheChromaSamplingModeAutomatic,
82                CVOpenGLTextureCacheChromaSamplingMode::HighestQuality => kCVOpenGLTextureCacheChromaSamplingModeHighestQuality,
83                CVOpenGLTextureCacheChromaSamplingMode::BestPerformance => kCVOpenGLTextureCacheChromaSamplingModeBestPerformance,
84            }
85        }
86    }
87}
88
89impl From<CVOpenGLTextureCacheChromaSamplingMode> for CFString {
90    fn from(mode: CVOpenGLTextureCacheChromaSamplingMode) -> Self {
91        unsafe { CFString::wrap_under_get_rule(CFStringRef::from(mode)) }
92    }
93}
94
95pub struct CVOpenGLTextureCache(CVOpenGLTextureCacheRef);
96
97impl Drop for CVOpenGLTextureCache {
98    fn drop(&mut self) {
99        unsafe { CVOpenGLTextureCacheRelease(self.0) }
100    }
101}
102
103impl_TCFType!(CVOpenGLTextureCache, CVOpenGLTextureCacheRef, CVOpenGLTextureCacheGetTypeID);
104impl_CFTypeDescription!(CVOpenGLTextureCache);
105
106impl CVOpenGLTextureCache {
107    #[inline]
108    pub unsafe fn new(
109        cache_attributes: Option<&CFDictionary<CFString, CFString>>,
110        cgl_context: CGLContextObj,
111        cgl_pixel_format: CGLPixelFormatObj,
112        texture_attributes: Option<&CFDictionary<CFString, CFType>>,
113    ) -> Result<CVOpenGLTextureCache, CVReturn> {
114        let mut cache: CVOpenGLTextureCacheRef = null_mut();
115        let status = unsafe {
116            CVOpenGLTextureCacheCreate(
117                kCFAllocatorDefault,
118                cache_attributes.map_or(null(), |attrs| attrs.as_concrete_TypeRef()),
119                cgl_context,
120                cgl_pixel_format,
121                texture_attributes.map_or(null(), |attrs| attrs.as_concrete_TypeRef()),
122                &mut cache,
123            )
124        };
125        if status == kCVReturnSuccess {
126            Ok(unsafe { TCFType::wrap_under_create_rule(cache) })
127        } else {
128            Err(status)
129        }
130    }
131
132    #[inline]
133    pub fn create_texture_from_image(
134        &self,
135        source_image: &CVImageBuffer,
136        attributes: Option<&CFDictionary<CFString, CFType>>,
137    ) -> Result<CVOpenGLTexture, CVReturn> {
138        let mut texture: CVOpenGLTextureRef = null_mut();
139        let status = unsafe {
140            CVOpenGLTextureCacheCreateTextureFromImage(
141                kCFAllocatorDefault,
142                self.as_concrete_TypeRef(),
143                source_image.as_concrete_TypeRef(),
144                attributes.map_or(null(), |attrs| attrs.as_concrete_TypeRef()),
145                &mut texture,
146            )
147        };
148        if status == kCVReturnSuccess {
149            Ok(unsafe { TCFType::wrap_under_create_rule(texture) })
150        } else {
151            Err(status)
152        }
153    }
154
155    #[inline]
156    pub fn flush(&self, options: CVOptionFlags) {
157        unsafe { CVOpenGLTextureCacheFlush(self.as_concrete_TypeRef(), options) }
158    }
159}