Merge branch 'master' into input/remove-dispatch-new

This commit is contained in:
i509VCB 2021-11-22 18:19:46 +00:00 committed by GitHub
commit d1fae4ba4e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 270 additions and 237 deletions

View File

@ -22,6 +22,7 @@
- All winit backend internal event types now use `WinitInput` as the backend type.
- `WinitEventLoop::dispatch_new_events` is now used to receive some `WinitEvent`s.
- Added `TabletToolType::Unknown` as an option for tablet events
- `render_texture` was removed from `Frame`, use `render_texture_at` or `render_texture_from_to` instead or use `Gles2Renderer::render_texture` as a direct replacement.
- Remove `InputBackend::dispatch_new_events`, turning `InputBackend` into a definition of backend event types. Future input backends should be a `calloop::EventSource`.
- Remove `InputBackend::EventError` associated type as it is unneeded since `dispatch_new_events` was removed.
@ -46,6 +47,7 @@
- `KeyState`, `MouseButton`, `ButtonState` and `Axis` in `backend::input` now derive `Hash`.
- New `DrmNode` type in drm backend. This is primarily for use a backend which needs to run as client inside another session.
- The button code for a `PointerButtonEvent` may now be obtained using `PointerButtonEvent::button_code`.
- `Renderer` now allows texture filtering methods to be set.
### Bugfixes

View File

