-
Notifications
You must be signed in to change notification settings - Fork 54
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
Make softbuffer window contexts own the pixel buffers. #40
Comments
Should be possible with dumb/gbm buffers for #42 too, right? Though the implications of working with references into mmaped gbm buffers may be subtler than just shared memory. Also to provide a slice into an shm buffer, we technically trust the compositor to not modify it for soundness. This is probably fine (and less a concern than the reverse) but it's something to be aware of. |
With dumbuffers I believe that would be possible. GBM I guess mapping memory is weird there. |
Redox supports memory mapping window buffers. In fact it is the only way to draw anything. The only problem is the memory needs to be remapped on window resizes, which may complicate the API. |
If we need to ensure that the buffer can't be resized while drawing, we could use a closure in the function to access the buffer which takes an &mut reference. |
According to the people that I've talked to about this, it may not actually be sound. On the X11 end, it's entirely possible for someone to write an implementation of the X server that maliciously modifies that buffer, and then run that server using our Rust program as a client. While the protocol says that the buffer can't be modified mid-transmission (or at least, not without the appropriate X11 events being delivered), there's nothing really stopping the server from disobeying it. I'm not sure about the Wayland end but I'd imagine that a similar problem exists. A copy may unfortunately be necessary in the name of safety, in this case. |
Yes the server can clobber the entire buffer on Wayland. But every client that has damage relies on the compositor not clobbering said buffer. No client I've seen however assumes the server will trash the buffer unless given to something like wlr-screencopy which writes to the shm buffer. |
This is the same concern I mentioned earlier. There are a few considerations here:
|
There is a significant usability harm if we aren't exposing slices. Many libraries like tiny-skia's PixmapMut takes a mutable slice. |
Yes, for a lot of APIs you would want the buffer or a part of it as a slice, so this could be quite limiting. While for some uses it would mostly work alright. |
Given that we're probably moving in this direction, I figure we should come up with an API for this. Here's some considerations:
|
For the Wayland backend, at least, we could possibly hand out an owned object that I think |
Another consideration is that One possible API for this, and #37: Context::new<T: HasRawDisplayHandle>(display: &T) -> Self;
Surface::new<T: HasRawWindowHandle>(context: &Context, window: &T, width: u32, height: u32);
Surface::resize(&mut self, width: u32, height: u32);
Surface::size(&self) -> (u32, u32);
Surface::buffer(&self) -> &[u8];
Surface::buffer_mut(&mut self) -> &mut [u8];
Surface::swap_buffers(&mut self); (Perhaps make all of these return a Considering the Wayland implementation, which is what I'm familiar with:
For other platforms:
|
My thoughts:
|
I disagree with the proposal to use &[u8]. For formats that nicely fit into &[u32], like we exclusively use right now, it's very convenient to have this type — and all associated alignment requirements — specified in the type. One way that we could nonetheless support different types is to have a Surface trait with multiple implementations, and then a SurfaceU8, SurfaceU32, etc. trait for each type. For example, you can have SurfaceRgbU32 implements Surface, SurfaceU32, and SurfaceU8 (because &[u32] can be bytemuck-casted to &[u8]), and others as applicable. But, SurfaceGreyscaleU8 would just implement SurfaceU8. You could also do something like the image crate where you have Surface or Surface instead of fully separate classes. |
I mean we'd zero the buffer when it is allocated or grown, but after swapping buffers it would have the contents of a previous draw. But with single/double/triple buffering that isn't guaranteed either. Oh right, I forgot the API is currently using
For #36, we want a way to read the pixels that are in the front buffer, essentially? For Wayland this is easy enough. For other backends it might not be available in an easily readable way client-side, especially with a no-copy API. (If the pixel data was sent over a socket, or uploaded to GPU.) |
This may seem obvious to some, but I think that it's important to point out that u8 is not required to be aligned to u32 boundaries. Bytemuck does runtime checks for alignment when casting, but there's no guarantee unless we use the larger types. But, of course, the larger types are guaranteed to be aligned compatibly with the smaller types. That's why I want SurfaceU32/SurfaceU8 etc. That way, we can auto-implement the smaller types for the larger ones via bytemuck, thus exposing all relevant alignment guarantees, and being flexible to users. |
Closed by #65 |
At the moment all backends need to perform a copy to present. Some backends such as Wayland (always) and X11 (with the SHM extensions) can simply share the pixel memory with the server. On Windows and Mac this saving wouldn't be possible, but it would help on other platforms.
Not sure what redox does in this case.
The text was updated successfully, but these errors were encountered: