1
0
Fork 0
forked from wry/wry

autocommit 2022-01-29 00:49:52 CET

This commit is contained in:
Julian Orth 2022-01-29 00:49:52 +01:00
parent b11a36729c
commit 85b019101a
41 changed files with 1322 additions and 61 deletions

View file

@ -6,6 +6,7 @@ pub mod wl_data_device_manager;
pub mod wl_data_offer;
pub mod wl_data_source;
pub mod wl_display;
pub mod wl_drm;
pub mod wl_output;
pub mod wl_region;
pub mod wl_registry;
@ -16,3 +17,5 @@ pub mod wl_subcompositor;
pub mod wl_surface;
pub mod xdg_positioner;
pub mod xdg_wm_base;
pub mod zwp_linux_buffer_params_v1;
pub mod zwp_linux_dmabuf_v1;

View file

@ -6,7 +6,7 @@ use crate::format::Format;
use crate::ifs::wl_surface::{WlSurface, WlSurfaceId};
use crate::object::{Interface, Object, ObjectId};
use crate::rect::Rect;
use crate::render::Texture;
use crate::render::{Image, Texture};
use crate::utils::buffd::MsgParser;
use crate::utils::clonecell::CloneCell;
use crate::utils::copyhashmap::CopyHashMap;
@ -19,14 +19,17 @@ const RELEASE: u32 = 0;
id!(WlBufferId);
pub enum WlBufferStorage {
Shm { mem: ClientMemOffset, stride: i32 },
Dmabuf(Rc<Image>),
}
pub struct WlBuffer {
id: WlBufferId,
pub client: Rc<Client>,
_offset: usize,
pub rect: Rect,
stride: i32,
format: &'static Format,
mem: ClientMemOffset,
storage: WlBufferStorage,
pub texture: CloneCell<Option<Rc<Texture>>>,
pub(super) surfaces: CopyHashMap<WlSurfaceId, Rc<WlSurface>>,
width: i32,
@ -35,7 +38,29 @@ pub struct WlBuffer {
impl WlBuffer {
#[allow(clippy::too_many_arguments)]
pub fn new(
pub fn new_dmabuf(
id: WlBufferId,
client: &Rc<Client>,
format: &'static Format,
img: &Rc<Image>,
) -> Self {
let width = img.width();
let height = img.height();
Self {
id,
client: client.clone(),
rect: Rect::new_sized(0, 0, width, height).unwrap(),
format,
width,
height,
texture: CloneCell::new(None),
surfaces: Default::default(),
storage: WlBufferStorage::Dmabuf(img.clone()),
}
}
#[allow(clippy::too_many_arguments)]
pub fn new_shm(
id: WlBufferId,
client: &Rc<Client>,
offset: usize,
@ -58,11 +83,9 @@ impl WlBuffer {
Ok(Self {
id,
client: client.clone(),
_offset: offset,
rect: Rect::new_sized(0, 0, width, height).unwrap(),
stride,
format,
mem,
storage: WlBufferStorage::Shm { mem, stride },
width,
height,
texture: CloneCell::new(None),
@ -71,12 +94,21 @@ impl WlBuffer {
}
pub fn update_texture(&self) -> Result<(), WlBufferError> {
self.texture.set(None);
let ctx = self.client.state.render_ctx.get().unwrap();
let tex = self.mem.access(|mem| {
ctx.shmem_texture(mem, self.format, self.width, self.height, self.stride)
})??;
self.texture.set(Some(tex));
match &self.storage {
WlBufferStorage::Shm { mem, stride } => {
self.texture.set(None);
let ctx = self.client.state.render_ctx.get().unwrap();
let tex = mem.access(|mem| {
ctx.shmem_texture(mem, self.format, self.width, self.height, *stride)
})??;
self.texture.set(Some(tex));
}
WlBufferStorage::Dmabuf(img) => {
if self.texture.get().is_none() {
self.texture.set(Some(img.to_texture()?));
}
}
}
Ok(())
}

145
src/ifs/wl_drm/mod.rs Normal file
View file

@ -0,0 +1,145 @@
use std::ffi::CString;
use crate::client::{Client, DynEventFormatter};
use crate::globals::{Global, GlobalName};
use crate::object::{Interface, Object, ObjectId};
use crate::utils::buffd::MsgParser;
use std::rc::Rc;
pub use types::*;
mod types;
id!(WlDrmId);
const AUTHENTICATE: u32 = 0;
const CREATE_BUFFER: u32 = 1;
const CREATE_PLANAR_BUFFER: u32 = 2;
const DEVICE: u32 = 0;
const FORMAT: u32 = 1;
const AUTHENTICATED: u32 = 2;
const CAPABILITIES: u32 = 3;
const PRIME: u32 = 1;
pub struct WlDrmGlobal {
name: GlobalName,
}
impl WlDrmGlobal {
pub fn new(name: GlobalName) -> Self {
Self { name }
}
fn bind_(
self: Rc<Self>,
id: WlDrmId,
client: &Rc<Client>,
version: u32,
) -> Result<(), WlDrmError> {
let obj = Rc::new(WlDrmObj {
id,
client: client.clone(),
_version: version,
});
client.add_client_obj(&obj)?;
if let Some(rc) = client.state.render_ctx.get() {
client.event(obj.device(&rc.render_node()));
client.event(obj.capabilities(PRIME));
}
Ok(())
}
}
bind!(WlDrmGlobal);
impl Global for WlDrmGlobal {
fn name(&self) -> GlobalName {
self.name
}
fn singleton(&self) -> bool {
true
}
fn interface(&self) -> Interface {
Interface::WlDrm
}
fn version(&self) -> u32 {
1
}
}
pub struct WlDrmObj {
id: WlDrmId,
pub client: Rc<Client>,
_version: u32,
}
impl WlDrmObj {
fn device(self: &Rc<Self>, device: &Rc<CString>) -> DynEventFormatter {
Box::new(Device {
obj: self.clone(),
name: device.clone(),
})
}
fn authenticated(self: &Rc<Self>) -> DynEventFormatter {
Box::new(Authenticated {
obj: self.clone(),
})
}
fn capabilities(self: &Rc<Self>, value: u32) -> DynEventFormatter {
Box::new(Capabilities {
obj: self.clone(),
value,
})
}
fn authenticate(self: &Rc<Self>, parser: MsgParser<'_, '_>) -> Result<(), AuthenticateError> {
let _req: Authenticate = self.client.parse(&**self, parser)?;
self.client.event(self.authenticated());
Ok(())
}
fn create_buffer(self: &Rc<Self>, parser: MsgParser<'_, '_>) -> Result<(), CreateBufferError> {
let _req: CreateBuffer = self.client.parse(&**self, parser)?;
Err(CreateBufferError::Unsupported)
}
fn create_planar_buffer(self: &Rc<Self>, parser: MsgParser<'_, '_>) -> Result<(), CreatePlanarBufferError> {
let _req: CreatePlanarBuffer = self.client.parse(&**self, parser)?;
Err(CreatePlanarBufferError::Unsupported)
}
fn handle_request_(
self: &Rc<Self>,
request: u32,
parser: MsgParser<'_, '_>,
) -> Result<(), WlDrmError> {
match request {
AUTHENTICATE => self.authenticate(parser)?,
CREATE_BUFFER => self.create_buffer(parser)?,
CREATE_PLANAR_BUFFER => self.create_planar_buffer(parser)?,
_ => unreachable!(),
}
Ok(())
}
}
handle_request!(WlDrmObj);
impl Object for WlDrmObj {
fn id(&self) -> ObjectId {
self.id.into()
}
fn interface(&self) -> Interface {
Interface::WlDrm
}
fn num_requests(&self) -> u32 {
CREATE_PLANAR_BUFFER + 1
}
}

223
src/ifs/wl_drm/types.rs Normal file
View file

@ -0,0 +1,223 @@
use std::ffi::CString;
use crate::client::{ClientError, EventFormatter, RequestParser};
use crate::ifs::wl_buffer::WlBufferId;
use crate::object::Object;
use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError};
use std::fmt::{Debug, Formatter};
use std::rc::Rc;
use thiserror::Error;
use crate::ifs::wl_drm::{AUTHENTICATED, CAPABILITIES, DEVICE, FORMAT, WlDrmObj};
#[derive(Debug, Error)]
pub enum WlDrmError {
#[error("Could not process a `authenticate` request")]
AuthenticateError(#[from] AuthenticateError),
#[error("Could not process a `create_buffer` request")]
CreateBufferError(#[from] CreateBufferError),
#[error("Could not process a `create_planar_buffer` request")]
CreatePlanarBufferError(#[from] CreatePlanarBufferError),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(WlDrmError, ClientError, ClientError);
#[derive(Debug, Error)]
pub enum AuthenticateError {
#[error("Parsing failed")]
ParseError(#[source] Box<MsgParserError>),
}
efrom!(AuthenticateError, ParseError, MsgParserError);
#[derive(Debug, Error)]
pub enum CreateBufferError {
#[error("Parsing failed")]
ParseError(#[source] Box<MsgParserError>),
#[error("This api is not supported")]
Unsupported,
}
efrom!(CreateBufferError, ParseError, MsgParserError);
#[derive(Debug, Error)]
pub enum CreatePlanarBufferError {
#[error("Parsing failed")]
ParseError(#[source] Box<MsgParserError>),
#[error("This api is not supported")]
Unsupported,
}
efrom!(CreatePlanarBufferError, ParseError, MsgParserError);
pub(super) struct Authenticate {
id: u32,
}
impl RequestParser<'_> for Authenticate {
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self { id: parser.uint()? })
}
}
impl Debug for Authenticate {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "authenticate(id: {})", self.id)
}
}
pub(super) struct CreateBuffer {
pub id: WlBufferId,
pub name: u32,
pub width: i32,
pub height: i32,
pub stride: u32,
pub format: u32,
}
impl RequestParser<'_> for CreateBuffer {
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self {
id: parser.object()?,
name: parser.uint()?,
width: parser.int()?,
height: parser.int()?,
stride: parser.uint()?,
format: parser.uint()?,
})
}
}
impl Debug for CreateBuffer {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"create_buffer(id: {}, name: {}, width: {}, height: {}, stride: {}, format: {})",
self.id, self.name, self.width, self.height, self.stride, self.format,
)
}
}
pub(super) struct CreatePlanarBuffer {
id: WlBufferId,
name: u32,
width: i32,
height: i32,
format: u32,
offset0: i32,
stride0: i32,
offset1: i32,
stride1: i32,
offset2: i32,
stride2: i32,
}
impl RequestParser<'_> for CreatePlanarBuffer {
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self {
id: parser.object()?,
name: parser.uint()?,
width: parser.int()?,
height: parser.int()?,
format: parser.uint()?,
offset0: parser.int()?,
stride0: parser.int()?,
offset1: parser.int()?,
stride1: parser.int()?,
offset2: parser.int()?,
stride2: parser.int()?,
})
}
}
impl Debug for CreatePlanarBuffer {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "create_params(id: {}, name: {}, width: {}, height: {}, format: {}, offset0: {}, stride0: {}, offset1: {}, stride1: {}, offset2: {}, stride2: {})",
self.id,
self.name,
self.width,
self.height,
self.format,
self.offset0,
self.stride0,
self.offset1,
self.stride1,
self.offset2,
self.stride2,
)
}
}
pub(super) struct Device {
pub obj: Rc<WlDrmObj>,
pub name: Rc<CString>,
}
impl EventFormatter for Device {
fn format(self: Box<Self>, fmt: &mut MsgFormatter<'_>) {
fmt.header(self.obj.id, DEVICE).string(self.name.as_bytes());
}
fn obj(&self) -> &dyn Object {
&*self.obj
}
}
impl Debug for Device {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "device(name: {:?})", self.name)
}
}
pub(super) struct Format {
pub obj: Rc<WlDrmObj>,
pub format: u32,
}
impl EventFormatter for Format {
fn format(self: Box<Self>, fmt: &mut MsgFormatter<'_>) {
fmt.header(self.obj.id, FORMAT)
.uint(self.format);
}
fn obj(&self) -> &dyn Object {
&*self.obj
}
}
impl Debug for Format {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"format(format: {})",
self.format,
)
}
}
pub(super) struct Authenticated {
pub obj: Rc<WlDrmObj>,
}
impl EventFormatter for Authenticated {
fn format(self: Box<Self>, fmt: &mut MsgFormatter<'_>) {
fmt.header(self.obj.id, AUTHENTICATED);
}
fn obj(&self) -> &dyn Object {
&*self.obj
}
}
impl Debug for Authenticated {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"authenticated()",
)
}
}
pub(super) struct Capabilities {
pub obj: Rc<WlDrmObj>,
pub value: u32,
}
impl EventFormatter for Capabilities {
fn format(self: Box<Self>, fmt: &mut MsgFormatter<'_>) {
fmt.header(self.obj.id, CAPABILITIES)
.uint(self.value);
}
fn obj(&self) -> &dyn Object {
&*self.obj
}
}
impl Debug for Capabilities {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"capabilities(value: {})",
self.value,
)
}
}

