824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 1 | //! Renders small scenes offscreen and checks pixels. Runs on whatever Vulkan |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 2 | //! driver is available. `nix flake check` forces lavapipe. |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 3 | |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 4 | use monolith_render_vk::{VulkanImage, VulkanRenderer, VulkanTexture}; |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 5 | use smithay::backend::allocator::Fourcc; |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 6 | use smithay::backend::renderer::{ |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 7 | Bind, Color32F, ExportMem, Frame, ImportMem, Offscreen, Renderer, TextureFilter, |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 8 | }; |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 9 | use smithay::utils::{Physical, Rectangle, Size, Transform}; |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 10 | |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 11 | const W: i32 = 64; |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 12 | const H: i32 = 64; |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 13 | |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 14 | type Pixel = [u8; 4]; |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 15 | |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 16 | const RED: Pixel = [255, 0, 0, 255]; |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 17 | const GREEN: Pixel = [0, 255, 0, 255]; |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 18 | const BLUE: Pixel = [0, 0, 255, 255]; |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 19 | const WHITE: Pixel = [255, 255, 255, 255]; |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 20 | const BLACK: Pixel = [0, 0, 0, 255]; |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 21 | |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 22 | struct Scene { |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 23 | renderer: VulkanRenderer, |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 24 | image: VulkanImage, |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 25 | } |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 26 | |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 27 | impl Scene { |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 28 | fn new() -> Self { |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 29 | let mut renderer = VulkanRenderer::new().expect("no usable Vulkan device"); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 30 | let image = renderer |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 31 | .create_buffer(Fourcc::Argb8888, (W, H).into()) |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 32 | .unwrap(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 33 | Self { renderer, image } |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 34 | } |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 35 | |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 36 | fn draw( |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 37 | &mut self, |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 38 | transform: Transform, |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 39 | f: impl FnOnce(&mut monolith_render_vk::VulkanFrame<'_, '_>), |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 40 | ) { |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 41 | let mut target = self.renderer.bind(&mut self.image).unwrap(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 42 | let mut frame = self |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 43 | .renderer |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 44 | .render(&mut target, (W, H).into(), transform) |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 45 | .unwrap(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 46 | f(&mut frame); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 47 | frame.finish().unwrap().wait().unwrap(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 48 | } |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 49 | |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 50 | /// Pixels as RGBA, whatever the image's byte order. |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 51 | fn pixels(&mut self) -> Vec<Pixel> { |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 52 | let target = self.renderer.bind(&mut self.image).unwrap(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 53 | let mapping = self |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 54 | .renderer |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 55 | .copy_framebuffer( |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 56 | &target, |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 57 | Rectangle::from_size((W, H).into()), |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 58 | Fourcc::Abgr8888, |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 59 | ) |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 60 | .unwrap(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 61 | self.renderer |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 62 | .map_texture(&mapping) |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 63 | .unwrap() |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 64 | .as_chunks::<4>() |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 65 | .0 |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 66 | .to_vec() |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 67 | } |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 68 | |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 69 | fn texture(&mut self, size: (i32, i32), rgba: &[Pixel]) -> VulkanTexture { |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 70 | let bytes: Vec<u8> = rgba.iter().flatten().copied().collect(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 71 | self.renderer |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 72 | .import_memory(&bytes, Fourcc::Abgr8888, size.into(), false) |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 73 | .unwrap() |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 74 | } |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 75 | } |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 76 | |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 77 | fn at(pixels: &[Pixel], x: i32, y: i32) -> Pixel { |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 78 | pixels[(y * W + x) as usize] |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 79 | } |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 80 | |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 81 | fn full() -> Rectangle<i32, Physical> { |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 82 | Rectangle::from_size((W, H).into()) |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 83 | } |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 84 | |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 85 | fn rgba(p: Pixel) -> Color32F { |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 86 | p.map(|c| f32::from(c) / 255.0).into() |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 87 | } |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 88 | |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 89 | #[test] |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 90 | fn clears_to_a_colour() { |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 91 | let mut s = Scene::new(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 92 | s.draw(Transform::Normal, |f| { |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 93 | f.clear(rgba(RED), &[full()]).unwrap() |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 94 | }); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 95 | let px = s.pixels(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 96 | assert!(px.iter().all(|&p| p == RED)); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 97 | } |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 98 | |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 99 | #[test] |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 100 | fn solid_fill_respects_its_rectangle() { |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 101 | let mut s = Scene::new(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 102 | s.draw(Transform::Normal, |f| { |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 103 | f.clear(rgba(BLACK), &[full()]).unwrap(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 104 | let dst = Rectangle::new((16, 16).into(), (32, 32).into()); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 105 | f.draw_solid(dst, &[Rectangle::from_size(dst.size)], rgba(GREEN)) |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 106 | .unwrap(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 107 | }); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 108 | let px = s.pixels(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 109 | assert_eq!(at(&px, 16, 16), GREEN); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 110 | assert_eq!(at(&px, 47, 47), GREEN); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 111 | assert_eq!(at(&px, 15, 16), BLACK); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 112 | assert_eq!(at(&px, 48, 47), BLACK); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 113 | } |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 114 | |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 115 | #[test] |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 116 | fn damage_limits_drawing() { |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 117 | let mut s = Scene::new(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 118 | s.draw(Transform::Normal, |f| { |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 119 | f.clear(rgba(BLACK), &[full()]).unwrap(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 120 | let damage = Rectangle::new((0, 0).into(), (8, 8).into()); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 121 | f.draw_solid(full(), &[damage], rgba(BLUE)).unwrap(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 122 | }); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 123 | let px = s.pixels(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 124 | assert_eq!(at(&px, 7, 7), BLUE); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 125 | assert_eq!(at(&px, 8, 8), BLACK); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 126 | } |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 127 | |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 128 | #[test] |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 129 | fn partial_clear_keeps_previous_contents() { |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 130 | let mut s = Scene::new(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 131 | s.draw(Transform::Normal, |f| { |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 132 | f.clear(rgba(RED), &[full()]).unwrap() |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 133 | }); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 134 | s.draw(Transform::Normal, |f| { |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 135 | f.clear( |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 136 | rgba(GREEN), |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 137 | &[Rectangle::new((0, 0).into(), (32, 64).into())], |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 138 | ) |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 139 | .unwrap() |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 140 | }); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 141 | let px = s.pixels(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 142 | assert_eq!(at(&px, 0, 0), GREEN); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 143 | assert_eq!(at(&px, 63, 0), RED); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 144 | } |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 145 | |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 146 | #[test] |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 147 | fn textures_sample_with_nearest_filtering() { |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 148 | let mut s = Scene::new(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 149 | s.renderer.upscale_filter(TextureFilter::Nearest).unwrap(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 150 | let tex = s.texture((2, 2), &[RED, GREEN, BLUE, WHITE]); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 151 | s.draw(Transform::Normal, |f| { |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 152 | f.render_texture_from_to( |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 153 | &tex, |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 154 | Rectangle::from_size((2.0, 2.0).into()), |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 155 | full(), |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 156 | &[full()], |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 157 | &[], |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 158 | Transform::Normal, |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 159 | 1.0, |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 160 | ) |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 161 | .unwrap(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 162 | }); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 163 | let px = s.pixels(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 164 | assert_eq!(at(&px, 8, 8), RED); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 165 | assert_eq!(at(&px, 56, 8), GREEN); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 166 | assert_eq!(at(&px, 8, 56), BLUE); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 167 | assert_eq!(at(&px, 56, 56), WHITE); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 168 | } |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 169 | |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 170 | #[test] |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 171 | fn alpha_blends_premultiplied() { |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 172 | let mut s = Scene::new(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 173 | let tex = s.texture((1, 1), &[WHITE]); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 174 | s.draw(Transform::Normal, |f| { |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 175 | f.clear(rgba(BLACK), &[full()]).unwrap(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 176 | f.render_texture_from_to( |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 177 | &tex, |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 178 | Rectangle::from_size((1.0, 1.0).into()), |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 179 | full(), |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 180 | &[full()], |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 181 | &[], |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 182 | Transform::Normal, |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 183 | 0.5, |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 184 | ) |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 185 | .unwrap(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 186 | }); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 187 | let p = at(&s.pixels(), 32, 32); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 188 | assert!( |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 189 | (127..=129).contains(&p[0]) && p[0] == p[1] && p[1] == p[2], |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 190 | "{p:?}" |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 191 | ); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 192 | } |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 193 | |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 194 | #[test] |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 195 | fn output_transform_moves_content() { |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 196 | let mut s = Scene::new(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 197 | s.draw(Transform::_180, |f| { |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 198 | f.clear(rgba(BLACK), &[full()]).unwrap(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 199 | let dst = Rectangle::new((0, 0).into(), (16, 16).into()); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 200 | f.draw_solid(dst, &[Rectangle::from_size(dst.size)], rgba(GREEN)) |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 201 | .unwrap(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 202 | }); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 203 | let px = s.pixels(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 204 | assert_eq!(at(&px, 0, 0), BLACK); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 205 | assert_eq!(at(&px, 63, 63), GREEN); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 206 | } |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 207 | |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 208 | #[test] |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 209 | fn offscreen_images_can_be_sampled() { |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 210 | let mut s = Scene::new(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 211 | let mut inner = s |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 212 | .renderer |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 213 | .create_buffer(Fourcc::Argb8888, Size::from((4, 4))) |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 214 | .unwrap(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 215 | { |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 216 | let mut t = s.renderer.bind(&mut inner).unwrap(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 217 | let mut f = s |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 218 | .renderer |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 219 | .render(&mut t, (4, 4).into(), Transform::Normal) |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 220 | .unwrap(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 221 | f.clear(rgba(BLUE), &[Rectangle::from_size((4, 4).into())]) |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 222 | .unwrap(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 223 | f.finish().unwrap().wait().unwrap(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 224 | } |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 225 | let tex = inner.texture(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 226 | s.draw(Transform::Normal, |f| { |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 227 | f.render_texture_from_to( |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 228 | &tex, |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 229 | Rectangle::from_size((4.0, 4.0).into()), |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 230 | full(), |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 231 | &[full()], |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 232 | &[], |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 233 | Transform::Normal, |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 234 | 1.0, |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 235 | ) |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 236 | .unwrap(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 237 | }); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 238 | assert_eq!(at(&s.pixels(), 32, 32), BLUE); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 239 | } |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 240 | |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 241 | #[test] |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 242 | fn reports_the_device() { |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 243 | let r = VulkanRenderer::new().unwrap(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 244 | eprintln!("rendering on {}", r.device_name()); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 245 | assert!(!r.device_name().is_empty()); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 246 | } |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 247 | |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 248 | #[test] |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 249 | fn solid_fill_in_the_corner_keeps_its_colour() { |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 250 | let mut s = Scene::new(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 251 | s.draw(Transform::Normal, |f| { |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 252 | f.clear(rgba(BLACK), &[full()]).unwrap(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 253 | let dst = Rectangle::new((48, 48).into(), (16, 16).into()); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 254 | f.draw_solid(dst, &[Rectangle::from_size(dst.size)], rgba(RED)) |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 255 | .unwrap(); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 256 | }); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 257 | assert_eq!(at(&s.pixels(), 56, 56), RED); |
824bf02b6e55 | atagen | 2026-10-16 09:15 UTC | 258 | } |