atagen

monolith

public
Star0
Watch0
b96f1a324a8807feaa85938ab4e8fef84273dee0
1
ssh://brewery@pls.lobotomise.me:33/atagen/monolith.git

Blame: crates/render-vk/src/frame.rs

824bf02b6e55atagen2026-10-16 09:15 UTC1
use crate::Error;
824bf02b6e55atagen2026-10-16 09:15 UTC2
use crate::image::{VulkanTarget, VulkanTexture};
824bf02b6e55atagen2026-10-16 09:15 UTC3
use crate::pipeline::{Kind, Push};
824bf02b6e55atagen2026-10-16 09:15 UTC4
use crate::renderer::VulkanRenderer;
824bf02b6e55atagen2026-10-16 09:15 UTC5
use crate::transform::{rect_to_framebuffer, texture_uvs, to_framebuffer};
824bf02b6e55atagen2026-10-16 09:15 UTC6
use ash::vk;
824bf02b6e55atagen2026-10-16 09:15 UTC7
use smithay::backend::renderer::sync::SyncPoint;
824bf02b6e55atagen2026-10-16 09:15 UTC8
use smithay::backend::renderer::{Color32F, ContextId, Frame, Texture};
824bf02b6e55atagen2026-10-16 09:15 UTC9
use smithay::utils::{Buffer, Physical, Rectangle, Size, Transform};
824bf02b6e55atagen2026-10-16 09:15 UTC10
use std::sync::Arc;
824bf02b6e55atagen2026-10-16 09:15 UTC11
824bf02b6e55atagen2026-10-16 09:15 UTC12
pub(crate) enum Op {
824bf02b6e55atagen2026-10-16 09:15 UTC13
    Clear {
824bf02b6e55atagen2026-10-16 09:15 UTC14
        color: [f32; 4],
824bf02b6e55atagen2026-10-16 09:15 UTC15
        rects: Vec<vk::Rect2D>,
824bf02b6e55atagen2026-10-16 09:15 UTC16
    },
824bf02b6e55atagen2026-10-16 09:15 UTC17
    Draw {
824bf02b6e55atagen2026-10-16 09:15 UTC18
        kind: Kind,
c0caa658decfatagen2026-10-19 07:37 UTC19
        opaque: bool,
824bf02b6e55atagen2026-10-16 09:15 UTC20
        texture: Option<VulkanTexture>,
824bf02b6e55atagen2026-10-16 09:15 UTC21
        push: Push,
824bf02b6e55atagen2026-10-16 09:15 UTC22
        scissors: Vec<vk::Rect2D>,
824bf02b6e55atagen2026-10-16 09:15 UTC23
    },
824bf02b6e55atagen2026-10-16 09:15 UTC24
}
824bf02b6e55atagen2026-10-16 09:15 UTC25
824bf02b6e55atagen2026-10-16 09:15 UTC26
/// A frame in progress. Draws are recorded and submitted together by [`Frame::finish`].
824bf02b6e55atagen2026-10-16 09:15 UTC27
pub struct VulkanFrame<'frame, 'buffer> {
824bf02b6e55atagen2026-10-16 09:15 UTC28
    renderer: &'frame mut VulkanRenderer,
824bf02b6e55atagen2026-10-16 09:15 UTC29
    target: &'frame mut VulkanTarget<'buffer>,
824bf02b6e55atagen2026-10-16 09:15 UTC30
    output: Size<i32, Physical>,
0b68ce424a32atagen2026-10-18 03:17 UTC31
    /// The output rotated into the space draws are given in, which differs
0b68ce424a32atagen2026-10-18 03:17 UTC32
    /// from `output` for 90 and 270 degree transforms.
0b68ce424a32atagen2026-10-18 03:17 UTC33
    area: Size<i32, Physical>,
824bf02b6e55atagen2026-10-16 09:15 UTC34
    transform: Transform,
824bf02b6e55atagen2026-10-16 09:15 UTC35
    ops: Vec<Op>,
47259c39793fatagen2026-10-17 10:13 UTC36
    clip: Option<Clip>,
47259c39793fatagen2026-10-17 10:13 UTC37
}
47259c39793fatagen2026-10-17 10:13 UTC38
47259c39793fatagen2026-10-17 10:13 UTC39
/// A rounded rect in output space that later draws are cut to, until
47259c39793fatagen2026-10-17 10:13 UTC40
/// [`VulkanFrame::set_clip`] changes it. A nonzero `ring` keeps only a band
47259c39793fatagen2026-10-17 10:13 UTC41
/// that wide inside the edge.
47259c39793fatagen2026-10-17 10:13 UTC42
#[derive(Clone, Copy, Debug, PartialEq)]
47259c39793fatagen2026-10-17 10:13 UTC43
pub struct Clip {
47259c39793fatagen2026-10-17 10:13 UTC44
    pub rect: Rectangle<i32, Physical>,
47259c39793fatagen2026-10-17 10:13 UTC45
    /// Top left, top right, bottom right and bottom left, in pixels.
47259c39793fatagen2026-10-17 10:13 UTC46
    pub radii: [f32; 4],
47259c39793fatagen2026-10-17 10:13 UTC47
    pub ring: f32,
824bf02b6e55atagen2026-10-16 09:15 UTC48
}
824bf02b6e55atagen2026-10-16 09:15 UTC49
824bf02b6e55atagen2026-10-16 09:15 UTC50
impl std::fmt::Debug for VulkanFrame<'_, '_> {
824bf02b6e55atagen2026-10-16 09:15 UTC51
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
824bf02b6e55atagen2026-10-16 09:15 UTC52
        f.debug_struct("VulkanFrame")
824bf02b6e55atagen2026-10-16 09:15 UTC53
            .field("output", &self.output)
824bf02b6e55atagen2026-10-16 09:15 UTC54
            .field("ops", &self.ops.len())
824bf02b6e55atagen2026-10-16 09:15 UTC55
            .finish()
824bf02b6e55atagen2026-10-16 09:15 UTC56
    }
