autocommit 2022-01-29 00:49:52 CET
This commit is contained in:
parent
b11a36729c
commit
85b019101a
41 changed files with 1322 additions and 61 deletions
|
|
@ -39,6 +39,7 @@ pub enum ScrollAxis {
|
|||
#[derive(Debug)]
|
||||
pub enum SeatEvent {
|
||||
OutputPosition(OutputId, Fixed, Fixed),
|
||||
#[allow(dead_code)]
|
||||
Motion(Fixed, Fixed),
|
||||
Button(u32, KeyState),
|
||||
Scroll(i32, ScrollAxis),
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ use crate::ifs::wl_surface::xdg_surface::{XdgSurface, XdgSurfaceError, XdgSurfac
|
|||
use crate::ifs::wl_surface::{WlSurface, WlSurfaceError, WlSurfaceId};
|
||||
use crate::ifs::xdg_positioner::{XdgPositioner, XdgPositionerError};
|
||||
use crate::ifs::xdg_wm_base::{XdgWmBaseError, XdgWmBaseObj};
|
||||
use crate::ifs::zwp_linux_buffer_params_v1::{ZwpLinuxBufferParamsV1, ZwpLinuxBufferParamsV1Error};
|
||||
use crate::ifs::zwp_linux_dmabuf_v1::{ZwpLinuxDmabufV1Error, ZwpLinuxDmabufV1Obj};
|
||||
use crate::object::{Object, ObjectId, WL_DISPLAY_ID};
|
||||
use crate::state::State;
|
||||
use crate::utils::buffd::{BufFdError, MsgFormatter, MsgParser, MsgParserError};
|
||||
|
|
@ -39,6 +41,7 @@ use std::mem;
|
|||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
use uapi::{c, OwnedFd};
|
||||
use crate::ifs::wl_drm::{WlDrmError, WlDrmObj};
|
||||
|
||||
mod objects;
|
||||
mod tasks;
|
||||
|
|
@ -135,6 +138,12 @@ pub enum ClientError {
|
|||
WlDataOfferError(#[source] Box<WlDataOfferError>),
|
||||
#[error("An error occurred in a `wl_data_source`")]
|
||||
WlDataSourceError(#[source] Box<WlDataSourceError>),
|
||||
#[error("An error occurred in a `zwp_linx_dmabuf_v1`")]
|
||||
ZwpLinuxDmabufV1Error(#[source] Box<ZwpLinuxDmabufV1Error>),
|
||||
#[error("An error occurred in a `zwp_linx_buffer_params_v1`")]
|
||||
ZwpLinuxBufferParamsV1Error(#[source] Box<ZwpLinuxBufferParamsV1Error>),
|
||||
#[error("An error occurred in a `wl_drm`")]
|
||||
WlDrmError(#[source] Box<WlDrmError>),
|
||||
}
|
||||
|
||||
efrom!(ClientError, ParserError, MsgParserError);
|
||||
|
|
@ -166,6 +175,13 @@ efrom!(
|
|||
efrom!(ClientError, WlDataDeviceError, WlDataDeviceError);
|
||||
efrom!(ClientError, WlDataSourceError, WlDataSourceError);
|
||||
efrom!(ClientError, WlDataOfferError, WlDataOfferError);
|
||||
efrom!(ClientError, ZwpLinuxDmabufV1Error, ZwpLinuxDmabufV1Error);
|
||||
efrom!(
|
||||
ClientError,
|
||||
ZwpLinuxBufferParamsV1Error,
|
||||
ZwpLinuxBufferParamsV1Error
|
||||
);
|
||||
efrom!(ClientError, WlDrmError, WlDrmError);
|
||||
|
||||
impl ClientError {
|
||||
fn peer_closed(&self) -> bool {
|
||||
|
|
@ -340,7 +356,7 @@ pub struct Client {
|
|||
pub dispatch_frame_requests: AsyncQueue<Rc<WlCallback>>,
|
||||
}
|
||||
|
||||
const MAX_PENDING_EVENTS: usize = 100;
|
||||
const MAX_PENDING_EVENTS: usize = 10000;
|
||||
|
||||
impl Client {
|
||||
pub fn invalid_request(&self, obj: &dyn Object, request: u32) {
|
||||
|
|
@ -364,6 +380,10 @@ impl Client {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn new_id<T: From<ObjectId>>(&self) -> Result<T, ClientError> {
|
||||
self.objects.id(self)
|
||||
}
|
||||
|
||||
pub fn display(&self) -> Result<Rc<WlDisplay>, ClientError> {
|
||||
match self.objects.display.get() {
|
||||
Some(d) => Ok(d),
|
||||
|
|
@ -538,6 +558,9 @@ simple_add_obj!(WlDataDeviceManagerObj);
|
|||
simple_add_obj!(WlDataDevice);
|
||||
simple_add_obj!(WlDataOffer);
|
||||
simple_add_obj!(WlDataSource);
|
||||
simple_add_obj!(ZwpLinuxDmabufV1Obj);
|
||||
simple_add_obj!(ZwpLinuxBufferParamsV1);
|
||||
simple_add_obj!(WlDrmObj);
|
||||
|
||||
macro_rules! dedicated_add_obj {
|
||||
($ty:ty, $field:ident) => {
|
||||
|
|
|
|||
|
|
@ -64,8 +64,7 @@ impl Objects {
|
|||
self.buffers.clear();
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn id<T>(&self, client_data: &Client) -> Result<T, ClientError>
|
||||
pub fn id<T>(&self, client_data: &Client) -> Result<T, ClientError>
|
||||
where
|
||||
ObjectId: Into<T>,
|
||||
{
|
||||
|
|
|
|||
|
|
@ -21,9 +21,11 @@ pub enum DrmError {
|
|||
GetDevice(#[source] std::io::Error),
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
const DRM_NODE_PRIMARY: c::c_int = 0;
|
||||
#[allow(dead_code)]
|
||||
const DRM_NODE_CONTROL: c::c_int = 1;
|
||||
const DRM_NODE_RENDER: c::c_int = 2;
|
||||
pub const DRM_NODE_RENDER: c::c_int = 2;
|
||||
const DRM_NODE_MAX: c::c_int = 3;
|
||||
|
||||
const DRM_BUS_PCI: c::c_int = 0;
|
||||
|
|
|
|||
|
|
@ -23,11 +23,16 @@ pub enum GbmError {
|
|||
type Device = u8;
|
||||
type Bo = u8;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub const GBM_BO_USE_SCANOUT: u32 = 1 << 0;
|
||||
#[allow(dead_code)]
|
||||
pub const GBM_BO_USE_CURSOR: u32 = 1 << 1;
|
||||
pub const GBM_BO_USE_RENDERING: u32 = 1 << 2;
|
||||
#[allow(dead_code)]
|
||||
pub const GBM_BO_USE_WRITE: u32 = 1 << 3;
|
||||
#[allow(dead_code)]
|
||||
pub const GBM_BO_USE_LINEAR: u32 = 1 << 4;
|
||||
#[allow(dead_code)]
|
||||
pub const GBM_BO_USE_PROTECTED: u32 = 1 << 5;
|
||||
|
||||
#[link(name = "gbm")]
|
||||
|
|
@ -48,17 +53,19 @@ extern "C" {
|
|||
fn gbm_bo_get_plane_count(bo: *mut Bo) -> c::c_int;
|
||||
fn gbm_bo_get_width(bo: *mut Bo) -> u32;
|
||||
fn gbm_bo_get_height(bo: *mut Bo) -> u32;
|
||||
#[allow(dead_code)]
|
||||
fn gbm_bo_get_stride(bo: *mut Bo) -> u32;
|
||||
fn gbm_bo_get_modifier(bo: *mut Bo) -> u64;
|
||||
fn gbm_bo_get_stride_for_plane(bo: *mut Bo, plane: c::c_int) -> u32;
|
||||
fn gbm_bo_get_fd_for_plane(bo: *mut Bo, plane: c::c_int) -> c::c_int;
|
||||
fn gbm_bo_get_offset(bo: *mut Bo, plane: c::c_int) -> u32;
|
||||
fn gbm_bo_get_format(bo: *mut Bo) -> u32;
|
||||
#[allow(dead_code)]
|
||||
fn gbm_bo_get_bpp(bo: *mut Bo) -> u32;
|
||||
}
|
||||
|
||||
pub struct GbmDevice {
|
||||
drm: Drm,
|
||||
_drm: Drm,
|
||||
dev: *mut Device,
|
||||
}
|
||||
|
||||
|
|
@ -67,7 +74,7 @@ struct BoHolder {
|
|||
}
|
||||
|
||||
pub struct GbmBo {
|
||||
bo: BoHolder,
|
||||
_bo: BoHolder,
|
||||
dma: DmaBuf,
|
||||
}
|
||||
|
||||
|
|
@ -110,7 +117,7 @@ impl GbmDevice {
|
|||
if dev.is_null() {
|
||||
Err(GbmError::CreateDevice)
|
||||
} else {
|
||||
Ok(Self { drm, dev })
|
||||
Ok(Self { _drm: drm, dev })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -141,7 +148,7 @@ impl GbmDevice {
|
|||
}
|
||||
let bo = BoHolder { bo };
|
||||
let dma = export_bo(bo.bo)?;
|
||||
Ok(GbmBo { bo, dma })
|
||||
Ok(GbmBo { _bo: bo, dma })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ pub fn map_wayland_format_id(id: u32) -> u32 {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub static ARGB8888: &Format = &FORMATS[0];
|
||||
pub static XRGB8888: &Format = &FORMATS[1];
|
||||
|
||||
|
|
|
|||
|
|
@ -7,36 +7,42 @@ use crate::ifs::wl_seat::{WlSeatError, WlSeatGlobal};
|
|||
use crate::ifs::wl_shm::WlShmError;
|
||||
use crate::ifs::wl_subcompositor::WlSubcompositorError;
|
||||
use crate::ifs::xdg_wm_base::XdgWmBaseError;
|
||||
use crate::ifs::zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1Error;
|
||||
use crate::object::{Interface, ObjectId};
|
||||
use crate::utils::copyhashmap::CopyHashMap;
|
||||
use crate::{
|
||||
NumCell, State, WlCompositorGlobal, WlDataDeviceManagerGlobal, WlShmGlobal,
|
||||
WlSubcompositorGlobal, XdgWmBaseGlobal,
|
||||
WlSubcompositorGlobal, XdgWmBaseGlobal, ZwpLinuxDmabufV1Global,
|
||||
};
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
use crate::ifs::wl_drm::{WlDrmError, WlDrmGlobal};
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum GlobalError {
|
||||
#[error("The requested global {0} does not exist")]
|
||||
GlobalDoesNotExist(GlobalName),
|
||||
#[error("An error occurred in a wl_compositor")]
|
||||
#[error("An error occurred in a `wl_compositor` global")]
|
||||
WlCompositorError(#[source] Box<WlCompositorError>),
|
||||
#[error("An error occurred in a wl_shm")]
|
||||
#[error("An error occurred in a `wl_shm` global")]
|
||||
WlShmError(#[source] Box<WlShmError>),
|
||||
#[error("An error occurred in a wl_subcompositor")]
|
||||
#[error("An error occurred in a `wl_subcompositor` global")]
|
||||
WlSubcompositorError(#[source] Box<WlSubcompositorError>),
|
||||
#[error("An error occurred in a xdg_wm_base")]
|
||||
#[error("An error occurred in a `xdg_wm_base` global")]
|
||||
XdgWmBaseError(#[source] Box<XdgWmBaseError>),
|
||||
#[error("An error occurred in a wl_output")]
|
||||
#[error("An error occurred in a `wl_output` global")]
|
||||
WlOutputError(#[source] Box<WlOutputError>),
|
||||
#[error("An error occurred in a wl_seat")]
|
||||
#[error("An error occurred in a `wl_seat` global")]
|
||||
WlSeatError(#[source] Box<WlSeatError>),
|
||||
#[error("The output with id {0} does not exist")]
|
||||
OutputDoesNotExist(GlobalName),
|
||||
#[error("An error occurred in a wl_data_device_manager")]
|
||||
#[error("An error occurred in a `wl_data_device_manager` global")]
|
||||
WlDataDeviceManagerError(#[source] Box<WlDataDeviceManagerError>),
|
||||
#[error("An error occurred in a `zwp_linux_dmabuf_v1` global")]
|
||||
ZwpLinuxDmabufV1Error(#[source] Box<ZwpLinuxDmabufV1Error>),
|
||||
#[error("An error occurred in a `wl_drm` global")]
|
||||
WlDrmError(#[source] Box<WlDrmError>),
|
||||
}
|
||||
|
||||
efrom!(GlobalError, WlCompositorError, WlCompositorError);
|
||||
|
|
@ -45,6 +51,8 @@ efrom!(GlobalError, WlSubcompositorError, WlSubcompositorError);
|
|||
efrom!(GlobalError, XdgWmBaseError, XdgWmBaseError);
|
||||
efrom!(GlobalError, WlOutputError, WlOutputError);
|
||||
efrom!(GlobalError, WlSeatError, WlSeatError);
|
||||
efrom!(GlobalError, ZwpLinuxDmabufV1Error, ZwpLinuxDmabufV1Error);
|
||||
efrom!(GlobalError, WlDrmError, WlDrmError);
|
||||
efrom!(
|
||||
GlobalError,
|
||||
WlDataDeviceManagerError,
|
||||
|
|
@ -211,6 +219,8 @@ simple_add_global!(WlShmGlobal);
|
|||
simple_add_global!(WlSubcompositorGlobal);
|
||||
simple_add_global!(XdgWmBaseGlobal);
|
||||
simple_add_global!(WlDataDeviceManagerGlobal);
|
||||
simple_add_global!(ZwpLinuxDmabufV1Global);
|
||||
simple_add_global!(WlDrmGlobal);
|
||||
|
||||
macro_rules! dedicated_add_global {
|
||||
($ty:ty, $field:ident) => {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
145
src/ifs/wl_drm/mod.rs
Normal 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
223
src/ifs/wl_drm/types.rs
Normal 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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -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(())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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(())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
202
src/ifs/zwp_linux_buffer_params_v1/mod.rs
Normal file
202
src/ifs/zwp_linux_buffer_params_v1/mod.rs
Normal 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
|
||||
}
|
||||
}
|
||||
227
src/ifs/zwp_linux_buffer_params_v1/types.rs
Normal file
227
src/ifs/zwp_linux_buffer_params_v1/types.rs
Normal 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()")
|
||||
}
|
||||
}
|
||||
139
src/ifs/zwp_linux_dmabuf_v1/mod.rs
Normal file
139
src/ifs/zwp_linux_dmabuf_v1/mod.rs
Normal 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(¶ms)?;
|
||||
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
|
||||
}
|
||||
}
|
||||
111
src/ifs/zwp_linux_dmabuf_v1/types.rs
Normal file
111
src/ifs/zwp_linux_dmabuf_v1/types.rs
Normal 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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -26,6 +26,7 @@ use crate::ifs::wl_shm::WlShmGlobal;
|
|||
use crate::ifs::wl_subcompositor::WlSubcompositorGlobal;
|
||||
use crate::ifs::wl_surface::NoneSurfaceExt;
|
||||
use crate::ifs::xdg_wm_base::XdgWmBaseGlobal;
|
||||
use crate::ifs::zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1Global;
|
||||
use crate::render::RenderError;
|
||||
use crate::sighand::SighandError;
|
||||
use crate::state::State;
|
||||
|
|
@ -41,6 +42,7 @@ use log::LevelFilter;
|
|||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
use wheel::Wheel;
|
||||
use crate::ifs::wl_drm::WlDrmGlobal;
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
|
|
@ -114,6 +116,8 @@ fn main_() -> Result<(), MainError> {
|
|||
globals.add_global_no_broadcast(&Rc::new(WlSubcompositorGlobal::new(globals.name())));
|
||||
globals.add_global_no_broadcast(&Rc::new(XdgWmBaseGlobal::new(globals.name())));
|
||||
globals.add_global_no_broadcast(&Rc::new(WlDataDeviceManagerGlobal::new(globals.name())));
|
||||
globals.add_global_no_broadcast(&Rc::new(ZwpLinuxDmabufV1Global::new(globals.name())));
|
||||
globals.add_global_no_broadcast(&Rc::new(WlDrmGlobal::new(globals.name())));
|
||||
let node_ids = NodeIds::default();
|
||||
let state = Rc::new(State {
|
||||
eng: engine.clone(),
|
||||
|
|
|
|||
|
|
@ -66,6 +66,9 @@ pub enum Interface {
|
|||
WlRegion,
|
||||
WlBuffer,
|
||||
WlSeat,
|
||||
WlDrm,
|
||||
ZwpLinuxDmabufV1,
|
||||
ZwpLinuxBufferParamsV1,
|
||||
}
|
||||
|
||||
impl Interface {
|
||||
|
|
@ -96,6 +99,9 @@ impl Interface {
|
|||
Interface::WlDataDevice => "wl_data_device",
|
||||
Interface::WlDataSource => "wl_data_source",
|
||||
Interface::WlDataOffer => "wl_data_offer",
|
||||
Interface::ZwpLinuxDmabufV1 => "zwp_linux_dmabuf_v1",
|
||||
Interface::ZwpLinuxBufferParamsV1 => "zwp_linux_buffer_params_v1",
|
||||
Interface::WlDrm => "wl_drm",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ impl Rect {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn intersects(&self, other: &Self) -> bool {
|
||||
let x1 = self.x1.max(other.x1);
|
||||
let y1 = self.y1.max(other.y1);
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ impl EglDevice {
|
|||
}
|
||||
let mut dpy = EglDisplay {
|
||||
exts: DisplayExt::empty(),
|
||||
formats: AHashMap::new(),
|
||||
formats: Rc::new(AHashMap::new()),
|
||||
dev: *self,
|
||||
dpy,
|
||||
};
|
||||
|
|
@ -68,7 +68,7 @@ impl EglDevice {
|
|||
if !dpy.exts.intersects(DisplayExt::KHR_SURFACELESS_CONTEXT) {
|
||||
return Err(RenderError::SurfacelessContext);
|
||||
}
|
||||
dpy.formats = query_formats(dpy.dpy)?;
|
||||
dpy.formats = Rc::new(query_formats(dpy.dpy)?);
|
||||
|
||||
Ok(Rc::new(dpy))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ use std::rc::Rc;
|
|||
#[derive(Debug, Clone)]
|
||||
pub struct EglDisplay {
|
||||
pub exts: DisplayExt,
|
||||
pub formats: AHashMap<u32, &'static Format>,
|
||||
pub formats: Rc<AHashMap<u32, &'static Format>>,
|
||||
pub dev: EglDevice,
|
||||
pub dpy: EGLDisplay,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use crate::drm::drm::Drm;
|
||||
use crate::drm::drm::{DrmDevice};
|
||||
use crate::render::egl::device::EglDevice;
|
||||
use crate::render::egl::sys::{
|
||||
eglBindAPI, EGLAttrib, EGLLabelKHR, EGLenum, EGLint, EGL_DEBUG_MSG_CRITICAL_KHR,
|
||||
|
|
@ -63,8 +63,7 @@ pub fn init() -> Result<(), RenderError> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn find_drm_device(drm: &Drm) -> Result<Option<EglDevice>, RenderError> {
|
||||
let drm_dev = drm.get_device()?;
|
||||
pub fn find_drm_device(drm_dev: &DrmDevice) -> Result<Option<EglDevice>, RenderError> {
|
||||
for device in query_devices()? {
|
||||
if device.exts.contains(DeviceExt::EXT_DEVICE_DRM) {
|
||||
let device_file = device.query_string(EGL_DRM_DEVICE_FILE_EXT)?;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ use uapi::c;
|
|||
pub type EGLint = i32;
|
||||
pub type EGLenum = c::c_uint;
|
||||
pub type EGLBoolean = c::c_uint;
|
||||
#[allow(dead_code)]
|
||||
pub type EGLuint64KHR = u64;
|
||||
pub type EGLAttrib = isize;
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ pub type GLenum = c::c_uint;
|
|||
pub type GLfloat = f32;
|
||||
pub type GLint = c::c_int;
|
||||
pub type GLsizei = c::c_int;
|
||||
#[allow(dead_code)]
|
||||
pub type GLubyte = u8;
|
||||
pub type GLuint = c::c_uint;
|
||||
|
||||
|
|
@ -29,6 +30,7 @@ pub const GL_RENDERBUFFER: GLenum = 0x8D41;
|
|||
pub const GL_SCISSOR_TEST: GLenum = 0x0C11;
|
||||
pub const GL_TEXTURE0: GLenum = 0x84C0;
|
||||
pub const GL_TEXTURE_2D: GLenum = 0x0DE1;
|
||||
#[allow(dead_code)]
|
||||
pub const GL_TEXTURE_MAG_FILTER: GLenum = 0x2800;
|
||||
pub const GL_TEXTURE_MIN_FILTER: GLenum = 0x2801;
|
||||
pub const GL_TEXTURE_WRAP_S: GLenum = 0x2802;
|
||||
|
|
@ -54,6 +56,7 @@ extern "C" {
|
|||
renderbuffertarget: GLenum,
|
||||
renderbuffer: GLuint,
|
||||
);
|
||||
#[allow(dead_code)]
|
||||
pub fn glFramebufferTexture2D(
|
||||
target: GLenum,
|
||||
attachment: GLenum,
|
||||
|
|
@ -64,6 +67,7 @@ extern "C" {
|
|||
pub fn glCheckFramebufferStatus(target: GLenum) -> GLenum;
|
||||
pub fn glClear(mask: GLbitfield);
|
||||
pub fn glClearColor(red: GLfloat, green: GLfloat, blue: GLfloat, alpha: GLfloat);
|
||||
#[allow(dead_code)]
|
||||
pub fn glFlush();
|
||||
|
||||
pub fn glGenTextures(n: GLsizei, textures: *mut GLuint);
|
||||
|
|
@ -112,6 +116,7 @@ extern "C" {
|
|||
pub fn glGetUniformLocation(prog: GLuint, name: *const GLchar) -> GLint;
|
||||
pub fn glGetAttribLocation(prog: GLuint, name: *const GLchar) -> GLint;
|
||||
pub fn glUniform1i(location: GLint, v0: GLint);
|
||||
#[allow(dead_code)]
|
||||
pub fn glUniform1f(location: GLint, v0: GLfloat);
|
||||
pub fn glUniform4f(location: GLint, v0: GLfloat, v1: GLfloat, v2: GLfloat, v3: GLfloat);
|
||||
pub fn glVertexAttribPointer(
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
use crate::format::Format;
|
||||
use crate::render::egl::context::EglContext;
|
||||
use crate::render::egl::image::EglImage;
|
||||
use crate::render::egl::PROCS;
|
||||
use crate::render::gl::frame_buffer::GlFrameBuffer;
|
||||
use crate::render::gl::sys::{
|
||||
glBindFramebuffer, glBindTexture, glCheckFramebufferStatus, glDeleteTextures,
|
||||
|
|
@ -8,6 +10,7 @@ use crate::render::gl::sys::{
|
|||
GL_FRAMEBUFFER_COMPLETE, GL_LINEAR, GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
|
||||
GL_TEXTURE_MIN_FILTER, GL_TEXTURE_WRAP_S, GL_TEXTURE_WRAP_T, GL_UNPACK_ROW_LENGTH_EXT,
|
||||
};
|
||||
use crate::render::sys::GLeglImageOES;
|
||||
use crate::render::RenderError;
|
||||
use std::cell::Cell;
|
||||
use std::ptr;
|
||||
|
|
@ -15,12 +18,14 @@ use std::rc::Rc;
|
|||
|
||||
pub struct GlTexture {
|
||||
pub(super) ctx: Rc<EglContext>,
|
||||
pub img: Option<Rc<EglImage>>,
|
||||
pub tex: GLuint,
|
||||
pub width: i32,
|
||||
pub height: i32,
|
||||
}
|
||||
|
||||
impl GlTexture {
|
||||
#[allow(dead_code)]
|
||||
pub fn new(
|
||||
ctx: &Rc<EglContext>,
|
||||
format: &'static Format,
|
||||
|
|
@ -49,12 +54,14 @@ impl GlTexture {
|
|||
})?;
|
||||
Ok(Rc::new(GlTexture {
|
||||
ctx: ctx.clone(),
|
||||
img: None,
|
||||
tex,
|
||||
width,
|
||||
height,
|
||||
}))
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub unsafe fn to_framebuffer(self: &Rc<Self>) -> Result<Rc<GlFrameBuffer>, RenderError> {
|
||||
self.ctx.with_current(|| unsafe {
|
||||
let mut fbo = 0;
|
||||
|
|
@ -84,7 +91,27 @@ impl GlTexture {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn import_texture(
|
||||
pub fn import_img(ctx: &Rc<EglContext>, img: &Rc<EglImage>) -> Result<GlTexture, RenderError> {
|
||||
let tex = ctx.with_current(|| unsafe {
|
||||
let mut tex = 0;
|
||||
glGenTextures(1, &mut tex);
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
PROCS.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, GLeglImageOES(img.img.0));
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
Ok(tex)
|
||||
})?;
|
||||
Ok(GlTexture {
|
||||
ctx: ctx.clone(),
|
||||
img: Some(img.clone()),
|
||||
tex,
|
||||
width: img.width,
|
||||
height: img.height,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn import_shm(
|
||||
ctx: &Rc<EglContext>,
|
||||
data: &[Cell<u8>],
|
||||
format: &'static Format,
|
||||
|
|
@ -119,6 +146,7 @@ impl GlTexture {
|
|||
})?;
|
||||
Ok(GlTexture {
|
||||
ctx: ctx.clone(),
|
||||
img: None,
|
||||
tex,
|
||||
width,
|
||||
height,
|
||||
|
|
@ -128,11 +156,9 @@ impl GlTexture {
|
|||
|
||||
impl Drop for GlTexture {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
self.ctx.with_current(|| {
|
||||
glDeleteTextures(1, &self.tex);
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
let _ = self.ctx.with_current(|| unsafe {
|
||||
glDeleteTextures(1, &self.tex);
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ pub enum RenderError {
|
|||
#[error("EGL display does not support `EGL_EXT_image_dma_buf_import_modifiers`")]
|
||||
DmaBufImport,
|
||||
#[error("GLES driver does not support `GL_OES_EGL_image`")]
|
||||
#[allow(dead_code)]
|
||||
OesEglImage,
|
||||
#[error("EGL display does not support `EGL_KHR_image_base`")]
|
||||
ImageBase,
|
||||
|
|
@ -89,4 +90,6 @@ pub enum RenderError {
|
|||
UnknownDrmDevice,
|
||||
#[error("The GLES driver does not support the XRGB8888 format")]
|
||||
XRGB888,
|
||||
#[error("The DRM device does not have a render node")]
|
||||
NoRenderNode,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
#![allow(non_snake_case)]
|
||||
#![allow(non_snake_case, dead_code)]
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/egl_procs.rs"));
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::drm::dma::DmaBuf;
|
||||
use crate::drm::drm::Drm;
|
||||
use crate::drm::drm::{Drm, DRM_NODE_RENDER};
|
||||
use crate::format::{Format, XRGB8888};
|
||||
use crate::render::egl::context::EglContext;
|
||||
use crate::render::egl::find_drm_device;
|
||||
|
|
@ -8,16 +8,21 @@ use crate::render::gl::render_buffer::GlRenderBuffer;
|
|||
use crate::render::gl::sys::GLint;
|
||||
use crate::render::gl::texture::GlTexture;
|
||||
use crate::render::renderer::framebuffer::Framebuffer;
|
||||
use crate::render::renderer::image::Image;
|
||||
use crate::render::renderer::RENDERDOC;
|
||||
use crate::render::{RenderError, Texture};
|
||||
use ahash::AHashMap;
|
||||
use renderdoc::{RenderDoc, V100};
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::ffi::CString;
|
||||
use std::rc::Rc;
|
||||
use uapi::ustr;
|
||||
|
||||
pub struct RenderContext {
|
||||
pub(super) ctx: Rc<EglContext>,
|
||||
|
||||
pub(super) render_node: Rc<CString>,
|
||||
|
||||
pub(super) renderdoc: Option<RefCell<RenderDoc<V100>>>,
|
||||
|
||||
pub(super) tex_prog: GlProgram,
|
||||
|
|
@ -32,7 +37,12 @@ pub struct RenderContext {
|
|||
|
||||
impl RenderContext {
|
||||
pub fn from_drm_device(drm: &Drm) -> Result<Self, RenderError> {
|
||||
let egl_dev = match find_drm_device(&drm)? {
|
||||
let drm_dev = drm.get_device()?;
|
||||
let node = match drm_dev.nodes().find(|(ty, _)| *ty == DRM_NODE_RENDER) {
|
||||
None => return Err(RenderError::NoRenderNode),
|
||||
Some((_, n)) => Rc::new(n.to_owned()),
|
||||
};
|
||||
let egl_dev = match find_drm_device(&drm_dev)? {
|
||||
Some(d) => d,
|
||||
None => return Err(RenderError::UnknownDrmDevice),
|
||||
};
|
||||
|
|
@ -41,10 +51,10 @@ impl RenderContext {
|
|||
return Err(RenderError::XRGB888);
|
||||
}
|
||||
let ctx = dpy.create_context()?;
|
||||
ctx.with_current(|| unsafe { Self::new(&ctx) })
|
||||
ctx.with_current(|| unsafe { Self::new(&ctx, &node) })
|
||||
}
|
||||
|
||||
unsafe fn new(ctx: &Rc<EglContext>) -> Result<Self, RenderError> {
|
||||
unsafe fn new(ctx: &Rc<EglContext>, node: &Rc<CString>) -> Result<Self, RenderError> {
|
||||
let tex_prog = GlProgram::from_shaders(
|
||||
ctx,
|
||||
include_str!("../shaders/tex.vert.glsl"),
|
||||
|
|
@ -58,6 +68,8 @@ impl RenderContext {
|
|||
Ok(Self {
|
||||
ctx: ctx.clone(),
|
||||
|
||||
render_node: node.clone(),
|
||||
|
||||
tex_prog_pos: tex_prog.get_attrib_location(ustr!("pos")),
|
||||
tex_prog_texcoord: tex_prog.get_attrib_location(ustr!("texcoord")),
|
||||
tex_prog_tex: tex_prog.get_uniform_location(ustr!("tex")),
|
||||
|
|
@ -75,6 +87,14 @@ impl RenderContext {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn render_node(&self) -> Rc<CString> {
|
||||
self.render_node.clone()
|
||||
}
|
||||
|
||||
pub fn formats(&self) -> Rc<AHashMap<u32, &'static Format>> {
|
||||
self.ctx.dpy.formats.clone()
|
||||
}
|
||||
|
||||
pub fn dmabuf_fb(self: &Rc<Self>, buf: &DmaBuf) -> Result<Rc<Framebuffer>, RenderError> {
|
||||
self.ctx.with_current(|| unsafe {
|
||||
let img = self.ctx.dpy.import_dmabuf(buf)?;
|
||||
|
|
@ -87,6 +107,16 @@ impl RenderContext {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn dmabuf_img(self: &Rc<Self>, buf: &DmaBuf) -> Result<Rc<Image>, RenderError> {
|
||||
self.ctx.with_current(|| {
|
||||
let img = self.ctx.dpy.import_dmabuf(buf)?;
|
||||
Ok(Rc::new(Image {
|
||||
ctx: self.clone(),
|
||||
gl: img,
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn shmem_texture(
|
||||
self: &Rc<Self>,
|
||||
data: &[Cell<u8>],
|
||||
|
|
@ -95,7 +125,7 @@ impl RenderContext {
|
|||
height: i32,
|
||||
stride: i32,
|
||||
) -> Result<Rc<Texture>, RenderError> {
|
||||
let gl = GlTexture::import_texture(&self.ctx, data, format, width, height, stride)?;
|
||||
let gl = GlTexture::import_shm(&self.ctx, data, format, width, height, stride)?;
|
||||
Ok(Rc::new(Texture {
|
||||
ctx: self.clone(),
|
||||
gl,
|
||||
|
|
|
|||
27
src/render/renderer/image.rs
Normal file
27
src/render/renderer/image.rs
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
use crate::render::egl::image::EglImage;
|
||||
use crate::render::gl::texture::GlTexture;
|
||||
use crate::render::{RenderContext, Texture};
|
||||
use crate::RenderError;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct Image {
|
||||
pub(super) ctx: Rc<RenderContext>,
|
||||
pub(super) gl: Rc<EglImage>,
|
||||
}
|
||||
|
||||
impl Image {
|
||||
pub fn width(&self) -> i32 {
|
||||
self.gl.width
|
||||
}
|
||||
|
||||
pub fn height(&self) -> i32 {
|
||||
self.gl.height
|
||||
}
|
||||
|
||||
pub fn to_texture(self: &Rc<Self>) -> Result<Rc<Texture>, RenderError> {
|
||||
Ok(Rc::new(Texture {
|
||||
ctx: self.ctx.clone(),
|
||||
gl: GlTexture::import_img(&self.ctx.ctx, &self.gl)?,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +1,12 @@
|
|||
pub use context::*;
|
||||
pub use framebuffer::*;
|
||||
pub use image::*;
|
||||
pub use renderer::*;
|
||||
pub use texture::*;
|
||||
|
||||
mod context;
|
||||
mod framebuffer;
|
||||
mod image;
|
||||
mod renderer;
|
||||
mod texture;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
#![allow(dead_code)]
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::ptr;
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ impl<T> LinkedList<T> {
|
|||
unsafe { self.endpoint(self.root.data.as_ref().prev.get()) }
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn first(&self) -> Option<NodeRef<T>> {
|
||||
unsafe { self.endpoint(self.root.data.as_ref().next.get()) }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -120,6 +120,7 @@ impl Wheel {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn periodic(
|
||||
&self,
|
||||
id: WheelId,
|
||||
|
|
|
|||
|
|
@ -76,12 +76,15 @@ extern "C" {
|
|||
fn xkb_keymap_unref(keymap: *mut xkb_keymap);
|
||||
fn xkb_state_unref(state: *mut xkb_state);
|
||||
fn xkb_state_new(keymap: *mut xkb_keymap) -> *mut xkb_state;
|
||||
#[allow(dead_code)]
|
||||
fn xkb_state_update_key(
|
||||
state: *mut xkb_state,
|
||||
key: u32,
|
||||
direction: xkb_key_direction,
|
||||
) -> xkb_state_component;
|
||||
#[allow(dead_code)]
|
||||
fn xkb_state_serialize_mods(state: *mut xkb_state, components: xkb_state_component) -> u32;
|
||||
#[allow(dead_code)]
|
||||
fn xkb_state_serialize_layout(state: *mut xkb_state, components: xkb_state_component) -> u32;
|
||||
}
|
||||
|
||||
|
|
@ -198,6 +201,7 @@ impl XkbState {
|
|||
self.mods
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn update(&mut self, key: u32, direction: XkbKeyDirection) -> Option<ModifierState> {
|
||||
unsafe {
|
||||
let changes = xkb_state_update_key(self.state, key + 8, direction.raw() as _);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue