Skip to content
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

X11 backend #371

Merged
merged 5 commits into from
Oct 18, 2021
Merged

X11 backend #371

merged 5 commits into from
Oct 18, 2021

Conversation

i509VCB
Copy link
Member

@i509VCB i509VCB commented Aug 25, 2021

This pull request is part of series in #293.

The X11 backend is renderer agnostic and imports a dmabuf for presentation to a window. The X11 backend also supplies input events, and events indicating window exposure, close requests and resizing.

This backend requires the X server to have the Xfixes, DRI3 and Present extensions. Namely the DRI3 extension means proprietary nvidia gpus cannot use the backend as the X server does not supply those when running with nvidia gpus.

FreeBSD and Non-Linux

These platforms should work although these were not tested. The only functionality not implemented is resolving another type of DrmNode from an existing DrmNode. This functionality isn't strictly necessary to run the backend but may mean some hardware configurations won't work.

@DemiMarie
Copy link
Contributor

libX11 is not thread-safe unless XInitThreads is called.

XCBConnection::from_raw_xcb_connection(xcb_connection_t, false)
};

if xcb_connection.is_err() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Off topic: I was briefly thinking "how can this be an error?!?". Then I looked at the code and saw that x11rb has to parse the .setup() that the X11 server sent here and that can go wrong (e.g. the server sent a too short setup claiming to contain 10000 screens). libxcb just does not handle this possibility at all...

Now I am happy about all the safety guarantees that Rust provides.

No one will get this, but since you already wrote on this issue: CC @DemiMarie x11rb is the Rust library I was talking about elsewhere (in case you even care about this - if not, that's totally fine as well).

Copy link
Contributor

Choose a reason for hiding this comment

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

I do care! For one, this means that Smithay has a chance to have XWayland support that is robust against malicious X servers, assuming that the X server someday gets sandboxed. That would allow for per-Flatpak X servers that run in the Flatpak sandbox, for example.

Does x11rb use libxcb internally and then validate its output, or does it do everything itself?

Copy link
Member Author

@i509VCB i509VCB Sep 9, 2021

Choose a reason for hiding this comment

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

x11rb I believe decodes the events and encodes requests itself, libxcb only being used to read and write across the socket when the XCBConnection is used.

Copy link
Contributor

@psychon psychon Sep 13, 2021

Choose a reason for hiding this comment

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

Does x11rb use libxcb internally and then validate its output, or does it do everything itself?

There are two options in x11rb. There is RustConnection that is pure rust. If you disable the allow-unsafe-code feature, then you lose support for FD-passing, but get all of Rust's safety guarantees always.

With the allow-unsafe-code feature, there is also a XCBConnection. Just as @i509VCB said, this only uses libxcb to send & receive raw bytes (This uses C APIs like xcb_send_request and xcb_wait_for_event / xcb_wait_for_reply from libxcb). Since libxcb does not provide an extra length return, the code has to look at something like three bytes of an X11 packet and figure out the length of the packet, then call the unsafe function std::slice::from_raw_parts. Afterwards, the same safe code is used as with RustConnection. I am pretty sure that these length calculations are exactly the same math as libxcb does internally, but obviously this is a bit less safe than RustConnection.

XCBConnection allows sharing the connection with C code that expects a libxcb xcb_connection_t* (e.g. cairo or mesa). RustConnection is a Rust-only thing that cannot be used in this way.

I bet no one cares, but x11rb even works on Windows. Obviously, there is no FD passing there.

x11::Event::Expose(expose) => {
// TODO: We would ideally use this to determine damage and render more efficiently that way.
//
// Although there is an Expose with damage event somewhere?
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't understand the question, but I'll try to answer it anyway:

A expose event contains a rectangle that was exposed (x, y, width, height). If a non-rectangular area is exposed (e.g. Two other windows partially cover your window and now your window is brought to front. Thus, these two rectangles are exposed), then two Expose events are sent. The first one contains .count == 1 to indicate that another event will follow.

(And if there were four rectangles, then the first one would have count = 3, the next one count = 2 etc...)

@i509VCB i509VCB changed the title Direct X11 backend X11 backend Sep 9, 2021
@i509VCB
Copy link
Member Author

i509VCB commented Sep 24, 2021

libX11 is not thread-safe unless XInitThreads is called.

XCB FFI is no longer necessary and is now no longer included in the backend.

@i509VCB i509VCB marked this pull request as ready for review September 26, 2021 04:38

Err(err) => {
if let SwapBuffersError::ContextLost(err) = err {
error!(log, "Critical Rendering Error: {}", err);
Copy link
Contributor

Choose a reason for hiding this comment

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

Errors other than ContextLost are just silently ignored? Is that right?

Copy link
Member Author

Choose a reason for hiding this comment

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

Copied from winit is the excuse here, probably not a great thing to copy either.

Copy link
Member Author

@i509VCB i509VCB left a comment

Choose a reason for hiding this comment

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

Reviewing my own code 🤔

impl AnvilState<X11Data> {
pub fn process_input_event<B: InputBackend>(&mut self, event: InputEvent<B>) {
match event {
InputEvent::Keyboard { event } => match self.keyboard_key_to_action::<B>(event) {
Copy link
Member

Choose a reason for hiding this comment

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

I feel like this could have some deduplication wrt other backends

@elinorbgr
Copy link
Member

Also it looks like this needs a rebase now.

@i509VCB i509VCB force-pushed the x-client branch 3 times, most recently from aed87a4 to 431fdce Compare October 17, 2021 07:31
Copy link
Member

@Drakulix Drakulix left a comment

Choose a reason for hiding this comment

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

Some minor nitpicks, but wow this PR is clean!
I really like it, thanks a lot.

Also there is some stuff, that should be de-duplicated in the future. E.g. X11's buffers share a lot of code with the GbmBufferedSurface, but we can do that later. This PR has gotten big enough.

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.

5 participants