1
0
Fork 0
forked from wry/wry

all: implement output transforms

This commit is contained in:
Julian Orth 2024-02-27 23:32:40 +01:00
parent 79df8d69f4
commit b7d2964e19
20 changed files with 254 additions and 71 deletions

View file

@ -181,6 +181,7 @@ impl JayScreencast {
x_off,
y_off,
size,
on.global.transform.get(),
);
self.client.event(Ready {
self_id: self.id,
@ -217,7 +218,7 @@ impl JayScreencast {
_ => return Err(JayScreencastError::XRGB8888),
};
if let Some(output) = self.output.get() {
let mode = output.global.mode.get();
let (width, height) = output.global.pixel_size();
let num = 3;
for _ in 0..num {
let mut usage = GBM_BO_USE_RENDERING;
@ -241,8 +242,8 @@ impl JayScreencast {
};
let buffer = ctx.gbm().create_bo(
&self.client.state.dma_buf_ids,
mode.width,
mode.height,
width,
height,
XRGB8888,
modifiers,
usage,
@ -492,10 +493,7 @@ efrom!(JayScreencastError, ClientError);
fn output_size(output: &Option<Rc<OutputNode>>) -> (i32, i32) {
match output {
Some(o) => {
let mode = o.global.mode.get();
(mode.width, mode.height)
}
Some(o) => o.global.pixel_size(),
_ => (0, 0),
}
}

View file

@ -19,10 +19,12 @@ use {
clonecell::CloneCell,
copyhashmap::CopyHashMap,
linkedlist::LinkedList,
transform_ext::TransformExt,
},
wire::{wl_output::*, WlOutputId, ZxdgOutputV1Id},
},
ahash::AHashMap,
jay_config::video::Transform,
std::{
cell::{Cell, RefCell},
collections::hash_map::Entry,
@ -73,9 +75,10 @@ pub struct WlOutputGlobal {
pub destroyed: Cell<bool>,
pub legacy_scale: Cell<u32>,
pub preferred_scale: Cell<crate::scale::Scale>,
pub transform: Cell<Transform>,
}
#[derive(Eq, PartialEq)]
#[derive(Eq, PartialEq, Hash)]
pub struct OutputId {
pub manufacturer: String,
pub model: String,
@ -100,16 +103,24 @@ impl WlOutputGlobal {
width_mm: i32,
height_mm: i32,
) -> Self {
let output_id = Rc::new(OutputId {
manufacturer: manufacturer.to_string(),
model: product.to_string(),
serial_number: serial_number.to_string(),
});
let transform = state
.output_transforms
.borrow()
.get(&output_id)
.copied()
.unwrap_or(Transform::None);
let (width, height) = transform.maybe_swap((mode.width, mode.height));
Self {
name,
state: state.clone(),
connector: connector.clone(),
pos: Cell::new(Rect::new_sized(x1, 0, mode.width, mode.height).unwrap()),
output_id: Rc::new(OutputId {
manufacturer: manufacturer.to_string(),
model: product.to_string(),
serial_number: serial_number.to_string(),
}),
pos: Cell::new(Rect::new_sized(x1, 0, width, height).unwrap()),
output_id,
mode: Cell::new(*mode),
node: Default::default(),
width_mm,
@ -120,6 +131,7 @@ impl WlOutputGlobal {
destroyed: Cell::new(false),
legacy_scale: Cell::new(1),
preferred_scale: Cell::new(crate::scale::Scale::from_int(1)),
transform: Cell::new(transform),
}
}
@ -240,6 +252,7 @@ impl WlOutputGlobal {
mem,
*stride,
wl_buffer.format,
Transform::None,
);
} else {
let fb = match wl_buffer.famebuffer.get() {
@ -258,6 +271,7 @@ impl WlOutputGlobal {
x_off - capture.rect.x1(),
y_off - capture.rect.y1(),
size,
Transform::None,
);
}
if capture.with_damage.get() {
@ -269,6 +283,11 @@ impl WlOutputGlobal {
capture.output_link.take();
}
}
pub fn pixel_size(&self) -> (i32, i32) {
let mode = self.mode.get();
self.transform.get().maybe_swap((mode.width, mode.height))
}
}
global_base!(WlOutputGlobal, WlOutput, WlOutputError);
@ -314,7 +333,7 @@ impl WlOutput {
subpixel: SP_UNKNOWN,
make: &self.global.output_id.manufacturer,
model: &self.global.output_id.model,
transform: TF_NORMAL,
transform: self.global.transform.get().to_wl(),
};
self.client.event(event);
}

View file

@ -57,6 +57,7 @@ use {
linkedlist::LinkedNode,
numcell::NumCell,
rc_eq::rc_eq,
transform_ext::TransformExt,
},
wire::{
wl_seat::*, ExtIdleNotificationV1Id, WlDataDeviceId, WlKeyboardId, WlPointerId,
@ -264,11 +265,13 @@ impl WlSeatGlobal {
let (x, y) = self.get_position();
for output in self.state.root.outputs.lock().values() {
if let Some(hc) = output.hardware_cursor.get() {
let transform = output.global.transform.get();
let render = render | output.hardware_cursor_needs_render.take();
let scale = output.global.preferred_scale.get();
let extents = cursor.extents_at_scale(scale);
let (hc_width, hc_height) = hc.size();
if render {
let (max_width, max_height) = hc.max_size();
let (max_width, max_height) = transform.maybe_swap((hc_width, hc_height));
if extents.width() > max_width || extents.height() > max_height {
hc.set_enabled(false);
hc.commit();
@ -285,17 +288,25 @@ impl WlSeatGlobal {
x_rel = ((x - Fixed::from_int(opos.x1())).to_f64() * scalef).round() as i32;
y_rel = ((y - Fixed::from_int(opos.y1())).to_f64() * scalef).round() as i32;
}
let mode = output.global.mode.get();
if extents
.intersects(&Rect::new_sized(-x_rel, -y_rel, mode.width, mode.height).unwrap())
{
let (width, height) = output.global.pixel_size();
if extents.intersects(&Rect::new_sized(-x_rel, -y_rel, width, height).unwrap()) {
if render {
let buffer = hc.get_buffer();
buffer.render_hardware_cursor(cursor.deref(), &self.state, scale);
buffer.render_hardware_cursor(
cursor.deref(),
&self.state,
scale,
transform,
);
hc.swap_buffer();
}
hc.set_enabled(true);
hc.set_position(x_rel + extents.x1(), y_rel + extents.y1());
let mode = output.global.mode.get();
let (x_rel, y_rel) =
transform.apply_point(mode.width, mode.height, (x_rel, y_rel));
let (hot_x, hot_y) =
transform.apply_point(hc_width, hc_height, (-extents.x1(), -extents.y1()));
hc.set_position(x_rel - hot_x, y_rel - hot_y);
} else {
if render {
output.hardware_cursor_needs_render.set(true);

View file

@ -81,6 +81,7 @@ const INVALID_SIZE: u32 = 2;
const OFFSET_SINCE: u32 = 5;
const BUFFER_SCALE_SINCE: u32 = 6;
const TRANSFORM_SINCE: u32 = 6;
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum SurfaceRole {
@ -117,6 +118,14 @@ impl NodeVisitorBase for SurfaceSendPreferredScaleVisitor {
}
}
pub struct SurfaceSendPreferredTransformVisitor;
impl NodeVisitorBase for SurfaceSendPreferredTransformVisitor {
fn visit_surface(&mut self, node: &Rc<WlSurface>) {
node.send_preferred_buffer_transform();
node.node_visit_children(self);
}
}
pub struct WlSurface {
pub id: WlSurfaceId,
pub node_id: SurfaceNodeId,
@ -350,6 +359,9 @@ impl WlSurface {
if old.global.preferred_scale.get() != output.global.preferred_scale.get() {
self.on_scale_change();
}
if old.global.transform.get() != output.global.transform.get() {
self.send_preferred_buffer_transform();
}
let children = self.children.borrow_mut();
if let Some(children) = &*children {
for ss in children.subsurfaces.values() {
@ -442,6 +454,15 @@ impl WlSurface {
}
}
pub fn send_preferred_buffer_transform(&self) {
if self.version >= TRANSFORM_SINCE {
self.client.event(PreferredBufferTransform {
self_id: self.id,
transform: self.output.get().global.transform.get().to_wl() as _,
});
}
}
fn set_toplevel(&self, tl: Option<Rc<dyn ToplevelNode>>) {
let ch = self.children.borrow();
if let Some(ch) = &*ch {