824bf02b6e55atagen2026-10-16 09:15 UTC57
}
824bf02b6e55atagen2026-10-16 09:15 UTC58
824bf02b6e55atagen2026-10-16 09:15 UTC59
impl<'frame, 'buffer> VulkanFrame<'frame, 'buffer> {
824bf02b6e55atagen2026-10-16 09:15 UTC60
    pub(crate) fn new(
824bf02b6e55atagen2026-10-16 09:15 UTC61
        renderer: &'frame mut VulkanRenderer,
824bf02b6e55atagen2026-10-16 09:15 UTC62
        target: &'frame mut VulkanTarget<'buffer>,
824bf02b6e55atagen2026-10-16 09:15 UTC63
        output: Size<i32, Physical>,
824bf02b6e55atagen2026-10-16 09:15 UTC64
        transform: Transform,
824bf02b6e55atagen2026-10-16 09:15 UTC65
    ) -> Self {
824bf02b6e55atagen2026-10-16 09:15 UTC66
        Self {
824bf02b6e55atagen2026-10-16 09:15 UTC67
            renderer,
824bf02b6e55atagen2026-10-16 09:15 UTC68
            target,
824bf02b6e55atagen2026-10-16 09:15 UTC69
            output,
0b68ce424a32atagen2026-10-18 03:17 UTC70
            area: transform.transform_size(output),
824bf02b6e55atagen2026-10-16 09:15 UTC71
            transform,
824bf02b6e55atagen2026-10-16 09:15 UTC72
            ops: Vec::new(),
47259c39793fatagen2026-10-17 10:13 UTC73
            clip: None,
824bf02b6e55atagen2026-10-16 09:15 UTC74
        }
824bf02b6e55atagen2026-10-16 09:15 UTC75
    }
824bf02b6e55atagen2026-10-16 09:15 UTC76
47259c39793fatagen2026-10-17 10:13 UTC77
    pub fn set_clip(&mut self, clip: Option<Clip>) {
47259c39793fatagen2026-10-17 10:13 UTC78
        self.clip = clip;
47259c39793fatagen2026-10-17 10:13 UTC79
    }
47259c39793fatagen2026-10-17 10:13 UTC80
47259c39793fatagen2026-10-17 10:13 UTC81
    /// The clip's push constants in framebuffer space, where an output
47259c39793fatagen2026-10-17 10:13 UTC82
    /// transform moves each radius to another corner.
47259c39793fatagen2026-10-17 10:13 UTC83
    fn clip_push(&self) -> ([f32; 4], [f32; 4], [f32; 4]) {
47259c39793fatagen2026-10-17 10:13 UTC84
        let Some(c) = self.clip else {
47259c39793fatagen2026-10-17 10:13 UTC85
            return ([0.0; 4], [0.0; 4], [0.0; 4]);
47259c39793fatagen2026-10-17 10:13 UTC86
        };
47259c39793fatagen2026-10-17 10:13 UTC87
        let [tl, tr, br, bl] = c.radii;
47259c39793fatagen2026-10-17 10:13 UTC88
        let corners = [[tl, 0.0], [tr, 0.0], [bl, 0.0], [br, 0.0]];
0b68ce424a32atagen2026-10-18 03:17 UTC89
        let (fb, r) = to_framebuffer(c.rect, corners, self.area, self.transform);
47259c39793fatagen2026-10-17 10:13 UTC90
        let rect = [
47259c39793fatagen2026-10-17 10:13 UTC91
            fb.loc.x as f32,
47259c39793fatagen2026-10-17 10:13 UTC92
            fb.loc.y as f32,
47259c39793fatagen2026-10-17 10:13 UTC93
            fb.size.w as f32,
47259c39793fatagen2026-10-17 10:13 UTC94
            fb.size.h as f32,
47259c39793fatagen2026-10-17 10:13 UTC95
        ];
47259c39793fatagen2026-10-17 10:13 UTC96
        let most = fb.size.w.min(fb.size.h) as f32 / 2.0;
47259c39793fatagen2026-10-17 10:13 UTC97
        let radii = [r[0][0], r[1][0], r[3][0], r[2][0]].map(|r| r.min(most));
47259c39793fatagen2026-10-17 10:13 UTC98
        (rect, radii, [c.ring, 0.0, 0.0, 0.0])
47259c39793fatagen2026-10-17 10:13 UTC99
    }
47259c39793fatagen2026-10-17 10:13 UTC100
824bf02b6e55atagen2026-10-16 09:15 UTC101
    fn fb_size(&self) -> Size<i32, Physical> {
824bf02b6e55atagen2026-10-16 09:15 UTC102
        (self.target.width() as i32, self.target.height() as i32).into()
824bf02b6e55atagen2026-10-16 09:15 UTC103
    }
824bf02b6e55atagen2026-10-16 09:15 UTC104
824bf02b6e55atagen2026-10-16 09:15 UTC105
    fn fb_rect(&self, r: Rectangle<i32, Physical>) -> Option<vk::Rect2D> {
0b68ce424a32atagen2026-10-18 03:17 UTC106
        let r = rect_to_framebuffer(r, self.area, self.transform)
824bf02b6e55atagen2026-10-16 09:15 UTC107
            .intersection(Rectangle::from_size(self.fb_size()))?;
824bf02b6e55atagen2026-10-16 09:15 UTC108
        Some(vk::Rect2D {
824bf02b6e55atagen2026-10-16 09:15 UTC109
            offset: vk::Offset2D {
824bf02b6e55atagen2026-10-16 09:15 UTC110
                x: r.loc.x,
824bf02b6e55atagen2026-10-16 09:15 UTC111
                y: r.loc.y,
824bf02b6e55atagen2026-10-16 09:15 UTC112
            },
824bf02b6e55atagen2026-10-16 09:15 UTC113
            extent: vk::Extent2D {
824bf02b6e55atagen2026-10-16 09:15 UTC114
                width: r.size.w as u32,
824bf02b6e55atagen2026-10-16 09:15 UTC115
                height: r.size.h as u32,
824bf02b6e55atagen2026-10-16 09:15 UTC116
            },
824bf02b6e55atagen2026-10-16 09:15 UTC117
        })
824bf02b6e55atagen2026-10-16 09:15 UTC118
    }
824bf02b6e55atagen2026-10-16 09:15 UTC119
824bf02b6e55atagen2026-10-16 09:15 UTC120
    fn scissors(
824bf02b6e55atagen2026-10-16 09:15 UTC121
        &self,
824bf02b6e55atagen2026-10-16 09:15 UTC122
        dst: Rectangle<i32, Physical>,
824bf02b6e55atagen2026-10-16 09:15 UTC123
        damage: &[Rectangle<i32, Physical>],
824bf02b6e55atagen2026-10-16 09:15 UTC124
    ) -> Vec<vk::Rect2D> {
824bf02b6e55atagen2026-10-16 09:15 UTC125
        damage
824bf02b6e55atagen2026-10-16 09:15 UTC126
            .iter()
824bf02b6e55atagen2026-10-16 09:15 UTC127
            .filter_map(|d| d.intersection(Rectangle::from_size(dst.size)))
824bf02b6e55atagen2026-10-16 09:15 UTC128
            .filter_map(|mut d| {
824bf02b6e55atagen2026-10-16 09:15 UTC129
                d.loc += dst.loc;
824bf02b6e55atagen2026-10-16 09:15 UTC130
                self.fb_rect(d)
824bf02b6e55atagen2026-10-16 09:15 UTC131
            })
824bf02b6e55atagen2026-10-16 09:15 UTC132
            .collect()
824bf02b6e55atagen2026-10-16 09:15 UTC133
    }
824bf02b6e55atagen2026-10-16 09:15 UTC134
96db497859dcatagen2026-10-16 11:27 UTC135
    /// Draws a texture through the transition hook in `shaders/effect.frag`.
96db497859dcatagen2026-10-16 11:27 UTC136
    #[expect(clippy::too_many_arguments)]
96db497859dcatagen2026-10-16 11:27 UTC137
    pub fn render_effect(
96db497859dcatagen2026-10-16 11:27 UTC138
        &mut self,
96db497859dcatagen2026-10-16 11:27 UTC139
        texture: &VulkanTexture,
96db497859dcatagen2026-10-16 11:27 UTC140
        src: Rectangle<f64, Buffer>,
96db497859dcatagen2026-10-16 11:27 UTC141
        dst: Rectangle<i32, Physical>,
96db497859dcatagen2026-10-16 11:27 UTC142
        damage: &[Rectangle<i32, Physical>],
96db497859dcatagen2026-10-16 11:27 UTC143
        src_transform: Transform,
96db497859dcatagen2026-10-16 11:27 UTC144
        alpha: f32,
96db497859dcatagen2026-10-16 11:27 UTC145
        effect: Effect,
96db497859dcatagen2026-10-16 11:27 UTC146
    ) -> Result<(), Error> {
96db497859dcatagen2026-10-16 11:27 UTC147
        let params = [effect.progress, effect.kind as u32 as f32, 0.0, 0.0];
96db497859dcatagen2026-10-16 11:27 UTC148
        self.draw_texture(
96db497859dcatagen2026-10-16 11:27 UTC149
            texture,
96db497859dcatagen2026-10-16 11:27 UTC150
            src,
96db497859dcatagen2026-10-16 11:27 UTC151
            dst,
96db497859dcatagen2026-10-16 11:27 UTC152
            damage,
96db497859dcatagen2026-10-16 11:27 UTC153
            src_transform,
96db497859dcatagen2026-10-16 11:27 UTC154
            alpha,
96db497859dcatagen2026-10-16 11:27 UTC155
            Kind::Effect,
96db497859dcatagen2026-10-16 11:27 UTC156
            params,
96db497859dcatagen2026-10-16 11:27 UTC157
        )
96db497859dcatagen2026-10-16 11:27 UTC158
    }
96db497859dcatagen2026-10-16 11:27 UTC159
96db497859dcatagen2026-10-16 11:27 UTC160
    #[expect(clippy::too_many_arguments)]
96db497859dcatagen2026-10-16 11:27 UTC161
    fn draw_texture(
96db497859dcatagen2026-10-16 11:27 UTC162
        &mut self,
96db497859dcatagen2026-10-16 11:27 UTC163
        texture: &VulkanTexture,
96db497859dcatagen2026-10-16 11:27 UTC164
        src: Rectangle<f64, Buffer>,
96db497859dcatagen2026-10-16 11:27 UTC165
        dst: Rectangle<i32, Physical>,
96db497859dcatagen2026-10-16 11:27 UTC166
        damage: &[Rectangle<i32, Physical>],
96db497859dcatagen2026-10-16 11:27 UTC167
        src_transform: Transform,
96db497859dcatagen2026-10-16 11:27 UTC168
        alpha: f32,
96db497859dcatagen2026-10-16 11:27 UTC169
        kind: Kind,
96db497859dcatagen2026-10-16 11:27 UTC170
        effect: [f32; 4],
96db497859dcatagen2026-10-16 11:27 UTC171
    ) -> Result<(), Error> {
96db497859dcatagen2026-10-16 11:27 UTC172
        if !Arc::ptr_eq(&texture.0.shared, self.renderer.shared()) {
96db497859dcatagen2026-10-16 11:27 UTC173
            return Err(Error::ForeignTexture);
96db497859dcatagen2026-10-16 11:27 UTC174
        }
96db497859dcatagen2026-10-16 11:27 UTC175
        if dst.size.w <= 0 || dst.size.h <= 0 || Arc::ptr_eq(&texture.0, &self.target.0) {
96db497859dcatagen2026-10-16 11:27 UTC176
            return Ok(());
96db497859dcatagen2026-10-16 11:27 UTC177
        }
96db497859dcatagen2026-10-16 11:27 UTC178
        let scissors = self.scissors(dst, damage);
96db497859dcatagen2026-10-16 11:27 UTC179
        if scissors.is_empty() {
96db497859dcatagen2026-10-16 11:27 UTC180
            return Ok(());
96db497859dcatagen2026-10-16 11:27 UTC181
        }
b03e3b32603aatagen2026-10-19 07:40 UTC182
        let mut uvs = texture_uvs(src, dst.size, texture.size(), src_transform);
b03e3b32603aatagen2026-10-19 07:40 UTC183
        if texture.0.y_inverted {
b03e3b32603aatagen2026-10-19 07:40 UTC184
            for uv in &mut uvs {
b03e3b32603aatagen2026-10-19 07:40 UTC185
                uv[1] = 1.0 - uv[1];
b03e3b32603aatagen2026-10-19 07:40 UTC186
            }
b03e3b32603aatagen2026-10-19 07:40 UTC187
        }
0b68ce424a32atagen2026-10-18 03:17 UTC188
        let (fb, uv) = to_framebuffer(dst, uvs, self.area, self.transform);
47259c39793fatagen2026-10-17 10:13 UTC189
        let (clip, radii, ring) = self.clip_push();
96db497859dcatagen2026-10-16 11:27 UTC190
        let push = Push {
96db497859dcatagen2026-10-16 11:27 UTC191
            dst: self.ndc(fb),
96db497859dcatagen2026-10-16 11:27 UTC192
            uv,
96db497859dcatagen2026-10-16 11:27 UTC193
            color: [1.0, 1.0, 1.0, alpha],
96db497859dcatagen2026-10-16 11:27 UTC194
            effect,
47259c39793fatagen2026-10-17 10:13 UTC195
            clip,
47259c39793fatagen2026-10-17 10:13 UTC196
            radii,
47259c39793fatagen2026-10-17 10:13 UTC197
            ring,
96db497859dcatagen2026-10-16 11:27 UTC198
        };
96db497859dcatagen2026-10-16 11:27 UTC199
        self.ops.push(Op::Draw {
96db497859dcatagen2026-10-16 11:27 UTC200
            kind,
c0caa658decfatagen2026-10-19 07:37 UTC201
            opaque: kind == Kind::Texture
c0caa658decfatagen2026-10-19 07:37 UTC202
                && alpha >= 1.0
c0caa658decfatagen2026-10-19 07:37 UTC203
                && self.clip.is_none()
c0caa658decfatagen2026-10-19 07:37 UTC204
                && texture.0.opaque(),
96db497859dcatagen2026-10-16 11:27 UTC205
            texture: Some(texture.clone()),
96db497859dcatagen2026-10-16 11:27 UTC206
            push,
96db497859dcatagen2026-10-16 11:27 UTC207
            scissors,
96db497859dcatagen2026-10-16 11:27 UTC208
        });
96db497859dcatagen2026-10-16 11:27 UTC209
        Ok(())
96db497859dcatagen2026-10-16 11:27 UTC210
    }
96db497859dcatagen2026-10-16 11:27 UTC211
824bf02b6e55atagen2026-10-16 09:15 UTC212
    fn ndc(&self, r: Rectangle<i32, Physical>) -> [f32; 4] {
824bf02b6e55atagen2026-10-16 09:15 UTC213
        let fb = self.fb_size();
824bf02b6e55atagen2026-10-16 09:15 UTC214
        let (w, h) = (fb.w as f32, fb.h as f32);
824bf02b6e55atagen2026-10-16 09:15 UTC215
        [
824bf02b6e55atagen2026-10-16 09:15 UTC216
            r.loc.x as f32 / w * 2.0 - 1.0,
824bf02b6e55atagen2026-10-16 09:15 UTC217
            r.loc.y as f32 / h * 2.0 - 1.0,
824bf02b6e55atagen2026-10-16 09:15 UTC218
            r.size.w as f32 / w * 2.0,
824bf02b6e55atagen2026-10-16 09:15 UTC219
            r.size.h as f32 / h * 2.0,
824bf02b6e55atagen2026-10-16 09:15 UTC220
        ]
824bf02b6e55atagen2026-10-16 09:15 UTC221
    }
824bf02b6e55atagen2026-10-16 09:15 UTC222
}
824bf02b6e55atagen2026-10-16 09:15 UTC223
824bf02b6e55atagen2026-10-16 09:15 UTC224
impl Frame for VulkanFrame<'_, '_> {
824bf02b6e55atagen2026-10-16 09:15 UTC225
    type Error = Error;
824bf02b6e55atagen2026-10-16 09:15 UTC226
    type TextureId = VulkanTexture;
824bf02b6e55atagen2026-10-16 09:15 UTC227
824bf02b6e55atagen2026-10-16 09:15 UTC228
    fn context_id(&self) -> ContextId<VulkanTexture> {
824bf02b6e55atagen2026-10-16 09:15 UTC229
        self.renderer.context_id_ref().clone()
824bf02b6e55atagen2026-10-16 09:15 UTC230
    }
824bf02b6e55atagen2026-10-16 09:15 UTC231
824bf02b6e55atagen2026-10-16 09:15 UTC232
    fn clear(&mut self, color: Color32F, at: &[Rectangle<i32, Physical>]) -> Result<(), Error> {
824bf02b6e55atagen2026-10-16 09:15 UTC233
        let rects: Vec<_> = at.iter().filter_map(|r| self.fb_rect(*r)).collect();
824bf02b6e55atagen2026-10-16 09:15 UTC234
        if !rects.is_empty() {
824bf02b6e55atagen2026-10-16 09:15 UTC235
            self.ops.push(Op::Clear {
824bf02b6e55atagen2026-10-16 09:15 UTC236
                color: color.components(),
824bf02b6e55atagen2026-10-16 09:15 UTC237
                rects,
824bf02b6e55atagen2026-10-16 09:15 UTC238
            });
824bf02b6e55atagen2026-10-16 09:15 UTC239
        }
824bf02b6e55atagen2026-10-16 09:15 UTC240
        Ok(())
824bf02b6e55atagen2026-10-16 09:15 UTC241
    }
824bf02b6e55atagen2026-10-16 09:15 UTC242
824bf02b6e55atagen2026-10-16 09:15 UTC243
    fn draw_solid(
824bf02b6e55atagen2026-10-16 09:15 UTC244
        &mut self,
824bf02b6e55atagen2026-10-16 09:15 UTC245
        dst: Rectangle<i32, Physical>,
824bf02b6e55atagen2026-10-16 09:15 UTC246
        damage: &[Rectangle<i32, Physical>],
824bf02b6e55atagen2026-10-16 09:15 UTC247
        color: Color32F,
824bf02b6e55atagen2026-10-16 09:15 UTC248
    ) -> Result<(), Error> {
824bf02b6e55atagen2026-10-16 09:15 UTC249
        let scissors = self.scissors(dst, damage);
824bf02b6e55atagen2026-10-16 09:15 UTC250
        if scissors.is_empty() {
824bf02b6e55atagen2026-10-16 09:15 UTC251
            return Ok(());
824bf02b6e55atagen2026-10-16 09:15 UTC252
        }
0b68ce424a32atagen2026-10-18 03:17 UTC253
        let (fb, _) = to_framebuffer(dst, [[0.0; 2]; 4], self.area, self.transform);
47259c39793fatagen2026-10-17 10:13 UTC254
        let (clip, radii, ring) = self.clip_push();
824bf02b6e55atagen2026-10-16 09:15 UTC255
        let push = Push {
824bf02b6e55atagen2026-10-16 09:15 UTC256
            dst: self.ndc(fb),
824bf02b6e55atagen2026-10-16 09:15 UTC257
            uv: [[0.0; 2]; 4],
824bf02b6e55atagen2026-10-16 09:15 UTC258
            color: color.components(),
96db497859dcatagen2026-10-16 11:27 UTC259
            effect: [0.0; 4],
47259c39793fatagen2026-10-17 10:13 UTC260
            clip,
47259c39793fatagen2026-10-17 10:13 UTC261
            radii,
47259c39793fatagen2026-10-17 10:13 UTC262
            ring,
824bf02b6e55atagen2026-10-16 09:15 UTC263
        };
824bf02b6e55atagen2026-10-16 09:15 UTC264
        self.ops.push(Op::Draw {
824bf02b6e55atagen2026-10-16 09:15 UTC265
            kind: Kind::Solid,
c0caa658decfatagen2026-10-19 07:37 UTC266
            opaque: color.a() >= 1.0 && self.clip.is_none(),
824bf02b6e55atagen2026-10-16 09:15 UTC267
            texture: None,
824bf02b6e55atagen2026-10-16 09:15 UTC268
            push,
824bf02b6e55atagen2026-10-16 09:15 UTC269
            scissors,
824bf02b6e55atagen2026-10-16 09:15 UTC270
        });
824bf02b6e55atagen2026-10-16 09:15 UTC271
        Ok(())
824bf02b6e55atagen2026-10-16 09:15 UTC272
    }
824bf02b6e55atagen2026-10-16 09:15 UTC273
824bf02b6e55atagen2026-10-16 09:15 UTC274
    fn render_texture_from_to(
824bf02b6e55atagen2026-10-16 09:15 UTC275
        &mut self,
824bf02b6e55atagen2026-10-16 09:15 UTC276
        texture: &VulkanTexture,
824bf02b6e55atagen2026-10-16 09:15 UTC277
        src: Rectangle<f64, Buffer>,
824bf02b6e55atagen2026-10-16 09:15 UTC278
        dst: Rectangle<i32, Physical>,
824bf02b6e55atagen2026-10-16 09:15 UTC279
        damage: &[Rectangle<i32, Physical>],
824bf02b6e55atagen2026-10-16 09:15 UTC280
        _opaque_regions: &[Rectangle<i32, Physical>],
824bf02b6e55atagen2026-10-16 09:15 UTC281
        src_transform: Transform,
824bf02b6e55atagen2026-10-16 09:15 UTC282
        alpha: f32,
824bf02b6e55atagen2026-10-16 09:15 UTC283
    ) -> Result<(), Error> {
96db497859dcatagen2026-10-16 11:27 UTC284
        self.draw_texture(
96db497859dcatagen2026-10-16 11:27 UTC285
            texture,
96db497859dcatagen2026-10-16 11:27 UTC286
            src,
96db497859dcatagen2026-10-16 11:27 UTC287
            dst,
96db497859dcatagen2026-10-16 11:27 UTC288
            damage,
96db497859dcatagen2026-10-16 11:27 UTC289
            src_transform,
96db497859dcatagen2026-10-16 11:27 UTC290
            alpha,
96db497859dcatagen2026-10-16 11:27 UTC291
            Kind::Texture,
96db497859dcatagen2026-10-16 11:27 UTC292
            [0.0; 4],
96db497859dcatagen2026-10-16 11:27 UTC293
        )
824bf02b6e55atagen2026-10-16 09:15 UTC294
    }
824bf02b6e55atagen2026-10-16 09:15 UTC295
824bf02b6e55atagen2026-10-16 09:15 UTC296
    fn transformation(&self) -> Transform {
824bf02b6e55atagen2026-10-16 09:15 UTC297
        self.transform
824bf02b6e55atagen2026-10-16 09:15 UTC298
    }
824bf02b6e55atagen2026-10-16 09:15 UTC299
824bf02b6e55atagen2026-10-16 09:15 UTC300
    fn output_size(&self) -> Size<i32, Physical> {
824bf02b6e55atagen2026-10-16 09:15 UTC301
        self.output
824bf02b6e55atagen2026-10-16 09:15 UTC302
    }
824bf02b6e55atagen2026-10-16 09:15 UTC303
824bf02b6e55atagen2026-10-16 09:15 UTC304
    fn wait(&mut self, sync: &SyncPoint) -> Result<(), Error> {
6dfb54e27e7fatagen2026-10-19 07:53 UTC305
        sync.wait().map_err(|_| crate::error::wait_error())
824bf02b6e55atagen2026-10-16 09:15 UTC306
    }
824bf02b6e55atagen2026-10-16 09:15 UTC307
824bf02b6e55atagen2026-10-16 09:15 UTC308
    fn finish(mut self) -> Result<SyncPoint, Error> {
824bf02b6e55atagen2026-10-16 09:15 UTC309
        let ops = std::mem::take(&mut self.ops);
824bf02b6e55atagen2026-10-16 09:15 UTC310
        self.renderer.submit(self.target, ops)
824bf02b6e55atagen2026-10-16 09:15 UTC311
    }
824bf02b6e55atagen2026-10-16 09:15 UTC312
}
96db497859dcatagen2026-10-16 11:27 UTC313
96db497859dcatagen2026-10-16 11:27 UTC314
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
96db497859dcatagen2026-10-16 11:27 UTC315
pub enum Transition {
96db497859dcatagen2026-10-16 11:27 UTC316
    Move = 0,
96db497859dcatagen2026-10-16 11:27 UTC317
    Spawn = 1,
96db497859dcatagen2026-10-16 11:27 UTC318
    Close = 2,
96db497859dcatagen2026-10-16 11:27 UTC319
}
96db497859dcatagen2026-10-16 11:27 UTC320
96db497859dcatagen2026-10-16 11:27 UTC321
/// A window transition for the effect shader, with `progress` in [0, 1].
96db497859dcatagen2026-10-16 11:27 UTC322
#[derive(Clone, Copy, Debug, PartialEq)]
96db497859dcatagen2026-10-16 11:27 UTC323
pub struct Effect {
96db497859dcatagen2026-10-16 11:27 UTC324
    pub kind: Transition,
96db497859dcatagen2026-10-16 11:27 UTC325
    pub progress: f32,
96db497859dcatagen2026-10-16 11:27 UTC326
}