1use super::placement::apply_placement;
2use super::*;
3use crate::animation::{Animation, lerp_i32, lerp_u32};
4use std::collections::BTreeMap;
5
6pub fn run<R>(renderer: R, options: LayerOptions, receiver: RenderReceiver) -> Result<()>
7where
8 R: Renderer + 'static,
9{
10 run_inner(
11 renderer,
12 Some((DEFAULT_SURFACE_ID, options)),
13 Some(receiver),
14 true,
15 )
16}
17
18pub fn run_surfaces<R>(renderer: R, receiver: RenderReceiver) -> Result<()>
19where
20 R: Renderer + 'static,
21{
22 run_inner(renderer, None, Some(receiver), false)
23}
24
25pub(in crate::wayland) fn run_inner<R>(
26 renderer: R,
27 initial_surface: Option<(SurfaceId, LayerOptions)>,
28 receiver: Option<RenderReceiver>,
29 exit_when_all_surfaces_closed: bool,
30) -> Result<()>
31where
32 R: Renderer + 'static,
33{
34 let connection = Connection::connect_to_env()?;
35 let (globals, event_queue) = registry_queue_init(&connection)?;
36 let qh = event_queue.handle();
37
38 let mut event_loop = EventLoop::<State<R>>::try_new()?;
39 let loop_handle = event_loop.handle();
40 WaylandSource::new(connection.clone(), event_queue).insert(loop_handle.clone())?;
41
42 let compositor = CompositorState::bind(&globals, &qh)?;
43 let layer_shell = LayerShell::bind(&globals, &qh)?;
44 let shm = Shm::bind(&globals, &qh)?;
45 let output_state = OutputState::new(&globals, &qh);
46 let seat_state = SeatState::new(&globals, &qh);
47
48 let mut surfaces = BTreeMap::new();
49 if let Some((id, options)) = initial_surface {
50 if let Some(output) = resolve_output_target(&output_state, options.output.as_ref()) {
51 surfaces.insert(
52 id,
53 RenderSurface::new(&qh, &compositor, &layer_shell, output.as_ref(), &options),
54 );
55 }
56 }
57 let mut state = State {
58 registry_state: RegistryState::new(&globals),
59 output_state,
60 seat_state,
61 compositor,
62 layer_shell,
63 shm,
64 surfaces,
65 pointer: None,
66 renderer,
67 running: true,
68 exit_when_all_surfaces_closed,
69 retired_frames: Vec::new(),
70 };
71
72 if let Some(receiver) = receiver {
73 let commands_qh = qh.clone();
74 loop_handle.insert_source(receiver, move |event, _, state| {
75 if let ChannelEvent::Msg(command) = event {
76 state.handle_command(&commands_qh, command);
77 }
78 })?;
79 }
80
81 while state.running {
82 event_loop.dispatch(None, &mut state)?;
83 state.collect_released_frames();
84 }
85
86 Ok(())
87}
88
89pub(in crate::wayland) struct State<R> {
90 pub(in crate::wayland) registry_state: RegistryState,
91 pub(in crate::wayland) output_state: OutputState,
92 pub(in crate::wayland) seat_state: SeatState,
93 compositor: CompositorState,
94 layer_shell: LayerShell,
95 pub(in crate::wayland) shm: Shm,
96 pub(in crate::wayland) surfaces: BTreeMap<SurfaceId, RenderSurface>,
97 pub(in crate::wayland) pointer: Option<wl_pointer::WlPointer>,
98 pub(in crate::wayland) renderer: R,
99 pub(in crate::wayland) running: bool,
100 exit_when_all_surfaces_closed: bool,
101 retired_frames: Vec<Frame>,
102}
103
104impl<R> State<R>
105where
106 R: Renderer,
107{
108 fn handle_command(&mut self, qh: &QueueHandle<Self>, command: RenderCommand) {
109 match command {
110 RenderCommand::Redraw => self.draw(qh, DEFAULT_SURFACE_ID, None),
111 RenderCommand::Resize { width, height } => {
112 self.resize_surface(qh, DEFAULT_SURFACE_ID, width, height)
113 }
114 RenderCommand::SetMargins(margins) => {
115 self.set_surface_margins(DEFAULT_SURFACE_ID, margins)
116 }
117 RenderCommand::SetAnchor(anchor) => self.set_surface_anchor(DEFAULT_SURFACE_ID, anchor),
118 RenderCommand::CreateSurface { id, options } => self.create_surface(qh, id, options),
119 RenderCommand::DestroySurface { id } => self.destroy_surface(id),
120 RenderCommand::RedrawSurface { id } => self.draw(qh, id, None),
121 RenderCommand::ResizeSurface { id, width, height } => {
122 self.resize_surface(qh, id, width, height)
123 }
124 RenderCommand::SetSurfaceMargins { id, margins } => {
125 self.set_surface_margins(id, margins)
126 }
127 RenderCommand::SetSurfaceAnchor { id, anchor } => self.set_surface_anchor(id, anchor),
128 RenderCommand::SetSurfaceLayer { id, layer } => self.set_surface_layer(id, layer),
129 RenderCommand::AnimateSurfaceMargins {
130 id,
131 to,
132 animation,
133 destroy_on_complete,
134 } => self.animate_surface_margins(qh, id, to, animation, destroy_on_complete),
135 RenderCommand::AnimateSurfaceSize {
136 id,
137 width,
138 height,
139 animation,
140 destroy_on_complete,
141 } => self.animate_surface_size(qh, id, width, height, animation, destroy_on_complete),
142 RenderCommand::CancelSurfaceAnimation { id } => self.cancel_surface_animation(id),
143 RenderCommand::RequestOutputs { reply } => {
144 let _ = reply.send(self.render_outputs());
145 }
146 RenderCommand::RequestSurfaceState { id, reply } => {
147 let _ = reply.send(self.surface_state(id));
148 }
149 RenderCommand::Exit => self.running = false,
150 }
151 }
152
153 fn create_surface(&mut self, qh: &QueueHandle<Self>, id: SurfaceId, options: LayerOptions) {
154 let Some(output) = self.resolve_output_target(options.output.as_ref()) else {
155 return;
156 };
157
158 if let Some(surface) = self.surfaces.get_mut(&id) {
159 if surface.output == options.output {
160 surface.update_options(options);
161 surface.layer.commit();
162 return;
163 }
164 self.remove_surface(id);
165 }
166
167 self.surfaces.insert(
168 id,
169 RenderSurface::new(
170 qh,
171 &self.compositor,
172 &self.layer_shell,
173 output.as_ref(),
174 &options,
175 ),
176 );
177 }
178
179 fn resolve_output_target(
180 &self,
181 target: Option<&OutputTarget>,
182 ) -> Option<Option<wl_output::WlOutput>> {
183 resolve_output_target(&self.output_state, target)
184 }
185
186 fn destroy_surface(&mut self, id: SurfaceId) {
187 self.remove_surface(id);
188 self.maybe_exit_after_surface_removal();
189 }
190
191 fn resize_surface(&mut self, qh: &QueueHandle<Self>, id: SurfaceId, width: u32, height: u32) {
192 let Some(surface) = self.surfaces.get_mut(&id) else {
193 return;
194 };
195 surface.cancel_animation();
196 surface.set_size(width, height);
197 if surface.configured {
198 self.draw(qh, id, None);
199 } else {
200 surface.layer.commit();
201 }
202 }
203
204 fn set_surface_margins(&mut self, id: SurfaceId, margins: Margins) {
205 let Some(surface) = self.surfaces.get_mut(&id) else {
206 return;
207 };
208 surface.set_margins(margins);
209 surface.layer.commit();
210 }
211
212 fn set_surface_anchor(&mut self, id: SurfaceId, anchor: Anchor) {
213 let Some(surface) = self.surfaces.get_mut(&id) else {
214 return;
215 };
216 surface.set_anchor(anchor);
217 surface.layer.commit();
218 }
219
220 fn set_surface_layer(&mut self, id: SurfaceId, layer: Layer) {
221 let Some(surface) = self.surfaces.get_mut(&id) else {
222 return;
223 };
224 surface.set_layer(layer);
225 surface.layer.commit();
226 }
227
228 fn animate_surface_margins(
229 &mut self,
230 qh: &QueueHandle<Self>,
231 id: SurfaceId,
232 to: Margins,
233 animation: Animation,
234 destroy_on_complete: bool,
235 ) {
236 let result = {
237 let Some(surface) = self.surfaces.get_mut(&id) else {
238 return;
239 };
240 let result = surface.start_margins_animation(to, animation, destroy_on_complete);
241 surface.layer.commit();
242 result
243 };
244
245 self.handle_surface_animation_start(qh, id, result);
246 }
247
248 fn animate_surface_size(
249 &mut self,
250 qh: &QueueHandle<Self>,
251 id: SurfaceId,
252 width: u32,
253 height: u32,
254 animation: Animation,
255 destroy_on_complete: bool,
256 ) {
257 let result = {
258 let Some(surface) = self.surfaces.get_mut(&id) else {
259 return;
260 };
261 let result =
262 surface.start_size_animation(width, height, animation, destroy_on_complete);
263 surface.layer.commit();
264 result
265 };
266
267 self.handle_surface_animation_start(qh, id, result);
268 }
269
270 fn handle_surface_animation_start(
271 &mut self,
272 qh: &QueueHandle<Self>,
273 id: SurfaceId,
274 result: SurfaceAnimationStart,
275 ) {
276 match result {
277 SurfaceAnimationStart::Animate => {
278 if let Some(surface) = self.surfaces.get_mut(&id) {
279 surface.request_frame(qh);
280 }
281 }
282 SurfaceAnimationStart::Complete => {
283 if self
284 .surfaces
285 .get(&id)
286 .is_some_and(|surface| surface.configured)
287 {
288 self.draw(qh, id, None);
289 }
290 }
291 SurfaceAnimationStart::Destroy => {
292 self.remove_surface(id);
293 self.maybe_exit_after_surface_removal();
294 }
295 }
296 }
297
298 fn cancel_surface_animation(&mut self, id: SurfaceId) {
299 let Some(surface) = self.surfaces.get_mut(&id) else {
300 return;
301 };
302 surface.cancel_animation();
303 }
304
305 pub(in crate::wayland) fn draw(
306 &mut self,
307 qh: &QueueHandle<Self>,
308 id: SurfaceId,
309 frame_time: Option<u32>,
310 ) {
311 let (animation, draw_result) = {
312 let Some(surface) = self.surfaces.get_mut(&id) else {
313 return;
314 };
315 if !surface.configured || surface.width == 0 || surface.height == 0 {
316 return;
317 }
318
319 let animation = frame_time
320 .map(|time| surface.advance_animation(time))
321 .unwrap_or(SurfaceAnimationFrame::Idle);
322 let draw_result = surface.draw(&self.shm, &mut self.renderer, id, frame_time);
323 (animation, draw_result)
324 };
325
326 match draw_result {
327 DrawResult::Drawn {
328 retired_frame,
329 next_frame,
330 } => {
331 if let Some(frame) = retired_frame {
332 self.retired_frames.push(frame);
333 }
334 if matches!(animation, SurfaceAnimationFrame::Destroy) {
335 self.remove_surface(id);
336 self.maybe_exit_after_surface_removal();
337 } else if next_frame || matches!(animation, SurfaceAnimationFrame::Animate) {
338 if let Some(surface) = self.surfaces.get_mut(&id) {
339 surface.request_frame(qh);
340 }
341 }
342 }
343 DrawResult::Exit { retired_frame } => {
344 if let Some(frame) = retired_frame {
345 self.retired_frames.push(frame);
346 }
347 self.remove_surface(id);
348 self.maybe_exit_after_surface_removal();
349 }
350 }
351 }
352
353 pub(in crate::wayland) fn handle_input_action(
354 &mut self,
355 qh: &QueueHandle<Self>,
356 id: SurfaceId,
357 action: InputAction,
358 ) {
359 match action {
360 InputAction::Ignore => {}
361 InputAction::Redraw => self.draw(qh, id, None),
362 InputAction::Animate => {
363 self.draw(qh, id, None);
364 if let Some(surface) = self.surfaces.get_mut(&id) {
365 surface.request_frame(qh);
366 }
367 }
368 InputAction::Exit => {
369 self.remove_surface(id);
370 self.maybe_exit_after_surface_removal();
371 }
372 }
373 }
374
375 pub(in crate::wayland) fn surface_id_for_wl_surface(
376 &self,
377 wl_surface: &wl_surface::WlSurface,
378 ) -> Option<SurfaceId> {
379 self.surfaces
380 .iter()
381 .find_map(|(id, surface)| (surface.layer.wl_surface() == wl_surface).then_some(*id))
382 }
383
384 pub(in crate::wayland) fn surface_id_for_layer(
385 &self,
386 layer: &LayerSurface,
387 ) -> Option<SurfaceId> {
388 self.surfaces
389 .iter()
390 .find_map(|(id, surface)| (&surface.layer == layer).then_some(*id))
391 }
392
393 pub(in crate::wayland) fn maybe_exit_after_surface_removal(&mut self) {
394 if self.exit_when_all_surfaces_closed && self.surfaces.is_empty() {
395 self.running = false;
396 }
397 }
398
399 pub(in crate::wayland) fn remove_surface(&mut self, id: SurfaceId) {
400 let Some(mut surface) = self.surfaces.remove(&id) else {
401 return;
402 };
403 if let Some(frame) = surface.take_frame() {
404 self.retired_frames.push(frame);
405 }
406 self.renderer.closed_surface(id);
407 }
408
409 pub(in crate::wayland) fn render_output(
410 &self,
411 output: &wl_output::WlOutput,
412 ) -> Option<RenderOutput> {
413 self.output_state.info(output).map(|info| RenderOutput {
414 id: info.id,
415 name: info.name,
416 description: info.description,
417 make: info.make,
418 model: info.model,
419 logical_position: info.logical_position,
420 logical_size: info.logical_size,
421 scale_factor: info.scale_factor,
422 })
423 }
424
425 fn render_outputs(&self) -> Vec<RenderOutput> {
426 self.output_state
427 .outputs()
428 .filter_map(|output| self.render_output(&output))
429 .collect()
430 }
431
432 fn surface_state(&self, id: SurfaceId) -> Option<RenderSurfaceState> {
433 self.surfaces.get(&id).map(|surface| surface.state(id))
434 }
435
436 fn collect_released_frames(&mut self) {
437 let retired_count = self.retired_frames.len();
438 self.retired_frames.retain(|frame| !frame.released());
439 if self.retired_frames.len() < retired_count {
440 crate::memory::trim_free_heap_pages();
441 }
442 }
443}
444
445fn resolve_output_target(
446 output_state: &OutputState,
447 target: Option<&OutputTarget>,
448) -> Option<Option<wl_output::WlOutput>> {
449 match target {
450 None | Some(OutputTarget::Any) => Some(None),
451 Some(OutputTarget::Id(target_id)) => output_state
452 .outputs()
453 .find(|output| {
454 output_state
455 .info(output)
456 .is_some_and(|info| info.id == *target_id)
457 })
458 .map(Some),
459 Some(OutputTarget::Name(target_name)) => output_state
460 .outputs()
461 .find(|output| {
462 output_state
463 .info(output)
464 .and_then(|info| info.name)
465 .is_some_and(|name| name == *target_name)
466 })
467 .map(Some),
468 }
469}
470
471struct SurfaceAnimation {
472 animation: Animation,
473 started_at: Option<u32>,
474 target: SurfaceAnimationTarget,
475 destroy_on_complete: bool,
476}
477
478#[derive(Clone, Copy)]
479enum SurfaceAnimationTarget {
480 Margins {
481 from: Margins,
482 to: Margins,
483 },
484 Size {
485 from_width: u32,
486 from_height: u32,
487 to_width: u32,
488 to_height: u32,
489 },
490}
491
492#[derive(Clone, Copy, PartialEq, Eq)]
493enum SurfaceAnimationStart {
494 Animate,
495 Complete,
496 Destroy,
497}
498
499#[derive(Clone, Copy, PartialEq, Eq)]
500enum SurfaceAnimationFrame {
501 Idle,
502 Animate,
503 Complete,
504 Destroy,
505}
506
507impl Margins {
508 fn lerp(self, to: Self, progress: f32) -> Self {
509 Self {
510 top: lerp_i32(self.top, to.top, progress),
511 right: lerp_i32(self.right, to.right, progress),
512 bottom: lerp_i32(self.bottom, to.bottom, progress),
513 left: lerp_i32(self.left, to.left, progress),
514 }
515 }
516}
517
518pub(in crate::wayland) struct RenderSurface {
519 pub(in crate::wayland) layer: LayerSurface,
520 pub(in crate::wayland) configured: bool,
521 pub(in crate::wayland) width: u32,
522 pub(in crate::wayland) height: u32,
523 output: Option<OutputTarget>,
524 layer_kind: Layer,
525 scale: u32,
526 anchor: Anchor,
527 margins: Margins,
528 animation: Option<SurfaceAnimation>,
529 frame: Option<Frame>,
530 pub(in crate::wayland) frame_pending: bool,
531}
532
533impl RenderSurface {
534 fn new<R: Renderer>(
535 qh: &QueueHandle<State<R>>,
536 compositor: &CompositorState,
537 layer_shell: &LayerShell,
538 output: Option<&wl_output::WlOutput>,
539 options: &LayerOptions,
540 ) -> Self {
541 let wl_surface = compositor.create_surface(qh);
542 let layer = layer_shell.create_layer_surface(
543 qh,
544 wl_surface,
545 options.layer.into_sctk(),
546 Some(options.namespace.as_str()),
547 output,
548 );
549 layer.set_keyboard_interactivity(options.keyboard_interactivity.into_sctk());
550 layer.set_exclusive_zone(options.exclusive_zone);
551 layer.set_size(options.width, options.height);
552 apply_placement(&layer, options.anchor, options.margins);
553 layer.commit();
554
555 Self {
556 layer,
557 configured: false,
558 width: options.width,
559 height: options.height,
560 output: options.output.clone(),
561 layer_kind: options.layer,
562 scale: 1,
563 anchor: options.anchor,
564 margins: options.margins,
565 animation: None,
566 frame: None,
567 frame_pending: false,
568 }
569 }
570
571 fn set_size(&mut self, width: u32, height: u32) {
572 self.width = width;
573 self.height = height;
574 self.layer.set_size(width, height);
575 }
576
577 pub(in crate::wayland) fn set_scale(&mut self, scale: u32) -> bool {
578 let scale = scale.max(1);
579 if self.scale == scale {
580 return false;
581 }
582
583 self.scale = scale;
584 true
585 }
586
587 fn set_margins(&mut self, margins: Margins) {
588 self.margins = margins;
589 self.animation = None;
590 apply_placement(&self.layer, self.anchor, self.margins);
591 }
592
593 fn set_anchor(&mut self, anchor: Anchor) {
594 self.anchor = anchor;
595 apply_placement(&self.layer, self.anchor, self.margins);
596 }
597
598 fn set_layer(&mut self, layer: Layer) {
599 self.layer_kind = layer;
600 self.layer.set_layer(layer.into_sctk());
601 }
602
603 fn update_options(&mut self, options: LayerOptions) {
604 self.layer
605 .set_keyboard_interactivity(options.keyboard_interactivity.into_sctk());
606 self.layer.set_exclusive_zone(options.exclusive_zone);
607 self.set_layer(options.layer);
608 self.set_size(options.width, options.height);
609 self.anchor = options.anchor;
610 self.margins = options.margins;
611 self.animation = None;
612 apply_placement(&self.layer, self.anchor, self.margins);
613 }
614
615 fn start_margins_animation(
616 &mut self,
617 to: Margins,
618 animation: Animation,
619 destroy_on_complete: bool,
620 ) -> SurfaceAnimationStart {
621 if animation.duration_ms == 0 {
622 self.margins = to;
623 self.animation = None;
624 apply_placement(&self.layer, self.anchor, self.margins);
625 return if destroy_on_complete {
626 SurfaceAnimationStart::Destroy
627 } else {
628 SurfaceAnimationStart::Complete
629 };
630 }
631
632 self.animation = Some(SurfaceAnimation {
633 animation,
634 started_at: None,
635 target: SurfaceAnimationTarget::Margins {
636 from: self.margins,
637 to,
638 },
639 destroy_on_complete,
640 });
641 SurfaceAnimationStart::Animate
642 }
643
644 fn start_size_animation(
645 &mut self,
646 width: u32,
647 height: u32,
648 animation: Animation,
649 destroy_on_complete: bool,
650 ) -> SurfaceAnimationStart {
651 if animation.duration_ms == 0 {
652 self.set_size(width, height);
653 self.animation = None;
654 return if destroy_on_complete {
655 SurfaceAnimationStart::Destroy
656 } else {
657 SurfaceAnimationStart::Complete
658 };
659 }
660
661 self.animation = Some(SurfaceAnimation {
662 animation,
663 started_at: None,
664 target: SurfaceAnimationTarget::Size {
665 from_width: self.width,
666 from_height: self.height,
667 to_width: width,
668 to_height: height,
669 },
670 destroy_on_complete,
671 });
672 SurfaceAnimationStart::Animate
673 }
674
675 fn cancel_animation(&mut self) {
676 self.animation = None;
677 }
678
679 fn advance_animation(&mut self, time: u32) -> SurfaceAnimationFrame {
680 let Some(mut animation) = self.animation.take() else {
681 return SurfaceAnimationFrame::Idle;
682 };
683
684 let started_at = *animation.started_at.get_or_insert(time);
685 let frame = animation.animation.frame(time.saturating_sub(started_at));
686 match animation.target {
687 SurfaceAnimationTarget::Margins { from, to } => {
688 self.margins = from.lerp(to, frame.progress);
689 apply_placement(&self.layer, self.anchor, self.margins);
690 }
691 SurfaceAnimationTarget::Size {
692 from_width,
693 from_height,
694 to_width,
695 to_height,
696 } => {
697 self.set_size(
698 lerp_u32(from_width, to_width, frame.progress),
699 lerp_u32(from_height, to_height, frame.progress),
700 );
701 }
702 }
703
704 if frame.complete {
705 if animation.destroy_on_complete {
706 SurfaceAnimationFrame::Destroy
707 } else {
708 SurfaceAnimationFrame::Complete
709 }
710 } else {
711 self.animation = Some(animation);
712 SurfaceAnimationFrame::Animate
713 }
714 }
715
716 fn draw<R>(
717 &mut self,
718 shm: &Shm,
719 renderer: &mut R,
720 id: SurfaceId,
721 frame_time: Option<u32>,
722 ) -> DrawResult
723 where
724 R: Renderer,
725 {
726 let dimensions = BufferDimensions::new(self.width, self.height, self.scale);
727 let (frame, action, damage) = self.draw_frame(shm, renderer, id, frame_time, dimensions);
728
729 if let Some(damage) = damage {
730 self.layer.wl_surface().damage_buffer(
731 damage.x as i32,
732 damage.y as i32,
733 damage.width as i32,
734 damage.height as i32,
735 );
736 }
737 let _ = self.layer.set_buffer_scale(self.scale);
738 frame.attach_to(self.layer.wl_surface());
739 self.layer.commit();
740
741 let retired_frame = self.frame.replace(frame);
742
743 match action {
744 FrameAction::Wait => DrawResult::Drawn {
745 retired_frame,
746 next_frame: false,
747 },
748 FrameAction::Animate => DrawResult::Drawn {
749 retired_frame,
750 next_frame: true,
751 },
752 FrameAction::Exit => DrawResult::Exit { retired_frame },
753 }
754 }
755
756 fn draw_frame<R>(
757 &mut self,
758 shm: &Shm,
759 renderer: &mut R,
760 id: SurfaceId,
761 frame_time: Option<u32>,
762 dimensions: BufferDimensions,
763 ) -> (Frame, FrameAction, Option<DamageRect>)
764 where
765 R: Renderer,
766 {
767 let mut pool = SlotPool::new(dimensions.bytes, shm).expect("allocate buffer pool");
768 let (buffer, pixels) = pool
769 .create_buffer(
770 dimensions.width as i32,
771 dimensions.height as i32,
772 dimensions.stride as i32,
773 wl_shm::Format::Argb8888,
774 )
775 .expect("allocate buffer");
776 let (action, damage) = draw_surface_to_pixels(renderer, id, pixels, dimensions, frame_time);
777
778 (
779 Frame {
780 buffer,
781 _pool: pool,
782 },
783 action,
784 damage,
785 )
786 }
787
788 fn request_frame<R: Renderer>(&mut self, qh: &QueueHandle<State<R>>) {
789 if self.frame_pending {
790 return;
791 }
792
793 let surface = self.layer.wl_surface();
794 surface.frame(qh, surface.clone());
795 self.frame_pending = true;
796 self.layer.commit();
797 }
798
799 fn take_frame(&mut self) -> Option<Frame> {
800 self.frame.take()
801 }
802
803 fn state(&self, id: SurfaceId) -> RenderSurfaceState {
804 RenderSurfaceState {
805 id,
806 configured: self.configured,
807 width: self.width,
808 height: self.height,
809 output: self.output.clone(),
810 layer: self.layer_kind,
811 anchor: self.anchor,
812 margins: self.margins,
813 scale: self.scale,
814 animating: self.animation.is_some(),
815 frame_pending: self.frame_pending,
816 }
817 }
818}
819
820#[derive(Clone, Copy)]
821pub(in crate::wayland) struct BufferDimensions {
822 pub(in crate::wayland) logical_width: u32,
823 pub(in crate::wayland) logical_height: u32,
824 pub(in crate::wayland) width: u32,
825 pub(in crate::wayland) height: u32,
826 pub(in crate::wayland) scale: u32,
827 pub(in crate::wayland) stride: u32,
828 pub(in crate::wayland) bytes: usize,
829}
830
831impl BufferDimensions {
832 pub(in crate::wayland) fn new(logical_width: u32, logical_height: u32, scale: u32) -> Self {
833 let scale = scale.max(1);
834 let width = logical_width
835 .checked_mul(scale)
836 .expect("scaled buffer width overflow");
837 let height = logical_height
838 .checked_mul(scale)
839 .expect("scaled buffer height overflow");
840 let stride = width.checked_mul(4).expect("buffer stride overflow");
841 let bytes = (stride as usize)
842 .checked_mul(height as usize)
843 .expect("buffer size overflow");
844 Self {
845 logical_width,
846 logical_height,
847 width,
848 height,
849 scale,
850 stride,
851 bytes,
852 }
853 }
854}
855
856fn draw_surface_to_pixels<R>(
857 renderer: &mut R,
858 id: SurfaceId,
859 pixels: &mut [u8],
860 dimensions: BufferDimensions,
861 frame_time: Option<u32>,
862) -> (FrameAction, Option<DamageRect>)
863where
864 R: Renderer,
865{
866 let mut canvas = Canvas {
867 pixels,
868 width: dimensions.width,
869 height: dimensions.height,
870 stride: dimensions.stride,
871 scale: dimensions.scale,
872 damage: None,
873 };
874 let action = renderer.draw_surface(
875 id,
876 &mut canvas,
877 RenderContext {
878 width: dimensions.logical_width,
879 height: dimensions.logical_height,
880 scale: dimensions.scale,
881 buffer_width: dimensions.width,
882 buffer_height: dimensions.height,
883 frame_time,
884 },
885 );
886 let damage = canvas.damage();
887 (action, damage)
888}
889
890enum DrawResult {
891 Drawn {
892 retired_frame: Option<Frame>,
893 next_frame: bool,
894 },
895 Exit {
896 retired_frame: Option<Frame>,
897 },
898}
899
900struct Frame {
901 buffer: Buffer,
902 _pool: SlotPool,
903}
904
905impl Frame {
906 fn attach_to(&self, surface: &wl_surface::WlSurface) {
907 self.buffer.attach_to(surface).expect("attach buffer");
908 }
909
910 fn released(&self) -> bool {
911 !self.buffer.slot().has_active_buffers()
912 }
913}