View file

@ -7,7 +7,7 @@ use crate::backend::{KeyState, OutputId, ScrollAxis, Seat, SeatEvent};
use crate::client::{Client, ClientId, DynEventFormatter};
use crate::fixed::Fixed;
use crate::globals::{Global, GlobalName};
use crate::ifs::wl_seat::wl_keyboard::{WlKeyboard, WlKeyboardId};
use crate::ifs::wl_seat::wl_keyboard::{REPEAT_INFO_SINCE, WlKeyboard, WlKeyboardId};
use crate::ifs::wl_seat::wl_pointer::{WlPointer, WlPointerId, POINTER_FRAME_SINCE_VERSION};
use crate::ifs::wl_seat::wl_touch::WlTouch;
use crate::ifs::wl_surface::xdg_surface::xdg_toplevel::{XdgToplevel, XdgToplevelId};
@ -502,7 +502,9 @@ impl WlSeatObj {
self.keyboards.set(req.id, p.clone());
self.client
.event(p.keymap(wl_keyboard::XKB_V1, p.keymap_fd()?, self.global.layout_size));
self.client.event(p.repeat_info(25, 250));
if self.version >= REPEAT_INFO_SINCE {
self.client.event(p.repeat_info(25, 250));
}
Ok(())
}

View file

@ -18,6 +18,8 @@ const KEY: u32 = 3;
const MODIFIERS: u32 = 4;
const REPEAT_INFO: u32 = 5;
pub const REPEAT_INFO_SINCE: u32 = 4;
#[allow(dead_code)]
const NO_KEYMAP: u32 = 0;
pub(super) const XKB_V1: u32 = 1;

