1
0
Fork 0
forked from wry/wry

wl-shm: add support for more formats

This commit is contained in:
Julian Orth 2025-10-01 20:31:00 +02:00
parent 09a56edd47
commit 0570669af2
20 changed files with 114 additions and 81 deletions

View file

@ -20,7 +20,6 @@ use {
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub struct FormatShmInfo { pub struct FormatShmInfo {
pub bpp: u32,
pub gl_format: GLint, pub gl_format: GLint,
pub gl_internal_format: GLenum, pub gl_internal_format: GLenum,
pub gl_type: GLint, pub gl_type: GLint,
@ -38,6 +37,7 @@ pub struct Format {
pub opaque: Option<&'static Format>, pub opaque: Option<&'static Format>,
pub shm_info: Option<FormatShmInfo>, pub shm_info: Option<FormatShmInfo>,
pub config: ConfigFormat, pub config: ConfigFormat,
pub bpp: u32,
} }
const fn default(config: ConfigFormat) -> Format { const fn default(config: ConfigFormat) -> Format {
@ -52,6 +52,7 @@ const fn default(config: ConfigFormat) -> Format {
opaque: None, opaque: None,
shm_info: None, shm_info: None,
config, config,
bpp: 4,
} }
} }
@ -159,12 +160,12 @@ pub fn map_wayland_format_id(id: u32) -> u32 {
pub static ARGB8888: &Format = &Format { pub static ARGB8888: &Format = &Format {
name: "argb8888", name: "argb8888",
shm_info: Some(FormatShmInfo { shm_info: Some(FormatShmInfo {
bpp: 4,
gl_format: GL_BGRA_EXT, gl_format: GL_BGRA_EXT,
gl_internal_format: GL_RGBA8, gl_internal_format: GL_RGBA8,
gl_type: GL_UNSIGNED_BYTE, gl_type: GL_UNSIGNED_BYTE,
}), }),
vk_format: vk::Format::B8G8R8A8_UNORM, vk_format: vk::Format::B8G8R8A8_UNORM,
bpp: 4,
drm: ARGB8888_DRM, drm: ARGB8888_DRM,
wl_id: Some(ARGB8888_ID), wl_id: Some(ARGB8888_ID),
external_only_guess: false, external_only_guess: false,
@ -177,12 +178,12 @@ pub static ARGB8888: &Format = &Format {
pub static XRGB8888: &Format = &Format { pub static XRGB8888: &Format = &Format {
name: "xrgb8888", name: "xrgb8888",
shm_info: Some(FormatShmInfo { shm_info: Some(FormatShmInfo {
bpp: 4,
gl_format: GL_BGRA_EXT, gl_format: GL_BGRA_EXT,
gl_internal_format: GL_RGBA8, gl_internal_format: GL_RGBA8,
gl_type: GL_UNSIGNED_BYTE, gl_type: GL_UNSIGNED_BYTE,
}), }),
vk_format: vk::Format::B8G8R8A8_UNORM, vk_format: vk::Format::B8G8R8A8_UNORM,
bpp: 4,
drm: XRGB8888_DRM, drm: XRGB8888_DRM,
wl_id: Some(XRGB8888_ID), wl_id: Some(XRGB8888_ID),
external_only_guess: false, external_only_guess: false,
@ -195,12 +196,12 @@ pub static XRGB8888: &Format = &Format {
static ABGR8888: &Format = &Format { static ABGR8888: &Format = &Format {
name: "abgr8888", name: "abgr8888",
shm_info: Some(FormatShmInfo { shm_info: Some(FormatShmInfo {
bpp: 4,
gl_format: GL_RGBA, gl_format: GL_RGBA,
gl_internal_format: GL_RGBA8, gl_internal_format: GL_RGBA8,
gl_type: GL_UNSIGNED_BYTE, gl_type: GL_UNSIGNED_BYTE,
}), }),
vk_format: vk::Format::R8G8B8A8_UNORM, vk_format: vk::Format::R8G8B8A8_UNORM,
bpp: 4,
drm: fourcc_code('A', 'B', '2', '4'), drm: fourcc_code('A', 'B', '2', '4'),
wl_id: None, wl_id: None,
external_only_guess: false, external_only_guess: false,
@ -213,12 +214,12 @@ static ABGR8888: &Format = &Format {
static XBGR8888: &Format = &Format { static XBGR8888: &Format = &Format {
name: "xbgr8888", name: "xbgr8888",
shm_info: Some(FormatShmInfo { shm_info: Some(FormatShmInfo {
bpp: 4,
gl_format: GL_RGBA, gl_format: GL_RGBA,
gl_internal_format: GL_RGBA8, gl_internal_format: GL_RGBA8,
gl_type: GL_UNSIGNED_BYTE, gl_type: GL_UNSIGNED_BYTE,
}), }),
vk_format: vk::Format::R8G8B8A8_UNORM, vk_format: vk::Format::R8G8B8A8_UNORM,
bpp: 4,
drm: fourcc_code('X', 'B', '2', '4'), drm: fourcc_code('X', 'B', '2', '4'),
wl_id: None, wl_id: None,
external_only_guess: false, external_only_guess: false,
@ -231,6 +232,7 @@ static XBGR8888: &Format = &Format {
static R8: &Format = &Format { static R8: &Format = &Format {
name: "r8", name: "r8",
vk_format: vk::Format::R8_UNORM, vk_format: vk::Format::R8_UNORM,
bpp: 1,
drm: fourcc_code('R', '8', ' ', ' '), drm: fourcc_code('R', '8', ' ', ' '),
pipewire: SPA_VIDEO_FORMAT_GRAY8, pipewire: SPA_VIDEO_FORMAT_GRAY8,
..default(ConfigFormat::R8) ..default(ConfigFormat::R8)
@ -239,6 +241,7 @@ static R8: &Format = &Format {
static GR88: &Format = &Format { static GR88: &Format = &Format {
name: "gr88", name: "gr88",
vk_format: vk::Format::R8G8_UNORM, vk_format: vk::Format::R8G8_UNORM,
bpp: 2,
drm: fourcc_code('G', 'R', '8', '8'), drm: fourcc_code('G', 'R', '8', '8'),
..default(ConfigFormat::GR88) ..default(ConfigFormat::GR88)
}; };
@ -246,6 +249,7 @@ static GR88: &Format = &Format {
static RGB888: &Format = &Format { static RGB888: &Format = &Format {
name: "rgb888", name: "rgb888",
vk_format: vk::Format::B8G8R8_UNORM, vk_format: vk::Format::B8G8R8_UNORM,
bpp: 3,
drm: fourcc_code('R', 'G', '2', '4'), drm: fourcc_code('R', 'G', '2', '4'),
pipewire: SPA_VIDEO_FORMAT_BGR, pipewire: SPA_VIDEO_FORMAT_BGR,
..default(ConfigFormat::RGB888) ..default(ConfigFormat::RGB888)
@ -254,6 +258,7 @@ static RGB888: &Format = &Format {
static BGR888: &Format = &Format { static BGR888: &Format = &Format {
name: "bgr888", name: "bgr888",
vk_format: vk::Format::R8G8B8_UNORM, vk_format: vk::Format::R8G8B8_UNORM,
bpp: 3,
drm: fourcc_code('B', 'G', '2', '4'), drm: fourcc_code('B', 'G', '2', '4'),
pipewire: SPA_VIDEO_FORMAT_RGB, pipewire: SPA_VIDEO_FORMAT_RGB,
..default(ConfigFormat::BGR888) ..default(ConfigFormat::BGR888)
@ -262,6 +267,7 @@ static BGR888: &Format = &Format {
static RGBA4444: &Format = &Format { static RGBA4444: &Format = &Format {
name: "rgba4444", name: "rgba4444",
vk_format: vk::Format::R4G4B4A4_UNORM_PACK16, vk_format: vk::Format::R4G4B4A4_UNORM_PACK16,
bpp: 2,
drm: fourcc_code('R', 'A', '1', '2'), drm: fourcc_code('R', 'A', '1', '2'),
has_alpha: true, has_alpha: true,
opaque: Some(RGBX4444), opaque: Some(RGBX4444),
@ -271,6 +277,7 @@ static RGBA4444: &Format = &Format {
static RGBX4444: &Format = &Format { static RGBX4444: &Format = &Format {
name: "rgbx4444", name: "rgbx4444",
vk_format: vk::Format::R4G4B4A4_UNORM_PACK16, vk_format: vk::Format::R4G4B4A4_UNORM_PACK16,
bpp: 2,
drm: fourcc_code('R', 'X', '1', '2'), drm: fourcc_code('R', 'X', '1', '2'),
..default(ConfigFormat::RGBX4444) ..default(ConfigFormat::RGBX4444)
}; };
@ -278,6 +285,7 @@ static RGBX4444: &Format = &Format {
static BGRA4444: &Format = &Format { static BGRA4444: &Format = &Format {
name: "bgra4444", name: "bgra4444",
vk_format: vk::Format::B4G4R4A4_UNORM_PACK16, vk_format: vk::Format::B4G4R4A4_UNORM_PACK16,
bpp: 2,
drm: fourcc_code('B', 'A', '1', '2'), drm: fourcc_code('B', 'A', '1', '2'),
has_alpha: true, has_alpha: true,
opaque: Some(BGRX4444), opaque: Some(BGRX4444),
@ -287,6 +295,7 @@ static BGRA4444: &Format = &Format {
static BGRX4444: &Format = &Format { static BGRX4444: &Format = &Format {
name: "bgrx4444", name: "bgrx4444",
vk_format: vk::Format::B4G4R4A4_UNORM_PACK16, vk_format: vk::Format::B4G4R4A4_UNORM_PACK16,
bpp: 2,
drm: fourcc_code('B', 'X', '1', '2'), drm: fourcc_code('B', 'X', '1', '2'),
..default(ConfigFormat::BGRX4444) ..default(ConfigFormat::BGRX4444)
}; };
@ -294,6 +303,7 @@ static BGRX4444: &Format = &Format {
static RGB565: &Format = &Format { static RGB565: &Format = &Format {
name: "rgb565", name: "rgb565",
vk_format: vk::Format::R5G6B5_UNORM_PACK16, vk_format: vk::Format::R5G6B5_UNORM_PACK16,
bpp: 2,
drm: fourcc_code('R', 'G', '1', '6'), drm: fourcc_code('R', 'G', '1', '6'),
pipewire: SPA_VIDEO_FORMAT_BGR16, pipewire: SPA_VIDEO_FORMAT_BGR16,
..default(ConfigFormat::RGB565) ..default(ConfigFormat::RGB565)
@ -302,6 +312,7 @@ static RGB565: &Format = &Format {
static BGR565: &Format = &Format { static BGR565: &Format = &Format {
name: "bgr565", name: "bgr565",
vk_format: vk::Format::B5G6R5_UNORM_PACK16, vk_format: vk::Format::B5G6R5_UNORM_PACK16,
bpp: 2,
drm: fourcc_code('B', 'G', '1', '6'), drm: fourcc_code('B', 'G', '1', '6'),
pipewire: SPA_VIDEO_FORMAT_RGB16, pipewire: SPA_VIDEO_FORMAT_RGB16,
..default(ConfigFormat::BGR565) ..default(ConfigFormat::BGR565)
@ -310,6 +321,7 @@ static BGR565: &Format = &Format {
static RGBA5551: &Format = &Format { static RGBA5551: &Format = &Format {
name: "rgba5551", name: "rgba5551",
vk_format: vk::Format::R5G5B5A1_UNORM_PACK16, vk_format: vk::Format::R5G5B5A1_UNORM_PACK16,
bpp: 2,
drm: fourcc_code('R', 'A', '1', '5'), drm: fourcc_code('R', 'A', '1', '5'),
has_alpha: true, has_alpha: true,
opaque: Some(RGBX5551), opaque: Some(RGBX5551),
@ -319,6 +331,7 @@ static RGBA5551: &Format = &Format {
static RGBX5551: &Format = &Format { static RGBX5551: &Format = &Format {
name: "rgbx5551", name: "rgbx5551",
vk_format: vk::Format::R5G5B5A1_UNORM_PACK16, vk_format: vk::Format::R5G5B5A1_UNORM_PACK16,
bpp: 2,
drm: fourcc_code('R', 'X', '1', '5'), drm: fourcc_code('R', 'X', '1', '5'),
..default(ConfigFormat::RGBX5551) ..default(ConfigFormat::RGBX5551)
}; };
@ -326,6 +339,7 @@ static RGBX5551: &Format = &Format {
static BGRA5551: &Format = &Format { static BGRA5551: &Format = &Format {
name: "bgra5551", name: "bgra5551",
vk_format: vk::Format::B5G5R5A1_UNORM_PACK16, vk_format: vk::Format::B5G5R5A1_UNORM_PACK16,
bpp: 2,
drm: fourcc_code('B', 'A', '1', '5'), drm: fourcc_code('B', 'A', '1', '5'),
has_alpha: true, has_alpha: true,
opaque: Some(BGRX5551), opaque: Some(BGRX5551),
@ -335,6 +349,7 @@ static BGRA5551: &Format = &Format {
static BGRX5551: &Format = &Format { static BGRX5551: &Format = &Format {
name: "bgrx5551", name: "bgrx5551",
vk_format: vk::Format::B5G5R5A1_UNORM_PACK16, vk_format: vk::Format::B5G5R5A1_UNORM_PACK16,
bpp: 2,
drm: fourcc_code('B', 'X', '1', '5'), drm: fourcc_code('B', 'X', '1', '5'),
..default(ConfigFormat::BGRX5551) ..default(ConfigFormat::BGRX5551)
}; };
@ -342,6 +357,7 @@ static BGRX5551: &Format = &Format {
static ARGB1555: &Format = &Format { static ARGB1555: &Format = &Format {
name: "argb1555", name: "argb1555",
vk_format: vk::Format::A1R5G5B5_UNORM_PACK16, vk_format: vk::Format::A1R5G5B5_UNORM_PACK16,
bpp: 2,
drm: fourcc_code('A', 'R', '1', '5'), drm: fourcc_code('A', 'R', '1', '5'),
has_alpha: true, has_alpha: true,
opaque: Some(XRGB1555), opaque: Some(XRGB1555),
@ -351,6 +367,7 @@ static ARGB1555: &Format = &Format {
static XRGB1555: &Format = &Format { static XRGB1555: &Format = &Format {
name: "xrgb1555", name: "xrgb1555",
vk_format: vk::Format::A1R5G5B5_UNORM_PACK16, vk_format: vk::Format::A1R5G5B5_UNORM_PACK16,
bpp: 2,
drm: fourcc_code('X', 'R', '1', '5'), drm: fourcc_code('X', 'R', '1', '5'),
pipewire: SPA_VIDEO_FORMAT_BGR15, pipewire: SPA_VIDEO_FORMAT_BGR15,
..default(ConfigFormat::XRGB1555) ..default(ConfigFormat::XRGB1555)
@ -359,6 +376,7 @@ static XRGB1555: &Format = &Format {
static ARGB2101010: &Format = &Format { static ARGB2101010: &Format = &Format {
name: "argb2101010", name: "argb2101010",
vk_format: vk::Format::A2R10G10B10_UNORM_PACK32, vk_format: vk::Format::A2R10G10B10_UNORM_PACK32,
bpp: 4,
drm: fourcc_code('A', 'R', '3', '0'), drm: fourcc_code('A', 'R', '3', '0'),
has_alpha: true, has_alpha: true,
opaque: Some(XRGB2101010), opaque: Some(XRGB2101010),
@ -369,6 +387,7 @@ static ARGB2101010: &Format = &Format {
static XRGB2101010: &Format = &Format { static XRGB2101010: &Format = &Format {
name: "xrgb2101010", name: "xrgb2101010",
vk_format: vk::Format::A2R10G10B10_UNORM_PACK32, vk_format: vk::Format::A2R10G10B10_UNORM_PACK32,
bpp: 4,
drm: fourcc_code('X', 'R', '3', '0'), drm: fourcc_code('X', 'R', '3', '0'),
pipewire: SPA_VIDEO_FORMAT_xRGB_210LE, pipewire: SPA_VIDEO_FORMAT_xRGB_210LE,
..default(ConfigFormat::XRGB2101010) ..default(ConfigFormat::XRGB2101010)
@ -377,6 +396,7 @@ static XRGB2101010: &Format = &Format {
static ABGR2101010: &Format = &Format { static ABGR2101010: &Format = &Format {
name: "abgr2101010", name: "abgr2101010",
vk_format: vk::Format::A2B10G10R10_UNORM_PACK32, vk_format: vk::Format::A2B10G10R10_UNORM_PACK32,
bpp: 4,
drm: fourcc_code('A', 'B', '3', '0'), drm: fourcc_code('A', 'B', '3', '0'),
has_alpha: true, has_alpha: true,
opaque: Some(XBGR2101010), opaque: Some(XBGR2101010),
@ -387,6 +407,7 @@ static ABGR2101010: &Format = &Format {
static XBGR2101010: &Format = &Format { static XBGR2101010: &Format = &Format {
name: "xbgr2101010", name: "xbgr2101010",
vk_format: vk::Format::A2B10G10R10_UNORM_PACK32, vk_format: vk::Format::A2B10G10R10_UNORM_PACK32,
bpp: 4,
drm: fourcc_code('X', 'B', '3', '0'), drm: fourcc_code('X', 'B', '3', '0'),
pipewire: SPA_VIDEO_FORMAT_xBGR_210LE, pipewire: SPA_VIDEO_FORMAT_xBGR_210LE,
..default(ConfigFormat::XBGR2101010) ..default(ConfigFormat::XBGR2101010)
@ -395,6 +416,7 @@ static XBGR2101010: &Format = &Format {
static ABGR16161616: &Format = &Format { static ABGR16161616: &Format = &Format {
name: "abgr16161616", name: "abgr16161616",
vk_format: vk::Format::R16G16B16A16_UNORM, vk_format: vk::Format::R16G16B16A16_UNORM,
bpp: 8,
drm: fourcc_code('A', 'B', '4', '8'), drm: fourcc_code('A', 'B', '4', '8'),
has_alpha: true, has_alpha: true,
opaque: Some(XBGR16161616), opaque: Some(XBGR16161616),
@ -404,6 +426,7 @@ static ABGR16161616: &Format = &Format {
static XBGR16161616: &Format = &Format { static XBGR16161616: &Format = &Format {
name: "xbgr16161616", name: "xbgr16161616",
vk_format: vk::Format::R16G16B16A16_UNORM, vk_format: vk::Format::R16G16B16A16_UNORM,
bpp: 8,
drm: fourcc_code('X', 'B', '4', '8'), drm: fourcc_code('X', 'B', '4', '8'),
..default(ConfigFormat::XBGR16161616) ..default(ConfigFormat::XBGR16161616)
}; };
@ -411,6 +434,7 @@ static XBGR16161616: &Format = &Format {
pub static ABGR16161616F: &Format = &Format { pub static ABGR16161616F: &Format = &Format {
name: "abgr16161616f", name: "abgr16161616f",
vk_format: vk::Format::R16G16B16A16_SFLOAT, vk_format: vk::Format::R16G16B16A16_SFLOAT,
bpp: 8,
drm: fourcc_code('A', 'B', '4', 'H'), drm: fourcc_code('A', 'B', '4', 'H'),
has_alpha: true, has_alpha: true,
opaque: Some(XBGR16161616F), opaque: Some(XBGR16161616F),
@ -420,6 +444,7 @@ pub static ABGR16161616F: &Format = &Format {
static XBGR16161616F: &Format = &Format { static XBGR16161616F: &Format = &Format {
name: "xbgr16161616f", name: "xbgr16161616f",
vk_format: vk::Format::R16G16B16A16_SFLOAT, vk_format: vk::Format::R16G16B16A16_SFLOAT,
bpp: 8,
drm: fourcc_code('X', 'B', '4', 'H'), drm: fourcc_code('X', 'B', '4', 'H'),
..default(ConfigFormat::XBGR16161616F) ..default(ConfigFormat::XBGR16161616F)
}; };

View file

@ -824,10 +824,12 @@ pub trait GfxContext: Debug {
dmabuf: &OwnedFd, dmabuf: &OwnedFd,
offset: usize, offset: usize,
size: usize, size: usize,
format: &'static Format,
) -> Result<Rc<dyn GfxBuffer>, GfxError> { ) -> Result<Rc<dyn GfxBuffer>, GfxError> {
let _ = dmabuf; let _ = dmabuf;
let _ = offset; let _ = offset;
let _ = size; let _ = size;
let _ = format;
#[derive(Debug, Error)] #[derive(Debug, Error)]
#[error("Host buffers are not supported")] #[error("Host buffers are not supported")]
@ -850,6 +852,7 @@ pub struct GfxFormat {
pub format: &'static Format, pub format: &'static Format,
pub read_modifiers: IndexSet<Modifier>, pub read_modifiers: IndexSet<Modifier>,
pub write_modifiers: IndexMap<Modifier, GfxWriteModifier>, pub write_modifiers: IndexMap<Modifier, GfxWriteModifier>,
pub supports_shm: bool,
} }
#[derive(Error)] #[derive(Error)]
@ -879,6 +882,7 @@ impl GfxFormat {
.map(|(m, v)| (*m, v.clone())) .map(|(m, v)| (*m, v.clone()))
.filter(|(m, _)| other.read_modifiers.contains(m)) .filter(|(m, _)| other.read_modifiers.contains(m))
.collect(), .collect(),
supports_shm: self.supports_shm && other.supports_shm,
} }
} }
} }

View file

@ -201,13 +201,17 @@ impl EglDisplay {
} }
read_modifiers.insert(modifier.modifier); read_modifiers.insert(modifier.modifier);
} }
if !read_modifiers.is_empty() || !write_modifiers.is_empty() { if !read_modifiers.is_empty()
|| !write_modifiers.is_empty()
|| format.format.shm_info.is_some()
{
formats.insert( formats.insert(
drm, drm,
GfxFormat { GfxFormat {
format: format.format, format: format.format,
read_modifiers, read_modifiers,
write_modifiers, write_modifiers,
supports_shm: format.format.shm_info.is_some(),
}, },
); );
} }

View file

@ -90,7 +90,7 @@ impl GlTexture {
(gles.glBindTexture)(GL_TEXTURE_2D, tex); (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_S, GL_CLAMP_TO_EDGE);
(gles.glTexParameteri)(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 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 / shm_info.bpp as GLint); (gles.glPixelStorei)(GL_UNPACK_ROW_LENGTH_EXT, stride / format.bpp as GLint);
(gles.glTexImage2D)( (gles.glTexImage2D)(
GL_TEXTURE_2D, GL_TEXTURE_2D,
0, 0,

View file

@ -90,7 +90,7 @@ impl AsyncShmGfxTexture for Texture {
(gles.glTexParameteri)(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); (gles.glTexParameteri)(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
(gles.glPixelStorei)( (gles.glPixelStorei)(
GL_UNPACK_ROW_LENGTH_EXT, GL_UNPACK_ROW_LENGTH_EXT,
self.gl.stride / shm_info.bpp as GLint, self.gl.stride / self.format.bpp as GLint,
); );
(gles.glTexImage2D)( (gles.glTexImage2D)(
GL_TEXTURE_2D, GL_TEXTURE_2D,

View file

@ -179,8 +179,6 @@ pub enum VulkanError {
InvalidStride, InvalidStride,
#[error("Shm stride and height do not match buffer size")] #[error("Shm stride and height do not match buffer size")]
InvalidBufferSize, InvalidBufferSize,
#[error("Buffer format {0} is not supported for shm buffers in Vulkan context")]
UnsupportedShmFormat(&'static str),
#[error("Only BO_USE_RENDERING and BO_USE_WRITE are supported")] #[error("Only BO_USE_RENDERING and BO_USE_WRITE are supported")]
UnsupportedBufferUsage, UnsupportedBufferUsage,
#[error("None of the supplied modifiers are supported")] #[error("None of the supplied modifiers are supported")]
@ -223,7 +221,7 @@ pub enum VulkanError {
GetFl(#[source] OsError), GetFl(#[source] OsError),
#[error("GBM implementation cannot be used with software renderer")] #[error("GBM implementation cannot be used with software renderer")]
SoftwareRendererNotUsable, SoftwareRendererNotUsable,
#[error("DMABUF buffer offsets must be aligned to 4 bytes")] #[error("DMABUF buffer offsets must be aligned to 4 bytes and the pixel size")]
DmaBufBufferOffsetAlignment, DmaBufBufferOffsetAlignment,
} }
@ -403,12 +401,13 @@ impl GfxContext for Context {
dmabuf: &OwnedFd, dmabuf: &OwnedFd,
offset: usize, offset: usize,
size: usize, size: usize,
format: &'static Format,
) -> Result<Rc<dyn GfxBuffer>, GfxError> { ) -> Result<Rc<dyn GfxBuffer>, GfxError> {
self.0.check_defunct()?; self.0.check_defunct()?;
let buffer = self let buffer =
.0 self.0
.device .device
.create_dmabuf_buffer(dmabuf, offset as u64, size as u64)?; .create_dmabuf_buffer(dmabuf, offset as u64, size as u64, format)?;
Ok(buffer) Ok(buffer)
} }
} }

View file

@ -457,10 +457,7 @@ impl Allocator for VulkanBoAllocator {
impl VulkanBo { impl VulkanBo {
fn map(self: &Rc<Self>, write: bool) -> Result<VulkanBoMapping, VulkanError> { fn map(self: &Rc<Self>, write: bool) -> Result<VulkanBoMapping, VulkanError> {
let format = self.buf.format; let format = self.buf.format;
let Some(shm_info) = &format.shm_info else { let stride = self.buf.width as u32 * format.bpp;
return Err(VulkanError::ShmNotSupported);
};
let stride = self.buf.width as u32 * shm_info.bpp;
let size = self.buf.height as u32 * stride; let size = self.buf.height as u32 * stride;
let data = &self.allocator; let data = &self.allocator;
let staging = let staging =

View file

@ -1,5 +1,6 @@
use { use {
crate::{ crate::{
format::Format,
gfx_api::GfxBuffer, gfx_api::GfxBuffer,
gfx_apis::vulkan::{VulkanError, device::VulkanDevice}, gfx_apis::vulkan::{VulkanError, device::VulkanDevice},
utils::on_drop::OnDrop, utils::on_drop::OnDrop,
@ -32,8 +33,9 @@ impl VulkanDevice {
dmabuf: &OwnedFd, dmabuf: &OwnedFd,
offset: u64, offset: u64,
size: u64, size: u64,
format: &'static Format,
) -> Result<Rc<VulkanDmabufBuffer>, VulkanError> { ) -> Result<Rc<VulkanDmabufBuffer>, VulkanError> {
if offset % TRANSFER_QUEUE_BUFFER_ALIGNMENT != 0 { if offset % TRANSFER_QUEUE_BUFFER_ALIGNMENT != 0 || offset % format.bpp as u64 != 0 {
return Err(VulkanError::DmaBufBufferOffsetAlignment); return Err(VulkanError::DmaBufBufferOffsetAlignment);
} }
let mut memory_fd_properties = MemoryFdPropertiesKHR::default(); let mut memory_fd_properties = MemoryFdPropertiesKHR::default();

View file

@ -171,9 +171,6 @@ impl VulkanInstance {
format: &Format, format: &Format,
props: &FormatProperties, props: &FormatProperties,
) -> Result<Option<VulkanInternalFormat>, VulkanError> { ) -> Result<Option<VulkanInternalFormat>, VulkanError> {
if format.shm_info.is_none() {
return Ok(None);
}
self.load_internal_format(phy_dev, format, props, SHM_FEATURES, SHM_USAGE) self.load_internal_format(phy_dev, format, props, SHM_FEATURES, SHM_USAGE)
} }

View file

@ -345,6 +345,7 @@ impl VulkanDevice {
) )
}) })
.collect(), .collect(),
supports_shm: vk.shm.is_some(),
}, },
) )
}) })

View file

@ -1,7 +1,7 @@
use { use {
crate::{ crate::{
cpu_worker::CpuWorker, cpu_worker::CpuWorker,
format::{Format, FormatShmInfo}, format::Format,
gfx_api::SyncFile, gfx_api::SyncFile,
gfx_apis::vulkan::{ gfx_apis::vulkan::{
VulkanError, VulkanError,
@ -33,7 +33,6 @@ pub struct VulkanShmImage {
pub(super) size: DeviceSize, pub(super) size: DeviceSize,
pub(super) stride: u32, pub(super) stride: u32,
pub(super) _allocation: VulkanAllocation, pub(super) _allocation: VulkanAllocation,
pub(super) shm_info: &'static FormatShmInfo,
pub(super) async_data: Option<VulkanShmImageAsyncData>, pub(super) async_data: Option<VulkanShmImageAsyncData>,
} }
@ -68,7 +67,7 @@ impl VulkanShmImage {
if full { if full {
builder = builder builder = builder
.buffer_image_height(img.height) .buffer_image_height(img.height)
.buffer_row_length(img.stride / self.shm_info.bpp); .buffer_row_length(img.stride / img.format.bpp);
} }
builder builder
}; };
@ -99,7 +98,7 @@ impl VulkanShmImage {
damage.width() as u32, damage.width() as u32,
damage.height() as u32, damage.height() as u32,
)); ));
total_size += damage.width() as u32 * damage.height() as u32 * self.shm_info.bpp; total_size += damage.width() as u32 * damage.height() as u32 * img.format.bpp;
} }
cpy = &cpy_many[..]; cpy = &cpy_many[..];
} else { } else {
@ -124,7 +123,7 @@ impl VulkanShmImage {
let width = cpy.image_extent.width as usize; let width = cpy.image_extent.width as usize;
let height = cpy.image_extent.height as usize; let height = cpy.image_extent.height as usize;
let stride = self.stride as usize; let stride = self.stride as usize;
let bpp = self.shm_info.bpp as usize; let bpp = img.format.bpp as usize;
for dy in 0..height { for dy in 0..height {
let lo = (y + dy) * stride + x * bpp; let lo = (y + dy) * stride + x * bpp;
let len = width * bpp; let len = width * bpp;
@ -367,16 +366,13 @@ impl VulkanRenderer {
for_download: bool, for_download: bool,
cpu_worker: Option<&Rc<CpuWorker>>, cpu_worker: Option<&Rc<CpuWorker>>,
) -> Result<Rc<VulkanImage>, VulkanError> { ) -> 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 { if width <= 0 || height <= 0 || stride <= 0 {
return Err(VulkanError::NonPositiveImageSize); return Err(VulkanError::NonPositiveImageSize);
} }
let width = width as u32; let width = width as u32;
let height = height as u32; let height = height as u32;
let stride = stride as u32; let stride = stride as u32;
if stride % shm_info.bpp != 0 || stride / shm_info.bpp < width { if stride % format.bpp != 0 || stride / format.bpp < width {
return Err(VulkanError::InvalidStride); return Err(VulkanError::InvalidStride);
} }
let vk_format = self let vk_format = self
@ -461,7 +457,6 @@ impl VulkanRenderer {
size, size,
stride, stride,
_allocation: allocation, _allocation: allocation,
shm_info,
async_data, async_data,
}; };
destroy_image.forget(); destroy_image.forget();

View file

@ -13,7 +13,7 @@ use {
gfx_apis::vulkan::{ gfx_apis::vulkan::{
VulkanError, VulkanError,
command::VulkanCommandBuffer, command::VulkanCommandBuffer,
dmabuf_buffer::VulkanDmabufBuffer, dmabuf_buffer::{TRANSFER_QUEUE_BUFFER_ALIGNMENT, VulkanDmabufBuffer},
fence::VulkanFence, fence::VulkanFence,
image::{QueueFamily, QueueState, QueueTransfer, VulkanImage, VulkanImageMemory}, image::{QueueFamily, QueueState, QueueTransfer, VulkanImage, VulkanImageMemory},
renderer::image_barrier, renderer::image_barrier,
@ -227,8 +227,25 @@ impl VulkanShmImage {
let mut copies_ref = data.regions.borrow_mut(); let mut copies_ref = data.regions.borrow_mut();
let copies = &mut *copies_ref; let copies = &mut *copies_ref;
copies.clear(); copies.clear();
let mut copy = |x, y, width, height| { let mut copy = |mut x, mut y, mut width, mut height| {
let buffer_offset = (y as u32 * img.stride + x as u32 * self.shm_info.bpp) as u64; let x_orig = x;
let width_orig = width;
let mut buffer_offset;
loop {
buffer_offset = (y as u32 * img.stride + x as u32 * img.format.bpp) as u64;
if buffer_offset.is_multiple_of(TRANSFER_QUEUE_BUFFER_ALIGNMENT) {
break;
}
if x > 0 {
x -= 1;
width += 1;
} else {
y -= 1;
height += 1;
x = x_orig;
width = width_orig;
}
}
let copy = BufferImageCopy2::default() let copy = BufferImageCopy2::default()
.buffer_offset(buffer_offset + extra_offset) .buffer_offset(buffer_offset + extra_offset)
.image_offset(Offset3D { x, y, z: 0 }) .image_offset(Offset3D { x, y, z: 0 })
@ -244,7 +261,7 @@ impl VulkanShmImage {
layer_count: 1, layer_count: 1,
}) })
.buffer_image_height(img.height) .buffer_image_height(img.height)
.buffer_row_length(img.stride / self.shm_info.bpp); .buffer_row_length(img.stride / img.format.bpp);
copies.push(copy); copies.push(copy);
}; };
let (width_mask, height_mask) = img.renderer.device.transfer_granularity_mask; let (width_mask, height_mask) = img.renderer.device.transfer_granularity_mask;
@ -451,7 +468,7 @@ impl VulkanShmImage {
} }
job.work.width = img.width as _; job.work.width = img.width as _;
job.work.stride = img.stride as _; job.work.stride = img.stride as _;
job.work.bpp = self.shm_info.bpp as _; job.work.bpp = img.format.bpp as _;
job.work.rects.clear(); job.work.rects.clear();
for copy in copies { for copy in copies {
job.work.rects.push( job.work.rects.push(
@ -472,7 +489,7 @@ impl VulkanShmImage {
for copy in copies { for copy in copies {
min_offset = min_offset.min(copy.buffer_offset); min_offset = min_offset.min(copy.buffer_offset);
let len = img.stride * (copy.image_extent.height - 1) let len = img.stride * (copy.image_extent.height - 1)
+ copy.image_extent.width * self.shm_info.bpp; + copy.image_extent.width * img.format.bpp;
max_offset = max_offset.max(copy.buffer_offset + len as u64); max_offset = max_offset.max(copy.buffer_offset + len as u64);
} }
let mut job = data.io_job.take().unwrap_or_else(|| { let mut job = data.io_job.take().unwrap_or_else(|| {

View file

@ -109,16 +109,13 @@ impl WlBuffer {
format: &'static Format, format: &'static Format,
mem: &Rc<ClientMem>, mem: &Rc<ClientMem>,
) -> Result<Self, WlBufferError> { ) -> 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 bytes = stride as u64 * height as u64;
let required = bytes + offset as u64; let required = bytes + offset as u64;
if required > mem.len() as u64 { if required > mem.len() as u64 {
return Err(WlBufferError::OutOfBounds); return Err(WlBufferError::OutOfBounds);
} }
let mem = Rc::new(mem.offset(offset)); let mem = Rc::new(mem.offset(offset));
let min_row_size = width as u64 * shm_info.bpp as u64; let min_row_size = width as u64 * format.bpp as u64;
if (stride as u64) < min_row_size { if (stride as u64) < min_row_size {
return Err(WlBufferError::StrideTooSmall); return Err(WlBufferError::StrideTooSmall);
} }
@ -310,14 +307,15 @@ impl WlBuffer {
} }
} }
}; };
let hb = match ctx.create_dmabuf_buffer(&udmabuf, *udmabuf_offset, *udmabuf_size) { let hb =
Ok(hb) => hb, match ctx.create_dmabuf_buffer(&udmabuf, *udmabuf_offset, *udmabuf_size, self.format) {
Err(e) => { Ok(hb) => hb,
*host_buffer_impossible = true; Err(e) => {
log::debug!("Could not create gfx host buffer: {}", ErrorFmt(e)); *host_buffer_impossible = true;
return Ok(None); log::debug!("Could not create gfx host buffer: {}", ErrorFmt(e));
} return Ok(None);
}; }
};
*host_buffer = Some(hb.clone()); *host_buffer = Some(hb.clone());
Ok(Some(hb)) Ok(Some(hb))
} }
@ -407,8 +405,6 @@ pub enum WlBufferError {
GfxError(#[from] GfxError), GfxError(#[from] GfxError),
#[error(transparent)] #[error(transparent)]
ClientError(Box<ClientError>), ClientError(Box<ClientError>),
#[error("Buffer format {0} is not supported for shm buffers")]
UnsupportedShmFormat(&'static str),
} }
efrom!(WlBufferError, ClientMemError); efrom!(WlBufferError, ClientMemError);
efrom!(WlBufferError, ClientError); efrom!(WlBufferError, ClientError);

View file

@ -1,7 +1,6 @@
use { use {
crate::{ crate::{
client::{Client, ClientError}, client::{Client, ClientError},
format::FORMATS,
globals::{Global, GlobalName}, globals::{Global, GlobalName},
ifs::wl_shm_pool::{WlShmPool, WlShmPoolError}, ifs::wl_shm_pool::{WlShmPool, WlShmPoolError},
leaks::Tracker, leaks::Tracker,
@ -44,12 +43,14 @@ impl WlShmGlobal {
}); });
track!(client, obj); track!(client, obj);
client.add_client_obj(&obj)?; client.add_client_obj(&obj)?;
for format in FORMATS { if let Some(ctx) = client.state.render_ctx.get() {
if format.shm_info.is_some() { for format in ctx.formats().values() {
client.event(Format { if format.supports_shm {
self_id: id, client.event(Format {
format: format.wl_id.unwrap_or(format.drm), self_id: id,
}); format: format.format.wl_id.unwrap_or(format.format.drm),
});
}
} }
} }
Ok(()) Ok(())

View file

@ -53,10 +53,9 @@ impl WlShmPoolRequestHandler for WlShmPool {
fn create_buffer(&self, req: CreateBuffer, _slf: &Rc<Self>) -> Result<(), Self::Error> { fn create_buffer(&self, req: CreateBuffer, _slf: &Rc<Self>) -> Result<(), Self::Error> {
let drm_format = map_wayland_format_id(req.format); let drm_format = map_wayland_format_id(req.format);
let format = match formats().get(&drm_format) { let format = formats()
Some(f) if f.shm_info.is_some() => *f, .get(&drm_format)
_ => return Err(WlShmPoolError::InvalidFormat(req.format)), .ok_or(WlShmPoolError::InvalidFormat(req.format))?;
};
if req.height < 0 || req.width < 0 || req.stride < 0 || req.offset < 0 { if req.height < 0 || req.width < 0 || req.stride < 0 || req.offset < 0 {
return Err(WlShmPoolError::NegativeParameters); return Err(WlShmPoolError::NegativeParameters);
} }

View file

@ -77,6 +77,7 @@ impl TestGfxCtx {
) )
}) })
.collect(), .collect(),
supports_shm: true,
}, },
); );
} }

View file

@ -10,6 +10,7 @@ testcase!();
/// Test that wl_shm supports the required formats /// Test that wl_shm supports the required formats
async fn test(run: Rc<TestRun>) -> Result<(), TestError> { async fn test(run: Rc<TestRun>) -> Result<(), TestError> {
run.backend.install_render_context(false)?;
let client = run.create_client().await?; let client = run.create_client().await?;
let formats = client.shm.formats().await; let formats = client.shm.formats().await;
tassert!(formats.contains(&XRGB8888.wl_id.unwrap())); tassert!(formats.contains(&XRGB8888.wl_id.unwrap()));

View file

@ -2,7 +2,7 @@ use {
crate::{ crate::{
cmm::cmm_eotf::Eotf, cmm::cmm_eotf::Eotf,
cpu_worker::{AsyncCpuWork, CpuJob, CpuWork, CpuWorker, PendingJob}, cpu_worker::{AsyncCpuWork, CpuJob, CpuWork, CpuWorker, PendingJob},
format::ARGB8888, format::{ARGB8888, Format},
gfx_api::{ gfx_api::{
AsyncShmGfxTexture, AsyncShmGfxTextureCallback, GfxBuffer, GfxContext, GfxError, AsyncShmGfxTexture, AsyncShmGfxTextureCallback, GfxBuffer, GfxContext, GfxError,
GfxStagingBuffer, GfxTexture, PendingShmTransfer, STAGING_UPLOAD, GfxStagingBuffer, GfxTexture, PendingShmTransfer, STAGING_UPLOAD,
@ -125,7 +125,8 @@ struct Data {
layout: PangoLayout, layout: PangoLayout,
} }
const FORMAT: CairoFormat = CAIRO_FORMAT_ARGB32; const CAIRO_FORMAT: CairoFormat = CAIRO_FORMAT_ARGB32;
const FORMAT: &Format = ARGB8888;
fn create_data( fn create_data(
memfd: &Memfd, memfd: &Memfd,
@ -134,12 +135,12 @@ fn create_data(
height: i32, height: i32,
scale: Option<f64>, scale: Option<f64>,
) -> Result<Data, TextError> { ) -> Result<Data, TextError> {
let Some((stride, size)) = cairo_size(FORMAT, width, height) else { let Some((stride, size)) = cairo_size(CAIRO_FORMAT, width, height) else {
return Err(TextError::SizeOverflow); return Err(TextError::SizeOverflow);
}; };
let data = memfd.get_pointer_for_size(size)?; let data = memfd.get_pointer_for_size(size)?;
let image = match unsafe { let image = match unsafe {
CairoImageSurface::new_image_surface_with_data(FORMAT, data, width, height, stride) CairoImageSurface::new_image_surface_with_data(CAIRO_FORMAT, data, width, height, stride)
} { } {
Ok(s) => s, Ok(s) => s,
Err(e) => return Err(TextError::CreateImage(e)), Err(e) => return Err(TextError::CreateImage(e)),
@ -397,7 +398,7 @@ impl Shared {
break 'res None; break 'res None;
} }
}; };
match self.ctx.create_dmabuf_buffer(&dmabuf, 0, size) { match self.ctx.create_dmabuf_buffer(&dmabuf, 0, size, FORMAT) {
Ok(b) => Some(b), Ok(b) => Some(b),
Err(e) => { Err(e) => {
log::debug!("Could not create GfxBuffer: {}", ErrorFmt(e)); log::debug!("Could not create GfxBuffer: {}", ErrorFmt(e));
@ -604,7 +605,7 @@ impl CpuJob for RenderJob {
return; return;
} }
if let Some(t) = &tex if let Some(t) = &tex
&& !t.compatible_with(ARGB8888, rt.width, rt.height, rt.stride) && !t.compatible_with(FORMAT, rt.width, rt.height, rt.stride)
{ {
tex = None; tex = None;
} }
@ -614,7 +615,7 @@ impl CpuJob for RenderJob {
let tex = data let tex = data
.ctx .ctx
.clone() .clone()
.async_shmem_texture(ARGB8888, rt.width, rt.height, rt.stride, &data.cpu_worker) .async_shmem_texture(FORMAT, rt.width, rt.height, rt.stride, &data.cpu_worker)
.map_err(TextError::CreateTexture); .map_err(TextError::CreateTexture);
match tex { match tex {
Ok(t) => t, Ok(t) => t,

View file

@ -30,8 +30,6 @@ pub enum UdmabufError {
Open(#[source] OsError), Open(#[source] OsError),
#[error("Only the linear modifier can be allocated")] #[error("Only the linear modifier can be allocated")]
Modifier, Modifier,
#[error("Format {0} is not supported")]
Format(&'static str),
#[error("Could not create a memfd")] #[error("Could not create a memfd")]
Memfd(#[source] OsError), Memfd(#[source] OsError),
#[error("Size calculation overflowed")] #[error("Size calculation overflowed")]
@ -131,16 +129,13 @@ impl Allocator for Udmabuf {
if !modifiers.contains(&LINEAR_MODIFIER) { if !modifiers.contains(&LINEAR_MODIFIER) {
return Err(UdmabufError::Modifier.into()); return Err(UdmabufError::Modifier.into());
} }
let Some(shm_info) = &format.shm_info else {
return Err(UdmabufError::Format(format.name).into());
};
let height = height as u64; let height = height as u64;
let width = width as u64; let width = width as u64;
if height > 1 << 16 || width > 1 << 16 { if height > 1 << 16 || width > 1 << 16 {
return Err(UdmabufError::Overflow.into()); return Err(UdmabufError::Overflow.into());
} }
let stride_mask = 255; let stride_mask = 255;
let stride = (width * shm_info.bpp as u64 + stride_mask) & !stride_mask; let stride = (width * format.bpp as u64 + stride_mask) & !stride_mask;
let size_mask = page_size() as u64 - 1; let size_mask = page_size() as u64 - 1;
let size = (height * stride + size_mask) & !size_mask; let size = (height * stride + size_mask) & !size_mask;
let memfd = match uapi::memfd_create("udmabuf", MFD_ALLOW_SEALING) { let memfd = match uapi::memfd_create("udmabuf", MFD_ALLOW_SEALING) {
@ -186,9 +181,6 @@ impl Allocator for Udmabuf {
return Err(UdmabufError::Modifier.into()); return Err(UdmabufError::Modifier.into());
} }
let plane = &dmabuf.planes[0]; let plane = &dmabuf.planes[0];
let Some(shm_info) = &dmabuf.format.shm_info else {
return Err(UdmabufError::Format(dmabuf.format.name).into());
};
let height = dmabuf.height as u64; let height = dmabuf.height as u64;
let width = dmabuf.width as u64; let width = dmabuf.width as u64;
let stride = plane.stride as u64; let stride = plane.stride as u64;
@ -196,7 +188,7 @@ impl Allocator for Udmabuf {
if height > 1 << 16 || width > 1 << 16 { if height > 1 << 16 || width > 1 << 16 {
return Err(UdmabufError::Overflow.into()); return Err(UdmabufError::Overflow.into());
} }
if stride < width * shm_info.bpp as u64 { if stride < width * dmabuf.format.bpp as u64 {
return Err(UdmabufError::Stride.into()); return Err(UdmabufError::Stride.into());
} }
let size = offset + stride * height; let size = offset + stride * height;

View file

@ -80,6 +80,7 @@ impl JayRenderCtxEventHandler for UsrJayRenderCtx {
format, format,
read_modifiers: Default::default(), read_modifiers: Default::default(),
write_modifiers: Default::default(), write_modifiers: Default::default(),
supports_shm: false,
}, },
); );
} }