Skip to content

Use fourcc value from the guest to set pixel format for VNC.#151

Merged
jordanhendricks merged 1 commit intooxidecomputer:masterfrom
jordanhendricks:fourcc
Jul 6, 2022
Merged

Use fourcc value from the guest to set pixel format for VNC.#151
jordanhendricks merged 1 commit intooxidecomputer:masterfrom
jordanhendricks:fourcc

Conversation

@jordanhendricks
Copy link
Contributor

@jordanhendricks jordanhendricks commented Jun 29, 2022

Summary

This PR uses the new interfaces added in oxidecomputer/rfb#6 to set the pixel format for the VNC server based on the guest's fourcc. Fourcc is a 4-byte code that maps to a pixel format. Support for understanding these codes has been added into the rfb crate.

Details

Previously, when booting a windows VM and viewing its framebuffer with VNC, one might see orange where the screen should be blue (such as the "Orange Screen of Death"). Here is an image of an orange screen that should be blue:
ksnip_20220503-093009

The problem here was two-fold: first, the VNC server in the rfb crate didn't have a way for consumers to specify what the input pixel format is (which in this case, we get from the fourcc value of the guest). Second, the rfb protocol allows for clients to request an alternate pxiel format, and the rfb crate didn't have support for translating between formats. So the client would display pixels in the format it requested, by the pixels wouldn't actually be in that format. Both of these issues are addressed for our purposes in oxidecomputer/rfb#6.

Testing

Here's an example of the windows lock screen before -- note that the sky is orange (orange where there should be blue):
ksnip_20220429-200648

Now, when we connect to a windows VM, the colors look correct, regardless of the pixel format requested by the client.

Example from noVNC (which requests pixel format little-endian xBGR):
ksnip_20220629-125435

Example from tigervnc (which requests pixel format little-endian xRGB):
ksnip_20220629-125742

propolis = { path = "../propolis", features = ["crucible"], default-features = false }
propolis-client = { path = "../client" }
rfb = { git = "https://github.com/oxidecomputer/rfb", branch = "main" }
rfb = { git = "https://github.com/oxidecomputer/rfb", branch = "fourcc" }
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: this is just here for until oxidecomputer/rfb#6 is merged -- I'll switch it back to the main branch before merging.

match fourcc {
// edk2 default - xRGB, 4 bytes per pixels
// The edk2 default: XR24, little-endian xRGB with 4 bytes per pixel.
0x34325258 => Some(4),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can/should this be rfb::pixel_formats::fourcc::FOURCC_XR24?

Comment on lines +94 to +100
let fb_spec = config.get_framebuffer_spec();
let fb = RamFb::new(fb_spec);
self.initialize_framebuffer(fb.clone()).await;

match fourcc::fourcc_to_pixel_format(fb.fourcc) {
Ok(pf) => {
vnc_server.set_pixel_format(pf).await;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small nit: Does this routine require that the caller have exclusive access to vnc_server? By itself and without that requirement, it looks like there's a race here (if two callers supply different configs, the last one to call initialize_framebuffer won't necessarily be the last one to call set_pixel_format, so the two could get out of sync).

The only caller I can see locks the vnc_server it provides before calling this function, so I don't think there's a bug here so much as a small seam that could tear later.

Would it make sense to make vnc_server a &mut reference to clarify that only one caller at a time can call this with the same server?

@jordanhendricks
Copy link
Contributor Author

jordanhendricks commented Jul 6, 2022

Merging for now because the related rfb PR is merged and will break propolis otherwise. I'll address Greg's feedback in a follow up PR.

@jordanhendricks jordanhendricks merged commit 1cc21c3 into oxidecomputer:master Jul 6, 2022
@jordanhendricks jordanhendricks deleted the fourcc branch July 6, 2022 22:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants