Skip to main content

simple_render/wayland/
runtime.rs

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}