Skip to main content

core_video/
metal_texture_cache.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::{c_void, size_t};
11
12use crate::{
13    base::CVOptionFlags,
14    image_buffer::CVImageBufferRef,
15    metal_texture::{CVMetalTexture, CVMetalTextureRef},
16    r#return::{kCVReturnSuccess, CVReturn},
17};
18
19#[repr(C)]
20pub struct __CVMetalTextureCache(c_void);
21
22pub type CVMetalTextureCacheRef = *mut __CVMetalTextureCache;
23
24extern "C" {
25    pub static kCVMetalTextureCacheMaximumTextureAgeKey: CFStringRef;
26
27    pub fn CVMetalTextureCacheGetTypeID() -> CFTypeID;
28    pub fn CVMetalTextureCacheCreate(
29        allocator: CFAllocatorRef,
30        cacheAttributes: CFDictionaryRef,
31        metalDevice: metal::Device,
32        textureAttributes: CFDictionaryRef,
33        cacheOut: *mut CVMetalTextureCacheRef,
34    ) -> CVReturn;
35    pub fn CVMetalTextureCacheCreateTextureFromImage(
36        allocator: CFAllocatorRef,
37        textureCache: CVMetalTextureCacheRef,
38        sourceImage: CVImageBufferRef,
39        textureAttributes: CFDictionaryRef,
40        pixelFormat: metal::MTLPixelFormat,
41        width: size_t,
42        height: size_t,
43        planeIndex: size_t,
44        textureOut: *mut CVMetalTextureRef,
45    ) -> CVReturn;
46    pub fn CVMetalTextureCacheFlush(textureCache: CVMetalTextureCacheRef, options: CVOptionFlags);
47}
48
49pub enum CVMetalTextureCacheKeys {
50    MaximumTextureAge,
51}
52
53impl From<CVMetalTextureCacheKeys> for CFStringRef {
54    fn from(key: CVMetalTextureCacheKeys) -> Self {
55        unsafe {
56            match key {
57                CVMetalTextureCacheKeys::MaximumTextureAge => kCVMetalTextureCacheMaximumTextureAgeKey,
58            }
59        }
60    }
61}
62
63impl From<CVMetalTextureCacheKeys> for CFString {
64    fn from(key: CVMetalTextureCacheKeys) -> Self {
65        unsafe { CFString::wrap_under_get_rule(CFStringRef::from(key)) }
66    }
67}
68
69declare_TCFType!(CVMetalTextureCache, CVMetalTextureCacheRef);
70impl_TCFType!(CVMetalTextureCache, CVMetalTextureCacheRef, CVMetalTextureCacheGetTypeID);
71impl_CFTypeDescription!(CVMetalTextureCache);
72
73impl CVMetalTextureCache {
74    #[inline]
75    pub fn new(
76        cache_attributes: Option<&CFDictionary<CFString, CFType>>,
77        metal_device: metal::Device,
78        texture_attributes: Option<&CFDictionary<CFString, CFType>>,
79    ) -> Result<CVMetalTextureCache, CVReturn> {
80        let mut cache: CVMetalTextureCacheRef = null_mut();
81        let status = unsafe {
82            CVMetalTextureCacheCreate(
83                kCFAllocatorDefault,
84                cache_attributes.map_or(null(), |attrs| attrs.as_concrete_TypeRef()),
85                metal_device,
86                texture_attributes.map_or(null(), |attrs| attrs.as_concrete_TypeRef()),
87                &mut cache,
88            )
89        };
90        if status == kCVReturnSuccess {
91            Ok(unsafe { TCFType::wrap_under_create_rule(cache) })
92        } else {
93            Err(status)
94        }
95    }
96
97    #[inline]
98    pub fn create_texture_from_image(
99        &self,
100        source_image: CVImageBufferRef,
101        texture_attributes: Option<&CFDictionary<CFString, CFType>>,
102        pixel_format: metal::MTLPixelFormat,
103        width: size_t,
104        height: size_t,
105        plane_index: size_t,
106    ) -> Result<CVMetalTexture, CVReturn> {
107        let mut texture: CVMetalTextureRef = null_mut();
108        let status = unsafe {
109            CVMetalTextureCacheCreateTextureFromImage(
110                kCFAllocatorDefault,
111                self.as_concrete_TypeRef(),
112                source_image,
113                texture_attributes.map_or(null(), |attrs| attrs.as_concrete_TypeRef()),
114                pixel_format,
115                width,
116                height,
117                plane_index,
118                &mut texture,
119            )
120        };
121        if status == kCVReturnSuccess {
122            Ok(unsafe { TCFType::wrap_under_create_rule(texture) })
123        } else {
124            Err(status)
125        }
126    }
127
128    #[inline]
129    pub fn flush(&self, options: CVOptionFlags) {
130        unsafe { CVMetalTextureCacheFlush(self.as_concrete_TypeRef(), options) }
131    }
132}