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