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

Add connector_id to DrmWindowHandle #170

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## Unreleased

* Add optional connector_id field to DrmWindowHandle (#170)

## 0.6.2 (2024-05-17)

* Add OpenHarmony OS support (#164)
Expand Down
29 changes: 28 additions & 1 deletion src/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,8 @@ impl DrmDisplayHandle {
pub struct DrmWindowHandle {
/// The primary drm plane handle.
pub plane: u32,
/// An optional handle to chosen drm connector
pub connector_id: Option<NonZeroU32>,
Copy link
Member

Choose a reason for hiding this comment

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

Should document what is it.

Copy link
Member

Choose a reason for hiding this comment

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

Also ideally with links to other documentation explaining it, if such docs exist.

}

impl DrmWindowHandle {
Expand All @@ -255,7 +257,32 @@ impl DrmWindowHandle {
/// let handle = DrmWindowHandle::new(plane);
Copy link
Member

Choose a reason for hiding this comment

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

Please update this example to also set the connector_id

Copy link
Member

Choose a reason for hiding this comment

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

What I mean here is something like:

Suggested change
/// let handle = DrmWindowHandle::new(plane);
/// # connector_id = unsafe { NonZeroU32::new_unchecked(1) };
/// let mut handle = DrmWindowHandle::new(plane);
/// handle.connector_id = Some(connector_id);

/// ```
pub fn new(plane: u32) -> Self {
Self { plane }
Self {
plane,
connector_id: None,
}
}

/// Create a new handle to a plane and associated connector_id.
///
///
/// # Example
///
/// ```
/// # use raw_window_handle::DrmWindowHandle;
/// # use core::num::NonZeroU32;
/// #
/// let plane: u32;
/// # plane = 0;
/// let connector_id: NonZeroU32;
/// # connector_id = unsafe { NonZeroU32::new_unchecked(1) };
/// let handle = DrmWindowHandle::new_with_connector_id(plane, connector_id);
/// ```
pub fn new_with_connector_id(plane: u32, connector_id: NonZeroU32) -> Self {
Copy link
Member

@madsmtm madsmtm Jul 15, 2024

Choose a reason for hiding this comment

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

Nit: This doesn't really match what's exposed for the other platforms, there, the user would just do:

let mut handle = DrmWindowHandle::new(...);
handle.connector_id = Some(...);

But perhaps this approach is indeed better? In any case, might make sense to not do such a change in this PR, as it's somewhat inconsistent with the other platforms.

Copy link
Author

@morr0ne morr0ne Jul 15, 2024

Choose a reason for hiding this comment

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

Using the _with_* suffix aligns better with rust's coding guidelines, promoting more idiomatic code. If there is a consensus that this requires further discussion, I can amend the changes and open a separate pr. However, I believe this approach is the most appropriate for exposing the api and that similar constructors should be considered for other platforms as well.

Implementing these constructors will not compromise backwards compatibility, as the only scenario requiring their removal would be the elimination of the corresponding fields. In such a case, a breaking change would be inevitable regardless.

Copy link
Author

Choose a reason for hiding this comment

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

Furthermore, implementing a separate constructor prevents unnecessary mutability of the created handle, which typically does not require any kind of modification.

Copy link
Member

Choose a reason for hiding this comment

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

I'm generally against constructors like that in this crate because they are prone to factorial growth. So if you want to add one more optional field you'd need to add permutations, since you don't generally require all the things to be present.

Unless you just stuck constructors with Option but I don't see a point in it given that you can just build with WindowHandle { } syntax because it's a pod with all fields being pub.

I'm also not that much in love with ::new methods, but it's more of a shorthand for essential stuff, I guess.

Copy link
Author

Choose a reason for hiding this comment

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

The primary justification for introducing a new constructor is that it is not feasible to manually instantiate a handle due to the struct being marked as non_exhaustive. This is not merely a matter of convenience or shorthand. Structs marked as non_exhaustive cannot be instantiated outside of their originating crate. A dedicated function to construct one is mandatory.

Copy link
Author

Choose a reason for hiding this comment

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

They can as long as they have Default but I forgot that we don't have it because we can not really provide Default. I still don't like the constructor because factorial growth.

The proper solution would be to only have one constructor that takes all the parameters but that would break backwards compatibility and require a version bump. My understanding was that we should avoid that if possible.

Copy link
Member

Choose a reason for hiding this comment

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

The connector is optional though, since not all APIs require it and some APIs may require a list of connectors.

Copy link
Author

Choose a reason for hiding this comment

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

The connector is optional though, since not all APIs require it and some APIs may require a list of connectors.

Which perfectly translates into the new constructor. A new constructor like this would only be necessary for an optional field.

I am also not aware of any API that requires a least of connectors that would also consume a window handle. Do you have any examples? If that's the case then maybe the signature of field should be reconsidered. My main use case for this is implementing a drm backend for wgpu which afaik would require only a specific connector, at least for the vulkan backend.

Copy link
Member

Choose a reason for hiding this comment

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

Do you have any examples? If that's the case then maybe the signature of field should be reconsidered. My main use case for this is implementing a drm backend for wgpu which afaik would require only a specific connector, at least for the vulkan backend.

I know that drm APIs accept an array IIRC, at least smithay uses arrays of connectors a lot. Though, they unlikely to use the raw-window-handle for that typo of things and if Vulkan needs just a single connector than it's fine the way it is.

In general I won't block on adding a constructor, it's just I don't really like it, though, I'm not sure there will be more fields to add.

Copy link
Member

@madsmtm madsmtm Jul 16, 2024

Choose a reason for hiding this comment

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

I'd like @Lokathor's opinion - but as stated in my first comment, this is very much nitpicking ;)

Self {
plane,
connector_id: Some(connector_id),
}
}
}

Expand Down
Loading