gioser

tawasuyu/mirada

Sovereign tiling Wayland compositor + window manager in Rust, on Llimphi.

Rust 50Markdown 30TOML 211282 Definiciones

⎇ main vendor/smithay/src/backend/renderer/utils/mod.rs Rust · 546 líneas · 15.9 KB Historia Quién tocó qué crudo

chore: refresco desde el monorepo (pin tawasuyu.git v0.2.0) a91da3fea · Sergio ·

1//! Utility module for helpers around drawing [`WlSurface`](wayland_server::protocol::wl_surface::WlSurface)s
2//! and [`RenderElement`](super::element::RenderElement)s with [`Renderer`](super::Renderer)s.
3
4use crate::utils::{Buffer as BufferCoord, Coordinate, Logical, Physical, Point, Rectangle, Size};
5use std::{collections::VecDeque, fmt, sync::Arc};
6
7#[cfg(feature = "wayland_frontend")]
8mod wayland;
9#[cfg(feature = "wayland_frontend")]
10pub use self::wayland::*;
11
12/// A simple wrapper for counting commits
13///
14/// The purpose of the counter is to keep track
15/// on the number of times something has changed.
16/// It provides an easy way to obtain the distance
17/// between two instances of a [`CommitCounter`].
18#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)]
19pub struct CommitCounter(usize);
20
21impl CommitCounter {
22    /// Increment the commit counter
23    pub fn increment(&mut self) {
24        self.0 = self.0.wrapping_add(1)
25    }
26
27    /// Get the distance between two [`CommitCounter`]s
28    ///
29    /// If the [`CommitCounter`] is incremented on each recorded
30    /// damage this returns the count of damage that happened
31    /// between the [`CommitCounter`]s
32    ///
33    /// Returns `None` in case the distance could not be calculated.
34    /// If uses as part of damage tracking the tracked element
35    /// should be considered as fully damaged.
36    pub fn distance(&self, previous_commit: Option<CommitCounter>) -> Option<usize> {
37        // if commit > commit_count we have overflown, in that case the following map might result
38        // in a false-positive, if commit is still very large. So we force false in those cases.
39        // That will result in a potentially sub-optimal full damage every usize::MAX frames,
40        // which is acceptable.
41        previous_commit
42            .filter(|commit| commit <= self)
43            .map(|commit| self.0.wrapping_sub(commit.0))
44    }
45}
46
47impl From<usize> for CommitCounter {
48    #[inline]
49    fn from(counter: usize) -> Self {
50        CommitCounter(counter)
51    }
52}
53
54/// A tracker for holding damage
55///
56/// It keeps track of the submitted damage
57/// and automatically caps the damage
58/// with the specified limit.
59///
60/// See [`DamageSnapshot`] for more
61/// information.
62pub struct DamageBag<N, Kind> {
63    limit: usize,
64    state: DamageSnapshot<N, Kind>,
65}
66
67/// A snapshot of the current state of a [`DamageBag`]
68///
69/// The snapshot can be used to get an immutable view
70/// into the current state of a [`DamageBag`].
71/// It provides an easy way to get the damage between two
72/// [`CommitCounter`]s.
73pub struct DamageSnapshot<N, Kind> {
74    limit: usize,
75    commit_counter: CommitCounter,
76    damage: Arc<VecDeque<smallvec::SmallVec<[Rectangle<N, Kind>; MAX_DAMAGE_RECTS]>>>,
77}
78
79impl<N, Kind> Clone for DamageSnapshot<N, Kind> {
80    #[inline]
81    fn clone(&self) -> Self {
82        Self {
83            limit: self.limit,
84            commit_counter: self.commit_counter,
85            damage: self.damage.clone(),
86        }
87    }
88}
89
90impl<N: fmt::Debug> fmt::Debug for DamageBag<N, BufferCoord> {
91    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
92        f.debug_struct("DamageBag")
93            .field("limit", &self.limit)
94            .field("state", &self.state)
95            .finish()
96    }
97}
98
99impl<N: fmt::Debug> fmt::Debug for DamageBag<N, Physical> {
100    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101        f.debug_struct("DamageBag")
102            .field("limit", &self.limit)
103            .field("state", &self.state)
104            .finish()
105    }
106}
107
108impl<N: fmt::Debug> fmt::Debug for DamageBag<N, Logical> {
109    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
110        f.debug_struct("DamageBag")
111            .field("limit", &self.limit)
112            .field("state", &self.state)
113            .finish()
114    }
115}
116
117impl<N: fmt::Debug> fmt::Debug for DamageSnapshot<N, BufferCoord> {
118    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
119        f.debug_struct("DamageSnapshot")
120            .field("commit_counter", &self.commit_counter)
121            .field("damage", &self.damage)
122            .finish()
123    }
124}
125
126impl<N: fmt::Debug> fmt::Debug for DamageSnapshot<N, Physical> {
127    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
128        f.debug_struct("DamageSnapshot")
129            .field("commit_counter", &self.commit_counter)
130            .field("damage", &self.damage)
131            .finish()
132    }
133}
134
135impl<N: fmt::Debug> fmt::Debug for DamageSnapshot<N, Logical> {
136    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
137        f.debug_struct("DamageSnapshot")
138            .field("commit_counter", &self.commit_counter)
139            .field("damage", &self.damage)
140            .finish()
141    }
142}
143
144const MAX_DAMAGE_AGE: usize = 4;
145const MAX_DAMAGE_RECTS: usize = 16;
146const MAX_DAMAGE_SET: usize = MAX_DAMAGE_RECTS * 2;
147
148impl<N: Clone, Kind> Default for DamageBag<N, Kind> {
149    #[inline]
150    fn default() -> Self {
151        DamageBag::new(MAX_DAMAGE_AGE)
152    }
153}
154
155impl<N: Clone, Kind> DamageSnapshot<N, Kind> {
156    fn new(limit: usize) -> Self {
157        DamageSnapshot {
158            limit,
159            commit_counter: CommitCounter::default(),
160            damage: Arc::new(VecDeque::with_capacity(limit)),
161        }
162    }
163
164    /// Create an empty damage snapshot
165    pub fn empty() -> Self {
166        DamageSnapshot {
167            limit: 0,
168            commit_counter: CommitCounter::default(),
169            damage: Default::default(),
170        }
171    }
172
173    /// Gets the current [`CommitCounter`] of this snapshot
174    ///
175    /// The returned [`CommitCounter`] should be stored after
176    /// calling [`damage_since`](DamageSnapshot::damage_since)
177    /// and provided to the next call of [`damage_since`](DamageSnapshot::damage_since)
178    /// to query the damage between these two [`CommitCounter`]s.
179    #[inline]
180    pub fn current_commit(&self) -> CommitCounter {
181        self.commit_counter
182    }
183
184    /// Provides raw access to the stored damage
185    pub fn raw(&self) -> impl Iterator<Item = impl Iterator<Item = &Rectangle<N, Kind>>> {
186        self.damage.iter().map(|d| d.iter())
187    }
188
189    fn reset(&mut self) {
190        Arc::make_mut(&mut self.damage).clear();
191        self.commit_counter.increment();
192    }
193}
194
195impl<N: Coordinate, Kind> DamageSnapshot<N, Kind> {
196    /// Get the damage since the last commit
197    ///
198    /// Returns `None` in case the [`CommitCounter`] is too old
199    /// or the damage has been reset. In that case the whole
200    /// element geometry should be considered as damaged
201    ///
202    /// If the commit is recent enough and no damage has occurred
203    /// an empty `Vec` will be returned
204    pub fn damage_since(&self, commit: Option<CommitCounter>) -> Option<DamageSet<N, Kind>> {
205        let distance = self.commit_counter.distance(commit);
206
207        if distance
208            .map(|distance| distance <= self.damage.len())
209            .unwrap_or(false)
210        {
211            let mut damage_set = DamageSet::default();
212            for damage in self.damage.iter().take(distance.unwrap()) {
213                damage_set.damage.extend_from_slice(damage);
214            }
215            Some(damage_set)
216        } else {
217            None
218        }
219    }
220
221    fn add(&mut self, damage: impl IntoIterator<Item = Rectangle<N, Kind>>) {
222        // FIXME: Get rid of this allocation here
223        let mut damage = damage.into_iter().filter(|d| !d.is_empty()).collect::<Vec<_>>();
224
225        if damage.is_empty() {
226            // do not track empty damage
227            return;
228        }
229
230        damage.dedup();
231
232        let inner_damage = Arc::make_mut(&mut self.damage);
233        inner_damage.push_front(smallvec::SmallVec::from_vec(damage));
234        inner_damage.truncate(self.limit);
235
236        self.commit_counter.increment();
237    }
238}
239
240impl<N: Clone, Kind> DamageBag<N, Kind> {
241    /// Initialize a a new [`DamageBag`] with the specified limit
242    pub fn new(limit: usize) -> Self {
243        DamageBag {
244            limit,
245            state: DamageSnapshot::new(limit),
246        }
247    }
248
249    /// Gets the current [`CommitCounter`] of this tracker
250    #[inline]
251    pub fn current_commit(&self) -> CommitCounter {
252        self.state.current_commit()
253    }
254
255    /// Provides raw access to the stored damage
256    pub fn raw(&self) -> impl Iterator<Item = impl Iterator<Item = &Rectangle<N, Kind>>> {
257        self.state.raw()
258    }
259
260    /// Reset the damage
261    ///
262    /// This should be called when the
263    /// tracked item has been resized
264    pub fn reset(&mut self) {
265        self.state.reset()
266    }
267}
268
269impl<N, Kind> DamageBag<N, Kind> {
270    /// Get a snapshot of the current damage
271    pub fn snapshot(&self) -> DamageSnapshot<N, Kind> {
272        self.state.clone()
273    }
274}
275
276impl<N: Coordinate, Kind> DamageBag<N, Kind> {
277    /// Add some damage to the tracker
278    pub fn add(&mut self, damage: impl IntoIterator<Item = Rectangle<N, Kind>>) {
279        self.state.add(damage)
280    }
281
282    /// Get the damage since the last commit
283    ///
284    /// Returns `None` in case the [`CommitCounter`] is too old
285    /// or the damage has been reset. In that case the whole
286    /// element geometry should be considered as damaged
287    ///
288    /// If the commit is recent enough and no damage has occurred
289    /// an empty `Vec` will be returned
290    pub fn damage_since(&self, commit: Option<CommitCounter>) -> Option<DamageSet<N, Kind>> {
291        self.state.damage_since(commit)
292    }
293}
294
295/// A set of damage returned from [`DamageBag::damage_since`] of [`DamageSnapshot::damage_since`]
296pub struct DamageSet<N, Kind> {
297    damage: smallvec::SmallVec<[Rectangle<N, Kind>; MAX_DAMAGE_SET]>,
298}
299
300impl<N, Kind> Default for DamageSet<N, Kind> {
301    fn default() -> Self {
302        Self {
303            damage: Default::default(),
304        }
305    }
306}
307
308impl<N: Copy, Kind> DamageSet<N, Kind> {
309    /// Copy the damage from a slice into a new `DamageSet`.
310    #[inline]
311    pub fn from_slice(slice: &[Rectangle<N, Kind>]) -> Self {
312        Self {
313            damage: smallvec::SmallVec::from_slice(slice),
314        }
315    }
316}
317
318impl<N, Kind> std::ops::Deref for DamageSet<N, Kind> {
319    type Target = [Rectangle<N, Kind>];
320
321    #[inline]
322    fn deref(&self) -> &Self::Target {
323        &self.damage
324    }
325}
326
327impl<N, Kind> IntoIterator for DamageSet<N, Kind> {
328    type Item = Rectangle<N, Kind>;
329
330    type IntoIter = DamageSetIter<N, Kind>;
331
332    #[inline]
333    fn into_iter(self) -> Self::IntoIter {
334        DamageSetIter {
335            inner: self.damage.into_iter(),
336        }
337    }
338}
339
340impl<N, Kind> FromIterator<Rectangle<N, Kind>> for DamageSet<N, Kind> {
341    #[inline]
342    fn from_iter<T: IntoIterator<Item = Rectangle<N, Kind>>>(iter: T) -> Self {
343        Self {
344            damage: smallvec::SmallVec::from_iter(iter),
345        }
346    }
347}
348
349/// Iterator for [`DamageSet::into_iter`]
350pub struct DamageSetIter<N, Kind> {
351    inner: smallvec::IntoIter<[Rectangle<N, Kind>; MAX_DAMAGE_SET]>,
352}
353
354impl<N: fmt::Debug> fmt::Debug for DamageSetIter<N, BufferCoord> {
355    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
356        f.debug_struct("DamageSetIter")
357            .field("inner", &self.inner)
358            .finish()
359    }
360}
361
362impl<N: fmt::Debug> fmt::Debug for DamageSetIter<N, Physical> {
363    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
364        f.debug_struct("DamageSetIter")
365            .field("inner", &self.inner)
366            .finish()
367    }
368}
369
370impl<N: fmt::Debug> fmt::Debug for DamageSetIter<N, Logical> {
371    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
372        f.debug_struct("DamageSetIter")
373            .field("inner", &self.inner)
374            .finish()
375    }
376}
377
378impl<N, Kind> Iterator for DamageSetIter<N, Kind> {
379    type Item = Rectangle<N, Kind>;
380
381    #[inline]
382    fn next(&mut self) -> Option<Self::Item> {
383        self.inner.next()
384    }
385
386    #[inline]
387    fn size_hint(&self) -> (usize, Option<usize>) {
388        self.inner.size_hint()
389    }
390}
391
392impl<N: fmt::Debug> fmt::Debug for DamageSet<N, BufferCoord> {
393    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
394        f.debug_struct("DamageSet").field("damage", &self.damage).finish()
395    }
396}
397
398impl<N: fmt::Debug> fmt::Debug for DamageSet<N, Physical> {
399    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
400        f.debug_struct("DamageSet").field("damage", &self.damage).finish()
401    }
402}
403
404impl<N: fmt::Debug> fmt::Debug for DamageSet<N, Logical> {
405    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
406        f.debug_struct("DamageSet").field("damage", &self.damage).finish()
407    }
408}
409
410const MAX_OPAQUE_REGIONS: usize = 16;
411
412/// Wrapper for a set of opaque regions
413pub struct OpaqueRegions<N, Kind> {
414    regions: smallvec::SmallVec<[Rectangle<N, Kind>; MAX_OPAQUE_REGIONS]>,
415}
416
417impl<N, Kind> Default for OpaqueRegions<N, Kind>
418where
419    N: Default,
420{
421    #[inline]
422    fn default() -> Self {
423        Self {
424            regions: Default::default(),
425        }
426    }
427}
428
429impl<N: Copy, Kind> OpaqueRegions<N, Kind> {
430    /// Copy the opaque regions from a slice into a new `OpaqueRegions`.
431    #[inline]
432    pub fn from_slice(slice: &[Rectangle<N, Kind>]) -> Self {
433        Self {
434            regions: smallvec::SmallVec::from_slice(slice),
435        }
436    }
437}
438
439impl<N, Kind> std::ops::Deref for OpaqueRegions<N, Kind> {
440    type Target = [Rectangle<N, Kind>];
441
442    #[inline]
443    fn deref(&self) -> &Self::Target {
444        &self.regions
445    }
446}
447
448impl<N, Kind> IntoIterator for OpaqueRegions<N, Kind> {
449    type Item = Rectangle<N, Kind>;
450
451    type IntoIter = OpaqueRegionsIter<N, Kind>;
452
453    #[inline]
454    fn into_iter(self) -> Self::IntoIter {
455        OpaqueRegionsIter {
456            inner: self.regions.into_iter(),
457        }
458    }
459}
460
461impl<N, Kind> FromIterator<Rectangle<N, Kind>> for OpaqueRegions<N, Kind> {
462    #[inline]
463    fn from_iter<T: IntoIterator<Item = Rectangle<N, Kind>>>(iter: T) -> Self {
464        Self {
465            regions: smallvec::SmallVec::from_iter(iter),
466        }
467    }
468}
469
470/// Iterator for [`OpaqueRegions::into_iter`]
471pub struct OpaqueRegionsIter<N, Kind> {
472    inner: smallvec::IntoIter<[Rectangle<N, Kind>; MAX_OPAQUE_REGIONS]>,
473}
474
475impl<N: fmt::Debug> fmt::Debug for OpaqueRegionsIter<N, BufferCoord> {
476    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
477        f.debug_struct("OpaqueRegionsIter")
478            .field("inner", &self.inner)
479            .finish()
480    }
481}
482
483impl<N: fmt::Debug> fmt::Debug for OpaqueRegionsIter<N, Physical> {
484    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
485        f.debug_struct("OpaqueRegionsIter")
486            .field("inner", &self.inner)
487            .finish()
488    }
489}
490
491impl<N: fmt::Debug> fmt::Debug for OpaqueRegionsIter<N, Logical> {
492    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
493        f.debug_struct("OpaqueRegionsIter")
494            .field("inner", &self.inner)
495            .finish()
496    }
497}
498
499impl<N, Kind> Iterator for OpaqueRegionsIter<N, Kind> {
500    type Item = Rectangle<N, Kind>;
501
502    #[inline]
503    fn next(&mut self) -> Option<Self::Item> {
504        self.inner.next()
505    }
506
507    #[inline]
508    fn size_hint(&self) -> (usize, Option<usize>) {
509        self.inner.size_hint()
510    }
511}
512
513impl<N: fmt::Debug> fmt::Debug for OpaqueRegions<N, BufferCoord> {
514    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
515        f.debug_struct("OpaqueRegions")
516            .field("regions", &self.regions)
517            .finish()
518    }
519}
520
521impl<N: fmt::Debug> fmt::Debug for OpaqueRegions<N, Physical> {
522    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
523        f.debug_struct("OpaqueRegions")
524            .field("regions", &self.regions)
525            .finish()
526    }
527}
528
529impl<N: fmt::Debug> fmt::Debug for OpaqueRegions<N, Logical> {
530    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
531        f.debug_struct("OpaqueRegions")
532            .field("regions", &self.regions)
533            .finish()
534    }
535}
536
537/// Defines a view into the surface
538#[derive(Debug, Default, PartialEq, Clone, Copy)]
539pub struct SurfaceView {
540    /// The logical source used for cropping
541    pub src: Rectangle<f64, Logical>,
542    /// The logical destination size used for scaling
543    pub dst: Size<i32, Logical>,
544    /// The logical offset for a sub-surface
545    pub offset: Point<i32, Logical>,
546}