atagen

monolith

public
Star0
Watch0
a1a05e799a71310e027e905881770331471257a8
1
ssh://brewery@pls.lobotomise.me:33/atagen/monolith.git
crates/render-vk/src/frame.rsRust201 lines5.7 KB
1
use crate::Error;
2
use crate::image::{VulkanTarget, VulkanTexture};
3
use crate::pipeline::{Kind, Push};
4
use crate::renderer::VulkanRenderer;
5
use crate::transform::{rect_to_framebuffer, texture_uvs, to_framebuffer};
6
use ash::vk;
7
use smithay::backend::renderer::sync::SyncPoint;
8
use smithay::backend::renderer::{Color32F, ContextId, Frame, Texture};
9
use smithay::utils::{Buffer, Physical, Rectangle, Size, Transform};
10
use std::sync::Arc;
11
12
pub(crate) enum Op {
13
    Clear {
14
        color: [f32; 4],
15
        rects: Vec<vk::Rect2D>,
16
    },
17
    Draw {
18
        kind: Kind,
19
        texture: Option<VulkanTexture>,
20
        push: Push,
21
        scissors: Vec<vk::Rect2D>,
22
    },
23
}
24
25
/// A frame in progress. Draws are recorded and submitted together by [`Frame::finish`].
26
pub struct VulkanFrame<'frame, 'buffer> {
27
    renderer: &'frame mut VulkanRenderer,
28
    target: &'frame mut VulkanTarget<'buffer>,
29
    output: Size<i32, Physical>,
30
    transform: Transform,
31
    ops: Vec<Op>,
32
}
33
34
impl std::fmt::Debug for VulkanFrame<'_, '_> {
35
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36
        f.debug_struct("VulkanFrame")
37
            .field("output", &self.output)
38
            .field("ops", &self.ops.len())
39
            .finish()
40
    }
41
}
42
43
impl<'frame, 'buffer> VulkanFrame<'frame, 'buffer> {
44
    pub(crate) fn new(
45
        renderer: &'frame mut VulkanRenderer,
46
        target: &'frame mut VulkanTarget<'buffer>,
47
        output: Size<i32, Physical>,
48
        transform: Transform,
49
    ) -> Self {
50
        Self {
51
            renderer,
52
            target,
53
            output,
54
            transform,
55
            ops: Vec::new(),
56
        }
57
    }
58
59
    fn fb_size(&self) -> Size<i32, Physical> {
60
        (self.target.width() as i32, self.target.height() as i32).into()
61
    }
62
63
    fn fb_rect(&self, r: Rectangle<i32, Physical>) -> Option<vk::Rect2D> {
64
        let r = rect_to_framebuffer(r, self.output, self.transform)
65
            .intersection(Rectangle::from_size(self.fb_size()))?;
66
        Some(vk::Rect2D {
67
            offset: vk::Offset2D {
68
                x: r.loc.x,
69
                y: r.loc.y,
70
            },
71
            extent: vk::Extent2D {
72
                width: r.size.w as u32,
73
                height: r.size.h as u32,
74
            },
75
        })
76
    }
77
78
    fn scissors(
79
        &self,
80
        dst: Rectangle<i32, Physical>,
81
        damage: &[Rectangle<i32, Physical>],
82
    ) -> Vec<vk::Rect2D> {
83
        damage
84
            .iter()
85
            .filter_map(|d| d.intersection(Rectangle::from_size(dst.size)))
86
            .filter_map(|mut d| {
87
                d.loc += dst.loc;
88
                self.fb_rect(d)
89
            })
90
            .collect()
91
    }
92
93
    fn ndc(&self, r: Rectangle<i32, Physical>) -> [f32; 4] {
94
        let fb = self.fb_size();
95
        let (w, h) = (fb.w as f32, fb.h as f32);
96
        [
97
            r.loc.x as f32 / w * 2.0 - 1.0,
98
            r.loc.y as f32 / h * 2.0 - 1.0,
99
            r.size.w as f32 / w * 2.0,
100
            r.size.h as f32 / h * 2.0,
101
        ]
102
    }
103
}
104
105
impl Frame for VulkanFrame<'_, '_> {
106
    type Error = Error;
107
    type TextureId = VulkanTexture;
108
109
    fn context_id(&self) -> ContextId<VulkanTexture> {
110
        self.renderer.context_id_ref().clone()
111
    }
112
113
    fn clear(&mut self, color: Color32F, at: &[Rectangle<i32, Physical>]) -> Result<(), Error> {
114
        let rects: Vec<_> = at.iter().filter_map(|r| self.fb_rect(*r)).collect();
115
        if !rects.is_empty() {
116
            self.ops.push(Op::Clear {
117
                color: color.components(),
118
                rects,
119
            });
120
        }
121
        Ok(())
122
    }
123
124
    fn draw_solid(
125
        &mut self,
126
        dst: Rectangle<i32, Physical>,
127
        damage: &[Rectangle<i32, Physical>],
128
        color: Color32F,
129
    ) -> Result<(), Error> {
130
        let scissors = self.scissors(dst, damage);
131
        if scissors.is_empty() {
132
            return Ok(());
133
        }
134
        let (fb, _) = to_framebuffer(dst, [[0.0; 2]; 4], self.output, self.transform);
135
        let push = Push {
136
            dst: self.ndc(fb),
137
            uv: [[0.0; 2]; 4],
138
            color: color.components(),
139
        };
140
        self.ops.push(Op::Draw {
141
            kind: Kind::Solid,
142
            texture: None,
143
            push,
144
            scissors,
145
        });
146
        Ok(())
147
    }
148
149
    fn render_texture_from_to(
150
        &mut self,
151
        texture: &VulkanTexture,
152
        src: Rectangle<f64, Buffer>,
153
        dst: Rectangle<i32, Physical>,
154
        damage: &[Rectangle<i32, Physical>],
155
        _opaque_regions: &[Rectangle<i32, Physical>],
156
        src_transform: Transform,
157
        alpha: f32,
158
    ) -> Result<(), Error> {
159
        if !Arc::ptr_eq(&texture.0.shared, self.renderer.shared()) {
160
            return Err(Error::ForeignTexture);
161
        }
162
        if dst.size.w <= 0 || dst.size.h <= 0 || Arc::ptr_eq(&texture.0, &self.target.0) {
163
            return Ok(());
164
        }
165
        let scissors = self.scissors(dst, damage);
166
        if scissors.is_empty() {
167
            return Ok(());
168
        }
169
        let uvs = texture_uvs(src, dst.size, texture.size(), src_transform);
170
        let (fb, uv) = to_framebuffer(dst, uvs, self.output, self.transform);
171
        let push = Push {
172
            dst: self.ndc(fb),
173
            uv,
174
            color: [1.0, 1.0, 1.0, alpha],
175
        };
176
        self.ops.push(Op::Draw {
177
            kind: Kind::Texture,
178
            texture: Some(texture.clone()),
179
            push,
180
            scissors,
181
        });
182
        Ok(())
183
    }
184
185
    fn transformation(&self) -> Transform {
186
        self.transform
187
    }
188
189
    fn output_size(&self) -> Size<i32, Physical> {
190
        self.output
191
    }
192
193
    fn wait(&mut self, sync: &SyncPoint) -> Result<(), Error> {
194
        sync.wait().map_err(|_| Error::Interrupted)
195
    }
196
197
    fn finish(mut self) -> Result<SyncPoint, Error> {
198
        let ops = std::mem::take(&mut self.ops);
199
        self.renderer.submit(self.target, ops)
200
    }
201
}