Owned pixel buffer for no-copy presentation

This is based on the API that will be used for no-copy presentation. But
wraps it in `set_buffer`.

This also fixes the Wayland buffer code to set `self.width` and
`self.height` on resize, and set the length of the shared memory file
when the buffer is created.

Co-authored-by: jtnunley <jtnunley01@gmail.com>
This commit is contained in:
Ian Douglas Scott 2023-04-06 00:30:59 -07:00 committed by GitHub
parent e5d546ff9e
commit a09e4cf679
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 1176 additions and 438 deletions

View file

@ -12,11 +12,23 @@ use cocoa::base::{id, nil};
use cocoa::quartzcore::{transaction, CALayer, ContentsGravity};
use foreign_types::ForeignType;
use std::num::NonZeroU32;
use std::sync::Arc;
struct Buffer(Vec<u32>);
impl AsRef<[u8]> for Buffer {
fn as_ref(&self) -> &[u8] {
bytemuck::cast_slice(&self.0)
}
}
pub struct CGImpl {
layer: CALayer,
window: id,
color_space: CGColorSpace,
width: u32,
height: u32,
}
impl CGImpl {
@ -35,22 +47,55 @@ impl CGImpl {
view.addSubview_(subview); // retains subview (+1) = 2
let _: () = msg_send![subview, release]; // releases subview (-1) = 1
}
Ok(Self { layer, window })
let color_space = CGColorSpace::create_device_rgb();
Ok(Self {
layer,
window,
color_space,
width: 0,
height: 0,
})
}
pub(crate) unsafe fn set_buffer(&mut self, buffer: &[u32], width: u16, height: u16) {
let color_space = CGColorSpace::create_device_rgb();
let data =
unsafe { std::slice::from_raw_parts(buffer.as_ptr() as *const u8, buffer.len() * 4) }
.to_vec();
let data_provider = CGDataProvider::from_buffer(Arc::new(data));
pub fn resize(&mut self, width: NonZeroU32, height: NonZeroU32) -> Result<(), SoftBufferError> {
self.width = width.get();
self.height = height.get();
Ok(())
}
pub fn buffer_mut(&mut self) -> Result<BufferImpl, SoftBufferError> {
Ok(BufferImpl {
buffer: vec![0; self.width as usize * self.height as usize],
imp: self,
})
}
}
pub struct BufferImpl<'a> {
imp: &'a mut CGImpl,
buffer: Vec<u32>,
}
impl<'a> BufferImpl<'a> {
#[inline]
pub fn pixels(&self) -> &[u32] {
&self.buffer
}
#[inline]
pub fn pixels_mut(&mut self) -> &mut [u32] {
&mut self.buffer
}
pub fn present(self) -> Result<(), SoftBufferError> {
let data_provider = CGDataProvider::from_buffer(Arc::new(Buffer(self.buffer)));
let image = CGImage::new(
width as usize,
height as usize,
self.imp.width as usize,
self.imp.height as usize,
8,
32,
(width * 4) as usize,
&color_space,
(self.imp.width * 4) as usize,
&self.imp.color_space,
kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst,
&data_provider,
false,
@ -64,12 +109,15 @@ impl CGImpl {
transaction::set_disable_actions(true);
unsafe {
self.layer
.set_contents_scale(self.window.backingScaleFactor());
self.layer.set_contents(image.as_ptr() as id);
self.imp
.layer
.set_contents_scale(self.imp.window.backingScaleFactor());
self.imp.layer.set_contents(image.as_ptr() as id);
};
transaction::commit();
Ok(())
}
}