View file

@ -49,7 +49,7 @@ impl WlShmPool {
if req.height < 0 || req.width < 0 || req.stride < 0 || req.offset < 0 {
return Err(CreateBufferError::NegativeParameters);
}
let buffer = Rc::new(WlBuffer::new(
let buffer = Rc::new(WlBuffer::new_shm(
req.id,
&self.client,
req.offset as usize,

View file

@ -334,9 +334,7 @@ impl WlSurface {
if let Some(buffer_change) = self.pending.buffer.take() {
let mut old_size = None;
let mut new_size = None;
log::info!("changing buffer");
if let Some(buffer) = self.buffer.take() {
log::info!("releasing buffer {}", buffer.id());
old_size = Some(buffer.rect);
self.client.event(buffer.release());
buffer.surfaces.remove(&self.id);

View file

@ -53,6 +53,14 @@ struct PendingXdgSurfaceData {
}
trait XdgSurfaceExt {
fn initial_configure(self: Rc<Self>) {
// nothing
}
fn pre_commit(self: Rc<Self>) {
// nothing
}
fn post_commit(self: Rc<Self>) {
// nothing
}
@ -243,6 +251,9 @@ impl SurfaceExt for XdgSurface {
let rse = self.requested_serial.get();
if ase != Some(rse) {
if ase.is_none() {
if let Some(ext) = self.ext.get() {
ext.initial_configure();
}
self.surface.client.event(self.configure(rse));
}
// return CommitAction::AbortCommit;

View file

@ -25,37 +25,39 @@ id!(XdgPopupId);
pub struct XdgPopup {
id: XdgPopupId,
node_id: PopupId,
pub(in super::super) surface: Rc<XdgSurface>,
pub(in super::super) xdg: Rc<XdgSurface>,
pub(super) parent: CloneCell<Option<Rc<XdgSurface>>>,
}
impl XdgPopup {
pub fn new(id: XdgPopupId, surface: &Rc<XdgSurface>, parent: Option<&Rc<XdgSurface>>) -> Self {
pub fn new(id: XdgPopupId, xdg: &Rc<XdgSurface>, parent: Option<&Rc<XdgSurface>>) -> Self {
Self {
id,
node_id: surface.surface.client.state.node_ids.next(),
surface: surface.clone(),
node_id: xdg.surface.client.state.node_ids.next(),
xdg: xdg.clone(),
parent: CloneCell::new(parent.cloned()),
}
}
fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> {
let _req: Destroy = self.surface.surface.client.parse(self, parser)?;
let _req: Destroy = self.xdg.surface.client.parse(self, parser)?;
{
if let Some(parent) = self.parent.take() {
parent.popups.remove(&self.id);
}
}
self.xdg.ext.set(None);
self.xdg.surface.client.remove_obj(self)?;
Ok(())
}
fn grab(&self, parser: MsgParser<'_, '_>) -> Result<(), GrabError> {
let _req: Grab = self.surface.surface.client.parse(self, parser)?;
let _req: Grab = self.xdg.surface.client.parse(self, parser)?;
Ok(())
}
fn reposition(&self, parser: MsgParser<'_, '_>) -> Result<(), RepositionError> {
let _req: Reposition = self.surface.surface.client.parse(self, parser)?;
let _req: Reposition = self.xdg.surface.client.parse(self, parser)?;
Ok(())
}

View file

@ -387,6 +387,10 @@ impl Node for XdgToplevel {
}
impl XdgSurfaceExt for XdgToplevel {
fn initial_configure(self: Rc<Self>) {
self.xdg.surface.client.event(self.configure(0, 0));
}
fn post_commit(self: Rc<Self>) {
let surface = &self.xdg.surface;
if let Some(parent) = self.parent_node.get() {

View file

@ -0,0 +1,202 @@
use crate::client::DynEventFormatter;
use crate::drm::dma::{DmaBuf, DmaBufPlane};
use crate::drm::INVALID_MODIFIER;
use crate::ifs::wl_buffer::{WlBuffer, WlBufferId};
use crate::ifs::zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1Obj;
use crate::object::{Interface, Object, ObjectId};
use crate::utils::buffd::MsgParser;
use crate::ErrorFmt;
use ahash::AHashMap;
use std::cell::{Cell, RefCell};
use std::rc::Rc;
pub use types::*;
mod types;
const DESTROY: u32 = 0;
const ADD: u32 = 1;
const CREATE: u32 = 2;
const CREATE_IMMED: u32 = 3;
const CREATED: u32 = 0;
const FAILED: u32 = 1;
#[allow(dead_code)]
const Y_INVERT: u32 = 1;
#[allow(dead_code)]
const INTERLACED: u32 = 2;
#[allow(dead_code)]
const BOTTOM_FIRST: u32 = 4;
id!(ZwpLinuxBufferParamsV1Id);
const MAX_PLANE: u32 = 3;
pub struct ZwpLinuxBufferParamsV1 {
id: ZwpLinuxBufferParamsV1Id,
parent: Rc<ZwpLinuxDmabufV1Obj>,
planes: RefCell<AHashMap<u32, Add>>,
used: Cell<bool>,
}
impl ZwpLinuxBufferParamsV1 {
pub fn new(id: ZwpLinuxBufferParamsV1Id, parent: &Rc<ZwpLinuxDmabufV1Obj>) -> Self {
Self {
id,
parent: parent.clone(),
planes: RefCell::new(Default::default()),
used: Cell::new(false),
}
}
fn created(self: &Rc<Self>, buffer_id: WlBufferId) -> DynEventFormatter {
Box::new(Created {
obj: self.clone(),
buffer: buffer_id,
})
}
fn failed(self: &Rc<Self>) -> DynEventFormatter {
Box::new(Failed { obj: self.clone() })
}
fn destroy(self: &Rc<Self>, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> {
let _req: Destroy = self.parent.client.parse(&**self, parser)?;
self.parent.client.remove_obj(&**self)?;
Ok(())
}
fn add(self: &Rc<Self>, parser: MsgParser<'_, '_>) -> Result<(), AddError> {
let req: Add = self.parent.client.parse(&**self, parser)?;
let modifier = ((req.modifier_hi as u64) << 32) | req.modifier_lo as u64;
if modifier != INVALID_MODIFIER {
return Err(AddError::InvalidModifier(modifier));
}
let plane = req.plane_idx;
if plane > MAX_PLANE {
return Err(AddError::MaxPlane);
}
if self.planes.borrow_mut().insert(plane, req).is_some() {
return Err(AddError::AlreadySet(plane));
}
Ok(())
}
fn do_create(
self: &Rc<Self>,
buffer_id: Option<WlBufferId>,
width: i32,
height: i32,
format: u32,
_flags: u32,
) -> Result<WlBufferId, DoCreateError> {
let ctx = match self.parent.client.state.render_ctx.get() {
Some(ctx) => ctx,
None => return Err(DoCreateError::NoRenderContext),
};
let formats = ctx.formats();
let format = match formats.get(&format) {
Some(f) => *f,
None => return Err(DoCreateError::InvalidFormat(format)),
};
let mut dmabuf = DmaBuf {
width,
height,
format,
modifier: INVALID_MODIFIER,
planes: vec![],
};
let mut planes: Vec<_> = self.planes.borrow_mut().drain().map(|v| v.1).collect();
planes.sort_by_key(|a| a.plane_idx);
for (i, p) in planes.into_iter().enumerate() {
if p.plane_idx as usize != i {
return Err(DoCreateError::MissingPlane(i));
}
dmabuf.planes.push(DmaBufPlane {
offset: p.offset,
stride: p.stride,
fd: p.fd,
});
}
let img = ctx.dmabuf_img(&dmabuf)?;
let (is_client_id, buffer_id) = match buffer_id {
Some(i) => (true, i),
None => (false, self.parent.client.new_id()?),
};
let buffer = Rc::new(WlBuffer::new_dmabuf(
buffer_id,
&self.parent.client,
format,
&img,
));
if is_client_id {
self.parent.client.add_client_obj(&buffer)?;
} else {
self.parent.client.add_server_obj(&buffer);
}
Ok(buffer_id)
}
fn create(self: &Rc<Self>, parser: MsgParser<'_, '_>) -> Result<(), CreateError> {
let req: Create = self.parent.client.parse(&**self, parser)?;
if self.used.replace(true) {
return Err(CreateError::AlreadyUsed);
}
match self.do_create(None, req.width, req.height, req.format, req.flags) {
Ok(id) => {
self.parent.client.event(self.created(id));
}
Err(e) => {
log::debug!("Could not create a dmabuf buffer: {}", ErrorFmt(e));
self.parent.client.event(self.failed());
}
}
Ok(())
}
fn create_immed(self: &Rc<Self>, parser: MsgParser<'_, '_>) -> Result<(), CreateImmedError> {
let req: CreateImmed = self.parent.client.parse(&**self, parser)?;
if self.used.replace(true) {
return Err(CreateImmedError::AlreadyUsed);
}
self.do_create(
Some(req.buffer_id),
req.width,
req.height,
req.format,
req.flags,
)?;
Ok(())
}
fn handle_request_(
self: &Rc<Self>,
request: u32,
parser: MsgParser<'_, '_>,
) -> Result<(), ZwpLinuxBufferParamsV1Error> {
match request {
DESTROY => self.destroy(parser)?,
ADD => self.add(parser)?,
CREATE => self.create(parser)?,
CREATE_IMMED => self.create_immed(parser)?,
_ => unreachable!(),
}
Ok(())
}
}
handle_request!(ZwpLinuxBufferParamsV1);
impl Object for ZwpLinuxBufferParamsV1 {
fn id(&self) -> ObjectId {
self.id.into()
}
fn interface(&self) -> Interface {
Interface::ZwpLinuxBufferParamsV1
}
fn num_requests(&self) -> u32 {
CREATE_IMMED + 1
}
}

View file

@ -0,0 +1,227 @@
use crate::client::{ClientError, EventFormatter, RequestParser};
use crate::ifs::wl_buffer::WlBufferId;
use crate::ifs::zwp_linux_buffer_params_v1::{ZwpLinuxBufferParamsV1, CREATED, FAILED};
use crate::object::Object;
use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError};
use crate::RenderError;
use std::fmt::{Debug, Formatter};
use std::rc::Rc;
use thiserror::Error;
use uapi::OwnedFd;
#[derive(Debug, Error)]
pub enum ZwpLinuxBufferParamsV1Error {
#[error("Could not process a `destroy` request")]
DestroyError(#[from] DestroyError),
#[error("Could not process a `add` request")]
AddError(#[from] AddError),
#[error("Could not process a `create` request")]
Create(#[from] CreateError),
#[error("Could not process a `create_immed` request")]
CreateImmed(#[from] CreateImmedError),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(ZwpLinuxBufferParamsV1Error, ClientError, ClientError);
#[derive(Debug, Error)]
pub enum DestroyError {
#[error("Parsing failed")]
ParseError(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(DestroyError, ClientError, ClientError);
efrom!(DestroyError, ParseError, MsgParserError);
#[derive(Debug, Error)]
pub enum AddError {
#[error("Parsing failed")]
ParseError(#[source] Box<MsgParserError>),
#[error("A buffer can contain at most 4 planes")]
MaxPlane,
#[error(transparent)]
ClientError(Box<ClientError>),
#[error("The modifier {0} is not supported")]
InvalidModifier(u64),
#[error("The plane {0} was already set")]
AlreadySet(u32),
}
efrom!(AddError, ClientError, ClientError);
efrom!(AddError, ParseError, MsgParserError);
#[derive(Debug, Error)]
pub enum DoCreateError {
#[error(transparent)]
ClientError(Box<ClientError>),
#[error("The compositor has no render context attached")]
NoRenderContext,
#[error("The format {0} is not supported")]
InvalidFormat(u32),
#[error("Plane {0} was not set")]
MissingPlane(usize),
#[error("Could not import the buffer")]
ImportError(#[from] RenderError),
}
efrom!(DoCreateError, ClientError, ClientError);
#[derive(Debug, Error)]
pub enum CreateError {
#[error("The params object has already been used")]
AlreadyUsed,
#[error("Parsing failed")]
ParseError(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(CreateError, ClientError, ClientError);
efrom!(CreateError, ParseError, MsgParserError);
#[derive(Debug, Error)]
pub enum CreateImmedError {
#[error("The params object has already been used")]
AlreadyUsed,
#[error("Parsing failed")]
ParseError(#[source] Box<MsgParserError>),
#[error(transparent)]
DoCreateError(#[from] DoCreateError),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(CreateImmedError, ClientError, ClientError);
efrom!(CreateImmedError, ParseError, MsgParserError);
pub(super) struct Destroy;
impl RequestParser<'_> for Destroy {
fn parse(_parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self)
}
}
impl Debug for Destroy {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "destroy()")
}
}
pub(super) struct Add {
pub fd: OwnedFd,
pub plane_idx: u32,
pub offset: u32,
pub stride: u32,
pub modifier_hi: u32,
pub modifier_lo: u32,
}
impl RequestParser<'_> for Add {
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self {
fd: parser.fd()?,
plane_idx: parser.uint()?,
offset: parser.uint()?,
stride: parser.uint()?,
modifier_hi: parser.uint()?,
modifier_lo: parser.uint()?,
})
}
}
impl Debug for Add {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"add(fd: {}, plane_idx: {}, offset: {}, stride: {}, modifier: {})",
self.fd.raw(),
self.plane_idx,
self.offset,
self.stride,
(self.modifier_hi as u64) << 32 | self.modifier_lo as u64,
)
}
}
pub(super) struct Create {
pub width: i32,
pub height: i32,
pub format: u32,
pub flags: u32,
}
impl RequestParser<'_> for Create {
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self {
width: parser.int()?,
height: parser.int()?,
format: parser.uint()?,
flags: parser.uint()?,
})
}
}
impl Debug for Create {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"create(width: {}, height: {}, format: {}, flags: {})",
self.width, self.height, self.format, self.flags,
)
}
}
pub(super) struct CreateImmed {
pub buffer_id: WlBufferId,
pub width: i32,
pub height: i32,
pub format: u32,
pub flags: u32,
}
impl RequestParser<'_> for CreateImmed {
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self {
buffer_id: parser.object()?,
width: parser.int()?,
height: parser.int()?,
format: parser.uint()?,
flags: parser.uint()?,
})
}
}
impl Debug for CreateImmed {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"create_immed(buffer_id: {}, width: {}, height: {}, format: {}, flags: {})",
self.buffer_id, self.width, self.height, self.format, self.flags,
)
}
}
pub(super) struct Created {
pub obj: Rc<ZwpLinuxBufferParamsV1>,
pub buffer: WlBufferId,
}
impl EventFormatter for Created {
fn format(self: Box<Self>, fmt: &mut MsgFormatter<'_>) {
fmt.header(self.obj.id, CREATED).object(self.buffer);
}
fn obj(&self) -> &dyn Object {
&*self.obj
}
}
impl Debug for Created {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "created(buffer: {})", self.buffer)
}
}
pub(super) struct Failed {
pub obj: Rc<ZwpLinuxBufferParamsV1>,
}
impl EventFormatter for Failed {
fn format(self: Box<Self>, fmt: &mut MsgFormatter<'_>) {
fmt.header(self.obj.id, FAILED);
}
fn obj(&self) -> &dyn Object {
&*self.obj
}
}
impl Debug for Failed {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "failed()")
}
}

View file

@ -0,0 +1,139 @@
use crate::client::{Client, DynEventFormatter};
use crate::drm::INVALID_MODIFIER;
use crate::globals::{Global, GlobalName};
use crate::ifs::zwp_linux_buffer_params_v1::ZwpLinuxBufferParamsV1;
use crate::object::{Interface, Object, ObjectId};
use crate::utils::buffd::MsgParser;
use std::rc::Rc;
pub use types::*;
mod types;
id!(ZwpLinuxDmabufV1Id);
const DESTROY: u32 = 0;
const CREATE_PARAMS: u32 = 1;
const FORMAT: u32 = 0;
const MODIFIER: u32 = 1;
pub struct ZwpLinuxDmabufV1Global {
name: GlobalName,
}
impl ZwpLinuxDmabufV1Global {
pub fn new(name: GlobalName) -> Self {
Self { name }
}
fn bind_(
self: Rc<Self>,
id: ZwpLinuxDmabufV1Id,
client: &Rc<Client>,
version: u32,
) -> Result<(), ZwpLinuxDmabufV1Error> {
let obj = Rc::new(ZwpLinuxDmabufV1Obj {
id,
client: client.clone(),
_version: version,
});
client.add_client_obj(&obj)?;
if let Some(ctx) = client.state.render_ctx.get() {
let formats = ctx.formats();
for format in formats.values() {
client.event(obj.format(format.drm));
if version >= MODIFIERS_SINCE_VERSION {
client.event(obj.modifier(format.drm, INVALID_MODIFIER));
}
}
}
Ok(())
}
}
const MODIFIERS_SINCE_VERSION: u32 = 3;
bind!(ZwpLinuxDmabufV1Global);
impl Global for ZwpLinuxDmabufV1Global {
fn name(&self) -> GlobalName {
self.name
}
fn singleton(&self) -> bool {
true
}
fn interface(&self) -> Interface {
Interface::ZwpLinuxDmabufV1
}
fn version(&self) -> u32 {
3
}
}
pub struct ZwpLinuxDmabufV1Obj {
id: ZwpLinuxDmabufV1Id,
pub client: Rc<Client>,
_version: u32,
}
impl ZwpLinuxDmabufV1Obj {
fn format(self: &Rc<Self>, format: u32) -> DynEventFormatter {
Box::new(Format {
obj: self.clone(),
format,
})
}
fn modifier(self: &Rc<Self>, format: u32, modifier: u64) -> DynEventFormatter {
Box::new(Modifier {
obj: self.clone(),
format,
modifier,
})
}
fn destroy(self: &Rc<Self>, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> {
let _req: Destroy = self.client.parse(&**self, parser)?;
self.client.remove_obj(&**self)?;
Ok(())
}
fn create_params(self: &Rc<Self>, parser: MsgParser<'_, '_>) -> Result<(), CreateParamsError> {
let req: CreateParams = self.client.parse(&**self, parser)?;
let params = Rc::new(ZwpLinuxBufferParamsV1::new(req.params_id, self));
self.client.add_client_obj(&params)?;
Ok(())
}
fn handle_request_(
self: &Rc<Self>,
request: u32,
parser: MsgParser<'_, '_>,
) -> Result<(), ZwpLinuxDmabufV1Error> {
match request {
DESTROY => self.destroy(parser)?,
CREATE_PARAMS => self.create_params(parser)?,
_ => unreachable!(),
}
Ok(())
}
}
handle_request!(ZwpLinuxDmabufV1Obj);
impl Object for ZwpLinuxDmabufV1Obj {
fn id(&self) -> ObjectId {
self.id.into()
}
fn interface(&self) -> Interface {
Interface::ZwpLinuxDmabufV1
}
fn num_requests(&self) -> u32 {
CREATE_PARAMS + 1
}
}

View file

@ -0,0 +1,111 @@
use crate::client::{ClientError, EventFormatter, RequestParser};
use crate::ifs::zwp_linux_buffer_params_v1::ZwpLinuxBufferParamsV1Id;
use crate::ifs::zwp_linux_dmabuf_v1::{ZwpLinuxDmabufV1Obj, FORMAT, MODIFIER};
use crate::object::Object;
use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError};
use std::fmt::{Debug, Formatter};
use std::rc::Rc;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum ZwpLinuxDmabufV1Error {
#[error("Could not process a `destroy` request")]
DestroyError(#[from] DestroyError),
#[error("Could not process a `create_params` request")]
CreateParamsError(#[from] CreateParamsError),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(ZwpLinuxDmabufV1Error, ClientError, ClientError);
#[derive(Debug, Error)]
pub enum DestroyError {
#[error("Parsing failed")]
ParseError(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(DestroyError, ClientError, ClientError);
efrom!(DestroyError, ParseError, MsgParserError);
#[derive(Debug, Error)]
pub enum CreateParamsError {
#[error("Parsing failed")]
ParseError(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(CreateParamsError, ClientError, ClientError);
efrom!(CreateParamsError, ParseError, MsgParserError);
pub(super) struct Destroy;
impl RequestParser<'_> for Destroy {
fn parse(_parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self)
}
}
impl Debug for Destroy {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "destroy()")
}
}
pub(super) struct CreateParams {
pub params_id: ZwpLinuxBufferParamsV1Id,
}
impl RequestParser<'_> for CreateParams {
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self {
params_id: parser.object()?,
})
}
}
impl Debug for CreateParams {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "create_params(params_id: {})", self.params_id)
}
}
pub(super) struct Format {
pub obj: Rc<ZwpLinuxDmabufV1Obj>,
pub format: u32,
}
impl EventFormatter for Format {
fn format(self: Box<Self>, fmt: &mut MsgFormatter<'_>) {
fmt.header(self.obj.id, FORMAT).uint(self.format);
}
fn obj(&self) -> &dyn Object {
&*self.obj
}
}
impl Debug for Format {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "format(format: {})", self.format)
}
}
pub(super) struct Modifier {
pub obj: Rc<ZwpLinuxDmabufV1Obj>,
pub format: u32,
pub modifier: u64,
}
impl EventFormatter for Modifier {
fn format(self: Box<Self>, fmt: &mut MsgFormatter<'_>) {
fmt.header(self.obj.id, MODIFIER)
.uint(self.format)
.uint((self.modifier >> 32) as u32)
.uint(self.modifier as u32);
}
fn obj(&self) -> &dyn Object {
&*self.obj
}
}
impl Debug for Modifier {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"modifiers(format: {}, modifier: {})",
self.format, self.modifier
)
}
}