Comments (9)
Originally Device
was implemented as a struct wrapping around a RawFd
. However, there needed to be a mechanism to close the file descriptor when the Device
goes out of scope, requiring a custom Drop
trait. But if the same RawFd
was used elsewhere in the user's code, then we can't just close it ourselves, which means the user would need to use unsafe
code (which I wanted to avoid).
Wrapping it around a File
worked for most cases that opened /dev/dri/*
directly, but surprisingly many C applications were preferring to open it using either dbus
or getting the file descriptor over a socket. You also lost any other traits/functionality you may want from File
.
Eventually, I found more and more issues while looking at how various display managers and desktop environments were working, and ended up with this over-engineered abomination:
pub struct Device<T, U> where T: Borrow<U>, U: AsRawFd {
inner: T
}
As beautiful as it was, some friends of mine convinced me to scrap the idea of a wrapper and make it a trait to just let the user figure out how they want to use it.
It would be simple enough to include a basic Card
wrapper for the less complex use-cases. On the other hand we could use a blanket implementation like impl<T> Device for T where T: AsRawFd
so that you can directly use File
and avoid requiring a wrapper at all.
What would you prefer?
from drm-rs.
Originally
Device
was implemented as a struct wrapping around aRawFd
. However, there needed to be a mechanism to close the file descriptor when theDevice
goes out of scope, requiring a customDrop
trait. But if the sameRawFd
was used elsewhere in the user's code, then we can't just close it ourselves, which means the user would need to useunsafe
code (which I wanted to avoid).
This is the main reason that the Trait-approach is a godsend for smithay.
Wrapping it around a
File
worked for most cases that opened/dev/dri/*
directly, but surprisingly many C applications were preferring to open it using eitherdbus
or getting the file descriptor over a socket. You also lost any other traits/functionality you may want fromFile
.
This happens a lot in compositors and close semantics are all over the place. Sometime we need to close the file descriptor, sometimes another process does this for us and sometimes we need multiple references of the same file. Tracking all those cases requires a lot of flexibility and having to use anything more then a RawFd
(maybe even with its own Drop
implementation, I would need to work around), would make things way more difficult for smithay.
Eventually, I found more and more issues while looking at how various display managers and desktop environments were working, and ended up with this over-engineered abomination:
pub struct Device<T, U> where T: Borrow<U>, U: AsRawFd { inner: T }As beautiful as it was, some friends of mine convinced me to scrap the idea of a wrapper and make it a trait to just let the user figure out how they want to use it.
A huge thanks to that friend.
It would be simple enough to include a basic
Card
wrapper for the less complex use-cases. On the other hand we could use a blanket implementation likeimpl<T> Device for T where T: AsRawFd
so that you can directly useFile
and avoid requiring a wrapper at all.What would you prefer?
The latter solution clashes with some use-cases in smithay. I could work around this, but I would strongly prefer the first approach, so I do not need to add more indirection in smithay. Not every file descriptor is a valid drm-device, but I deal with a lot of different structs implementing AsRawFd
in smithay. As a result a blanket implementation does also not make much sense from a logical point of view.
from drm-rs.
Those are pretty good excuses for not having a default implementation? Do you see display managers the primary use-case for this crate? If that's the case, then I will admit to being wrong about the 99% case just wanting to own the display for the life of the process.
My thinking was definitely biased towards embedded use-cases like kiosks, touch-screen interfaces, retro game consoles, etc. In my case I'm specifically looking to get graphics onscreen as quickly as possible after boot (a custom dashboard for an automotive project).
from drm-rs.
I think I would also favor the first option of just having a standard Card implementation for those that want it.
from drm-rs.
Do you see display managers the primary use-case for this crate? If that's the case, then I will admit to being wrong about the 99% case just wanting to own the display for the life of the process.
That's difficult to determine. Display managers and desktop environments are definitely the most complex use cases for this crate. They need to be able to dynamically switch modes throughout the session, share graphics buffers with multiple process', and work across a large number of different graphics cards. Not to mention the new 'syncobj' and 'leasing` parts that the kernels have recently implemented.
Those requirements make it a bit difficult to provide default simple solutions. Instead of trying to guess how people are going to use it, I just made the goal of this crate to provide a safe, direct interface to the DRM sybsystem with minimal overhead (even more minimal than libdrm :P).
I will likely include some sort of prelude
module that re-exports the traits and provides a simple, concrete implementation of them. Until then, the examples provide a really simple Card
structure that you can paste into your code. If there's an issue with it, let me know.
from drm-rs.
Originally
Device
was implemented as a struct wrapping around aRawFd
. However, there needed to be a mechanism to close the file descriptor when theDevice
goes out of scope, requiring a customDrop
trait. But if the sameRawFd
was used elsewhere in the user's code, then we can't just close it ourselves, which means the user would need to useunsafe
code (which I wanted to avoid).
I wonder if the issue is that RawFd
doesn't encode ownership, and if the right answer would be to add the notion of a a "scoped file descriptor", which would be either owned (implementing Drop), or borrowed (not implementing drop), but both themselves implementing AsRawFd
. Then the struct itself can simply be a wrapper around an AsRawFd
. Like with the type system in general, it should be possible to temporarily borrow and OwnedFd, and it should also be possible permanently move an OwnedFd to some external place. Meanwhile, if we're receiving and file descriptor from an external process, we simply need to choose the right type.
As I write this I'm wondering about the case for a WeakFd
?
from drm-rs.
File
is a basically an owned file descriptor. When a File
drops it closes the underlying file descriptor.
You can get around that with IntoRawFd
, which turns the File
into a RawFd
without closing it. Then there's also FromRawFd
, which takes a RawFd
and creates an owned File
. However, the latter is unsafe as it can't assume it's the sole owner of the underlying file descriptor.
However, I'm not quite sure what the issue you're trying to solve here is. It sounds like you dislike the design pattern used, but I don't see any scenario that it fails to perform well in.
from drm-rs.
However, I'm not quite sure what the issue you're trying to solve here is. It sounds like you dislike the design pattern used, but I don't see any scenario that it fails to perform well in.
Well at this point I've kinda gotten over it. What is it about pub struct Device<T, U> where T: Borrow<U>, U: AsRawFd
that people find so painful? Coming from the outside, and being a bit new to rust, that's roughly what I expected to see.
from drm-rs.
Well at this point I've kinda gotten over it. What is it about
pub struct Device<T, U> where T: Borrow<U>, U: AsRawFd
that people find so painful? Coming from the outside, and being a bit new to rust, that's roughly what I expected to see.
In terms of how the code works? Nothing. But nesting generics blows up function signatures and requires even more generics if you have an object that needs to reference one. Makes writing clean code difficult, and doesn't provide any extra safety guarantees compared to the trait-based method.
from drm-rs.
Related Issues (20)
- Support for driver-specific APIs HOT 1
- Missing zero in control/mod.rs? HOT 2
- thread 'main' panicked at 'Could not set CRTC: InvalidArgument' in Examples/legacy_modeset.rs HOT 13
- Atomic mode setting compatibility with libdrm HOT 2
- transmuting Vec might lead to undefined behavior HOT 9
- Failing to get encoders for connector HOT 4
- Atomic modesetting on RPi HOT 12
- Expose drm_sys::drm_clip_rect in the main crate HOT 2
- invalid link HOT 1
- Automate binding updates + Use kernel rather than libdrm HOT 3
- Export drm RDWR/CLOEXEC flags HOT 1
- Async atomic flips
- Various valgrind errors related to uninitialized memory HOT 2
- Consider replacing drm-sys with linux-raw-sys HOT 5
- Taking screenshot HOT 1
- No license file HOT 1
- 0.3.x stable Rust support HOT 4
- Continuous integration using Github Actions HOT 2
- Is the main branch abandoned ? HOT 2
- [Question] Failed to create framebuffer HOT 4
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from drm-rs.