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:
parent
e5d546ff9e
commit
a09e4cf679
19 changed files with 1176 additions and 438 deletions
76
src/cg.rs
76
src/cg.rs
|
|
@ -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(())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue