-
Notifications
You must be signed in to change notification settings - Fork 50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a function for retrieving the window contents #104
Conversation
On Wayland, if we want to read from the back buffer we can just do that. If we want to get window contents that this softbuffer I'm not sure exactly how this API would be used though. It doesn't seem ideal to use every frame. If we have make a request to the display server and copy all the pixels to do this, would to be better for the application that wants to retain graphics to just have it's own persistent buffer and copy into the |
Web implementation: #105.
I assumed that this is the purpose of this API. I implemented the Web implementation accordingly, otherwise it would be no-op like you suggested. |
Additionally, I'm unsure how other platforms then Web handle this, but what if the surface was resized, what does fetch do in this case, error? Or just get part of the contents that fit into the buffer? Does it zero out the rest if the fetched content is smaller then the current size? |
If so, this isn't possible on Wayland. I'm guessing it's not possible on macOS given how the APIs work, but I would be less confident there. It's not necessarily bad to expose features that only work on some backends, but I'd like to see more clearly what the actual application for this would be. And whether or not its the best way to achieve that. |
The goal of this API is to get the currently presented contents of the buffer and download it to the client. This is nice for testing, since it allows you to get the image created by the user. It would be nice for testing not only |
Ah. For debugging uses it makes more sense. Then the performance concerns that would otherwise apply here aren't so much of a problem. It should be clearly documented what this is and is not suitable for though. I also wonder whether a method on |
That's probably a good idea. I've changed this PR to use this design. |
tests/present_and_fetch.rs
Outdated
|
||
// Set all pixels to red. | ||
let mut buffer = surface.buffer_mut().unwrap(); | ||
buffer.fill(0xFF0000FF); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That looks like blue to me.
Line 340 in fcda747
/// 00000000RRRRRRRRGGGGGGGGBBBBBBBB |
buffer.fill(0xFF0000FF); | |
buffer.fill(0x00FF0000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
0x00FF0000
won't be the same color on big-endian systems, right? If we care about those.
Something like u32::from_ne_bytes
could be used for consistent behavior.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think so? I went down a rabbit hole for a bit there and confirmed two things:
- Literals are always written in big-endian in Rust. I couldn't find any documentation on that, so I tried it out: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=c1a0820eba008226bae7771c1f510fe8.
- Bitshift operators always act in big-endian (except on some old PowerPC architectures I read somewhere?).
So I think what we are doing in Rust right now, seems to be pretty much cross-endianness compatible.
What I don't know is if the APIs expect us to turn things around on big-endian targets.
I also assume nobody here actually has a big-endian system lying around to try it out?
That said, on Web, my purview, this isn't a concern.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the use of bitshifts in the examples would also be wrong on big endian. We represent color with u32
, but it's really interpreted more like [u8; 4]
but with 4 byte alignment. Which isn't dependent on endianess.
I don't have a big endian system to test on, though I fixed a similar issue in tiny-skia that someone reported: linebender/tiny-skia#69. That one is easy to test with virtualization, but this is a bit more complicated since one may want a full OS with a display server. Maybe X11 backend over TCP could work...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe X11 backend over TCP could work...
Sounds like fun, please share the results when you get them 🤣.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It can be faster to work with 32-bit values than individual bytes. And things like tiny-skia work on &[u32]
. And you can safely cast &[u32]
to &[u8]
but not the other way around due to alignment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure what to think of this, there isn't actually a safe method to cast &[u32]
to &[u8]
I know of. I would argue that u32
is definitely a worse user interface and the improved speed is speculation (I actually agree with that speculation).
Just an idea: what do you think of &[[u8; 4]]
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[u32]
has alignment 4
(on typical architectures), while [u8; 4]
has alignment 1
. So there's not currently a standard library method to cast &[u32]
to &[u8]
, but it's always sound while the reverse is not true. Likewise it is potentially unsound to cast &[[u8; 4]]
to &[u32]
.
bytemuck
is popular for this sort of thing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
while
[u8; 4]
has alignment1
.
Ah, apologies, was thinking that this does have an alignment of 4 actually, for some reason (I think I played around with too much shaders lately ...).
Alright, w/e, I think I'm still in favor of &[u8]
until we can show a reasonable performance degradation, but this is an issue for another time.
In the meantime, your original problem still needs to be addressed. I think we should also document this somewhere.
Line 340 in fcda747
/// 00000000RRRRRRRRGGGGGGGGBBBBBBBB |
This could be a bit confusing, because it's showing big-endian order, which most platforms aren't, but it's also representative of how literals are written in Rust.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I say we handle it afterwards: #109.
So should this account for stuff not presented by |
Yes, this is what I wanted. Right now, my goal is to have a reproducible test harness; not only in
|
We'll need to consider how this interacts with #98. Does the method Conversion is not necessarily lossless, if we support pixel formats that aren't just orderings RGB (though again, things like 10 bit color won't work with #98 is probably the most important feature missing in softbuffer currently, though I'm still not sure how best to design that, including conversion functionality. |
On Web, the Same if |
I think this is ready now. macOS, Wayland and Redox are unimplemented for now; I'm hoping that the platform maintainers will be able to take care of that. |
Fix X11 bugs - Vec not being filled all the way - Tests need to be run with Xvfb - Add note about visibility
Use winit-test as a test harness Redo testing harness for WASM Make sure the wayland runner doesn't use xvfb
Adjust Web code style
Adjust `fetch()` test for Web Test fixes
Add line to docs about unsupported platforms Test fixes
I'm unsure why WASM is failing by returning an empty buffer, nor am I sure why Windows seems to spurious fail in the same way. |
Web fails because #104 (comment) wasn't applied. Currently fails on X11 because of that too. I confirmed that both succeed when applying #104 (comment). |
Looks like adding |
* On MacOS, the contents scale is updated when set_buffer() is called, to adapt when the window is on a new screen (#68). * **Breaking:** Split the `GraphicsContext` type into `Context` and `Surface` (#64). * On Web, cache the document in the `Context` type (#66). * **Breaking:** Introduce a new "owned buffer" for no-copy presentation (#65). * Enable support for multi-threaded WASM (#77). * Fix buffer resizing on X11 (#69). * Add a set of functions for handling buffer damage (#99). * Add a `fetch()` function for getting the window contents (#104). * Bump MSRV to 1.64 (#81).
Closes #36 by adding a
fetch()
method for theBuffer
method. Might need a rework in the face of #98 or #99.WIP for now, with only implementations for X11 and Win32. I would appreciate guidance from the platform maintainers on how this would be implemented on other platforms.