Skip to content

Commit 7a79a1d

Browse files
authored
Merge pull request tock#4957 from alevy/bug/virtio-gpu
bug-fixes: Virtio GPU brightness and framed-write correctness
2 parents c9f19f9 + d387191 commit 7a79a1d

1 file changed

Lines changed: 23 additions & 19 deletions

File tree

  • chips/virtio/src/devices/virtio_gpu

chips/virtio/src/devices/virtio_gpu/mod.rs

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -409,25 +409,26 @@ impl<'a, 'b, F: DmaFence> VirtIOGPU<'a, 'b, F> {
409409
// areas when using `rect.width` or `rect.height` as a divisor:
410410
0
411411
} else if current_draw_offset.0 == 0 {
412-
// Okay, we can start drawing the full rectangle. We want to try
413-
// drawing any full rows, if there are any left, and if not the
414-
// last partial row:
412+
// We're at the start of a row. If the client buffer holds less than
413+
// a full row, copy just those pixels as a partial trailing row.
414+
// Otherwise, copy as many full rows as fit in the buffer (leaving
415+
// any remainder to a subsequent iteration).
416+
//
417+
// However, batching multiple rows into a single
418+
// `TRANSFER_TO_HOST_2D` is only safe when `draw_rect.width` matches
419+
// the resource's width: the device reads row `h` of the transfer
420+
// rectangle from backing offset `t2d.offset + h * (resource_width *
421+
// bpp)`, but our backing is a compact `draw_rect.width * bpp`
422+
// per-row buffer. When the widths don't match, cap to a single row
423+
// so the strided read collapses to a single contiguous copy:
415424
assert!(current_draw_offset.1 <= draw_rect.height || remaining_pixels == 0);
416-
if current_draw_offset.1 >= draw_rect.height {
417-
// Just one row left to draw, and we start from `x ==
418-
// 0`. This means we can just copy however much more data
419-
// the client buffer holds. We've previously checked that
420-
// the client buffer fully fits into the draw area, but
421-
// re-check that assertion here:
422-
assert!(draw_rect.width as usize >= write_buffer_remaining_pixels);
425+
if write_buffer_remaining_pixels < draw_rect.width as usize {
423426
write_buffer_remaining_pixels
427+
} else if draw_rect.width == self.width {
428+
(write_buffer_remaining_pixels / draw_rect.width as usize)
429+
* draw_rect.width as usize
424430
} else {
425-
// There is more than one row left to copy, and we start
426-
// from `x == 0`. If the client buffer lines up with the end
427-
// of a row, we can copy them as a single
428-
// rectangle. Otherwise, we need two copies:
429-
write_buffer_remaining_pixels / (draw_rect.width as usize)
430-
* (draw_rect.width as usize)
431+
draw_rect.width as usize
431432
}
432433
} else {
433434
// Our current draw offset is not zero. This means we must copy
@@ -580,7 +581,9 @@ impl<'a, 'b, F: DmaFence> VirtIOGPU<'a, 'b, F> {
580581

581582
// We always draw left -> right, top -> bottom, so we can simply set the
582583
// current `x` and `y` coordinates to the bottom-right most coordinates
583-
// we've just drawn (while wrapping and carrying the one):
584+
// we've just drawn (while wrapping and carrying the one). `y` is the
585+
// last row we drew (relative to `draw_rect`); the wrap below advances
586+
// it to the next row when we've finished the row's rightmost column.
584587
current_draw_offset.0 = drawn_area
585588
.x
586589
.checked_add(drawn_area.width)
@@ -589,7 +592,8 @@ impl<'a, 'b, F: DmaFence> VirtIOGPU<'a, 'b, F> {
589592
current_draw_offset.1 = drawn_area
590593
.y
591594
.checked_add(drawn_area.height)
592-
.and_then(|drawn_y1| drawn_y1.checked_sub(draw_rect.y))
595+
.and_then(|drawn_y1| drawn_y1.checked_sub(1))
596+
.and_then(|last_row| last_row.checked_sub(draw_rect.y))
593597
.unwrap();
594598

595599
// Wrap to the next line when we've finished writing the column of our
@@ -1016,7 +1020,7 @@ impl<'a, F: DmaFence> Screen<'a> for VirtIOGPU<'a, '_, F> {
10161020

10171021
fn set_brightness(&self, _brightness: u16) -> Result<(), ErrorCode> {
10181022
// nop, not supported
1019-
Ok(())
1023+
Err(ErrorCode::NOSUPPORT)
10201024
}
10211025

10221026
fn set_power(&self, enabled: bool) -> Result<(), ErrorCode> {

0 commit comments

Comments
 (0)