Cargo.lock 🔗
@@ -3036,6 +3036,7 @@ version = "0.1.0"
dependencies = [
"block",
"core-foundation",
+ "metal",
"objc",
]
Nathan Sobo created
Cargo.lock | 1
crates/gpui/src/platform/mac/renderer.rs | 30 ++++++-
crates/media/Cargo.toml | 3
crates/media/src/media.rs | 100 ++++++++++++++++++++++++++
4 files changed, 129 insertions(+), 5 deletions(-)
@@ -3036,6 +3036,7 @@ version = "0.1.0"
dependencies = [
"block",
"core-foundation",
+ "metal",
"objc",
]
@@ -9,10 +9,13 @@ use crate::{
scene::{Glyph, Icon, Image, ImageGlyph, Layer, Quad, Scene, Shadow, Underline},
};
use cocoa::foundation::NSUInteger;
+use core_foundation::base::TCFType;
+use foreign_types::ForeignTypeRef;
use log::warn;
+use media::core_video::{self, CVMetalTextureCache};
use metal::{MTLPixelFormat, MTLResourceOptions, NSRange};
use shaders::ToFloat2 as _;
-use std::{collections::HashMap, ffi::c_void, iter::Peekable, mem, sync::Arc, vec};
+use std::{collections::HashMap, ffi::c_void, iter::Peekable, mem, ptr, sync::Arc, vec};
const SHADERS_METALLIB: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/shaders.metallib"));
const INSTANCE_BUFFER_SIZE: usize = 8192 * 1024; // This is an arbitrary decision. There's probably a more optimal value.
@@ -29,6 +32,7 @@ pub struct Renderer {
underline_pipeline_state: metal::RenderPipelineState,
unit_vertices: metal::Buffer,
instances: metal::Buffer,
+ cv_texture_cache: core_video::CVMetalTextureCache,
}
struct PathSprite {
@@ -39,7 +43,7 @@ struct PathSprite {
pub struct Surface {
pub bounds: RectF,
- pub image_buffer: media::core_video::CVImageBuffer,
+ pub image_buffer: core_video::CVImageBuffer,
}
impl Renderer {
@@ -128,6 +132,7 @@ impl Renderer {
"underline_fragment",
pixel_format,
);
+ let cv_texture_cache = CVMetalTextureCache::new(device.as_ptr());
Self {
sprite_cache,
image_cache,
@@ -140,6 +145,7 @@ impl Renderer {
underline_pipeline_state,
unit_vertices,
instances,
+ cv_texture_cache,
}
}
@@ -786,10 +792,26 @@ impl Renderer {
}
for surface in surfaces {
- let origin = surface.bounds.origin() * scale_factor;
- let target_size = surface.bounds.size() * scale_factor;
+ // let origin = surface.bounds.origin() * scale_factor;
+ // let target_size = surface.bounds.size() * scale_factor;
// let corner_radius = surface.corner_radius * scale_factor;
// let border_width = surface.border.width * scale_factor;
+
+ let width = surface.image_buffer.width();
+ let height = surface.image_buffer.height();
+
+ // We should add this method, but this return CVPixelFormatType and we need MTLPixelFormat
+ // I found at least one code example that manually maps them. Not sure what other options we have.
+ let pixel_format = surface.image_buffer.pixel_format_type();
+
+ let texture = self.cv_texture_cache.create_texture_from_image(
+ surface.image_buffer.as_concrete_TypeRef(),
+ ptr::null(),
+ pixel_format,
+ width,
+ height,
+ 0,
+ );
}
// command_encoder.set_render_pipeline_state(&self.image_pipeline_state);
@@ -10,4 +10,5 @@ doctest = false
[dependencies]
block = "0.1"
core-foundation = "0.9.3"
-objc = "0.2"
+metal = "0.21.0"
+objc = "0.2"
@@ -1,11 +1,15 @@
#![allow(non_snake_case)]
+#![allow(non_camel_case_types)]
use core_foundation::{
base::{CFTypeID, TCFType},
declare_TCFType, impl_CFTypeDescription, impl_TCFType,
};
+use objc::runtime;
use std::ffi::c_void;
+pub type id = *mut runtime::Object;
+
pub mod io_surface {
use super::*;
@@ -27,8 +31,14 @@ pub mod io_surface {
pub mod core_video {
#![allow(non_snake_case)]
+ use std::ptr;
+
use super::*;
+ use core_foundation::{
+ base::kCFAllocatorDefault, dictionary::CFDictionaryRef, mach_port::CFAllocatorRef,
+ };
use io_surface::{IOSurface, IOSurfaceRef};
+ use metal::{MTLDevice, MTLPixelFormat};
#[repr(C)]
pub struct __CVImageBuffer(c_void);
@@ -63,4 +73,94 @@ pub mod core_video {
fn CVPixelBufferGetWidth(buffer: CVImageBufferRef) -> usize;
fn CVPixelBufferGetHeight(buffer: CVImageBufferRef) -> usize;
}
+
+ #[repr(C)]
+ pub struct __CVMetalTextureCache(c_void);
+ pub type CVMetalTextureCacheRef = *const __CVMetalTextureCache;
+
+ declare_TCFType!(CVMetalTextureCache, CVMetalTextureCacheRef);
+ impl_TCFType!(
+ CVMetalTextureCache,
+ CVMetalTextureCacheRef,
+ CVMetalTextureCacheGetTypeID
+ );
+ impl_CFTypeDescription!(CVMetalTextureCache);
+
+ impl CVMetalTextureCache {
+ pub fn new(metal_device: *mut MTLDevice) -> Self {
+ unsafe {
+ let mut this = ptr::null();
+ let result = CVMetalTextureCacheCreate(
+ kCFAllocatorDefault,
+ ptr::null_mut(),
+ metal_device,
+ ptr::null_mut(),
+ &mut this,
+ );
+ // TODO: Check result
+ CVMetalTextureCache::wrap_under_create_rule(this)
+ }
+ }
+
+ pub fn create_texture_from_image(
+ &self,
+ source: CVImageBufferRef,
+ texture_attributes: CFDictionaryRef,
+ pixel_format: MTLPixelFormat,
+ width: usize,
+ height: usize,
+ plane_index: usize,
+ ) -> CVMetalTexture {
+ unsafe {
+ let mut this = ptr::null();
+ let result = CVMetalTextureCacheCreateTextureFromImage(
+ kCFAllocatorDefault,
+ self.as_concrete_TypeRef(),
+ source,
+ texture_attributes,
+ pixel_format,
+ width,
+ height,
+ plane_index,
+ &mut this,
+ );
+ // TODO: Check result
+ CVMetalTexture::wrap_under_create_rule(this)
+ }
+ }
+ }
+
+ extern "C" {
+ fn CVMetalTextureCacheGetTypeID() -> CFTypeID;
+ fn CVMetalTextureCacheCreate(
+ allocator: CFAllocatorRef,
+ cache_attributes: CFDictionaryRef,
+ metal_device: *const MTLDevice,
+ texture_attributes: CFDictionaryRef,
+ cache_out: *mut CVMetalTextureCacheRef,
+ ) -> i32; // TODO: This should be a CVReturn enum
+ fn CVMetalTextureCacheCreateTextureFromImage(
+ allocator: CFAllocatorRef,
+ texture_cache: CVMetalTextureCacheRef,
+ source_image: CVImageBufferRef,
+ texture_attributes: CFDictionaryRef,
+ pixel_format: MTLPixelFormat,
+ width: usize,
+ height: usize,
+ plane_index: usize,
+ texture_out: *mut CVMetalTextureRef,
+ ) -> i32;
+ }
+
+ #[repr(C)]
+ pub struct __CVMetalTexture(c_void);
+ pub type CVMetalTextureRef = *const __CVMetalTexture;
+
+ declare_TCFType!(CVMetalTexture, CVMetalTextureRef);
+ impl_TCFType!(CVMetalTexture, CVMetalTextureRef, CVMetalTextureGetTypeID);
+ impl_CFTypeDescription!(CVMetalTexture);
+
+ extern "C" {
+ fn CVMetalTextureGetTypeID() -> CFTypeID;
+ }
}