Merge branch 'master' into input/remove-dispatch-new
This commit is contained in:
commit
d1fae4ba4e
|
@ -22,6 +22,7 @@
|
||||||
- All winit backend internal event types now use `WinitInput` as the backend type.
|
- 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.
|
- `WinitEventLoop::dispatch_new_events` is now used to receive some `WinitEvent`s.
|
||||||
- Added `TabletToolType::Unknown` as an option for tablet events
|
- 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::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.
|
- 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`.
|
- `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.
|
- 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`.
|
- The button code for a `PointerButtonEvent` may now be obtained using `PointerButtonEvent::button_code`.
|
||||||
|
- `Renderer` now allows texture filtering methods to be set.
|
||||||
|
|
||||||
### Bugfixes
|
### Bugfixes
|
||||||
|
|
||||||
|
|
|
@ -4,10 +4,6 @@ use crate::AnvilState;
|
||||||
|
|
||||||
#[cfg(feature = "udev")]
|
#[cfg(feature = "udev")]
|
||||||
use crate::udev::UdevData;
|
use crate::udev::UdevData;
|
||||||
#[cfg(feature = "winit")]
|
|
||||||
use crate::winit::WinitData;
|
|
||||||
#[cfg(feature = "x11")]
|
|
||||||
use crate::x11::X11Data;
|
|
||||||
|
|
||||||
use smithay::{
|
use smithay::{
|
||||||
backend::input::{
|
backend::input::{
|
||||||
|
@ -38,6 +34,34 @@ use smithay::{
|
||||||
};
|
};
|
||||||
|
|
||||||
impl<Backend> AnvilState<Backend> {
|
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 {
|
fn keyboard_key_to_action<B: InputBackend>(&mut self, evt: B::KeyboardKeyEvent) -> KeyAction {
|
||||||
let keycode = evt.key_code();
|
let keycode = evt.key_code();
|
||||||
let state = evt.state();
|
let state = evt.state();
|
||||||
|
@ -143,72 +167,72 @@ impl<Backend> AnvilState<Backend> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "winit")]
|
#[cfg(any(feature = "winit", feature = "x11"))]
|
||||||
impl AnvilState<WinitData> {
|
impl<Backend> AnvilState<Backend> {
|
||||||
pub fn process_input_event<B: InputBackend>(&mut self, event: InputEvent<B>) {
|
pub fn process_input_event_windowed<B: InputBackend>(&mut self, event: InputEvent<B>, output_name: &str) {
|
||||||
match event {
|
match event {
|
||||||
InputEvent::Keyboard { event, .. } => match self.keyboard_key_to_action::<B>(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 => {
|
KeyAction::ScaleUp => {
|
||||||
let current_scale = {
|
let current_scale = {
|
||||||
self.output_map
|
self.output_map
|
||||||
.borrow()
|
.borrow()
|
||||||
.find_by_name(crate::winit::OUTPUT_NAME)
|
.find_by_name(output_name)
|
||||||
.map(|o| o.scale())
|
.map(|o| o.scale())
|
||||||
.unwrap_or(1.0)
|
.unwrap_or(1.0)
|
||||||
};
|
};
|
||||||
|
|
||||||
self.output_map
|
self.output_map
|
||||||
.borrow_mut()
|
.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 => {
|
KeyAction::ScaleDown => {
|
||||||
let current_scale = {
|
let current_scale = {
|
||||||
self.output_map
|
self.output_map
|
||||||
.borrow()
|
.borrow()
|
||||||
.find_by_name(crate::winit::OUTPUT_NAME)
|
.find_by_name(output_name)
|
||||||
.map(|o| o.scale())
|
.map(|o| o.scale())
|
||||||
.unwrap_or(1.0)
|
.unwrap_or(1.0)
|
||||||
};
|
};
|
||||||
|
|
||||||
self.output_map.borrow_mut().update_scale_by_name(
|
self.output_map
|
||||||
f32::max(1.0f32, current_scale - 0.25f32),
|
.borrow_mut()
|
||||||
crate::winit::OUTPUT_NAME,
|
.update_scale_by_name(f32::max(1.0f32, current_scale + 0.25f32), output_name);
|
||||||
);
|
|
||||||
}
|
|
||||||
action => {
|
|
||||||
warn!(self.log, "Key action {:?} unsupported on winit backend.", action);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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::PointerMotionAbsolute { event } => {
|
||||||
InputEvent::PointerAxis { event, .. } => self.on_pointer_axis::<B>(event),
|
self.on_pointer_move_absolute_windowed::<B>(event, output_name)
|
||||||
_ => {
|
|
||||||
// other events are not handled in anvil (yet)
|
|
||||||
}
|
}
|
||||||
|
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
|
let output_size = self
|
||||||
.output_map
|
.output_map
|
||||||
.borrow()
|
.borrow()
|
||||||
.find_by_name(crate::winit::OUTPUT_NAME)
|
.find_by_name(output_name)
|
||||||
.map(|o| o.size())
|
.map(|o| o.size())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let pos = evt.position_transformed(output_size);
|
let pos = evt.position_transformed(output_size);
|
||||||
self.pointer_location = pos;
|
self.pointer_location = pos;
|
||||||
let serial = SCOUNTER.next_serial();
|
let serial = SCOUNTER.next_serial();
|
||||||
|
@ -222,11 +246,6 @@ impl AnvilState<UdevData> {
|
||||||
pub fn process_input_event<B: InputBackend>(&mut self, event: InputEvent<B>) {
|
pub fn process_input_event<B: InputBackend>(&mut self, event: InputEvent<B>) {
|
||||||
match event {
|
match event {
|
||||||
InputEvent::Keyboard { event, .. } => match self.keyboard_key_to_action::<B>(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")]
|
#[cfg(feature = "udev")]
|
||||||
KeyAction::VtSwitch(vt) => {
|
KeyAction::VtSwitch(vt) => {
|
||||||
info!(self.log, "Trying to switch to vt {}", 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);
|
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) => {
|
KeyAction::Screen(num) => {
|
||||||
let geometry = self.output_map.borrow().find_by_index(num).map(|o| o.geometry());
|
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);
|
.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::PointerMotion { event, .. } => self.on_pointer_move::<B>(event),
|
||||||
InputEvent::PointerButton { event, .. } => self.on_pointer_button::<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
|
/// Possible results of a keyboard action
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum KeyAction {
|
enum KeyAction {
|
||||||
|
|
|
@ -132,16 +132,16 @@ pub fn run_winit(log: Logger) {
|
||||||
size,
|
size,
|
||||||
refresh: 60_000,
|
refresh: 60_000,
|
||||||
},
|
},
|
||||||
crate::winit::OUTPUT_NAME,
|
OUTPUT_NAME,
|
||||||
);
|
);
|
||||||
|
|
||||||
let output_mut = state.output_map.borrow();
|
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);
|
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),
|
||||||
|
|
||||||
_ => (),
|
_ => (),
|
||||||
})
|
})
|
||||||
|
|
|
@ -164,7 +164,7 @@ pub fn run_x11(log: Logger) {
|
||||||
state.backend_data.render = true;
|
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");
|
.expect("Failed to insert X11 Backend into event loop");
|
||||||
|
|
||||||
|
|
|
@ -62,16 +62,21 @@ where
|
||||||
// Once we have proper color management and possibly HDR support,
|
// Once we have proper color management and possibly HDR support,
|
||||||
// we need to have a more sophisticated picker.
|
// we need to have a more sophisticated picker.
|
||||||
// (Or maybe just pick ARGB2101010, if available, we will see.)
|
// (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"));
|
let logger = crate::slog_or_fallback(log).new(o!("backend" => "drm_render"));
|
||||||
|
|
||||||
// select a format
|
// select a format
|
||||||
let plane_formats = drm
|
let mut plane_formats = drm
|
||||||
.supported_formats(drm.plane())?
|
.supported_formats(drm.plane())?
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|fmt| fmt.code == code)
|
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect::<HashSet<_>>();
|
.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);
|
renderer_formats.retain(|fmt| fmt.code == code);
|
||||||
|
|
||||||
trace!(logger, "Plane formats: {:?}", plane_formats);
|
trace!(logger, "Plane formats: {:?}", plane_formats);
|
||||||
|
|
|
@ -11,12 +11,12 @@ use std::sync::{
|
||||||
};
|
};
|
||||||
use std::{collections::HashSet, os::raw::c_char};
|
use std::{collections::HashSet, os::raw::c_char};
|
||||||
|
|
||||||
use cgmath::{prelude::*, Matrix3, Vector2};
|
use cgmath::{prelude::*, Matrix3, Vector2, Vector3};
|
||||||
|
|
||||||
mod shaders;
|
mod shaders;
|
||||||
mod version;
|
mod version;
|
||||||
|
|
||||||
use super::{Bind, Frame, Renderer, Texture, Transform, Unbind};
|
use super::{Bind, Frame, Renderer, Texture, TextureFilter, Transform, Unbind};
|
||||||
use crate::backend::allocator::{
|
use crate::backend::allocator::{
|
||||||
dmabuf::{Dmabuf, WeakDmabuf},
|
dmabuf::{Dmabuf, WeakDmabuf},
|
||||||
Format,
|
Format,
|
||||||
|
@ -26,7 +26,7 @@ use crate::backend::egl::{
|
||||||
EGLContext, EGLSurface, MakeCurrentError,
|
EGLContext, EGLSurface, MakeCurrentError,
|
||||||
};
|
};
|
||||||
use crate::backend::SwapBuffersError;
|
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"))]
|
#[cfg(all(feature = "wayland_frontend", feature = "use_system_lib"))]
|
||||||
use super::ImportEgl;
|
use super::ImportEgl;
|
||||||
|
@ -35,8 +35,6 @@ use super::{ImportDma, ImportShm};
|
||||||
#[cfg(all(feature = "wayland_frontend", feature = "use_system_lib"))]
|
#[cfg(all(feature = "wayland_frontend", feature = "use_system_lib"))]
|
||||||
use crate::backend::egl::{display::EGLBufferReader, Format as EGLFormat};
|
use crate::backend::egl::{display::EGLBufferReader, Format as EGLFormat};
|
||||||
#[cfg(feature = "wayland_frontend")]
|
#[cfg(feature = "wayland_frontend")]
|
||||||
use crate::utils::Rectangle;
|
|
||||||
#[cfg(feature = "wayland_frontend")]
|
|
||||||
use wayland_server::protocol::{wl_buffer, wl_shm};
|
use wayland_server::protocol::{wl_buffer, wl_shm};
|
||||||
|
|
||||||
use slog::{debug, error, info, o, trace, warn};
|
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.
|
/// - 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.
|
/// - 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.
|
/// - 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>
|
pub unsafe fn new<L>(context: EGLContext, logger: L) -> Result<Gles2Renderer, Gles2Error>
|
||||||
where
|
where
|
||||||
L: Into<Option<::slog::Logger>>,
|
L: Into<Option<::slog::Logger>>,
|
||||||
|
@ -495,7 +494,7 @@ impl Gles2Renderer {
|
||||||
];
|
];
|
||||||
|
|
||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
let renderer = Gles2Renderer {
|
let mut renderer = Gles2Renderer {
|
||||||
id: RENDERER_COUNTER.fetch_add(1, Ordering::SeqCst),
|
id: RENDERER_COUNTER.fetch_add(1, Ordering::SeqCst),
|
||||||
gl,
|
gl,
|
||||||
egl: context,
|
egl: context,
|
||||||
|
@ -514,6 +513,8 @@ impl Gles2Renderer {
|
||||||
logger: log,
|
logger: log,
|
||||||
_not_send: std::ptr::null_mut(),
|
_not_send: std::ptr::null_mut(),
|
||||||
};
|
};
|
||||||
|
renderer.downscale_filter(TextureFilter::Nearest)?;
|
||||||
|
renderer.upscale_filter(TextureFilter::Linear)?;
|
||||||
renderer.egl.unbind()?;
|
renderer.egl.unbind()?;
|
||||||
Ok(renderer)
|
Ok(renderer)
|
||||||
}
|
}
|
||||||
|
@ -1007,6 +1008,35 @@ impl Renderer for Gles2Renderer {
|
||||||
type TextureId = Gles2Texture;
|
type TextureId = Gles2Texture;
|
||||||
type Frame = Gles2Frame;
|
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>(
|
fn render<F, R>(
|
||||||
&mut self,
|
&mut self,
|
||||||
size: Size<i32, Physical>,
|
size: Size<i32, Physical>,
|
||||||
|
@ -1100,13 +1130,60 @@ impl Frame for Gles2Frame {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_texture(
|
fn render_texture_from_to(
|
||||||
&mut self,
|
&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>,
|
mut matrix: Matrix3<f32>,
|
||||||
tex_coords: [Vector2<f32>; 4],
|
tex_coords: [Vector2<f32>; 4],
|
||||||
alpha: f32,
|
alpha: f32,
|
||||||
) -> Result<(), Self::Error> {
|
) -> Result<(), Gles2Error> {
|
||||||
//apply output transformation
|
//apply output transformation
|
||||||
matrix = self.current_projection * matrix;
|
matrix = self.current_projection * matrix;
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ use crate::utils::{Buffer, Physical, Point, Rectangle, Size};
|
||||||
|
|
||||||
#[cfg(feature = "wayland_frontend")]
|
#[cfg(feature = "wayland_frontend")]
|
||||||
use crate::wayland::compositor::SurfaceData;
|
use crate::wayland::compositor::SurfaceData;
|
||||||
use cgmath::{prelude::*, Matrix3, Vector2, Vector3};
|
use cgmath::Matrix3;
|
||||||
#[cfg(feature = "wayland_frontend")]
|
#[cfg(feature = "wayland_frontend")]
|
||||||
use wayland_server::protocol::{wl_buffer, wl_shm};
|
use wayland_server::protocol::{wl_buffer, wl_shm};
|
||||||
|
|
||||||
|
@ -53,6 +53,15 @@ pub enum Transform {
|
||||||
Flipped270,
|
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 {
|
impl Transform {
|
||||||
/// A projection matrix to apply this transformation
|
/// A projection matrix to apply this transformation
|
||||||
pub fn matrix(&self) -> Matrix3<f32> {
|
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.
|
/// 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.
|
/// 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>;
|
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
|
/// 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.
|
/// 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(
|
fn render_texture_at(
|
||||||
&mut self,
|
&mut self,
|
||||||
texture: &Self::TextureId,
|
texture: &Self::TextureId,
|
||||||
pos: Point<f64, Physical>,
|
pos: Point<f64, Physical>,
|
||||||
texture_scale: i32,
|
texture_scale: i32,
|
||||||
output_scale: f64,
|
output_scale: f64,
|
||||||
transform: Transform,
|
src_transform: Transform,
|
||||||
alpha: f32,
|
alpha: f32,
|
||||||
) -> Result<(), Self::Error> {
|
) -> Result<(), Self::Error> {
|
||||||
self.render_texture_from_to(
|
self.render_texture_from_to(
|
||||||
|
@ -195,55 +196,22 @@ pub trait Frame {
|
||||||
.to_f64()
|
.to_f64()
|
||||||
.to_physical(output_scale),
|
.to_physical(output_scale),
|
||||||
),
|
),
|
||||||
transform,
|
src_transform,
|
||||||
alpha,
|
alpha,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Render part of a texture as given by src to the current target into the rectangle described by dest
|
/// 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 given transformations.
|
/// 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(
|
fn render_texture_from_to(
|
||||||
&mut self,
|
&mut self,
|
||||||
texture: &Self::TextureId,
|
texture: &Self::TextureId,
|
||||||
src: Rectangle<i32, Buffer>,
|
src: Rectangle<i32, Buffer>,
|
||||||
dest: Rectangle<f64, Physical>,
|
dst: Rectangle<f64, Physical>,
|
||||||
transform: Transform,
|
src_transform: Transform,
|
||||||
alpha: f32,
|
alpha: f32,
|
||||||
) -> Result<(), Self::Error> {
|
) -> 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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Abstraction of commonly used rendering operations for compositors.
|
/// 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 representing a currently in-progress frame during the [`Renderer::render`]-call
|
||||||
type Frame: Frame<Error = Self::Error, TextureId = Self::TextureId>;
|
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.
|
/// Initialize a rendering context on the current rendering target with given dimensions and transformation.
|
||||||
///
|
///
|
||||||
/// This function *may* error, if:
|
/// This function *may* error, if:
|
||||||
|
@ -265,7 +238,7 @@ pub trait Renderer {
|
||||||
fn render<F, R>(
|
fn render<F, R>(
|
||||||
&mut self,
|
&mut self,
|
||||||
size: Size<i32, Physical>,
|
size: Size<i32, Physical>,
|
||||||
transform: Transform,
|
dst_transform: Transform,
|
||||||
rendering: F,
|
rendering: F,
|
||||||
) -> Result<R, Self::Error>
|
) -> Result<R, Self::Error>
|
||||||
where
|
where
|
||||||
|
|
|
@ -129,7 +129,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need dri3 >= 1.2 in order to use the enhanced dri3_pixmap_from_buffers function.
|
// 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 {
|
if dmabuf.num_planes() > 4 {
|
||||||
return Err(CreatePixmapError::TooManyPlanes);
|
return Err(CreatePixmapError::TooManyPlanes);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ macro_rules! extensions {
|
||||||
$(
|
$(
|
||||||
$extension:ident { // Extension name for path lookup
|
$extension:ident { // Extension name for path lookup
|
||||||
$extension_fn:ident, // Function used to look up the version of the extension
|
$extension_fn:ident, // Function used to look up the version of the extension
|
||||||
|
required: $required:expr,
|
||||||
minimum: ($min_major:expr, $min_minor:expr),
|
minimum: ($min_major:expr, $min_minor:expr),
|
||||||
request: ($req_major:expr, $req_minor:expr),
|
request: ($req_major:expr, $req_minor:expr),
|
||||||
},
|
},
|
||||||
|
@ -34,7 +35,7 @@ macro_rules! extensions {
|
||||||
pub struct Extensions {
|
pub struct Extensions {
|
||||||
$(
|
$(
|
||||||
#[doc = concat!(" The version of the `", stringify!($extension), "` extension.")]
|
#[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.minor_version,
|
||||||
);
|
);
|
||||||
|
|
||||||
(version.major_version, version.minor_version)
|
Some((version.major_version, version.minor_version))
|
||||||
} else {
|
} else {
|
||||||
slog::error!(
|
if $required {
|
||||||
logger,
|
slog::error!(
|
||||||
"{} extension version is too low (have {}.{}, expected {}.{})",
|
logger,
|
||||||
X11_EXTENSION_NAME,
|
"required extension {} version is too low (have {}.{}, expected {}.{})",
|
||||||
version.major_version,
|
X11_EXTENSION_NAME,
|
||||||
version.minor_version,
|
version.major_version,
|
||||||
$req_major,
|
version.minor_version,
|
||||||
$req_minor,
|
$req_major,
|
||||||
);
|
$req_minor,
|
||||||
|
);
|
||||||
|
|
||||||
return Err(MissingExtensionError::WrongVersion {
|
return Err(MissingExtensionError::WrongVersion {
|
||||||
name: X11_EXTENSION_NAME,
|
name: X11_EXTENSION_NAME,
|
||||||
required_major: $req_major,
|
required_major: $req_major,
|
||||||
required_minor: $req_minor,
|
required_minor: $req_minor,
|
||||||
available_major: version.major_version,
|
available_major: version.major_version,
|
||||||
available_minor: version.minor_version,
|
available_minor: version.minor_version,
|
||||||
}.into());
|
}.into());
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} 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 {
|
return Err(MissingExtensionError::NotFound {
|
||||||
name: X11_EXTENSION_NAME,
|
name: X11_EXTENSION_NAME,
|
||||||
major: $min_major,
|
major: $min_major,
|
||||||
minor: $min_minor,
|
minor: $min_minor,
|
||||||
|
}
|
||||||
|
.into());
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
.into());
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
)*
|
)*
|
||||||
|
@ -105,18 +114,21 @@ macro_rules! extensions {
|
||||||
extensions! {
|
extensions! {
|
||||||
present {
|
present {
|
||||||
present_query_version,
|
present_query_version,
|
||||||
|
required: true,
|
||||||
minimum: (1, 0),
|
minimum: (1, 0),
|
||||||
request: (1, 0),
|
request: (1, 0),
|
||||||
},
|
},
|
||||||
|
|
||||||
xfixes {
|
xfixes {
|
||||||
xfixes_query_version,
|
xfixes_query_version,
|
||||||
|
required: true,
|
||||||
minimum: (4, 0),
|
minimum: (4, 0),
|
||||||
request: (4, 0),
|
request: (4, 0),
|
||||||
},
|
},
|
||||||
|
|
||||||
dri3 {
|
dri3 {
|
||||||
dri3_query_version,
|
dri3_query_version,
|
||||||
|
required: true,
|
||||||
minimum: (1, 0),
|
minimum: (1, 0),
|
||||||
request: (1, 2),
|
request: (1, 2),
|
||||||
},
|
},
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
//! # Smithay: the Wayland compositor smithy
|
//! # 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.
|
//! 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
|
//! The window management and drawing logic is however at the time not provided (but helpers for this
|
||||||
//! are planned for future version).
|
//! are planned for future version).
|
||||||
|
|
|
@ -18,7 +18,7 @@ pub struct Buffer;
|
||||||
pub struct Raw;
|
pub struct Raw;
|
||||||
|
|
||||||
pub trait Coordinate:
|
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 downscale(self, scale: Self) -> Self;
|
||||||
fn upscale(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> {
|
impl<N: Clone, Kind> Clone for Size<N, Kind> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
|
|
|
@ -903,6 +903,11 @@ impl ToplevelSurface {
|
||||||
self.shell_surface.as_ref().is_alive() && self.wl_surface.as_ref().is_alive()
|
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
|
/// Retrieve the shell client owning this toplevel surface
|
||||||
///
|
///
|
||||||
/// Returns `None` if the surface does actually no longer exist.
|
/// Returns `None` if the surface does actually no longer exist.
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
|
||||||
use cgmath::Vector2;
|
|
||||||
use smithay::{
|
use smithay::{
|
||||||
backend::{
|
backend::{
|
||||||
allocator::dmabuf::Dmabuf,
|
allocator::dmabuf::Dmabuf,
|
||||||
renderer::{Frame, ImportDma, ImportShm, Renderer, Texture, Transform},
|
renderer::{Frame, ImportDma, ImportShm, Renderer, Texture, TextureFilter, Transform},
|
||||||
SwapBuffersError,
|
SwapBuffersError,
|
||||||
},
|
},
|
||||||
reexports::wayland_server::protocol::wl_buffer,
|
reexports::wayland_server::protocol::wl_buffer,
|
||||||
|
@ -28,7 +27,7 @@ impl Renderer for DummyRenderer {
|
||||||
fn render<F, R>(
|
fn render<F, R>(
|
||||||
&mut self,
|
&mut self,
|
||||||
_size: Size<i32, Physical>,
|
_size: Size<i32, Physical>,
|
||||||
_transform: Transform,
|
_dst_transform: Transform,
|
||||||
rendering: F,
|
rendering: F,
|
||||||
) -> Result<R, Self::Error>
|
) -> Result<R, Self::Error>
|
||||||
where
|
where
|
||||||
|
@ -37,6 +36,14 @@ impl Renderer for DummyRenderer {
|
||||||
let mut frame = DummyFrame {};
|
let mut frame = DummyFrame {};
|
||||||
Ok(rendering(self, &mut frame))
|
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 {
|
impl ImportShm for DummyRenderer {
|
||||||
|
@ -94,11 +101,12 @@ impl Frame for DummyFrame {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_texture(
|
fn render_texture_from_to(
|
||||||
&mut self,
|
&mut self,
|
||||||
_texture: &Self::TextureId,
|
_texture: &Self::TextureId,
|
||||||
_matrix: cgmath::Matrix3<f32>,
|
_src: Rectangle<i32, Buffer>,
|
||||||
_tex_coords: [Vector2<f32>; 4],
|
_dst: Rectangle<f64, Physical>,
|
||||||
|
_src_transform: Transform,
|
||||||
_alpha: f32,
|
_alpha: f32,
|
||||||
) -> Result<(), Self::Error> {
|
) -> Result<(), Self::Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
Loading…
Reference in New Issue