@@ -261,21 +261,10 @@ impl<'window> Surface<'window> {
261261 . unwrap_or_else ( || * capabilities. formats . first ( ) . unwrap ( ) ) ;
262262
263263 let requested_present_mode = present_mode. to_wgpu ( ) ;
264- config. present_mode = if capabilities
265- . present_modes
266- . contains ( & requested_present_mode)
267- {
268- requested_present_mode
269- } else {
270- capabilities
271- . present_modes
272- . iter ( )
273- . copied ( )
274- . find ( |mode| {
275- matches ! ( mode, wgpu:: PresentMode :: Fifo | wgpu:: PresentMode :: AutoVsync )
276- } )
277- . unwrap_or ( wgpu:: PresentMode :: Fifo )
278- } ;
264+ config. present_mode = select_present_mode (
265+ requested_present_mode,
266+ capabilities. present_modes . as_slice ( ) ,
267+ ) ;
279268
280269 if capabilities. usages . contains ( usage. to_wgpu ( ) ) {
281270 config. usage = usage. to_wgpu ( ) ;
@@ -321,6 +310,54 @@ impl<'window> Surface<'window> {
321310 }
322311}
323312
313+ fn select_present_mode (
314+ requested : wgpu:: PresentMode ,
315+ available : & [ wgpu:: PresentMode ] ,
316+ ) -> wgpu:: PresentMode {
317+ if available. contains ( & requested) {
318+ return requested;
319+ }
320+
321+ let candidates: & [ wgpu:: PresentMode ] = match requested {
322+ wgpu:: PresentMode :: Immediate | wgpu:: PresentMode :: AutoNoVsync => & [
323+ wgpu:: PresentMode :: Immediate ,
324+ wgpu:: PresentMode :: Mailbox ,
325+ wgpu:: PresentMode :: AutoNoVsync ,
326+ wgpu:: PresentMode :: Fifo ,
327+ wgpu:: PresentMode :: AutoVsync ,
328+ ] ,
329+ wgpu:: PresentMode :: Mailbox => & [
330+ wgpu:: PresentMode :: Mailbox ,
331+ wgpu:: PresentMode :: Fifo ,
332+ wgpu:: PresentMode :: AutoVsync ,
333+ ] ,
334+ wgpu:: PresentMode :: FifoRelaxed => & [
335+ wgpu:: PresentMode :: FifoRelaxed ,
336+ wgpu:: PresentMode :: Fifo ,
337+ wgpu:: PresentMode :: AutoVsync ,
338+ ] ,
339+ wgpu:: PresentMode :: Fifo | wgpu:: PresentMode :: AutoVsync => & [
340+ wgpu:: PresentMode :: Fifo ,
341+ wgpu:: PresentMode :: AutoVsync ,
342+ wgpu:: PresentMode :: FifoRelaxed ,
343+ wgpu:: PresentMode :: Mailbox ,
344+ wgpu:: PresentMode :: Immediate ,
345+ wgpu:: PresentMode :: AutoNoVsync ,
346+ ] ,
347+ } ;
348+
349+ for candidate in candidates {
350+ if available. contains ( candidate) {
351+ return * candidate;
352+ }
353+ }
354+
355+ return available
356+ . first ( )
357+ . copied ( )
358+ . unwrap_or ( wgpu:: PresentMode :: Fifo ) ;
359+ }
360+
324361/// A single acquired frame and its default `TextureView`.
325362#[ derive( Debug ) ]
326363pub struct Frame {
@@ -345,3 +382,36 @@ impl Frame {
345382 self . texture . present ( ) ;
346383 }
347384}
385+
386+ #[ cfg( test) ]
387+ mod tests {
388+ use super :: * ;
389+
390+ #[ test]
391+ fn select_present_mode_prefers_requested ( ) {
392+ let available = & [ wgpu:: PresentMode :: Fifo , wgpu:: PresentMode :: Immediate ] ;
393+ let selected = select_present_mode ( wgpu:: PresentMode :: Immediate , available) ;
394+ assert_eq ! ( selected, wgpu:: PresentMode :: Immediate ) ;
395+ }
396+
397+ #[ test]
398+ fn select_present_mode_falls_back_from_immediate_to_mailbox ( ) {
399+ let available = & [ wgpu:: PresentMode :: Fifo , wgpu:: PresentMode :: Mailbox ] ;
400+ let selected = select_present_mode ( wgpu:: PresentMode :: Immediate , available) ;
401+ assert_eq ! ( selected, wgpu:: PresentMode :: Mailbox ) ;
402+ }
403+
404+ #[ test]
405+ fn select_present_mode_falls_back_from_mailbox_to_fifo ( ) {
406+ let available = & [ wgpu:: PresentMode :: Fifo , wgpu:: PresentMode :: Immediate ] ;
407+ let selected = select_present_mode ( wgpu:: PresentMode :: Mailbox , available) ;
408+ assert_eq ! ( selected, wgpu:: PresentMode :: Fifo ) ;
409+ }
410+
411+ #[ test]
412+ fn select_present_mode_uses_auto_no_vsync_when_available ( ) {
413+ let available = & [ wgpu:: PresentMode :: AutoNoVsync , wgpu:: PresentMode :: Fifo ] ;
414+ let selected = select_present_mode ( wgpu:: PresentMode :: Immediate , available) ;
415+ assert_eq ! ( selected, wgpu:: PresentMode :: AutoNoVsync ) ;
416+ }
417+ }
0 commit comments