core_video/
metal_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, size_t};
9
10use crate::{
11    base::CVOptionFlags,
12    image_buffer::CVImageBufferRef,
13    metal_texture::{CVMetalTexture, CVMetalTextureRef},
14    r#return::{kCVReturnSuccess, CVReturn},
15};
16
17#[repr(C)]
18pub struct __CVMetalTextureCache(c_void);
19
20pub type CVMetalTextureCacheRef = *mut __CVMetalTextureCache;
21
22extern "C" {
23    pub static kCVMetalTextureCacheMaximumTextureAgeKey: CFStringRef;
24
25    pub fn CVMetalTextureCacheGetTypeID() -> CFTypeID;
26    pub fn CVMetalTextureCacheCreate(
27        allocator: CFAllocatorRef,
28        cacheAttributes: CFDictionaryRef,
29        metalDevice: metal::Device,
30        textureAttributes: CFDictionaryRef,
31        cacheOut: *mut CVMetalTextureCacheRef,
32    ) -> CVReturn;
33    pub fn CVMetalTextureCacheCreateTextureFromImage(
34        allocator: CFAllocatorRef,
35        textureCache: CVMetalTextureCacheRef,
36        sourceImage: CVImageBufferRef,
37        textureAttributes: CFDictionaryRef,
38        pixelFormat: metal::MTLPixelFormat,
39        width: size_t,
40        height: size_t,
41        planeIndex: size_t,
42        textureOut: *mut CVMetalTextureRef,
43    ) -> CVReturn;
44    pub fn CVMetalTextureCacheFlush(textureCache: CVMetalTextureCacheRef, options: CVOptionFlags);
45}
46
47pub enum CVMetalTextureCacheKeys {
48    MaximumTextureAge,
49}
50
51impl From<CVMetalTextureCacheKeys> for CFStringRef {
52    fn from(key: CVMetalTextureCacheKeys) -> Self {
53        unsafe {
54            match key {
55                CVMetalTextureCacheKeys::MaximumTextureAge => kCVMetalTextureCacheMaximumTextureAgeKey,
56            }
57        }
58    }
59}
60
61impl From<CVMetalTextureCacheKeys> for CFString {
62    fn from(key: CVMetalTextureCacheKeys) -> Self {
63        unsafe { CFString::wrap_under_get_rule(CFStringRef::from(key)) }
64    }
65}
66
67declare_TCFType! {
68    CVMetalTextureCache, CVMetalTextureCacheRef
69}
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}