deps: smithay + egui update
This commit is contained in:
parent
aa3ee245d1
commit
7a034c8e52
20 changed files with 906 additions and 657 deletions
|
|
@ -19,19 +19,20 @@ use anyhow::{Context, Result};
|
|||
use smithay::{
|
||||
backend::{
|
||||
allocator::{dmabuf::Dmabuf, gbm::GbmDevice, Format},
|
||||
drm::{DrmDevice, DrmEvent, DrmNode, GbmBufferedSurface, NodeType},
|
||||
drm::{DrmDevice, DrmEvent, DrmEventTime, DrmNode, GbmBufferedSurface, NodeType},
|
||||
egl::{EGLContext, EGLDevice, EGLDisplay},
|
||||
input::InputEvent,
|
||||
libinput::{LibinputInputBackend, LibinputSessionInterface},
|
||||
renderer::{
|
||||
damage::DamageTrackedRenderer,
|
||||
gles2::{Gles2Renderbuffer, Gles2Renderer},
|
||||
gles2::Gles2Renderbuffer,
|
||||
glow::GlowRenderer,
|
||||
multigpu::{egl::EglGlesBackend, GpuManager},
|
||||
Bind,
|
||||
},
|
||||
session::{auto::AutoSession, Session, Signal},
|
||||
udev::{all_gpus, primary_gpu, UdevBackend, UdevEvent},
|
||||
},
|
||||
desktop::utils::OutputPresentationFeedback,
|
||||
output::{Mode as OutputMode, Output, PhysicalProperties, Subpixel},
|
||||
reexports::{
|
||||
calloop::{
|
||||
|
|
@ -41,6 +42,7 @@ use smithay::{
|
|||
drm::control::{connector, crtc, Device as ControlDevice, ModeTypeFlags},
|
||||
input::Libinput,
|
||||
nix::{fcntl::OFlag, sys::stat::dev_t},
|
||||
wayland_protocols::wp::presentation_time::server::wp_presentation_feedback,
|
||||
wayland_server::{protocol::wl_surface::WlSurface, DisplayHandle, Resource},
|
||||
},
|
||||
utils::{
|
||||
|
|
@ -69,7 +71,7 @@ use super::render::{CursorMode, GlMultiRenderer};
|
|||
|
||||
pub struct KmsState {
|
||||
devices: HashMap<DrmNode, Device>,
|
||||
pub api: GpuManager<EglGlesBackend<Gles2Renderer>>,
|
||||
pub api: GpuManager<EglGlesBackend<GlowRenderer>>,
|
||||
pub primary: DrmNode,
|
||||
session: AutoSession,
|
||||
signaler: Signaler<Signal>,
|
||||
|
|
@ -89,7 +91,13 @@ pub struct Device {
|
|||
}
|
||||
|
||||
pub struct Surface {
|
||||
surface: Option<GbmBufferedSurface<Rc<RefCell<GbmDevice<SessionFd>>>, SessionFd>>,
|
||||
surface: Option<
|
||||
GbmBufferedSurface<
|
||||
Rc<RefCell<GbmDevice<SessionFd>>>,
|
||||
SessionFd,
|
||||
Option<OutputPresentationFeedback>,
|
||||
>,
|
||||
>,
|
||||
damage_tracker: DamageTrackedRenderer,
|
||||
connector: connector::Handle,
|
||||
output: Output,
|
||||
|
|
@ -131,6 +139,7 @@ pub fn init_backend(
|
|||
&data.state.common.event_loop_handle,
|
||||
output,
|
||||
None,
|
||||
None,
|
||||
) {
|
||||
slog_scope::crit!(
|
||||
"Error scheduling event loop for output {}: {:?}",
|
||||
|
|
@ -148,7 +157,7 @@ pub fn init_backend(
|
|||
.map_err(|err| err.error)
|
||||
.context("Failed to initialize session event source")?;
|
||||
|
||||
let api = GpuManager::new(EglGlesBackend::<Gles2Renderer>::default(), None)
|
||||
let api = GpuManager::new(EglGlesBackend::<GlowRenderer>::default(), None)
|
||||
.context("Failed to initialize renderers")?;
|
||||
|
||||
// TODO get this info from system76-power, if available and setup a watcher
|
||||
|
|
@ -267,6 +276,7 @@ pub fn init_backend(
|
|||
if let Err(err) = data.state.backend.kms().schedule_render(
|
||||
&data.state.common.event_loop_handle,
|
||||
output,
|
||||
None,
|
||||
if !sessions.is_empty() {
|
||||
Some(sessions)
|
||||
} else {
|
||||
|
|
@ -372,8 +382,44 @@ impl State {
|
|||
if let Some(device) = data.state.backend.kms().devices.get_mut(&drm_node) {
|
||||
if let Some(surface) = device.surfaces.get_mut(&crtc) {
|
||||
match surface.surface.as_mut().map(|x| x.frame_submitted()) {
|
||||
Some(Ok(_)) => {
|
||||
let _submit_time = metadata.take().map(|data| data.time);
|
||||
Some(Ok(feedback)) => {
|
||||
if let Some(mut feedback) = feedback.flatten() {
|
||||
let submit_time =
|
||||
match metadata.take().map(|data| data.time) {
|
||||
Some(DrmEventTime::Monotonic(tp)) => Some(tp),
|
||||
_ => None,
|
||||
};
|
||||
let seq = metadata
|
||||
.as_ref()
|
||||
.map(|metadata| metadata.sequence)
|
||||
.unwrap_or(0);
|
||||
|
||||
let (clock, flags) = if let Some(tp) = submit_time {
|
||||
(
|
||||
tp.into(),
|
||||
wp_presentation_feedback::Kind::Vsync
|
||||
| wp_presentation_feedback::Kind::HwClock
|
||||
| wp_presentation_feedback::Kind::HwCompletion,
|
||||
)
|
||||
} else {
|
||||
(
|
||||
data.state.common.clock.now(),
|
||||
wp_presentation_feedback::Kind::Vsync,
|
||||
)
|
||||
};
|
||||
|
||||
feedback.presented(
|
||||
clock,
|
||||
surface
|
||||
.output
|
||||
.current_mode()
|
||||
.map(|mode| mode.refresh as u32)
|
||||
.unwrap_or_default(),
|
||||
seq as u64,
|
||||
flags,
|
||||
);
|
||||
}
|
||||
|
||||
surface.pending = false;
|
||||
surface.dirty.then(|| surface.output.clone())
|
||||
}
|
||||
|
|
@ -400,9 +446,19 @@ impl State {
|
|||
.extend(sessions.borrow_mut().drain(..));
|
||||
}
|
||||
|
||||
let output_refresh = match output.current_mode() {
|
||||
Some(mode) => mode.refresh,
|
||||
None => return,
|
||||
};
|
||||
// TODO: Record rendering times and use sliding window to estimate duration for next render
|
||||
let repaint_delay = Duration::from_secs_f64(
|
||||
((1000.0 / output_refresh as f64) * 0.6).max(0.003), // for now we assume we need at least 3ms
|
||||
);
|
||||
|
||||
if let Err(err) = data.state.backend.kms().schedule_render(
|
||||
&data.state.common.event_loop_handle,
|
||||
&output,
|
||||
Some(repaint_delay),
|
||||
scheduled_sessions,
|
||||
) {
|
||||
slog_scope::warn!("Failed to schedule render: {}", err);
|
||||
|
|
@ -738,7 +794,7 @@ impl Surface {
|
|||
pub fn render_output(
|
||||
&mut self,
|
||||
dh: &DisplayHandle,
|
||||
api: &mut GpuManager<EglGlesBackend<Gles2Renderer>>,
|
||||
api: &mut GpuManager<EglGlesBackend<GlowRenderer>>,
|
||||
target_node: &DrmNode,
|
||||
state: &mut Common,
|
||||
screencopy: Option<&[(ScreencopySession, BufferParams)]>,
|
||||
|
|
@ -755,13 +811,10 @@ impl Surface {
|
|||
.next_buffer()
|
||||
.with_context(|| "Failed to allocate buffer")?;
|
||||
|
||||
renderer
|
||||
.bind(buffer.clone())
|
||||
.with_context(|| "Failed to bind buffer")?;
|
||||
|
||||
match render::render_output::<_, Gles2Renderbuffer, _>(
|
||||
match render::render_output::<GlMultiRenderer, _, Gles2Renderbuffer, _>(
|
||||
Some(&render_node),
|
||||
&mut renderer,
|
||||
buffer.clone(),
|
||||
&mut self.damage_tracker,
|
||||
age as usize,
|
||||
state,
|
||||
|
|
@ -771,10 +824,15 @@ impl Surface {
|
|||
#[cfg(feature = "debug")]
|
||||
Some(&mut self.fps),
|
||||
) {
|
||||
Ok((_damage, states)) => {
|
||||
Ok((damage, states)) => {
|
||||
let feedback = if damage.is_some() {
|
||||
Some(state.take_presentation_feedback(&self.output, &states))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
state.send_frames(&self.output, &states);
|
||||
surface
|
||||
.queue_buffer()
|
||||
.queue_buffer(feedback)
|
||||
.with_context(|| "Failed to submit buffer for display")?;
|
||||
}
|
||||
Err(err) => {
|
||||
|
|
@ -895,6 +953,7 @@ impl KmsState {
|
|||
if let Err(err) = self.schedule_render(
|
||||
loop_handle,
|
||||
output,
|
||||
None,
|
||||
if !sessions.is_empty() {
|
||||
Some(sessions)
|
||||
} else {
|
||||
|
|
@ -963,6 +1022,7 @@ impl KmsState {
|
|||
&mut self,
|
||||
loop_handle: &LoopHandle<'_, Data>,
|
||||
output: &Output,
|
||||
delay: Option<Duration>,
|
||||
mut screencopy_sessions: Option<Vec<(ScreencopySession, BufferParams)>>,
|
||||
) -> Result<(), InsertError<Timer>> {
|
||||
if let Some((device, crtc, surface)) = self
|
||||
|
|
@ -977,19 +1037,6 @@ impl KmsState {
|
|||
if !surface.pending {
|
||||
surface.dirty = false;
|
||||
surface.pending = true;
|
||||
/*
|
||||
let instant = surface
|
||||
.last_submit
|
||||
.as_ref()
|
||||
.and_then(|x| match x {
|
||||
DrmEventTime::Monotonic(instant) => Some(instant),
|
||||
DrmEventTime::Realtime(_) => None,
|
||||
})
|
||||
.map(|i| {
|
||||
*i + Duration::from_secs_f64(1.0 / surface.refresh_rate as f64)
|
||||
- Duration::from_millis(20) // render budget
|
||||
});
|
||||
*/
|
||||
|
||||
let device = *device;
|
||||
let crtc = *crtc;
|
||||
|
|
@ -997,10 +1044,11 @@ impl KmsState {
|
|||
loop_handle.remove(token);
|
||||
}
|
||||
surface.render_timer_token = Some(loop_handle.insert_source(
|
||||
//if surface.vrr || instant.is_none() {
|
||||
Timer::immediate(), /*} else {
|
||||
Timer::from_deadline(instant.unwrap())
|
||||
}*/
|
||||
if surface.vrr || delay.is_none() {
|
||||
Timer::immediate()
|
||||
} else {
|
||||
Timer::from_duration(delay.unwrap())
|
||||
},
|
||||
move |_time, _, data| {
|
||||
let backend = data.state.backend.kms();
|
||||
if let Some(device) = backend.devices.get_mut(&device) {
|
||||
|
|
@ -1020,7 +1068,7 @@ impl KmsState {
|
|||
if backend.session.is_active() {
|
||||
slog_scope::error!("Error rendering: {}", err);
|
||||
return TimeoutAction::ToDuration(Duration::from_secs_f64(
|
||||
1.0 / surface.refresh_rate as f64,
|
||||
(1000.0 / surface.refresh_rate as f64) - 0.003,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ use smithay::{
|
|||
},
|
||||
reexports::wayland_server::protocol::wl_surface,
|
||||
render_elements,
|
||||
utils::{IsAlive, Logical, Point, Scale, Transform},
|
||||
utils::{IsAlive, Logical, Monotonic, Point, Scale, Time, Transform},
|
||||
wayland::compositor::{get_role, with_states},
|
||||
};
|
||||
use std::{
|
||||
|
|
@ -24,6 +24,7 @@ use std::{
|
|||
collections::HashMap,
|
||||
io::Read,
|
||||
sync::Mutex,
|
||||
time::Duration,
|
||||
};
|
||||
use xcursor::{
|
||||
parser::{parse_xcursor, Image},
|
||||
|
|
@ -193,93 +194,85 @@ pub fn draw_cursor<R>(
|
|||
seat: &Seat<State>,
|
||||
location: Point<f64, Logical>,
|
||||
scale: Scale<f64>,
|
||||
start_time: &std::time::Instant,
|
||||
time: Time<Monotonic>,
|
||||
draw_default: bool,
|
||||
) -> Vec<CursorRenderElement<R>>
|
||||
where
|
||||
R: Renderer + ImportAll + ImportMem,
|
||||
R: Renderer + ImportMem + ImportAll,
|
||||
<R as Renderer>::TextureId: Clone + 'static,
|
||||
{
|
||||
// draw the cursor as relevant
|
||||
{
|
||||
// reset the cursor if the surface is no longer alive
|
||||
let cursor_status = seat
|
||||
.user_data()
|
||||
.get::<RefCell<CursorImageStatus>>()
|
||||
.map(|cell| {
|
||||
let mut cursor_status = cell.borrow_mut();
|
||||
if let CursorImageStatus::Surface(ref surface) = *cursor_status {
|
||||
if !surface.alive() {
|
||||
*cursor_status = CursorImageStatus::Default;
|
||||
}
|
||||
// reset the cursor if the surface is no longer alive
|
||||
let cursor_status = seat
|
||||
.user_data()
|
||||
.get::<RefCell<CursorImageStatus>>()
|
||||
.map(|cell| {
|
||||
let mut cursor_status = cell.borrow_mut();
|
||||
if let CursorImageStatus::Surface(ref surface) = *cursor_status {
|
||||
if !surface.alive() {
|
||||
*cursor_status = CursorImageStatus::Default;
|
||||
}
|
||||
cursor_status.clone()
|
||||
})
|
||||
.unwrap_or(CursorImageStatus::Default);
|
||||
}
|
||||
cursor_status.clone()
|
||||
})
|
||||
.unwrap_or(CursorImageStatus::Default);
|
||||
|
||||
if let CursorImageStatus::Surface(ref wl_surface) = cursor_status {
|
||||
return draw_surface_cursor(wl_surface, location.to_i32_round(), scale);
|
||||
} else if draw_default && CursorImageStatus::Default == cursor_status {
|
||||
let integer_scale = scale.x.max(scale.y).ceil() as u32;
|
||||
if let CursorImageStatus::Surface(ref wl_surface) = cursor_status {
|
||||
return draw_surface_cursor(wl_surface, location.to_i32_round(), scale);
|
||||
} else if draw_default && CursorImageStatus::Default == cursor_status {
|
||||
let integer_scale = scale.x.max(scale.y).ceil() as u32;
|
||||
|
||||
let seat_userdata = seat.user_data();
|
||||
seat_userdata.insert_if_missing(CursorState::default);
|
||||
let state = seat_userdata.get::<CursorState>().unwrap();
|
||||
let frame = state
|
||||
.cursor
|
||||
.get_image(integer_scale, start_time.elapsed().as_millis() as u32);
|
||||
let seat_userdata = seat.user_data();
|
||||
seat_userdata.insert_if_missing(CursorState::default);
|
||||
let state = seat_userdata.get::<CursorState>().unwrap();
|
||||
let frame = state.cursor.get_image(
|
||||
integer_scale,
|
||||
Into::<Duration>::into(time).as_millis() as u32,
|
||||
);
|
||||
|
||||
let mut cache = state.image_cache.borrow_mut();
|
||||
let pointer_images = cache
|
||||
.entry((
|
||||
TypeId::of::<TextureBuffer<<R as Renderer>::TextureId>>(),
|
||||
renderer.id(),
|
||||
))
|
||||
.or_default();
|
||||
let mut cache = state.image_cache.borrow_mut();
|
||||
let pointer_images = cache
|
||||
.entry((TypeId::of::<TextureBuffer<R::TextureId>>(), renderer.id()))
|
||||
.or_default();
|
||||
|
||||
let maybe_image = pointer_images
|
||||
.iter()
|
||||
.find_map(|(image, texture)| if image == &frame { Some(texture) } else { None })
|
||||
.and_then(|texture| {
|
||||
texture.downcast_ref::<TextureBuffer<<R as Renderer>::TextureId>>()
|
||||
});
|
||||
let pointer_image = match maybe_image {
|
||||
Some(image) => image,
|
||||
None => {
|
||||
let texture = TextureBuffer::from_memory(
|
||||
renderer,
|
||||
&frame.pixels_rgba,
|
||||
(frame.width as i32, frame.height as i32),
|
||||
false,
|
||||
integer_scale as i32,
|
||||
Transform::Normal,
|
||||
None,
|
||||
)
|
||||
.expect("Failed to import cursor bitmap");
|
||||
pointer_images.push((frame.clone(), Box::new(texture.clone())));
|
||||
pointer_images
|
||||
.last()
|
||||
.and_then(|(_, i)| {
|
||||
i.downcast_ref::<TextureBuffer<<R as Renderer>::TextureId>>()
|
||||
})
|
||||
.unwrap()
|
||||
}
|
||||
};
|
||||
|
||||
let hotspot =
|
||||
Point::<i32, Logical>::from((frame.xhot as i32, frame.yhot as i32)).to_f64();
|
||||
*state.current_image.borrow_mut() = Some(frame);
|
||||
|
||||
return vec![CursorRenderElement::Static(
|
||||
TextureRenderElement::from_texture_buffer(
|
||||
(location - hotspot).to_physical(scale),
|
||||
pointer_image,
|
||||
let maybe_image = pointer_images
|
||||
.iter()
|
||||
.find_map(|(image, texture)| if image == &frame { Some(texture) } else { None })
|
||||
.and_then(|texture| texture.downcast_ref::<TextureBuffer<R::TextureId>>());
|
||||
let pointer_image = match maybe_image {
|
||||
Some(image) => image,
|
||||
None => {
|
||||
let texture = TextureBuffer::from_memory(
|
||||
renderer,
|
||||
&frame.pixels_rgba,
|
||||
(frame.width as i32, frame.height as i32),
|
||||
false,
|
||||
integer_scale as i32,
|
||||
Transform::Normal,
|
||||
None,
|
||||
None,
|
||||
),
|
||||
)];
|
||||
} else {
|
||||
Vec::new()
|
||||
}
|
||||
)
|
||||
.expect("Failed to import cursor bitmap");
|
||||
pointer_images.push((frame.clone(), Box::new(texture.clone())));
|
||||
pointer_images
|
||||
.last()
|
||||
.and_then(|(_, i)| i.downcast_ref::<TextureBuffer<R::TextureId>>())
|
||||
.unwrap()
|
||||
}
|
||||
};
|
||||
|
||||
let hotspot = Point::<i32, Logical>::from((frame.xhot as i32, frame.yhot as i32)).to_f64();
|
||||
*state.current_image.borrow_mut() = Some(frame);
|
||||
|
||||
return vec![CursorRenderElement::Static(
|
||||
TextureRenderElement::from_texture_buffer(
|
||||
(location - hotspot).to_physical(scale),
|
||||
pointer_image,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
),
|
||||
)];
|
||||
} else {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
302
src/backend/render/element.rs
Normal file
302
src/backend/render/element.rs
Normal file
|
|
@ -0,0 +1,302 @@
|
|||
use crate::shell::{CosmicMappedRenderElement, WorkspaceRenderElement};
|
||||
|
||||
use smithay::{
|
||||
backend::renderer::{
|
||||
element::{texture::TextureRenderElement, Element, RenderElement, UnderlyingStorage},
|
||||
gles2::{Gles2Frame, Gles2Texture},
|
||||
glow::GlowRenderer,
|
||||
multigpu::Error as MultiError,
|
||||
Frame, ImportAll, Renderer,
|
||||
},
|
||||
utils::{Physical, Point, Rectangle, Scale},
|
||||
};
|
||||
|
||||
use super::{cursor::CursorRenderElement, GlMultiFrame, GlMultiRenderer};
|
||||
|
||||
pub enum CosmicElement<R>
|
||||
where
|
||||
R: AsGlowRenderer + Renderer + ImportAll,
|
||||
<R as Renderer>::TextureId: 'static,
|
||||
<R as Renderer>::Frame: AsGles2Frame,
|
||||
{
|
||||
Workspace(WorkspaceRenderElement<R>),
|
||||
Cursor(CursorRenderElement<R>),
|
||||
MoveGrab(CosmicMappedRenderElement<R>),
|
||||
#[cfg(feature = "debug")]
|
||||
Egui(TextureRenderElement<Gles2Texture>),
|
||||
}
|
||||
|
||||
impl<R> Element for CosmicElement<R>
|
||||
where
|
||||
R: AsGlowRenderer + Renderer + ImportAll,
|
||||
<R as Renderer>::TextureId: 'static,
|
||||
<R as Renderer>::Frame: AsGles2Frame,
|
||||
{
|
||||
fn id(&self) -> &smithay::backend::renderer::element::Id {
|
||||
match self {
|
||||
CosmicElement::Workspace(elem) => elem.id(),
|
||||
CosmicElement::Cursor(elem) => elem.id(),
|
||||
CosmicElement::MoveGrab(elem) => elem.id(),
|
||||
#[cfg(feature = "debug")]
|
||||
CosmicElement::Egui(elem) => elem.id(),
|
||||
}
|
||||
}
|
||||
|
||||
fn current_commit(&self) -> smithay::backend::renderer::utils::CommitCounter {
|
||||
match self {
|
||||
CosmicElement::Workspace(elem) => elem.current_commit(),
|
||||
CosmicElement::Cursor(elem) => elem.current_commit(),
|
||||
CosmicElement::MoveGrab(elem) => elem.current_commit(),
|
||||
#[cfg(feature = "debug")]
|
||||
CosmicElement::Egui(elem) => elem.current_commit(),
|
||||
}
|
||||
}
|
||||
|
||||
fn src(&self) -> Rectangle<f64, smithay::utils::Buffer> {
|
||||
match self {
|
||||
CosmicElement::Workspace(elem) => elem.src(),
|
||||
CosmicElement::Cursor(elem) => elem.src(),
|
||||
CosmicElement::MoveGrab(elem) => elem.src(),
|
||||
#[cfg(feature = "debug")]
|
||||
CosmicElement::Egui(elem) => elem.src(),
|
||||
}
|
||||
}
|
||||
|
||||
fn geometry(&self, scale: Scale<f64>) -> Rectangle<i32, Physical> {
|
||||
match self {
|
||||
CosmicElement::Workspace(elem) => elem.geometry(scale),
|
||||
CosmicElement::Cursor(elem) => elem.geometry(scale),
|
||||
CosmicElement::MoveGrab(elem) => elem.geometry(scale),
|
||||
#[cfg(feature = "debug")]
|
||||
CosmicElement::Egui(elem) => elem.geometry(scale),
|
||||
}
|
||||
}
|
||||
|
||||
fn location(&self, scale: Scale<f64>) -> Point<i32, Physical> {
|
||||
match self {
|
||||
CosmicElement::Workspace(elem) => elem.location(scale),
|
||||
CosmicElement::Cursor(elem) => elem.location(scale),
|
||||
CosmicElement::MoveGrab(elem) => elem.location(scale),
|
||||
#[cfg(feature = "debug")]
|
||||
CosmicElement::Egui(elem) => elem.location(scale),
|
||||
}
|
||||
}
|
||||
|
||||
fn transform(&self) -> smithay::utils::Transform {
|
||||
match self {
|
||||
CosmicElement::Workspace(elem) => elem.transform(),
|
||||
CosmicElement::Cursor(elem) => elem.transform(),
|
||||
CosmicElement::MoveGrab(elem) => elem.transform(),
|
||||
#[cfg(feature = "debug")]
|
||||
CosmicElement::Egui(elem) => elem.transform(),
|
||||
}
|
||||
}
|
||||
|
||||
fn damage_since(
|
||||
&self,
|
||||
scale: Scale<f64>,
|
||||
commit: Option<smithay::backend::renderer::utils::CommitCounter>,
|
||||
) -> Vec<Rectangle<i32, Physical>> {
|
||||
match self {
|
||||
CosmicElement::Workspace(elem) => elem.damage_since(scale, commit),
|
||||
CosmicElement::Cursor(elem) => elem.damage_since(scale, commit),
|
||||
CosmicElement::MoveGrab(elem) => elem.damage_since(scale, commit),
|
||||
#[cfg(feature = "debug")]
|
||||
CosmicElement::Egui(elem) => elem.damage_since(scale, commit),
|
||||
}
|
||||
}
|
||||
|
||||
fn opaque_regions(&self, scale: Scale<f64>) -> Vec<Rectangle<i32, Physical>> {
|
||||
match self {
|
||||
CosmicElement::Workspace(elem) => elem.opaque_regions(scale),
|
||||
CosmicElement::Cursor(elem) => elem.opaque_regions(scale),
|
||||
CosmicElement::MoveGrab(elem) => elem.opaque_regions(scale),
|
||||
#[cfg(feature = "debug")]
|
||||
CosmicElement::Egui(elem) => elem.opaque_regions(scale),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderElement<GlowRenderer> for CosmicElement<GlowRenderer> {
|
||||
fn draw(
|
||||
&self,
|
||||
renderer: &mut GlowRenderer,
|
||||
frame: &mut <GlowRenderer as Renderer>::Frame,
|
||||
location: Point<i32, Physical>,
|
||||
scale: Scale<f64>,
|
||||
damage: &[Rectangle<i32, Physical>],
|
||||
log: &slog::Logger,
|
||||
) -> Result<(), <GlowRenderer as Renderer>::Error> {
|
||||
match self {
|
||||
CosmicElement::Workspace(elem) => {
|
||||
elem.draw(renderer, frame, location, scale, damage, log)
|
||||
}
|
||||
CosmicElement::Cursor(elem) => elem.draw(renderer, frame, location, scale, damage, log),
|
||||
CosmicElement::MoveGrab(elem) => {
|
||||
elem.draw(renderer, frame, location, scale, damage, log)
|
||||
}
|
||||
#[cfg(feature = "debug")]
|
||||
CosmicElement::Egui(elem) => elem.draw(renderer, frame, location, scale, damage, log),
|
||||
}
|
||||
}
|
||||
|
||||
fn underlying_storage(
|
||||
&self,
|
||||
renderer: &GlowRenderer,
|
||||
) -> Option<UnderlyingStorage<'_, GlowRenderer>> {
|
||||
match self {
|
||||
CosmicElement::Workspace(elem) => elem.underlying_storage(renderer),
|
||||
CosmicElement::Cursor(elem) => elem.underlying_storage(renderer),
|
||||
CosmicElement::MoveGrab(elem) => elem.underlying_storage(renderer),
|
||||
#[cfg(feature = "debug")]
|
||||
CosmicElement::Egui(elem) => elem.underlying_storage(renderer),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> RenderElement<GlMultiRenderer<'a>> for CosmicElement<GlMultiRenderer<'a>> {
|
||||
fn draw(
|
||||
&self,
|
||||
renderer: &mut GlMultiRenderer<'a>,
|
||||
frame: &mut <GlMultiRenderer<'a> as Renderer>::Frame,
|
||||
location: Point<i32, Physical>,
|
||||
scale: Scale<f64>,
|
||||
damage: &[Rectangle<i32, Physical>],
|
||||
log: &slog::Logger,
|
||||
) -> Result<(), <GlMultiRenderer<'_> as Renderer>::Error> {
|
||||
match self {
|
||||
CosmicElement::Workspace(elem) => {
|
||||
elem.draw(renderer, frame, location, scale, damage, log)
|
||||
}
|
||||
CosmicElement::Cursor(elem) => elem.draw(renderer, frame, location, scale, damage, log),
|
||||
CosmicElement::MoveGrab(elem) => {
|
||||
elem.draw(renderer, frame, location, scale, damage, log)
|
||||
}
|
||||
#[cfg(feature = "debug")]
|
||||
CosmicElement::Egui(elem) => {
|
||||
let glow_renderer = renderer.glow_renderer_mut();
|
||||
let gles2_frame = frame.gles2_frame_mut();
|
||||
elem.draw(glow_renderer, gles2_frame, location, scale, damage, log)
|
||||
.map_err(|err| MultiError::Render(err))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn underlying_storage(
|
||||
&self,
|
||||
renderer: &GlMultiRenderer<'a>,
|
||||
) -> Option<UnderlyingStorage<'_, GlMultiRenderer<'a>>> {
|
||||
match self {
|
||||
CosmicElement::Workspace(elem) => elem.underlying_storage(renderer),
|
||||
CosmicElement::Cursor(elem) => elem.underlying_storage(renderer),
|
||||
CosmicElement::MoveGrab(elem) => elem.underlying_storage(renderer),
|
||||
#[cfg(feature = "debug")]
|
||||
CosmicElement::Egui(elem) => {
|
||||
let glow_renderer = renderer.glow_renderer();
|
||||
match elem.underlying_storage(glow_renderer) {
|
||||
Some(UnderlyingStorage::Wayland(buffer)) => {
|
||||
Some(UnderlyingStorage::Wayland(buffer))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> From<WorkspaceRenderElement<R>> for CosmicElement<R>
|
||||
where
|
||||
R: Renderer + ImportAll + AsGlowRenderer,
|
||||
<R as Renderer>::TextureId: 'static,
|
||||
<R as Renderer>::Frame: AsGles2Frame,
|
||||
{
|
||||
fn from(elem: WorkspaceRenderElement<R>) -> Self {
|
||||
Self::Workspace(elem)
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> From<CursorRenderElement<R>> for CosmicElement<R>
|
||||
where
|
||||
R: Renderer + ImportAll + AsGlowRenderer,
|
||||
<R as Renderer>::TextureId: 'static,
|
||||
<R as Renderer>::Frame: AsGles2Frame,
|
||||
{
|
||||
fn from(elem: CursorRenderElement<R>) -> Self {
|
||||
Self::Cursor(elem)
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> From<CosmicMappedRenderElement<R>> for CosmicElement<R>
|
||||
where
|
||||
R: Renderer + ImportAll + AsGlowRenderer,
|
||||
<R as Renderer>::TextureId: 'static,
|
||||
<R as Renderer>::Frame: AsGles2Frame,
|
||||
{
|
||||
fn from(elem: CosmicMappedRenderElement<R>) -> Self {
|
||||
Self::MoveGrab(elem)
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> From<TextureRenderElement<Gles2Texture>> for CosmicElement<R>
|
||||
where
|
||||
R: Renderer + ImportAll + AsGlowRenderer,
|
||||
<R as Renderer>::TextureId: 'static,
|
||||
<R as Renderer>::Frame: AsGles2Frame,
|
||||
{
|
||||
fn from(elem: TextureRenderElement<Gles2Texture>) -> Self {
|
||||
Self::Egui(elem)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AsGlowRenderer
|
||||
where
|
||||
Self: Renderer,
|
||||
<Self as Renderer>::Frame: AsGles2Frame,
|
||||
{
|
||||
fn glow_renderer(&self) -> &GlowRenderer;
|
||||
fn glow_renderer_mut(&mut self) -> &mut GlowRenderer;
|
||||
}
|
||||
|
||||
impl AsGlowRenderer for GlowRenderer {
|
||||
fn glow_renderer(&self) -> &GlowRenderer {
|
||||
self
|
||||
}
|
||||
fn glow_renderer_mut(&mut self) -> &mut GlowRenderer {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> AsGlowRenderer for GlMultiRenderer<'a> {
|
||||
fn glow_renderer(&self) -> &GlowRenderer {
|
||||
self.as_ref()
|
||||
}
|
||||
fn glow_renderer_mut(&mut self) -> &mut GlowRenderer {
|
||||
self.as_mut()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AsGles2Frame
|
||||
where
|
||||
Self: Frame,
|
||||
{
|
||||
fn gles2_frame(&self) -> &Gles2Frame;
|
||||
fn gles2_frame_mut(&mut self) -> &mut Gles2Frame;
|
||||
}
|
||||
|
||||
impl AsGles2Frame for Gles2Frame {
|
||||
fn gles2_frame(&self) -> &Gles2Frame {
|
||||
self
|
||||
}
|
||||
fn gles2_frame_mut(&mut self) -> &mut Gles2Frame {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl AsGles2Frame for GlMultiFrame {
|
||||
fn gles2_frame(&self) -> &Gles2Frame {
|
||||
self.as_ref()
|
||||
}
|
||||
fn gles2_frame_mut(&mut self) -> &mut Gles2Frame {
|
||||
self.as_mut()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +1,12 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
#[cfg(feature = "debug")]
|
||||
use crate::{debug::fps_ui, state::Fps, utils::prelude::*};
|
||||
use crate::{
|
||||
debug::{debug_ui, fps_ui, log_ui, EguiFrame},
|
||||
state::Fps,
|
||||
utils::prelude::*,
|
||||
};
|
||||
use crate::{
|
||||
shell::{
|
||||
layout::floating::SeatMoveGrabState, CosmicMappedRenderElement, WorkspaceRenderElement,
|
||||
},
|
||||
shell::{layout::floating::SeatMoveGrabState, CosmicMappedRenderElement},
|
||||
state::Common,
|
||||
wayland::{
|
||||
handlers::{data_device::get_dnd_icon, screencopy::render_to_buffer},
|
||||
handlers::{data_device::get_dnd_icon, screencopy::render_session},
|
||||
protocols::{
|
||||
screencopy::{
|
||||
BufferParams, CursorMode as ScreencopyCursorMode, Session as ScreencopySession,
|
||||
|
|
@ -28,42 +22,38 @@ use smithay::{
|
|||
allocator::dmabuf::Dmabuf,
|
||||
drm::DrmNode,
|
||||
renderer::{
|
||||
buffer_dimensions,
|
||||
damage::{
|
||||
DamageTrackedRenderer, DamageTrackedRendererError as RenderError, OutputNoMode,
|
||||
},
|
||||
element::RenderElementStates,
|
||||
gles2::{Gles2Renderbuffer, Gles2Renderer},
|
||||
element::{RenderElement, RenderElementStates},
|
||||
gles2::{Gles2Error, Gles2Renderbuffer},
|
||||
glow::GlowRenderer,
|
||||
multigpu::{egl::EglGlesBackend, MultiFrame, MultiRenderer},
|
||||
Bind, Blit, ExportMem, ImportAll, ImportMem, Offscreen, Renderer, TextureFilter,
|
||||
},
|
||||
},
|
||||
output::Output,
|
||||
utils::{Physical, Rectangle},
|
||||
wayland::dmabuf::get_dmabuf,
|
||||
};
|
||||
|
||||
pub mod cursor;
|
||||
use self::cursor::CursorRenderElement;
|
||||
pub mod element;
|
||||
use self::element::{AsGles2Frame, AsGlowRenderer, CosmicElement};
|
||||
|
||||
pub type GlMultiRenderer<'a> = MultiRenderer<
|
||||
'a,
|
||||
'a,
|
||||
EglGlesBackend<Gles2Renderer>,
|
||||
EglGlesBackend<Gles2Renderer>,
|
||||
EglGlesBackend<GlowRenderer>,
|
||||
EglGlesBackend<GlowRenderer>,
|
||||
Gles2Renderbuffer,
|
||||
>;
|
||||
pub type GlMultiFrame = MultiFrame<EglGlesBackend<Gles2Renderer>, EglGlesBackend<Gles2Renderer>>;
|
||||
pub type GlMultiFrame = MultiFrame<EglGlesBackend<GlowRenderer>, EglGlesBackend<GlowRenderer>>;
|
||||
|
||||
pub static CLEAR_COLOR: [f32; 4] = [0.153, 0.161, 0.165, 1.0];
|
||||
|
||||
smithay::render_elements! {
|
||||
pub CosmicElement<R> where R: ImportAll;
|
||||
WorkspaceElement=WorkspaceRenderElement<R>,
|
||||
CursorElement=CursorRenderElement<R>,
|
||||
MoveGrabRenderElement=CosmicMappedRenderElement<R>,
|
||||
//#[cfg(feature = "debug")]
|
||||
//EguiFrame=EguiFrame,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum CursorMode {
|
||||
None,
|
||||
|
|
@ -79,6 +69,7 @@ pub fn cursor_elements<E, R>(
|
|||
) -> Vec<E>
|
||||
where
|
||||
R: Renderer + ImportAll + ImportMem,
|
||||
<R as Renderer>::Frame: AsGles2Frame,
|
||||
<R as Renderer>::TextureId: Clone + 'static,
|
||||
E: From<CursorRenderElement<R>> + From<CosmicMappedRenderElement<R>>,
|
||||
{
|
||||
|
|
@ -101,7 +92,7 @@ where
|
|||
seat,
|
||||
location,
|
||||
scale.into(),
|
||||
&state.start_time,
|
||||
state.clock.now(),
|
||||
mode != CursorMode::NotDefault,
|
||||
)
|
||||
.into_iter()
|
||||
|
|
@ -132,16 +123,17 @@ where
|
|||
elements
|
||||
}
|
||||
|
||||
pub fn render_output<R, Target, Source>(
|
||||
pub fn render_output<R, Target, OffTarget, Source>(
|
||||
gpu: Option<&DrmNode>,
|
||||
renderer: &mut R,
|
||||
target: Target,
|
||||
damage_tracker: &mut DamageTrackedRenderer,
|
||||
age: usize,
|
||||
state: &mut Common,
|
||||
output: &Output,
|
||||
cursor_mode: CursorMode,
|
||||
screencopy: Option<(Source, &[(ScreencopySession, BufferParams)])>,
|
||||
#[cfg(feature = "debug")] mut fps: Option<&mut Fps>,
|
||||
#[cfg(feature = "debug")] fps: Option<&mut Fps>,
|
||||
) -> Result<(Option<Vec<Rectangle<i32, Physical>>>, RenderElementStates), RenderError<R>>
|
||||
where
|
||||
R: Renderer
|
||||
|
|
@ -149,16 +141,21 @@ where
|
|||
+ ImportMem
|
||||
+ ExportMem
|
||||
+ Bind<Dmabuf>
|
||||
+ Offscreen<Target>
|
||||
+ Bind<Source>
|
||||
+ Blit<Source>,
|
||||
+ Bind<Target>
|
||||
+ Offscreen<OffTarget>
|
||||
+ Blit<Source>
|
||||
+ AsGlowRenderer,
|
||||
<R as Renderer>::Frame: AsGles2Frame,
|
||||
<R as Renderer>::TextureId: Clone + 'static,
|
||||
<R as Renderer>::Error: From<Gles2Error>,
|
||||
CosmicElement<R>: RenderElement<R>,
|
||||
Source: Clone,
|
||||
{
|
||||
let handle = state.shell.workspaces.active(output).handle;
|
||||
render_workspace(
|
||||
gpu,
|
||||
renderer,
|
||||
target,
|
||||
damage_tracker,
|
||||
age,
|
||||
state,
|
||||
|
|
@ -166,12 +163,15 @@ where
|
|||
&handle,
|
||||
cursor_mode,
|
||||
screencopy,
|
||||
#[cfg(feature = "debug")]
|
||||
fps,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn render_workspace<R, Target, Source>(
|
||||
pub fn render_workspace<R, Target, OffTarget, Source>(
|
||||
gpu: Option<&DrmNode>,
|
||||
renderer: &mut R,
|
||||
target: Target,
|
||||
damage_tracker: &mut DamageTrackedRenderer,
|
||||
age: usize,
|
||||
state: &mut Common,
|
||||
|
|
@ -187,11 +187,15 @@ where
|
|||
+ ImportMem
|
||||
+ ExportMem
|
||||
+ Bind<Dmabuf>
|
||||
+ Offscreen<Target>
|
||||
+ Bind<Source>
|
||||
+ Blit<Source>,
|
||||
Source: Clone,
|
||||
+ Bind<Target>
|
||||
+ Offscreen<OffTarget>
|
||||
+ Blit<Source>
|
||||
+ AsGlowRenderer,
|
||||
<R as Renderer>::Frame: AsGles2Frame,
|
||||
<R as Renderer>::TextureId: Clone + 'static,
|
||||
<R as Renderer>::Error: From<Gles2Error>,
|
||||
CosmicElement<R>: RenderElement<R>,
|
||||
Source: Clone,
|
||||
{
|
||||
#[cfg(feature = "debug")]
|
||||
if let Some(ref mut fps) = fps {
|
||||
|
|
@ -219,68 +223,67 @@ where
|
|||
|
||||
#[cfg(feature = "debug")]
|
||||
{
|
||||
// TODO add debug elements
|
||||
let workspace = &state.shell.spaces[space_idx];
|
||||
let output_geo = workspace
|
||||
.space
|
||||
.output_geometry(output)
|
||||
.unwrap_or(Rectangle::from_loc_and_size((0, 0), (0, 0)));
|
||||
let output_geo = output.geometry();
|
||||
let scale = output.current_scale().fractional_scale();
|
||||
|
||||
if let Some(fps) = fps {
|
||||
if let Some(fps) = fps.as_mut() {
|
||||
let fps_overlay = fps_ui(
|
||||
_gpu,
|
||||
gpu,
|
||||
state,
|
||||
renderer.glow_renderer_mut(),
|
||||
fps,
|
||||
output_geo.to_f64().to_physical(scale),
|
||||
Rectangle::from_loc_and_size(
|
||||
(0, 0),
|
||||
(output_geo.size.w.min(400), output_geo.size.h.min(800)),
|
||||
),
|
||||
scale,
|
||||
);
|
||||
custom_elements.push(fps_overlay.into());
|
||||
}
|
||||
|
||||
let area = Rectangle::<f64, smithay::utils::Logical>::from_loc_and_size(
|
||||
state
|
||||
.shell
|
||||
.space_relative_output_geometry((0.0f64, 0.0f64), output),
|
||||
state.shell.global_space().to_f64().size,
|
||||
)
|
||||
.to_physical(scale);
|
||||
if let Some(log_ui) = log_ui(state, area, scale, output_geo.size.w as f32 * 0.6) {
|
||||
custom_elements.push(log_ui.into());
|
||||
}
|
||||
if let Some(debug_overlay) = debug_ui(state, area, scale) {
|
||||
custom_elements.push(debug_overlay.into());
|
||||
)
|
||||
.map_err(<R as Renderer>::Error::from)
|
||||
.map_err(RenderError::Rendering)?;
|
||||
elements.push(fps_overlay.into());
|
||||
}
|
||||
}
|
||||
|
||||
elements.extend(
|
||||
workspace
|
||||
.render_output(output)
|
||||
.render_output::<R>(output)
|
||||
.map_err(|_| OutputNoMode)?
|
||||
.into_iter()
|
||||
.map(Into::into),
|
||||
);
|
||||
|
||||
renderer.bind(target).map_err(RenderError::Rendering)?;
|
||||
let res = damage_tracker.render_output(renderer, age, &elements, CLEAR_COLOR, None);
|
||||
|
||||
#[cfg(feature = "debug")]
|
||||
if let Some(ref mut fps) = fps {
|
||||
if let Some(fps) = fps.as_mut() {
|
||||
fps.end();
|
||||
}
|
||||
|
||||
if let Some((source, buffers)) = screencopy {
|
||||
if res.is_ok() {
|
||||
for (session, params) in buffers {
|
||||
match render_to_buffer(
|
||||
match render_session(
|
||||
gpu.cloned(),
|
||||
renderer,
|
||||
&session,
|
||||
params,
|
||||
output.current_transform(),
|
||||
|_node, renderer, dtr, age| {
|
||||
|_node, buffer, renderer, dtr, age| {
|
||||
let res = dtr.damage_output(age, &elements, slog_scope::logger())?;
|
||||
|
||||
if let (Some(ref damage), _) = &res {
|
||||
if let Ok(dmabuf) = get_dmabuf(buffer) {
|
||||
renderer.bind(dmabuf).map_err(RenderError::Rendering)?;
|
||||
} else {
|
||||
let size = buffer_dimensions(buffer).unwrap();
|
||||
let render_buffer = renderer
|
||||
.create_buffer(size)
|
||||
.map_err(RenderError::Rendering)?;
|
||||
renderer
|
||||
.bind(render_buffer)
|
||||
.map_err(RenderError::Rendering)?;
|
||||
}
|
||||
for rect in damage {
|
||||
renderer
|
||||
.blit_from(source.clone(), *rect, *rect, TextureFilter::Nearest)
|
||||
|
|
|
|||
|
|
@ -11,13 +11,17 @@ use crate::{
|
|||
use anyhow::{anyhow, Context, Result};
|
||||
use smithay::{
|
||||
backend::{
|
||||
renderer::{damage::DamageTrackedRenderer, gles2::Gles2Renderbuffer, ImportDma, ImportEgl},
|
||||
renderer::{
|
||||
damage::DamageTrackedRenderer, gles2::Gles2Renderbuffer, glow::GlowRenderer, ImportDma,
|
||||
ImportEgl,
|
||||
},
|
||||
winit::{self, WinitEvent, WinitGraphicsBackend, WinitVirtualDevice},
|
||||
},
|
||||
desktop::layer_map_for_output,
|
||||
output::{Mode, Output, PhysicalProperties, Scale, Subpixel},
|
||||
reexports::{
|
||||
calloop::{ping, EventLoop},
|
||||
wayland_protocols::wp::presentation_time::server::wp_presentation_feedback,
|
||||
wayland_server::DisplayHandle,
|
||||
},
|
||||
utils::Transform,
|
||||
|
|
@ -31,7 +35,7 @@ use super::render::CursorMode;
|
|||
|
||||
pub struct WinitState {
|
||||
// The winit backend currently has no notion of multiple windows
|
||||
pub backend: WinitGraphicsBackend,
|
||||
pub backend: WinitGraphicsBackend<GlowRenderer>,
|
||||
output: Output,
|
||||
damage_tracker: DamageTrackedRenderer,
|
||||
screencopy: Vec<(ScreencopySession, BufferParams)>,
|
||||
|
|
@ -47,9 +51,10 @@ impl WinitState {
|
|||
let age = self.backend.buffer_age().unwrap_or(0);
|
||||
|
||||
let surface = self.backend.egl_surface();
|
||||
match render::render_output::<_, Gles2Renderbuffer, _>(
|
||||
match render::render_output::<_, _, Gles2Renderbuffer, _>(
|
||||
None,
|
||||
self.backend.renderer(),
|
||||
surface.clone(),
|
||||
&mut self.damage_tracker,
|
||||
age,
|
||||
state,
|
||||
|
|
@ -69,6 +74,19 @@ impl WinitState {
|
|||
.submit(damage.as_deref())
|
||||
.with_context(|| "Failed to submit buffer for display")?;
|
||||
state.send_frames(&self.output, &states);
|
||||
if damage.is_some() {
|
||||
let mut output_presentation_feedback =
|
||||
state.take_presentation_feedback(&self.output, &states);
|
||||
output_presentation_feedback.presented(
|
||||
state.clock.now(),
|
||||
self.output
|
||||
.current_mode()
|
||||
.map(|mode| mode.refresh as u32)
|
||||
.unwrap_or_default(),
|
||||
0,
|
||||
wp_presentation_feedback::Kind::Vsync,
|
||||
)
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
for (session, params) in self.screencopy.drain(..) {
|
||||
|
|
@ -227,7 +245,7 @@ pub fn init_backend(
|
|||
fn init_egl_client_side(
|
||||
dh: &DisplayHandle,
|
||||
state: &mut State,
|
||||
renderer: &mut WinitGraphicsBackend,
|
||||
renderer: &mut WinitGraphicsBackend<GlowRenderer>,
|
||||
) -> Result<()> {
|
||||
let bind_result = renderer.renderer().bind_wl_display(dh);
|
||||
match bind_result {
|
||||
|
|
|
|||
|
|
@ -15,9 +15,8 @@ use smithay::{
|
|||
egl::{EGLContext, EGLDisplay},
|
||||
input::{Event, InputEvent},
|
||||
renderer::{
|
||||
damage::DamageTrackedRenderer,
|
||||
gles2::{Gles2Renderbuffer, Gles2Renderer},
|
||||
Bind, ImportDma, ImportEgl,
|
||||
damage::DamageTrackedRenderer, gles2::Gles2Renderbuffer, glow::GlowRenderer, Bind,
|
||||
ImportDma, ImportEgl,
|
||||
},
|
||||
x11::{Window, WindowBuilder, X11Backend, X11Event, X11Handle, X11Input, X11Surface},
|
||||
},
|
||||
|
|
@ -26,6 +25,7 @@ use smithay::{
|
|||
reexports::{
|
||||
calloop::{ping, EventLoop, LoopHandle},
|
||||
gbm::{Device as GbmDevice, FdWrapper},
|
||||
wayland_protocols::wp::presentation_time::server::wp_presentation_feedback,
|
||||
wayland_server::DisplayHandle,
|
||||
},
|
||||
utils::Transform,
|
||||
|
|
@ -41,7 +41,7 @@ use crate::state::Fps;
|
|||
pub struct X11State {
|
||||
allocator: Arc<Mutex<GbmDevice<FdWrapper>>>,
|
||||
_egl: EGLDisplay,
|
||||
pub renderer: Gles2Renderer,
|
||||
pub renderer: GlowRenderer,
|
||||
surfaces: Vec<Surface>,
|
||||
handle: X11Handle,
|
||||
}
|
||||
|
|
@ -194,22 +194,15 @@ pub struct Surface {
|
|||
}
|
||||
|
||||
impl Surface {
|
||||
pub fn render_output(
|
||||
&mut self,
|
||||
renderer: &mut Gles2Renderer,
|
||||
state: &mut Common,
|
||||
) -> Result<()> {
|
||||
pub fn render_output(&mut self, renderer: &mut GlowRenderer, state: &mut Common) -> Result<()> {
|
||||
let (buffer, age) = self
|
||||
.surface
|
||||
.buffer()
|
||||
.with_context(|| "Failed to allocate buffer")?;
|
||||
renderer
|
||||
.bind(buffer.clone())
|
||||
.with_context(|| "Failed to bind buffer")?;
|
||||
|
||||
match render::render_output::<_, Gles2Renderbuffer, _>(
|
||||
match render::render_output::<_, _, Gles2Renderbuffer, _>(
|
||||
None,
|
||||
renderer,
|
||||
buffer.clone(),
|
||||
&mut self.damage_tracker,
|
||||
age as usize,
|
||||
state,
|
||||
|
|
@ -223,12 +216,25 @@ impl Surface {
|
|||
#[cfg(feature = "debug")]
|
||||
Some(&mut self.fps),
|
||||
) {
|
||||
Ok((_damage, states)) => {
|
||||
Ok((damage, states)) => {
|
||||
self.screencopy.clear();
|
||||
self.surface
|
||||
.submit()
|
||||
.with_context(|| "Failed to submit buffer for display")?;
|
||||
state.send_frames(&self.output, &states);
|
||||
if damage.is_some() {
|
||||
let mut output_presentation_feedback =
|
||||
state.take_presentation_feedback(&self.output, &states);
|
||||
output_presentation_feedback.presented(
|
||||
state.clock.now(),
|
||||
self.output
|
||||
.current_mode()
|
||||
.map(|mode| mode.refresh as u32)
|
||||
.unwrap_or_default(),
|
||||
0,
|
||||
wp_presentation_feedback::Kind::Vsync,
|
||||
)
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
for (session, params) in self.screencopy.drain(..) {
|
||||
|
|
@ -265,7 +271,7 @@ pub fn init_backend(
|
|||
// Create the OpenGL context
|
||||
let context = EGLContext::new(&egl, None).with_context(|| "Failed to create EGL context")?;
|
||||
// Create a renderer
|
||||
let mut renderer = unsafe { Gles2Renderer::new(context, None) }
|
||||
let mut renderer = unsafe { GlowRenderer::new(context, None) }
|
||||
.with_context(|| "Failed to initialize renderer")?;
|
||||
|
||||
init_egl_client_side(dh, state, &mut renderer)?;
|
||||
|
|
@ -383,11 +389,10 @@ pub fn init_backend(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn init_egl_client_side(
|
||||
dh: &DisplayHandle,
|
||||
state: &mut State,
|
||||
renderer: &mut Gles2Renderer,
|
||||
) -> Result<()> {
|
||||
fn init_egl_client_side<R>(dh: &DisplayHandle, state: &mut State, renderer: &mut R) -> Result<()>
|
||||
where
|
||||
R: ImportEgl + ImportDma,
|
||||
{
|
||||
let bind_result = renderer.bind_wl_display(dh);
|
||||
match bind_result {
|
||||
Ok(_) => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue