1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
use std::{mem, ptr};

use crate::*;

pub struct FrameStream<G: Graphics> {
    session: Session<G>,
    state: State,
}

impl<G: Graphics> FrameStream<G> {
    pub(crate) fn new(session: Session<G>) -> Self {
        Self {
            session,
            state: State::End,
        }
    }

    /// Block until rendering should begin
    #[inline]
    pub fn wait(&mut self) -> Result<FrameState> {
        assert_eq!(self.state, State::End, "wait must be called after end");
        let mut out = sys::FrameState {
            ty: sys::FrameState::TYPE,
            next: ptr::null_mut(),
            ..unsafe { mem::uninitialized() }
        };
        unsafe {
            cvt((self.fp().wait_frame)(
                self.session.as_raw(),
                builder::FrameWaitInfo::new().as_raw(),
                &mut out,
            ))?;
        }
        self.state = State::Wait;
        Ok(FrameState {
            predicted_display_time: out.predicted_display_time,
            predicted_display_period: out.predicted_display_period,
        })
    }

    /// Indicate that graphics device work is beginning
    #[inline]
    pub fn begin(&mut self) -> Result<sys::Result> {
        assert_eq!(self.state, State::Wait, "begin must be called after wait");
        let x = unsafe {
            cvt((self.fp().begin_frame)(
                self.session.as_raw(),
                builder::FrameBeginInfo::new().as_raw(),
            ))?
        };
        self.state = State::Begin;
        Ok(x)
    }

    /// Indicate that all graphics work for the frame has been submitted
    #[inline]
    pub fn end(
        &mut self,
        display_time: Time,
        environment_blend_mode: EnvironmentBlendMode,
        layers: &[&CompositionLayerBase<'_, G>],
    ) -> Result<()> {
        assert!(layers.len() <= u32::max_value() as usize);
        assert_eq!(self.state, State::Begin, "end must be called after begin");
        let info = sys::FrameEndInfo {
            ty: sys::FrameEndInfo::TYPE,
            next: ptr::null(),
            display_time,
            environment_blend_mode,
            layer_count: layers.len() as u32,
            layers: layers.as_ptr() as _,
        };
        unsafe {
            cvt((self.fp().end_frame)(self.session.as_raw(), &info))?;
        }
        self.state = State::End;
        Ok(())
    }

    // Private helper
    #[inline]
    fn fp(&self) -> &raw::Instance {
        self.session.instance().fp()
    }
}

#[derive(Debug, Eq, PartialEq)]
enum State {
    End,
    Wait,
    Begin,
}

#[derive(Debug, Copy, Clone)]
pub struct FrameState {
    pub predicted_display_time: Time,
    pub predicted_display_period: Duration,
}