@ -4,10 +4,6 @@ use crate::AnvilState;
#[cfg(feature = "udev")]
use crate::udev::UdevData;
#[cfg(feature = "winit")]
use crate::winit::WinitData;
#[cfg(feature = "x11")]
use crate::x11::X11Data;
use smithay::{
backend::input::{
@ -38,6 +34,34 @@ use smithay::{
};
impl<Backend> AnvilState<Backend> {
fn process_common_key_action(&mut self, action: KeyAction) {
match action {
KeyAction::None => (),
KeyAction::Quit => {
info!(self.log, "Quitting.");
self.running.store(false, Ordering::SeqCst);
}
KeyAction::Run(cmd) => {
info!(self.log, "Starting program"; "cmd" => cmd.clone());
if let Err(e) = Command::new(&cmd).spawn() {
error!(self.log,
"Failed to start program";
"cmd" => cmd,
"err" => format!("{:?}", e)
);
}
}
_ => unreachable!(
"Common key action handler encountered backend specific action {:?}",
action
),
}
}
fn keyboard_key_to_action<B: InputBackend>(&mut self, evt: B::KeyboardKeyEvent) -> KeyAction {
let keycode = evt.key_code();
let state = evt.state();
@ -143,72 +167,72 @@ impl<Backend> AnvilState<Backend> {
}
}
#[cfg(feature = "winit")]
impl AnvilState<WinitData> {
pub fn process_input_event<B: InputBackend>(&mut self, event: InputEvent<B>) {
#[cfg(any(feature = "winit", feature = "x11"))]
impl<Backend> AnvilState<Backend> {
pub fn process_input_event_windowed<B: InputBackend>(&mut self, event: InputEvent<B>, output_name: &str) {
match event {
InputEvent::Keyboard { event, .. } => match self.keyboard_key_to_action::<B>(event) {
KeyAction::None => {}
KeyAction::Quit => {
info!(self.log, "Quitting.");
self.running.store(false, Ordering::SeqCst);
}
KeyAction::Run(cmd) => {
info!(self.log, "Starting program"; "cmd" => cmd.clone());
if let Err(e) = Command::new(&cmd).spawn() {
error!(self.log,
"Failed to start program";
"cmd" => cmd,
"err" => format!("{:?}", e)
);
}
}
InputEvent::Keyboard { event } => match self.keyboard_key_to_action::<B>(event) {
KeyAction::ScaleUp => {
let current_scale = {
self.output_map
.borrow()
.find_by_name(crate::winit::OUTPUT_NAME)
.find_by_name(output_name)
.map(|o| o.scale())
.unwrap_or(1.0)
};
self.output_map
.borrow_mut()
.update_scale_by_name(current_scale + 0.25f32, crate::winit::OUTPUT_NAME);
.update_scale_by_name(current_scale + 0.25f32, output_name);
}
KeyAction::ScaleDown => {
let current_scale = {
self.output_map
.borrow()
.find_by_name(crate::winit::OUTPUT_NAME)
.find_by_name(output_name)
.map(|o| o.scale())
.unwrap_or(1.0)
};
self.output_map.borrow_mut().update_scale_by_name(
f32::max(1.0f32, current_scale - 0.25f32),
crate::winit::OUTPUT_NAME,
);
}
action => {
warn!(self.log, "Key action {:?} unsupported on winit backend.", action);
self.output_map
.borrow_mut()
.update_scale_by_name(f32::max(1.0f32, current_scale + 0.25f32), output_name);
}
action => match action {
KeyAction::None | KeyAction::Quit | KeyAction::Run(_) => {
self.process_common_key_action(action)
}
_ => warn!(
self.log,
"Key action {:?} unsupported on on output {} backend.", action, output_name
),
},
},
InputEvent::PointerMotionAbsolute { event, .. } => self.on_pointer_move_absolute::<B>(event),
InputEvent::PointerButton { event, .. } => self.on_pointer_button::<B>(event),
InputEvent::PointerAxis { event, .. } => self.on_pointer_axis::<B>(event),
_ => {
// other events are not handled in anvil (yet)
InputEvent::PointerMotionAbsolute { event } => {
self.on_pointer_move_absolute_windowed::<B>(event, output_name)
}
InputEvent::PointerButton { event } => self.on_pointer_button::<B>(event),
InputEvent::PointerAxis { event } => self.on_pointer_axis::<B>(event),
_ => (), // other events are not handled in anvil (yet)
}
}
fn on_pointer_move_absolute<B: InputBackend>(&mut self, evt: B::PointerMotionAbsoluteEvent) {
fn on_pointer_move_absolute_windowed<B: InputBackend>(
&mut self,
evt: B::PointerMotionAbsoluteEvent,
output_name: &str,
) {
let output_size = self
.output_map
.borrow()
.find_by_name(crate::winit::OUTPUT_NAME)
.find_by_name(output_name)
.map(|o| o.size())
.unwrap();
let pos = evt.position_transformed(output_size);
self.pointer_location = pos;
let serial = SCOUNTER.next_serial();
@ -222,11 +246,6 @@ impl AnvilState<UdevData> {
pub fn process_input_event<B: InputBackend>(&mut self, event: InputEvent<B>) {
match event {
InputEvent::Keyboard { event, .. } => match self.keyboard_key_to_action::<B>(event) {
KeyAction::None => {}
KeyAction::Quit => {
info!(self.log, "Quitting.");
self.running.store(false, Ordering::SeqCst);
}
#[cfg(feature = "udev")]
KeyAction::VtSwitch(vt) => {
info!(self.log, "Trying to switch to vt {}", vt);
@ -234,16 +253,6 @@ impl AnvilState<UdevData> {
error!(self.log, "Error switching to vt {}: {}", vt, err);
}
}
KeyAction::Run(cmd) => {
info!(self.log, "Starting program"; "cmd" => cmd.clone());
if let Err(e) = Command::new(&cmd).spawn() {
error!(self.log,
"Failed to start program";
"cmd" => cmd,
"err" => format!("{:?}", e)
);
}
}
KeyAction::Screen(num) => {
let geometry = self.output_map.borrow().find_by_index(num).map(|o| o.geometry());
@ -300,6 +309,14 @@ impl AnvilState<UdevData> {
.motion(self.pointer_location, under, SCOUNTER.next_serial(), 0);
}
}
action => match action {
KeyAction::None | KeyAction::Quit | KeyAction::Run(_) => {
self.process_common_key_action(action)
}
_ => unreachable!(),
},
},
InputEvent::PointerMotion { event, .. } => self.on_pointer_move::<B>(event),
InputEvent::PointerButton { event, .. } => self.on_pointer_button::<B>(event),
@ -486,87 +503,6 @@ impl AnvilState<UdevData> {
}
}
#[cfg(feature = "x11")]
impl AnvilState<X11Data> {
pub fn process_input_event<B: InputBackend>(&mut self, event: InputEvent<B>) {
match event {
InputEvent::Keyboard { event } => match self.keyboard_key_to_action::<B>(event) {
KeyAction::None => (),
KeyAction::Quit => {
info!(self.log, "Quitting.");
self.running.store(false, Ordering::SeqCst);
}
KeyAction::Run(cmd) => {
info!(self.log, "Starting program"; "cmd" => cmd.clone());
if let Err(e) = Command::new(&cmd).spawn() {
error!(self.log,
"Failed to start program";
"cmd" => cmd,
"err" => format!("{:?}", e)
);
}
}
KeyAction::ScaleUp => {
let current_scale = {
self.output_map
.borrow()
.find_by_name(crate::x11::OUTPUT_NAME)
.map(|o| o.scale())
.unwrap_or(1.0)
};
self.output_map
.borrow_mut()
.update_scale_by_name(current_scale + 0.25f32, crate::x11::OUTPUT_NAME);
}
KeyAction::ScaleDown => {
let current_scale = {
self.output_map
.borrow()
.find_by_name(crate::x11::OUTPUT_NAME)
.map(|o| o.scale())
.unwrap_or(1.0)
};
self.output_map.borrow_mut().update_scale_by_name(
f32::max(1.0f32, current_scale + 0.25f32),
crate::x11::OUTPUT_NAME,
);
}
action => {
warn!(self.log, "Key action {:?} unsupported on x11 backend.", action);
}
},
InputEvent::PointerMotionAbsolute { event } => self.on_pointer_move_absolute::<B>(event),
InputEvent::PointerButton { event } => self.on_pointer_button::<B>(event),
InputEvent::PointerAxis { event } => self.on_pointer_axis::<B>(event),
_ => (), // other events are not handled in anvil (yet)
}
}
fn on_pointer_move_absolute<B: InputBackend>(&mut self, evt: B::PointerMotionAbsoluteEvent) {
let output_size = self
.output_map
.borrow()
.find_by_name(crate::x11::OUTPUT_NAME)
.map(|o| o.size())
.unwrap();
let pos = evt.position_transformed(output_size);
self.pointer_location = pos;
let serial = SCOUNTER.next_serial();
let under = self.window_map.borrow().get_surface_under(pos);
self.pointer.motion(pos, under, serial, evt.time());
}
}
/// Possible results of a keyboard action
#[derive(Debug)]
enum KeyAction {

View File

@ -132,16 +132,16 @@ pub fn run_winit(log: Logger) {
size,
refresh: 60_000,
},
crate::winit::OUTPUT_NAME,
OUTPUT_NAME,
);
let output_mut = state.output_map.borrow();
let output = output_mut.find_by_name(crate::winit::OUTPUT_NAME).unwrap();
let output = output_mut.find_by_name(OUTPUT_NAME).unwrap();
state.window_map.borrow_mut().layers.arange_layers(output);
}
WinitEvent::Input(event) => state.process_input_event(event),
WinitEvent::Input(event) => state.process_input_event_windowed(event, OUTPUT_NAME),
_ => (),
})

View File

@ -164,7 +164,7 @@ pub fn run_x11(log: Logger) {
state.backend_data.render = true;
}
X11Event::Input(event) => state.process_input_event(event),
X11Event::Input(event) => state.process_input_event_windowed(event, OUTPUT_NAME),
})
.expect("Failed to insert X11 Backend into event loop");

View File

@ -62,16 +62,21 @@ where
// Once we have proper color management and possibly HDR support,
// we need to have a more sophisticated picker.
// (Or maybe just pick ARGB2101010, if available, we will see.)
let code = Fourcc::Argb8888;
let mut code = Fourcc::Argb8888;
let logger = crate::slog_or_fallback(log).new(o!("backend" => "drm_render"));
// select a format
let plane_formats = drm
let mut plane_formats = drm
.supported_formats(drm.plane())?
.iter()
.filter(|fmt| fmt.code == code)
.cloned()
.collect::<HashSet<_>>();
// try non alpha variant if not available
if !plane_formats.iter().any(|fmt| fmt.code == code) {
code = Fourcc::Xrgb8888;
}
plane_formats.retain(|fmt| fmt.code == code);
renderer_formats.retain(|fmt| fmt.code == code);
trace!(logger, "Plane formats: {:?}", plane_formats);

View File

@ -11,12 +11,12 @@ use std::sync::{
};
use std::{collections::HashSet, os::raw::c_char};
use cgmath::{prelude::*, Matrix3, Vector2};
use cgmath::{prelude::*, Matrix3, Vector2, Vector3};
mod shaders;
mod version;
use super::{Bind, Frame, Renderer, Texture, Transform, Unbind};
use super::{Bind, Frame, Renderer, Texture, TextureFilter, Transform, Unbind};
use crate::backend::allocator::{
dmabuf::{Dmabuf, WeakDmabuf},
Format,
@ -26,7 +26,7 @@ use crate::backend::egl::{
EGLContext, EGLSurface, MakeCurrentError,
};
use crate::backend::SwapBuffersError;
use crate::utils::{Buffer, Physical, Size};
use crate::utils::{Buffer, Physical, Rectangle, Size};
#[cfg(all(feature = "wayland_frontend", feature = "use_system_lib"))]
use super::ImportEgl;
@ -35,8 +35,6 @@ use super::{ImportDma, ImportShm};
#[cfg(all(feature = "wayland_frontend", feature = "use_system_lib"))]
use crate::backend::egl::{display::EGLBufferReader, Format as EGLFormat};
#[cfg(feature = "wayland_frontend")]
use crate::utils::Rectangle;
#[cfg(feature = "wayland_frontend")]
use wayland_server::protocol::{wl_buffer, wl_shm};
use slog::{debug, error, info, o, trace, warn};
@ -420,6 +418,7 @@ impl Gles2Renderer {
/// - This renderer has no default framebuffer, use `Bind::bind` before rendering.
/// - Binding a new target, while another one is already bound, will replace the current target.
/// - Shm buffers can be released after a successful import, without the texture handle becoming invalid.
/// - Texture filtering starts with Nearest-downscaling and Linear-upscaling
pub unsafe fn new<L>(context: EGLContext, logger: L) -> Result<Gles2Renderer, Gles2Error>
where
L: Into<Option<::slog::Logger>>,
@ -495,7 +494,7 @@ impl Gles2Renderer {
];
let (tx, rx) = channel();
let renderer = Gles2Renderer {
let mut renderer = Gles2Renderer {
id: RENDERER_COUNTER.fetch_add(1, Ordering::SeqCst),
gl,
egl: context,
@ -514,6 +513,8 @@ impl Gles2Renderer {
logger: log,
_not_send: std::ptr::null_mut(),
};
renderer.downscale_filter(TextureFilter::Nearest)?;
renderer.upscale_filter(TextureFilter::Linear)?;
renderer.egl.unbind()?;
Ok(renderer)
}
@ -1007,6 +1008,35 @@ impl Renderer for Gles2Renderer {
type TextureId = Gles2Texture;
type Frame = Gles2Frame;
fn downscale_filter(&mut self, filter: TextureFilter) -> Result<(), Self::Error> {
self.make_current()?;
unsafe {
self.gl.TexParameteri(
ffi::TEXTURE_2D,
ffi::TEXTURE_MIN_FILTER,
match filter {
TextureFilter::Nearest => ffi::NEAREST as i32,
TextureFilter::Linear => ffi::LINEAR as i32,
},
);
}
Ok(())
}
fn upscale_filter(&mut self, filter: TextureFilter) -> Result<(), Self::Error> {
self.make_current()?;
unsafe {
self.gl.TexParameteri(
ffi::TEXTURE_2D,
ffi::TEXTURE_MAG_FILTER,
match filter {
TextureFilter::Nearest => ffi::NEAREST as i32,
TextureFilter::Linear => ffi::LINEAR as i32,
},
);
}
Ok(())
}
fn render<F, R>(
&mut self,
size: Size<i32, Physical>,
@ -1100,13 +1130,60 @@ impl Frame for Gles2Frame {
Ok(())
}
fn render_texture(
fn render_texture_from_to(
&mut self,
tex: &Self::TextureId,
texture: &Self::TextureId,
src: Rectangle<i32, Buffer>,
dest: Rectangle<f64, Physical>,
transform: Transform,
alpha: f32,
) -> Result<(), Self::Error> {
let mut mat = Matrix3::<f32>::identity();
// position and scale
mat = mat * Matrix3::from_translation(Vector2::new(dest.loc.x as f32, dest.loc.y as f32));
mat = mat * Matrix3::from_nonuniform_scale(dest.size.w as f32, dest.size.h as f32);
//apply surface transformation
mat = mat * Matrix3::from_translation(Vector2::new(0.5, 0.5));
if transform == Transform::Normal {
assert_eq!(mat, mat * transform.invert().matrix());
assert_eq!(transform.matrix(), Matrix3::<f32>::identity());
}
mat = mat * transform.invert().matrix();
mat = mat * Matrix3::from_translation(Vector2::new(-0.5, -0.5));
// this matrix should be regular, we can expect invert to succeed
let tex_size = texture.size();
let texture_mat = Matrix3::from_nonuniform_scale(tex_size.w as f32, tex_size.h as f32)
.invert()
.unwrap();
let verts = [
(texture_mat * Vector3::new((src.loc.x + src.size.w) as f32, src.loc.y as f32, 0.0)).truncate(), // top-right
(texture_mat * Vector3::new(src.loc.x as f32, src.loc.y as f32, 0.0)).truncate(), // top-left
(texture_mat
* Vector3::new(
(src.loc.x + src.size.w) as f32,
(src.loc.y + src.size.h) as f32,
0.0,
))
.truncate(), // bottom-right
(texture_mat * Vector3::new(src.loc.x as f32, (src.loc.y + src.size.h) as f32, 0.0)).truncate(), // bottom-left
];
self.render_texture(texture, mat, verts, alpha)
}
}
impl Gles2Frame {
/// Render a texture to the current target using given projection matrix and alpha.
/// The given vertices are used to source the texture. This is mostly useful for cropping the texture.
pub fn render_texture(
&mut self,
tex: &Gles2Texture,
mut matrix: Matrix3<f32>,
tex_coords: [Vector2<f32>; 4],
alpha: f32,
) -> Result<(), Self::Error> {
) -> Result<(), Gles2Error> {
//apply output transformation
matrix = self.current_projection * matrix;

View File

@ -14,7 +14,7 @@ use crate::utils::{Buffer, Physical, Point, Rectangle, Size};
#[cfg(feature = "wayland_frontend")]
use crate::wayland::compositor::SurfaceData;
use cgmath::{prelude::*, Matrix3, Vector2, Vector3};
use cgmath::Matrix3;
#[cfg(feature = "wayland_frontend")]
use wayland_server::protocol::{wl_buffer, wl_shm};
@ -53,6 +53,15 @@ pub enum Transform {
Flipped270,
}
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
/// Texture filtering methods
pub enum TextureFilter {
/// Returns the value of the texture element that is nearest (in Manhattan distance) to the center of the pixel being textured.
Linear,
/// Returns the weighted average of the four texture elements that are closest to the center of the pixel being textured.
Nearest,
}
impl Transform {
/// A projection matrix to apply this transformation
pub fn matrix(&self) -> Matrix3<f32> {
@ -163,25 +172,17 @@ pub trait Frame {
/// This operation is only valid in between a `begin` and `finish`-call.
/// If called outside this operation may error-out, do nothing or modify future rendering results in any way.
fn clear(&mut self, color: [f32; 4]) -> Result<(), Self::Error>;
/// Render a texture to the current target using given projection matrix and alpha.
/// The given vertices are used to source the texture. This is mostly useful for cropping the texture.
fn render_texture(
&mut self,
texture: &Self::TextureId,
matrix: Matrix3<f32>,
tex_coords: [Vector2<f32>; 4],
alpha: f32,
) -> Result<(), Self::Error>;
/// Render a texture to the current target as a flat 2d-plane at a given
/// position and applying the given transformation with the given alpha value.
/// (Meaning `src_transform` should match the orientation of surface being rendered).
fn render_texture_at(
&mut self,
texture: &Self::TextureId,
pos: Point<f64, Physical>,
texture_scale: i32,
output_scale: f64,
transform: Transform,
src_transform: Transform,
alpha: f32,
) -> Result<(), Self::Error> {
self.render_texture_from_to(
@ -195,55 +196,22 @@ pub trait Frame {
.to_f64()
.to_physical(output_scale),
),
transform,
src_transform,
alpha,
)
}
/// Render part of a texture as given by src to the current target into the rectangle described by dest
/// as a flat 2d-plane after applying the given transformations.
/// Render part of a texture as given by src to the current target into the rectangle described by dst
/// as a flat 2d-plane after applying the inverse of the given transformation.
/// (Meaning `src_transform` should match the orientation of surface being rendered).
fn render_texture_from_to(
&mut self,
texture: &Self::TextureId,
src: Rectangle<i32, Buffer>,
dest: Rectangle<f64, Physical>,
transform: Transform,
dst: Rectangle<f64, Physical>,
src_transform: Transform,
alpha: f32,
) -> Result<(), Self::Error> {
let mut mat = Matrix3::<f32>::identity();
// position and scale
mat = mat * Matrix3::from_translation(Vector2::new(dest.loc.x as f32, dest.loc.y as f32));
mat = mat * Matrix3::from_nonuniform_scale(dest.size.w as f32, dest.size.h as f32);
//apply surface transformation
mat = mat * Matrix3::from_translation(Vector2::new(0.5, 0.5));
if transform == Transform::Normal {
assert_eq!(mat, mat * transform.invert().matrix());
assert_eq!(transform.matrix(), Matrix3::<f32>::identity());
}
mat = mat * transform.invert().matrix();
mat = mat * Matrix3::from_translation(Vector2::new(-0.5, -0.5));
// this matrix should be regular, we can expect invert to succeed
let tex_size = texture.size();
let texture_mat = Matrix3::from_nonuniform_scale(tex_size.w as f32, tex_size.h as f32)
.invert()
.unwrap();
let verts = [
(texture_mat * Vector3::new((src.loc.x + src.size.w) as f32, src.loc.y as f32, 0.0)).truncate(), // top-right
(texture_mat * Vector3::new(src.loc.x as f32, src.loc.y as f32, 0.0)).truncate(), // top-left
(texture_mat
* Vector3::new(
(src.loc.x + src.size.w) as f32,
(src.loc.y + src.size.h) as f32,
0.0,
))
.truncate(), // bottom-right
(texture_mat * Vector3::new(src.loc.x as f32, (src.loc.y + src.size.h) as f32, 0.0)).truncate(), // bottom-left
];
self.render_texture(texture, mat, verts, alpha)
}
) -> Result<(), Self::Error>;
}
/// Abstraction of commonly used rendering operations for compositors.
@ -255,6 +223,11 @@ pub trait Renderer {
/// Type representing a currently in-progress frame during the [`Renderer::render`]-call
type Frame: Frame<Error = Self::Error, TextureId = Self::TextureId>;
/// Set the filter method to be used when rendering a texture into a smaller area than its size
fn downscale_filter(&mut self, filter: TextureFilter) -> Result<(), Self::Error>;
/// Set the filter method to be used when rendering a texture into a larger area than its size
fn upscale_filter(&mut self, filter: TextureFilter) -> Result<(), Self::Error>;
/// Initialize a rendering context on the current rendering target with given dimensions and transformation.
///
/// This function *may* error, if:
@ -265,7 +238,7 @@ pub trait Renderer {
fn render<F, R>(
&mut self,
size: Size<i32, Physical>,
transform: Transform,
dst_transform: Transform,
rendering: F,
) -> Result<R, Self::Error>
where

View File

@ -129,7 +129,7 @@ where
}
// We need dri3 >= 1.2 in order to use the enhanced dri3_pixmap_from_buffers function.
let xid = if window_inner.extensions.dri3 >= (1, 2) {
let xid = if window_inner.extensions.dri3 >= Some((1, 2)) {
if dmabuf.num_planes() > 4 {
return Err(CreatePixmapError::TooManyPlanes);
}

View File

@ -25,6 +25,7 @@ macro_rules! extensions {
$(
$extension:ident { // Extension name for path lookup
$extension_fn:ident, // Function used to look up the version of the extension
required: $required:expr,
minimum: ($min_major:expr, $min_minor:expr),
request: ($req_major:expr, $req_minor:expr),
},
@ -34,7 +35,7 @@ macro_rules! extensions {
pub struct Extensions {
$(
#[doc = concat!(" The version of the `", stringify!($extension), "` extension.")]
pub $extension: (u32, u32),
pub $extension: Option<(u32, u32)>,
)*
}
@ -59,35 +60,43 @@ macro_rules! extensions {
version.minor_version,
);
(version.major_version, version.minor_version)
Some((version.major_version, version.minor_version))
} else {
slog::error!(
logger,
"{} extension version is too low (have {}.{}, expected {}.{})",
X11_EXTENSION_NAME,
version.major_version,
version.minor_version,
$req_major,
$req_minor,
);
if $required {
slog::error!(
logger,
"required extension {} version is too low (have {}.{}, expected {}.{})",
X11_EXTENSION_NAME,
version.major_version,
version.minor_version,
$req_major,
$req_minor,
);
return Err(MissingExtensionError::WrongVersion {
name: X11_EXTENSION_NAME,
required_major: $req_major,
required_minor: $req_minor,
available_major: version.major_version,
available_minor: version.minor_version,
}.into());
return Err(MissingExtensionError::WrongVersion {
name: X11_EXTENSION_NAME,
required_major: $req_major,
required_minor: $req_minor,
available_major: version.major_version,
available_minor: version.minor_version,
}.into());
} else {
None
}
}
} else {
slog::error!(logger, "{} extension not found", X11_EXTENSION_NAME);
if $required {
slog::error!(logger, "required extension {} not found", X11_EXTENSION_NAME);
return Err(MissingExtensionError::NotFound {
name: X11_EXTENSION_NAME,
major: $min_major,
minor: $min_minor,
return Err(MissingExtensionError::NotFound {
name: X11_EXTENSION_NAME,
major: $min_major,
minor: $min_minor,
}
.into());
} else {
None
}
.into());
}
};
)*
@ -105,18 +114,21 @@ macro_rules! extensions {
extensions! {
present {
present_query_version,
required: true,
minimum: (1, 0),
request: (1, 0),
},
xfixes {
xfixes_query_version,
required: true,
minimum: (4, 0),
request: (4, 0),
},
dri3 {
dri3_query_version,
required: true,
minimum: (1, 0),
request: (1, 2),
},

View File

@ -4,7 +4,7 @@
//! # Smithay: the Wayland compositor smithy
//!
//! This crate is a general framework for build wayland compositors. It currently focuses on low-level,
//! This crate is a general framework for building wayland compositors. It currently focuses on low-level,
//! helpers and abstractions, handling most of the system-level and wayland protocol interactions.
//! The window management and drawing logic is however at the time not provided (but helpers for this
//! are planned for future version).

View File

@ -18,7 +18,7 @@ pub struct Buffer;
pub struct Raw;
pub trait Coordinate:
Sized + Add<Self, Output = Self> + Sub<Self, Output = Self> + PartialOrd + Default + Copy + std::fmt::Debug
Sized + Add<Self, Output = Self> + Sub<Self, Output = Self> + PartialOrd + Default + Copy + fmt::Debug
{
fn downscale(self, scale: Self) -> Self;
fn upscale(self, scale: Self) -> Self;
@ -637,6 +637,21 @@ impl<N: AddAssign, Kind> AddAssign for Size<N, Kind> {
}
}
impl<N: SubAssign + fmt::Debug + PartialOrd, Kind> SubAssign for Size<N, Kind> {
#[inline]
fn sub_assign(&mut self, rhs: Self) {
debug_assert!(
self.w >= rhs.w && self.h >= rhs.h,
"Attempting to subtract bigger from smaller size: {:?} - {:?}",
(&self.w, &self.h),
(&rhs.w, &rhs.h),
);
self.w -= rhs.w;
self.h -= rhs.h
}
}
impl<N: Clone, Kind> Clone for Size<N, Kind> {
#[inline]
fn clone(&self) -> Self {

View File

@ -903,6 +903,11 @@ impl ToplevelSurface {
self.shell_surface.as_ref().is_alive() && self.wl_surface.as_ref().is_alive()
}
/// Supported XDG shell protocol version.
pub fn version(&self) -> u32 {
self.shell_surface.as_ref().version()
}
/// Retrieve the shell client owning this toplevel surface
///
/// Returns `None` if the surface does actually no longer exist.

View File

@ -1,10 +1,9 @@
use std::cell::Cell;
use cgmath::Vector2;
use smithay::{
backend::{
allocator::dmabuf::Dmabuf,
renderer::{Frame, ImportDma, ImportShm, Renderer, Texture, Transform},
renderer::{Frame, ImportDma, ImportShm, Renderer, Texture, TextureFilter, Transform},
SwapBuffersError,
},
reexports::wayland_server::protocol::wl_buffer,
@ -28,7 +27,7 @@ impl Renderer for DummyRenderer {
fn render<F, R>(
&mut self,
_size: Size<i32, Physical>,
_transform: Transform,
_dst_transform: Transform,
rendering: F,
) -> Result<R, Self::Error>
where
@ -37,6 +36,14 @@ impl Renderer for DummyRenderer {
let mut frame = DummyFrame {};
Ok(rendering(self, &mut frame))
}
fn upscale_filter(&mut self, _filter: TextureFilter) -> Result<(), Self::Error> {
Ok(())
}
fn downscale_filter(&mut self, _filter: TextureFilter) -> Result<(), Self::Error> {
Ok(())
}
}
impl ImportShm for DummyRenderer {
@ -94,11 +101,12 @@ impl Frame for DummyFrame {
Ok(())
}
fn render_texture(
fn render_texture_from_to(
&mut self,
_texture: &Self::TextureId,
_matrix: cgmath::Matrix3<f32>,
_tex_coords: [Vector2<f32>; 4],
_src: Rectangle<i32, Buffer>,
_dst: Rectangle<f64, Physical>,
_src_transform: Transform,
_alpha: f32,
) -> Result<(), Self::Error> {
Ok(())