Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

render: add support for more formats #148

Merged
merged 1 commit into from
Apr 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
769 changes: 297 additions & 472 deletions src/format.rs

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions src/gfx_apis/gl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,8 @@ enum RenderError {
ExportSyncFile,
#[error("Could not insert wait for EGLSyncKHR")]
WaitSync,
#[error("Buffer format {0} is not supported for shm buffers in OpenGL context")]
UnsupportedShmFormat(&'static str),
}

#[derive(Default)]
Expand Down
5 changes: 4 additions & 1 deletion src/gfx_apis/gl/gl/render_buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,14 @@ impl GlRenderBuffer {
height: i32,
format: &'static Format,
) -> Result<Rc<GlRenderBuffer>, RenderError> {
let Some(shm_info) = &format.shm_info else {
return Err(RenderError::UnsupportedShmFormat(format.name));
};
let gles = &ctx.dpy.gles;
let mut rbo = 0;
(gles.glGenRenderbuffers)(1, &mut rbo);
(gles.glBindRenderbuffer)(GL_RENDERBUFFER, rbo);
(gles.glRenderbufferStorage)(GL_RENDERBUFFER, format.gl_internal_format, width, height);
(gles.glRenderbufferStorage)(GL_RENDERBUFFER, shm_info.gl_internal_format, width, height);
(gles.glBindRenderbuffer)(GL_RENDERBUFFER, 0);
Ok(Rc::new(GlRenderBuffer {
_img: None,
Expand Down
11 changes: 7 additions & 4 deletions src/gfx_apis/gl/gl/texture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ impl GlTexture {
height: i32,
stride: i32,
) -> Result<GlTexture, RenderError> {
let Some(shm_info) = &format.shm_info else {
return Err(RenderError::UnsupportedShmFormat(format.name));
};
if (stride * height) as usize > data.len() {
return Err(RenderError::SmallImageBuffer);
}
Expand All @@ -83,16 +86,16 @@ impl GlTexture {
(gles.glBindTexture)(GL_TEXTURE_2D, tex);
(gles.glTexParameteri)(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
(gles.glTexParameteri)(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
(gles.glPixelStorei)(GL_UNPACK_ROW_LENGTH_EXT, stride / format.bpp as GLint);
(gles.glPixelStorei)(GL_UNPACK_ROW_LENGTH_EXT, stride / shm_info.bpp as GLint);
(gles.glTexImage2D)(
GL_TEXTURE_2D,
0,
format.gl_format,
shm_info.gl_format,
width,
height,
0,
format.gl_format as _,
format.gl_type as _,
shm_info.gl_format as _,
shm_info.gl_type as _,
data.as_ptr() as _,
);
(gles.glPixelStorei)(GL_UNPACK_ROW_LENGTH_EXT, 0);
Expand Down
15 changes: 10 additions & 5 deletions src/gfx_apis/gl/renderer/framebuffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@ impl Framebuffer {
height: i32,
format: &Format,
shm: &[Cell<u8>],
) {
) -> Result<(), RenderError> {
let Some(shm_info) = &format.shm_info else {
return Err(RenderError::UnsupportedShmFormat(format.name));
};
let gles = self.ctx.ctx.dpy.gles;
let y = self.gl.height - y - height;
let _ = self.ctx.ctx.with_current(|| {
Expand All @@ -55,14 +58,15 @@ impl Framebuffer {
y,
width,
height,
format.gl_format as _,
format.gl_type as _,
shm_info.gl_format as _,
shm_info.gl_type as _,
shm.len() as _,
shm.as_ptr() as _,
);
}
Ok(())
});
Ok(())
}

pub fn render(
Expand Down Expand Up @@ -126,8 +130,9 @@ impl GfxFramebuffer for Framebuffer {
format: &'static Format,
shm: &[Cell<u8>],
) -> Result<(), GfxError> {
(*self).copy_to_shm(x, y, width, height, format, shm);
Ok(())
(*self)
.copy_to_shm(x, y, width, height, format, shm)
.map_err(|e| e.into())
}

fn format(&self) -> &'static Format {
Expand Down
4 changes: 2 additions & 2 deletions src/gfx_apis/gl/renderer/texture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ impl GfxTexture for Texture {
shm: &[Cell<u8>],
) -> Result<(), GfxError> {
self.to_framebuffer()?
.copy_to_shm(x, y, width, height, format, shm);
Ok(())
.copy_to_shm(x, y, width, height, format, shm)
.map_err(|e| e.into())
}

fn dmabuf(&self) -> Option<&DmaBuf> {
Expand Down
2 changes: 2 additions & 0 deletions src/gfx_apis/vulkan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,8 @@ pub enum VulkanError {
},
#[error(transparent)]
GfxError(GfxError),
#[error("Buffer format {0} is not supported for shm buffers in Vulkan context")]
UnsupportedShmFormat(&'static str),
}

impl From<VulkanError> for GfxError {
Expand Down
3 changes: 3 additions & 0 deletions src/gfx_apis/vulkan/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ impl VulkanInstance {
format: &Format,
props: &FormatProperties2,
) -> Result<Option<VulkanShmFormat>, VulkanError> {
if format.shm_info.is_none() {
return Ok(None);
}
if !props
.format_properties
.optimal_tiling_features
Expand Down
5 changes: 4 additions & 1 deletion src/gfx_apis/vulkan/image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,16 @@ impl VulkanRenderer {
data: &[Cell<u8>],
for_download: bool,
) -> Result<Rc<VulkanImage>, VulkanError> {
let Some(shm_info) = &format.shm_info else {
return Err(VulkanError::UnsupportedShmFormat(format.name));
};
if width <= 0 || height <= 0 || stride <= 0 {
return Err(VulkanError::NonPositiveImageSize);
}
let width = width as u32;
let height = height as u32;
let stride = stride as u32;
if stride % format.bpp != 0 || stride / format.bpp < width {
if stride % shm_info.bpp != 0 || stride / shm_info.bpp < width {
return Err(VulkanError::InvalidStride);
}
let vk_format = self
Expand Down
12 changes: 9 additions & 3 deletions src/gfx_apis/vulkan/renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,9 +294,12 @@ impl VulkanRenderer {
fn copy_shm_to_image(&self, cmd: CommandBuffer) {
let memory = self.memory.borrow_mut();
for (img, staging) in &memory.flush_staging {
let Some(shm_info) = &img.format.shm_info else {
continue;
};
let cpy = BufferImageCopy2::builder()
.buffer_image_height(img.height)
.buffer_row_length(img.stride / img.format.bpp)
.buffer_row_length(img.stride / shm_info.bpp)
.image_extent(Extent3D {
width: img.width,
height: img.height,
Expand Down Expand Up @@ -751,15 +754,18 @@ impl VulkanRenderer {
stride: u32,
dst: &[Cell<u8>],
) -> Result<(), VulkanError> {
if stride < tex.width * tex.format.bpp || stride % tex.format.bpp != 0 {
let Some(shm_info) = &tex.format.shm_info else {
return Err(VulkanError::UnsupportedShmFormat(tex.format.name));
};
if stride < tex.width * shm_info.bpp || stride % shm_info.bpp != 0 {
return Err(VulkanError::InvalidStride);
}
let size = stride as u64 * tex.height as u64;
if size != dst.len() as u64 {
return Err(VulkanError::InvalidBufferSize);
}
let region = BufferImageCopy::builder()
.buffer_row_length(stride / tex.format.bpp)
.buffer_row_length(stride / shm_info.bpp)
.buffer_image_height(tex.height)
.image_subresource(ImageSubresourceLayers {
aspect_mask: ImageAspectFlags::COLOR,
Expand Down
7 changes: 6 additions & 1 deletion src/ifs/wl_buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,16 @@ impl WlBuffer {
format: &'static Format,
mem: &Rc<ClientMem>,
) -> Result<Self, WlBufferError> {
let Some(shm_info) = &format.shm_info else {
return Err(WlBufferError::UnsupportedShmFormat(format.name));
};
let bytes = stride as u64 * height as u64;
let required = bytes + offset as u64;
if required > mem.len() as u64 {
return Err(WlBufferError::OutOfBounds);
}
let mem = mem.offset(offset);
let min_row_size = width as u64 * format.bpp as u64;
let min_row_size = width as u64 * shm_info.bpp as u64;
if (stride as u64) < min_row_size {
return Err(WlBufferError::StrideTooSmall);
}
Expand Down Expand Up @@ -270,6 +273,8 @@ pub enum WlBufferError {
MsgParserError(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
#[error("Buffer format {0} is not supported for shm buffers")]
UnsupportedShmFormat(&'static str),
}
efrom!(WlBufferError, ClientMemError);
efrom!(WlBufferError, MsgParserError);
Expand Down
2 changes: 1 addition & 1 deletion src/ifs/wl_shm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ impl WlShmGlobal {
track!(client, obj);
client.add_client_obj(&obj)?;
for format in FORMATS {
if format.shm_supported {
if format.shm_info.is_some() {
client.event(Format {
self_id: id,
format: format.wl_id.unwrap_or(format.drm),
Expand Down
2 changes: 1 addition & 1 deletion src/ifs/wl_shm_pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ impl WlShmPool {
let req: CreateBuffer = self.client.parse(self, parser)?;
let drm_format = map_wayland_format_id(req.format);
let format = match formats().get(&drm_format) {
Some(f) if f.shm_supported => *f,
Some(f) if f.shm_info.is_some() => *f,
_ => return Err(WlShmPoolError::InvalidFormat(req.format)),
};
if req.height < 0 || req.width < 0 || req.stride < 0 || req.offset < 0 {
Expand Down
Loading