Merge pull request #155 from YaLTeR/fix-dimensions
anvil: retrieve buffer dimensions on commit
This commit is contained in:
commit
7fa7fe03be
|
@ -0,0 +1,59 @@
|
||||||
|
use std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
|
use slog::Logger;
|
||||||
|
|
||||||
|
#[cfg(feature = "egl")]
|
||||||
|
use smithay::backend::egl::{BufferAccessError, EGLDisplay};
|
||||||
|
use smithay::{
|
||||||
|
reexports::wayland_server::protocol::wl_buffer::WlBuffer,
|
||||||
|
wayland::shm::with_buffer_contents as shm_buffer_contents,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Utilities for working with `WlBuffer`s.
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct BufferUtils {
|
||||||
|
#[cfg(feature = "egl")]
|
||||||
|
egl_display: Rc<RefCell<Option<EGLDisplay>>>,
|
||||||
|
log: Logger,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BufferUtils {
|
||||||
|
/// Creates a new `BufferUtils`.
|
||||||
|
#[cfg(feature = "egl")]
|
||||||
|
pub fn new(egl_display: Rc<RefCell<Option<EGLDisplay>>>, log: Logger) -> Self {
|
||||||
|
Self { egl_display, log }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new `BufferUtils`.
|
||||||
|
#[cfg(not(feature = "egl"))]
|
||||||
|
pub fn new(log: Logger) -> Self {
|
||||||
|
Self { log }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the dimensions of an image stored in the buffer.
|
||||||
|
#[cfg(feature = "egl")]
|
||||||
|
pub fn dimensions(&self, buffer: &WlBuffer) -> Option<(i32, i32)> {
|
||||||
|
// Try to retrieve the EGL dimensions of this buffer, and, if that fails, the shm dimensions.
|
||||||
|
self.egl_display
|
||||||
|
.borrow()
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|display| display.egl_buffer_dimensions(buffer))
|
||||||
|
.or_else(|| self.shm_buffer_dimensions(buffer))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the dimensions of an image stored in the buffer.
|
||||||
|
#[cfg(not(feature = "egl"))]
|
||||||
|
pub fn dimensions(&self, buffer: &WlBuffer) -> Option<(i32, i32)> {
|
||||||
|
self.shm_buffer_dimensions(buffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the dimensions of an image stored in the shm buffer.
|
||||||
|
fn shm_buffer_dimensions(&self, buffer: &WlBuffer) -> Option<(i32, i32)> {
|
||||||
|
shm_buffer_contents(buffer, |_, data| (data.width, data.height))
|
||||||
|
.map_err(|err| {
|
||||||
|
warn!(self.log, "Unable to load buffer contents"; "err" => format!("{:?}", err));
|
||||||
|
err
|
||||||
|
})
|
||||||
|
.ok()
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,6 +12,7 @@ use smithay::reexports::{calloop::EventLoop, wayland_server::Display};
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod shaders;
|
mod shaders;
|
||||||
|
mod buffer_utils;
|
||||||
mod glium_drawer;
|
mod glium_drawer;
|
||||||
mod input_handler;
|
mod input_handler;
|
||||||
mod shell;
|
mod shell;
|
||||||
|
|
|
@ -29,7 +29,10 @@ use smithay::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::window_map::{Kind as SurfaceKind, WindowMap};
|
use crate::{
|
||||||
|
buffer_utils::BufferUtils,
|
||||||
|
window_map::{Kind as SurfaceKind, WindowMap},
|
||||||
|
};
|
||||||
|
|
||||||
define_roles!(Roles =>
|
define_roles!(Roles =>
|
||||||
[ XdgSurface, XdgSurfaceRole ]
|
[ XdgSurface, XdgSurfaceRole ]
|
||||||
|
@ -98,6 +101,7 @@ impl PointerGrab for MoveSurfaceGrab {
|
||||||
|
|
||||||
pub fn init_shell(
|
pub fn init_shell(
|
||||||
display: &mut Display,
|
display: &mut Display,
|
||||||
|
buffer_utils: BufferUtils,
|
||||||
log: ::slog::Logger,
|
log: ::slog::Logger,
|
||||||
) -> (
|
) -> (
|
||||||
CompositorToken<Roles>,
|
CompositorToken<Roles>,
|
||||||
|
@ -109,7 +113,7 @@ pub fn init_shell(
|
||||||
let (compositor_token, _, _) = compositor_init(
|
let (compositor_token, _, _) = compositor_init(
|
||||||
display,
|
display,
|
||||||
move |request, surface, ctoken| match request {
|
move |request, surface, ctoken| match request {
|
||||||
SurfaceEvent::Commit => surface_commit(&surface, ctoken),
|
SurfaceEvent::Commit => surface_commit(&surface, ctoken, &buffer_utils),
|
||||||
SurfaceEvent::Frame { callback } => callback
|
SurfaceEvent::Frame { callback } => callback
|
||||||
.implement_closure(|_, _| unreachable!(), None::<fn(_)>, ())
|
.implement_closure(|_, _| unreachable!(), None::<fn(_)>, ())
|
||||||
.done(0),
|
.done(0),
|
||||||
|
@ -273,10 +277,15 @@ pub fn init_shell(
|
||||||
pub struct SurfaceData {
|
pub struct SurfaceData {
|
||||||
pub buffer: Option<wl_buffer::WlBuffer>,
|
pub buffer: Option<wl_buffer::WlBuffer>,
|
||||||
pub texture: Option<crate::glium_drawer::TextureMetadata>,
|
pub texture: Option<crate::glium_drawer::TextureMetadata>,
|
||||||
|
pub dimensions: Option<(i32, i32)>,
|
||||||
pub input_region: Option<RegionAttributes>,
|
pub input_region: Option<RegionAttributes>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn surface_commit(surface: &wl_surface::WlSurface, token: CompositorToken<Roles>) {
|
fn surface_commit(
|
||||||
|
surface: &wl_surface::WlSurface,
|
||||||
|
token: CompositorToken<Roles>,
|
||||||
|
buffer_utils: &BufferUtils,
|
||||||
|
) {
|
||||||
token.with_surface_data(surface, |attributes| {
|
token.with_surface_data(surface, |attributes| {
|
||||||
attributes.user_data.insert_if_missing(SurfaceData::default);
|
attributes.user_data.insert_if_missing(SurfaceData::default);
|
||||||
let data = attributes.user_data.get_mut::<SurfaceData>().unwrap();
|
let data = attributes.user_data.get_mut::<SurfaceData>().unwrap();
|
||||||
|
@ -292,6 +301,8 @@ fn surface_commit(surface: &wl_surface::WlSurface, token: CompositorToken<Roles>
|
||||||
old_buffer.release();
|
old_buffer.release();
|
||||||
}
|
}
|
||||||
data.texture = None;
|
data.texture = None;
|
||||||
|
// If this fails, the buffer will be discarded later by the drawing code.
|
||||||
|
data.dimensions = buffer_utils.dimensions(data.buffer.as_ref().unwrap());
|
||||||
}
|
}
|
||||||
Some(None) => {
|
Some(None) => {
|
||||||
// erase the contents
|
// erase the contents
|
||||||
|
@ -299,6 +310,7 @@ fn surface_commit(surface: &wl_surface::WlSurface, token: CompositorToken<Roles>
|
||||||
old_buffer.release();
|
old_buffer.release();
|
||||||
}
|
}
|
||||||
data.texture = None;
|
data.texture = None;
|
||||||
|
data.dimensions = None;
|
||||||
}
|
}
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
|
@ -306,12 +318,10 @@ fn surface_commit(surface: &wl_surface::WlSurface, token: CompositorToken<Roles>
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_size(attrs: &SurfaceAttributes) -> Option<(i32, i32)> {
|
fn get_size(attrs: &SurfaceAttributes) -> Option<(i32, i32)> {
|
||||||
attrs.user_data.get::<SurfaceData>().and_then(|data| {
|
attrs
|
||||||
data.texture
|
.user_data
|
||||||
.as_ref()
|
.get::<SurfaceData>()
|
||||||
.map(|ref meta| meta.dimensions)
|
.and_then(|data| data.dimensions)
|
||||||
.map(|(x, y)| (x as i32, y as i32))
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn contains_point(attrs: &SurfaceAttributes, point: (f64, f64)) -> bool {
|
fn contains_point(attrs: &SurfaceAttributes, point: (f64, f64)) -> bool {
|
||||||
|
|
|
@ -61,6 +61,7 @@ use smithay::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::buffer_utils::BufferUtils;
|
||||||
use crate::glium_drawer::GliumDrawer;
|
use crate::glium_drawer::GliumDrawer;
|
||||||
use crate::input_handler::AnvilInputHandler;
|
use crate::input_handler::AnvilInputHandler;
|
||||||
use crate::shell::{init_shell, MyWindowMap, Roles};
|
use crate::shell::{init_shell, MyWindowMap, Roles};
|
||||||
|
@ -85,6 +86,11 @@ pub fn run_udev(mut display: Display, mut event_loop: EventLoop<()>, log: Logger
|
||||||
#[cfg(feature = "egl")]
|
#[cfg(feature = "egl")]
|
||||||
let active_egl_context = Rc::new(RefCell::new(None));
|
let active_egl_context = Rc::new(RefCell::new(None));
|
||||||
|
|
||||||
|
#[cfg(feature = "egl")]
|
||||||
|
let buffer_utils = BufferUtils::new(active_egl_context.clone(), log.clone());
|
||||||
|
#[cfg(not(feature = "egl"))]
|
||||||
|
let buffer_utils = BufferUtils::new(log.clone());
|
||||||
|
|
||||||
let display = Rc::new(RefCell::new(display));
|
let display = Rc::new(RefCell::new(display));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -92,7 +98,8 @@ pub fn run_udev(mut display: Display, mut event_loop: EventLoop<()>, log: Logger
|
||||||
*/
|
*/
|
||||||
init_shm_global(&mut display.borrow_mut(), vec![], log.clone());
|
init_shm_global(&mut display.borrow_mut(), vec![], log.clone());
|
||||||
|
|
||||||
let (compositor_token, _, _, window_map) = init_shell(&mut display.borrow_mut(), log.clone());
|
let (compositor_token, _, _, window_map) =
|
||||||
|
init_shell(&mut display.borrow_mut(), buffer_utils, log.clone());
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize session
|
* Initialize session
|
||||||
|
|
|
@ -23,6 +23,7 @@ use smithay::{
|
||||||
|
|
||||||
use slog::Logger;
|
use slog::Logger;
|
||||||
|
|
||||||
|
use crate::buffer_utils::BufferUtils;
|
||||||
use crate::glium_drawer::GliumDrawer;
|
use crate::glium_drawer::GliumDrawer;
|
||||||
use crate::input_handler::AnvilInputHandler;
|
use crate::input_handler::AnvilInputHandler;
|
||||||
use crate::shell::init_shell;
|
use crate::shell::init_shell;
|
||||||
|
@ -42,10 +43,15 @@ pub fn run_winit(display: &mut Display, event_loop: &mut EventLoop<()>, log: Log
|
||||||
|
|
||||||
let (w, h) = renderer.get_framebuffer_dimensions();
|
let (w, h) = renderer.get_framebuffer_dimensions();
|
||||||
#[cfg(feature = "egl")]
|
#[cfg(feature = "egl")]
|
||||||
let drawer = GliumDrawer::init(renderer, egl_display, log.clone());
|
let drawer = GliumDrawer::init(renderer, egl_display.clone(), log.clone());
|
||||||
#[cfg(not(feature = "egl"))]
|
#[cfg(not(feature = "egl"))]
|
||||||
let drawer = GliumDrawer::init(renderer, log.clone());
|
let drawer = GliumDrawer::init(renderer, log.clone());
|
||||||
|
|
||||||
|
#[cfg(feature = "egl")]
|
||||||
|
let buffer_utils = BufferUtils::new(egl_display, log.clone());
|
||||||
|
#[cfg(not(feature = "egl"))]
|
||||||
|
let buffer_utils = BufferUtils::new(log.clone());
|
||||||
|
|
||||||
let name = display.add_socket_auto().unwrap().into_string().unwrap();
|
let name = display.add_socket_auto().unwrap().into_string().unwrap();
|
||||||
info!(log, "Listening on wayland socket"; "name" => name.clone());
|
info!(log, "Listening on wayland socket"; "name" => name.clone());
|
||||||
::std::env::set_var("WAYLAND_DISPLAY", name);
|
::std::env::set_var("WAYLAND_DISPLAY", name);
|
||||||
|
@ -58,7 +64,7 @@ pub fn run_winit(display: &mut Display, event_loop: &mut EventLoop<()>, log: Log
|
||||||
|
|
||||||
init_shm_global(display, vec![], log.clone());
|
init_shm_global(display, vec![], log.clone());
|
||||||
|
|
||||||
let (compositor_token, _, _, window_map) = init_shell(display, log.clone());
|
let (compositor_token, _, _, window_map) = init_shell(display, buffer_utils, log.clone());
|
||||||
|
|
||||||
let dnd_icon = Arc::new(Mutex::new(None));
|
let dnd_icon = Arc::new(Mutex::new(None));
|
||||||
|
|
||||||
|
|
|
@ -472,6 +472,42 @@ impl EGLDisplay {
|
||||||
Err(BufferAccessError::ContextLost)
|
Err(BufferAccessError::ContextLost)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Try to receive the dimensions of a given [`WlBuffer`].
|
||||||
|
///
|
||||||
|
/// In case the buffer is not managed by EGL (but e.g. the [`wayland::shm` module](::wayland::shm)) or the
|
||||||
|
/// context has been lost, `None` is returned.
|
||||||
|
pub fn egl_buffer_dimensions(&self, buffer: &WlBuffer) -> Option<(i32, i32)> {
|
||||||
|
if let Some(display) = self.egl.upgrade() {
|
||||||
|
let mut width: i32 = 0;
|
||||||
|
if unsafe {
|
||||||
|
ffi::egl::QueryWaylandBufferWL(
|
||||||
|
*display,
|
||||||
|
buffer.as_ref().c_ptr() as *mut _,
|
||||||
|
ffi::egl::WIDTH as i32,
|
||||||
|
&mut width as *mut _,
|
||||||
|
) == 0
|
||||||
|
} {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut height: i32 = 0;
|
||||||
|
if unsafe {
|
||||||
|
ffi::egl::QueryWaylandBufferWL(
|
||||||
|
*display,
|
||||||
|
buffer.as_ref().c_ptr() as *mut _,
|
||||||
|
ffi::egl::HEIGHT as i32,
|
||||||
|
&mut height as *mut _,
|
||||||
|
) == 0
|
||||||
|
} {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some((width, height))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "native_lib")]
|
#[cfg(feature = "native_lib")]
|
||||||
|
|
Loading…
Reference in New Issue