Switch fully to Rust Livekit (redux) (#27126)

Swift bindings BEGONE

Release Notes:

- Switched from using the Swift LiveKit bindings, to the Rust bindings,
fixing https://github.com/zed-industries/zed/issues/9396, a crash when
leaving a collaboration session, and making Zed easier to build.

---------

Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
Co-authored-by: Michael Sloan <michael@zed.dev>
This commit is contained in:
Mikayla Maki 2025-03-28 10:58:23 -07:00 committed by GitHub
parent c8fb95cd1b
commit 8a307e7b89
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
68 changed files with 2393 additions and 7579 deletions

View file

@ -12,7 +12,7 @@ license = "Apache-2.0"
workspace = true
[features]
default = ["http_client", "font-kit", "wayland", "x11"]
default = ["macos-blade", "http_client", "font-kit", "wayland", "x11"]
test-support = [
"leak-detection",
"collections/test-support",
@ -123,10 +123,11 @@ lyon = "1.0"
block = "0.1"
cocoa.workspace = true
core-foundation.workspace = true
core-foundation-sys = "0.8"
core-graphics = "0.23"
core-text = "20.1"
font-kit = { git = "https://github.com/zed-industries/font-kit", rev = "40391b7", optional = true }
core-foundation-sys.workspace = true
core-graphics = "0.24"
core-video.workspace = true
core-text = "21"
font-kit = { git = "https://github.com/zed-industries/font-kit", rev = "5474cfad4b719a72ec8ed2cb7327b2b01fd10568", optional = true }
foreign-types = "0.5"
log.workspace = true
media.workspace = true
@ -154,9 +155,10 @@ blade-macros = { workspace = true, optional = true }
blade-util = { workspace = true, optional = true }
bytemuck = { version = "1", optional = true }
cosmic-text = { version = "0.13.2", optional = true }
font-kit = { git = "https://github.com/zed-industries/font-kit", rev = "40391b7", features = [
font-kit = { git = "https://github.com/zed-industries/font-kit", rev = "5474cfad4b719a72ec8ed2cb7327b2b01fd10568", features = [
"source-fontconfig-dlopen",
], optional = true }
calloop = { version = "0.13.0" }
filedescriptor = { version = "0.8.2", optional = true }
open = { version = "5.2.0", optional = true }

View file

@ -3,7 +3,7 @@ use crate::{
Style, StyleRefinement, Styled, Window,
};
#[cfg(target_os = "macos")]
use media::core_video::CVImageBuffer;
use core_video::pixel_buffer::CVPixelBuffer;
use refineable::Refineable;
/// A source of a surface's content.
@ -11,12 +11,12 @@ use refineable::Refineable;
pub enum SurfaceSource {
/// A macOS image buffer from CoreVideo
#[cfg(target_os = "macos")]
Surface(CVImageBuffer),
Surface(CVPixelBuffer),
}
#[cfg(target_os = "macos")]
impl From<CVImageBuffer> for SurfaceSource {
fn from(value: CVImageBuffer) -> Self {
impl From<CVPixelBuffer> for SurfaceSource {
fn from(value: CVPixelBuffer) -> Self {
SurfaceSource::Surface(value)
}
}
@ -87,7 +87,7 @@ impl Element for Surface {
match &self.source {
#[cfg(target_os = "macos")]
SurfaceSource::Surface(surface) => {
let size = crate::size(surface.width().into(), surface.height().into());
let size = crate::size(surface.get_width().into(), surface.get_height().into());
let new_bounds = self.object_fit.get_bounds(bounds, size);
// TODO: Add support for corner_radii
window.paint_surface(new_bounds, surface.clone());

View file

@ -725,8 +725,8 @@ impl BladeRenderer {
use std::ptr;
assert_eq!(
surface.image_buffer.pixel_format_type(),
media::core_video::kCVPixelFormatType_420YpCbCr8BiPlanarFullRange
surface.image_buffer.get_pixel_format(),
core_video::pixel_buffer::kCVPixelFormatType_420YpCbCr8BiPlanarFullRange
);
let y_texture = self
@ -735,8 +735,8 @@ impl BladeRenderer {
surface.image_buffer.as_concrete_TypeRef(),
ptr::null(),
metal::MTLPixelFormat::R8Unorm,
surface.image_buffer.plane_width(0),
surface.image_buffer.plane_height(0),
surface.image_buffer.get_width_of_plane(0),
surface.image_buffer.get_height_of_plane(0),
0,
)
.unwrap();
@ -746,8 +746,8 @@ impl BladeRenderer {
surface.image_buffer.as_concrete_TypeRef(),
ptr::null(),
metal::MTLPixelFormat::RG8Unorm,
surface.image_buffer.plane_width(1),
surface.image_buffer.plane_height(1),
surface.image_buffer.get_width_of_plane(1),
surface.image_buffer.get_height_of_plane(1),
1,
)
.unwrap();

View file

@ -11,7 +11,7 @@ mod metal_atlas;
#[cfg(not(feature = "macos-blade"))]
pub mod metal_renderer;
use media::core_video::CVImageBuffer;
use core_video::image_buffer::CVImageBuffer;
#[cfg(not(feature = "macos-blade"))]
use metal_renderer as renderer;

View file

@ -13,8 +13,11 @@ use cocoa::{
};
use collections::HashMap;
use core_foundation::base::TCFType;
use foreign_types::ForeignType;
use media::core_video::CVMetalTextureCache;
use core_video::{
metal_texture::CVMetalTextureGetTexture, metal_texture_cache::CVMetalTextureCache,
pixel_buffer::kCVPixelFormatType_420YpCbCr8BiPlanarFullRange,
};
use foreign_types::{ForeignType, ForeignTypeRef};
use metal::{CAMetalLayer, CommandQueue, MTLPixelFormat, MTLResourceOptions, NSRange};
use objc::{self, msg_send, sel, sel_impl};
use parking_lot::Mutex;
@ -107,7 +110,7 @@ pub(crate) struct MetalRenderer {
#[allow(clippy::arc_with_non_send_sync)]
instance_buffer_pool: Arc<Mutex<InstanceBufferPool>>,
sprite_atlas: Arc<MetalAtlas>,
core_video_texture_cache: CVMetalTextureCache,
core_video_texture_cache: core_video::metal_texture_cache::CVMetalTextureCache,
}
impl MetalRenderer {
@ -235,7 +238,7 @@ impl MetalRenderer {
let command_queue = device.new_command_queue();
let sprite_atlas = Arc::new(MetalAtlas::new(device.clone(), PATH_SAMPLE_COUNT));
let core_video_texture_cache =
unsafe { CVMetalTextureCache::new(device.as_ptr()).unwrap() };
CVMetalTextureCache::new(None, device.clone(), None).unwrap();
Self {
device,
@ -1054,39 +1057,37 @@ impl MetalRenderer {
for surface in surfaces {
let texture_size = size(
DevicePixels::from(surface.image_buffer.width() as i32),
DevicePixels::from(surface.image_buffer.height() as i32),
DevicePixels::from(surface.image_buffer.get_width() as i32),
DevicePixels::from(surface.image_buffer.get_height() as i32),
);
assert_eq!(
surface.image_buffer.pixel_format_type(),
media::core_video::kCVPixelFormatType_420YpCbCr8BiPlanarFullRange
surface.image_buffer.get_pixel_format(),
kCVPixelFormatType_420YpCbCr8BiPlanarFullRange
);
let y_texture = unsafe {
self.core_video_texture_cache
.create_texture_from_image(
surface.image_buffer.as_concrete_TypeRef(),
ptr::null(),
MTLPixelFormat::R8Unorm,
surface.image_buffer.plane_width(0),
surface.image_buffer.plane_height(0),
0,
)
.unwrap()
};
let cb_cr_texture = unsafe {
self.core_video_texture_cache
.create_texture_from_image(
surface.image_buffer.as_concrete_TypeRef(),
ptr::null(),
MTLPixelFormat::RG8Unorm,
surface.image_buffer.plane_width(1),
surface.image_buffer.plane_height(1),
1,
)
.unwrap()
};
let y_texture = self
.core_video_texture_cache
.create_texture_from_image(
surface.image_buffer.as_concrete_TypeRef(),
None,
MTLPixelFormat::R8Unorm,
surface.image_buffer.get_width_of_plane(0),
surface.image_buffer.get_height_of_plane(0),
0,
)
.unwrap();
let cb_cr_texture = self
.core_video_texture_cache
.create_texture_from_image(
surface.image_buffer.as_concrete_TypeRef(),
None,
MTLPixelFormat::RG8Unorm,
surface.image_buffer.get_width_of_plane(1),
surface.image_buffer.get_height_of_plane(1),
1,
)
.unwrap();
align_offset(instance_offset);
let next_offset = *instance_offset + mem::size_of::<Surface>();
@ -1104,14 +1105,15 @@ impl MetalRenderer {
mem::size_of_val(&texture_size) as u64,
&texture_size as *const Size<DevicePixels> as *const _,
);
command_encoder.set_fragment_texture(
SurfaceInputIndex::YTexture as u64,
Some(y_texture.as_texture_ref()),
);
command_encoder.set_fragment_texture(
SurfaceInputIndex::CbCrTexture as u64,
Some(cb_cr_texture.as_texture_ref()),
);
// let y_texture = y_texture.get_texture().unwrap().
command_encoder.set_fragment_texture(SurfaceInputIndex::YTexture as u64, unsafe {
let texture = CVMetalTextureGetTexture(y_texture.as_concrete_TypeRef());
Some(metal::TextureRef::from_ptr(texture as *mut _))
});
command_encoder.set_fragment_texture(SurfaceInputIndex::CbCrTexture as u64, unsafe {
let texture = CVMetalTextureGetTexture(cb_cr_texture.as_concrete_TypeRef());
Some(metal::TextureRef::from_ptr(texture as *mut _))
});
unsafe {
let buffer_contents = (instance_buffer.metal_buffer.contents() as *mut u8)

View file

@ -9,6 +9,10 @@ use cocoa::{
foundation::NSArray,
};
use core_foundation::base::TCFType;
use core_graphics::display::{
CGDirectDisplayID, CGDisplayCopyDisplayMode, CGDisplayModeGetPixelHeight,
CGDisplayModeGetPixelWidth, CGDisplayModeRelease,
};
use ctor::ctor;
use futures::channel::oneshot;
use media::core_media::{CMSampleBuffer, CMSampleBufferRef};
@ -45,8 +49,12 @@ const SCStreamOutputTypeScreen: NSInteger = 0;
impl ScreenCaptureSource for MacScreenCaptureSource {
fn resolution(&self) -> Result<Size<Pixels>> {
unsafe {
let width: i64 = msg_send![self.sc_display, width];
let height: i64 = msg_send![self.sc_display, height];
let display_id: CGDirectDisplayID = msg_send![self.sc_display, displayID];
let display_mode_ref = CGDisplayCopyDisplayMode(display_id);
let width = CGDisplayModeGetPixelWidth(display_mode_ref);
let height = CGDisplayModeGetPixelHeight(display_mode_ref);
CGDisplayModeRelease(display_mode_ref);
Ok(size(px(width as f32), px(height as f32)))
}
}
@ -65,6 +73,10 @@ impl ScreenCaptureSource for MacScreenCaptureSource {
let excluded_windows = NSArray::array(nil);
let filter: id = msg_send![filter, initWithDisplay:self.sc_display excludingWindows:excluded_windows];
let configuration: id = msg_send![configuration, init];
let _: id = msg_send![configuration, setScalesToFit: true];
let _: id = msg_send![configuration, setPixelFormat: 0x42475241];
// let _: id = msg_send![configuration, setShowsCursor: false];
// let _: id = msg_send![configuration, setCaptureResolution: 3];
let delegate: id = msg_send![delegate, init];
let output: id = msg_send![output, init];
@ -73,6 +85,9 @@ impl ScreenCaptureSource for MacScreenCaptureSource {
Box::into_raw(Box::new(frame_callback)) as *mut c_void,
);
let resolution = self.resolution().unwrap();
let _: id = msg_send![configuration, setWidth: resolution.width.0 as i64];
let _: id = msg_send![configuration, setHeight: resolution.height.0 as i64];
let stream: id = msg_send![stream, initWithFilter:filter configuration:configuration delegate:delegate];
let (mut tx, rx) = oneshot::channel();

View file

@ -662,7 +662,7 @@ pub(crate) struct PaintSurface {
pub bounds: Bounds<ScaledPixels>,
pub content_mask: ContentMask<ScaledPixels>,
#[cfg(target_os = "macos")]
pub image_buffer: media::core_video::CVImageBuffer,
pub image_buffer: core_video::pixel_buffer::CVPixelBuffer,
}
impl From<PaintSurface> for Primitive {

View file

@ -17,11 +17,11 @@ use crate::{
};
use anyhow::{anyhow, Context as _, Result};
use collections::{FxHashMap, FxHashSet};
#[cfg(target_os = "macos")]
use core_video::pixel_buffer::CVPixelBuffer;
use derive_more::{Deref, DerefMut};
use futures::channel::oneshot;
use futures::FutureExt;
#[cfg(target_os = "macos")]
use media::core_video::CVImageBuffer;
use parking_lot::RwLock;
use raw_window_handle::{HandleError, HasWindowHandle};
use refineable::Refineable;
@ -2658,7 +2658,7 @@ impl Window {
///
/// This method should only be called as part of the paint phase of element drawing.
#[cfg(target_os = "macos")]
pub fn paint_surface(&mut self, bounds: Bounds<Pixels>, image_buffer: CVImageBuffer) {
pub fn paint_surface(&mut self, bounds: Bounds<Pixels>, image_buffer: CVPixelBuffer) {
use crate::PaintSurface;
self.invalidator.debug_assert_paint();