1use crate::resources::RawImageFormat;
17
18#[repr(C, u8)]
20#[derive(Debug, Clone, Copy, PartialEq, Eq)]
21#[derive(Default)]
22pub enum ScreenCaptureSource {
23 #[default]
25 PrimaryDisplay,
26 Display(u32),
28 Window(u64),
30}
31
32
33#[repr(C)]
36#[derive(Debug, Clone, Copy, PartialEq, Eq)]
37pub struct ScreenCaptureConfig {
38 pub source: ScreenCaptureSource,
40 pub fps: u32,
42 pub output_format: RawImageFormat,
46}
47
48impl Default for ScreenCaptureConfig {
49 fn default() -> Self {
50 Self {
51 source: ScreenCaptureSource::PrimaryDisplay,
52 fps: 0,
53 output_format: RawImageFormat::BGRA8,
54 }
55 }
56}
57
58impl ScreenCaptureConfig {
59 #[must_use] pub fn new(source: ScreenCaptureSource) -> Self {
61 Self {
62 source,
63 ..Self::default()
64 }
65 }
66}
67
68#[cfg(test)]
69mod autotest_generated {
70 use core::mem::size_of;
71
72 use super::*;
73
74 const ALL_SOURCES: [ScreenCaptureSource; 7] = [
77 ScreenCaptureSource::PrimaryDisplay,
78 ScreenCaptureSource::Display(0),
79 ScreenCaptureSource::Display(1),
80 ScreenCaptureSource::Display(u32::MAX),
81 ScreenCaptureSource::Window(0),
82 ScreenCaptureSource::Window(1),
83 ScreenCaptureSource::Window(u64::MAX),
84 ];
85
86 #[test]
89 fn new_does_not_panic_for_representative_or_extreme_sources() {
90 for &source in &ALL_SOURCES {
91 let _ = ScreenCaptureConfig::new(source);
92 }
93 }
94
95 #[test]
96 fn new_is_deterministic() {
97 for &source in &ALL_SOURCES {
100 assert_eq!(
101 ScreenCaptureConfig::new(source),
102 ScreenCaptureConfig::new(source)
103 );
104 }
105 }
106
107 #[test]
110 fn new_sets_source_and_leaves_everything_else_at_default() {
111 let def = ScreenCaptureConfig::default();
115 for &source in &ALL_SOURCES {
116 let cfg = ScreenCaptureConfig::new(source);
117 assert_eq!(cfg.source, source, "source must equal the argument");
118 assert_eq!(cfg.fps, def.fps);
119 assert_eq!(cfg.output_format, def.output_format);
120 assert_eq!(cfg.fps, 0, "0 => backend picks the frame rate");
122 assert_eq!(
123 cfg.output_format,
124 RawImageFormat::BGRA8,
125 "BGRA8 is the documented portable default"
126 );
127 }
128 }
129
130 #[test]
131 fn new_equals_struct_update_syntax() {
132 for &source in &ALL_SOURCES {
133 let via_new = ScreenCaptureConfig::new(source);
134 let via_update = ScreenCaptureConfig {
135 source,
136 ..ScreenCaptureConfig::default()
137 };
138 assert_eq!(via_new, via_update);
139 }
140 }
141
142 #[test]
143 fn default_config_is_new_of_default_source() {
144 assert_eq!(
147 ScreenCaptureConfig::default(),
148 ScreenCaptureConfig::new(ScreenCaptureSource::default())
149 );
150 assert_eq!(
151 ScreenCaptureSource::default(),
152 ScreenCaptureSource::PrimaryDisplay
153 );
154 assert_eq!(
155 ScreenCaptureConfig::default().source,
156 ScreenCaptureSource::PrimaryDisplay
157 );
158 }
159
160 #[test]
163 fn new_preserves_full_payload_width() {
164 let cfg = ScreenCaptureConfig::new(ScreenCaptureSource::Window(u64::MAX));
167 match cfg.source {
168 ScreenCaptureSource::Window(h) => assert_eq!(h, u64::MAX),
169 other => panic!("expected Window(u64::MAX), got {other:?}"),
170 }
171
172 let cfg = ScreenCaptureConfig::new(ScreenCaptureSource::Display(u32::MAX));
173 match cfg.source {
174 ScreenCaptureSource::Display(i) => assert_eq!(i, u32::MAX),
175 other => panic!("expected Display(u32::MAX), got {other:?}"),
176 }
177
178 assert!(size_of::<ScreenCaptureSource>() >= size_of::<u64>());
180 }
181
182 #[test]
183 fn distinct_sources_stay_distinct() {
184 assert_ne!(
186 ScreenCaptureSource::Display(1),
187 ScreenCaptureSource::Window(1)
188 );
189 assert_ne!(
191 ScreenCaptureSource::PrimaryDisplay,
192 ScreenCaptureSource::Display(0)
193 );
194 assert_ne!(
195 ScreenCaptureConfig::new(ScreenCaptureSource::PrimaryDisplay),
196 ScreenCaptureConfig::new(ScreenCaptureSource::Display(0))
197 );
198
199 for (i, a) in ALL_SOURCES.iter().enumerate() {
201 for (j, b) in ALL_SOURCES.iter().enumerate() {
202 let cfg_a = ScreenCaptureConfig::new(*a);
203 let cfg_b = ScreenCaptureConfig::new(*b);
204 if i == j {
205 assert_eq!(cfg_a, cfg_b, "Eq must be reflexive for {a:?}");
206 } else {
207 assert_ne!(cfg_a, cfg_b, "{a:?} and {b:?} must not compare equal");
208 }
209 }
210 }
211 }
212
213 #[test]
214 fn config_is_copy_and_fields_are_independently_settable() {
215 let original = ScreenCaptureConfig::new(ScreenCaptureSource::Window(u64::MAX));
219 let mut copy = original;
220 copy.fps = u32::MAX;
221 copy.output_format = RawImageFormat::RGBAF32;
222
223 assert_eq!(original.fps, 0, "original must be untouched (Copy)");
224 assert_eq!(original.output_format, RawImageFormat::BGRA8);
225 assert_eq!(copy.source, original.source, "source must survive the writes");
226 assert_eq!(copy.fps, u32::MAX);
227 assert_eq!(copy.output_format, RawImageFormat::RGBAF32);
228 }
229}