Commit 0b68ce424a32
tarball2 files changed+61-4
@@ -27,6 +27,9 @@ pub struct VulkanFrame<'frame, 'buffer> {
2727
renderer: &'frame mut VulkanRenderer,2828
target: &'frame mut VulkanTarget<'buffer>,2929
output: Size<i32, Physical>,30
+ /// The output rotated into the space draws are given in, which differs31
+ /// from `output` for 90 and 270 degree transforms.32
+ area: Size<i32, Physical>,3033
transform: Transform,3134
ops: Vec<Op>,3235
clip: Option<Clip>,@@ -63,6 +66,7 @@ impl<'frame, 'buffer> VulkanFrame<'frame, 'buffer> {
6366
renderer,6467
target,6568
output,69
+ area: transform.transform_size(output),6670
transform,6771
ops: Vec::new(),6872
clip: None,@@ -81,7 +85,7 @@ impl<'frame, 'buffer> VulkanFrame<'frame, 'buffer> {
8185
};8286
let [tl, tr, br, bl] = c.radii;8387
let corners = [[tl, 0.0], [tr, 0.0], [bl, 0.0], [br, 0.0]];84
- let (fb, r) = to_framebuffer(c.rect, corners, self.output, self.transform);88
+ let (fb, r) = to_framebuffer(c.rect, corners, self.area, self.transform);8589
let rect = [8690
fb.loc.x as f32,8791
fb.loc.y as f32,@@ -98,7 +102,7 @@ impl<'frame, 'buffer> VulkanFrame<'frame, 'buffer> {
98102
}99103
100104
fn fb_rect(&self, r: Rectangle<i32, Physical>) -> Option<vk::Rect2D> {101
- let r = rect_to_framebuffer(r, self.output, self.transform)105
+ let r = rect_to_framebuffer(r, self.area, self.transform)102106
.intersection(Rectangle::from_size(self.fb_size()))?;103107
Some(vk::Rect2D {104108
offset: vk::Offset2D {@@ -175,7 +179,7 @@ impl<'frame, 'buffer> VulkanFrame<'frame, 'buffer> {
175179
return Ok(());176180
}177181
let uvs = texture_uvs(src, dst.size, texture.size(), src_transform);178
- let (fb, uv) = to_framebuffer(dst, uvs, self.output, self.transform);182
+ let (fb, uv) = to_framebuffer(dst, uvs, self.area, self.transform);179183
let (clip, radii, ring) = self.clip_push();180184
let push = Push {181185
dst: self.ndc(fb),@@ -236,7 +240,7 @@ impl Frame for VulkanFrame<'_, '_> {
236240
if scissors.is_empty() {237241
return Ok(());238242
}239
- let (fb, _) = to_framebuffer(dst, [[0.0; 2]; 4], self.output, self.transform);243
+ let (fb, _) = to_framebuffer(dst, [[0.0; 2]; 4], self.area, self.transform);240244
let (clip, radii, ring) = self.clip_push();241245
let push = Push {242246
dst: self.ndc(fb),@@ -185,3 +185,56 @@ fn clip_radius_stays_on_its_corner_when_rotated() {
185185
}186186
assert_eq!(at(&px, W / 2, H / 2), GREEN);187187
}188
+189
+/// Draws arrive in the rotated space, which for a quarter turn on a wide190
+/// output is tall, so its far corner has to land inside the framebuffer.191
+#[test]192
+fn quarter_turn_on_a_wide_output_fills_it() {193
+ let (fw, fh) = (64, 32);194
+ let mut renderer = VulkanRenderer::new().expect("no usable Vulkan device");195
+ let mut image = renderer196
+ .create_buffer(Fourcc::Argb8888, (fw, fh).into())197
+ .unwrap();198
+ for transform in [Transform::_90, Transform::_270, Transform::Flipped90] {199
+ let mut target = renderer.bind(&mut image).unwrap();200
+ let mut frame = renderer201
+ .render(&mut target, (fw, fh).into(), transform)202
+ .unwrap();203
+ let area = Rectangle::from_size((fh, fw).into());204
+ frame.clear(rgba(BLACK), &[area]).unwrap();205
+ let near = Rectangle::new((0, 0).into(), (8, 8).into());206
+ let far = Rectangle::new((fh - 8, fw - 8).into(), (8, 8).into());207
+ frame208
+ .draw_solid(near, &[Rectangle::from_size(near.size)], rgba(GREEN))209
+ .unwrap();210
+ frame211
+ .draw_solid(far, &[Rectangle::from_size(far.size)], rgba(RED))212
+ .unwrap();213
+ frame.finish().unwrap().wait().unwrap();214
+ drop(target);215
+ let target = renderer.bind(&mut image).unwrap();216
+ let mapping = renderer217
+ .copy_framebuffer(218
+ &target,219
+ Rectangle::from_size((fw, fh).into()),220
+ Fourcc::Abgr8888,221
+ )222
+ .unwrap();223
+ let px = renderer224
+ .map_texture(&mapping)225
+ .unwrap()226
+ .as_chunks::<4>()227
+ .0228
+ .to_vec();229
+ let at = |x: i32, y: i32| px[(y * fw + x) as usize];230
+ let corners = [(0, 0), (fw - 1, 0), (0, fh - 1), (fw - 1, fh - 1)];231
+ let green: Vec<_> = corners232
+ .iter()233
+ .filter(|&&(x, y)| at(x, y) == GREEN)234
+ .collect();235
+ let red: Vec<_> = corners.iter().filter(|&&(x, y)| at(x, y) == RED).collect();236
+ assert_eq!((green.len(), red.len()), (1, 1), "{transform:?}");237
+ let (g, r) = (green[0], red[0]);238
+ assert!(g.0 != r.0 && g.1 != r.1, "{transform:?} not diagonal");239
+ }240
+}