all: implement output transforms
This commit is contained in:
parent
79df8d69f4
commit
b7d2964e19
20 changed files with 254 additions and 71 deletions
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue