Skip to content
Snippets Groups Projects
  • Lyude Paul's avatar
    553c6a9a
    WIP: rust: drm/kms: Add drm_atomic_state bindings · 553c6a9a
    Lyude Paul authored
    
    Next up is introducing bindings that we can use to represent the global DRM
    atomic state, along with all of the various object states contained within.
    We do this by introducing a few new concepts: borrowed states, atomic state
    mutators, and atomic state composers.
    
    To understand these, we need to quickly touch upon the general life of an
    atomic commit. Assuming a driver does its own internal atomic commit, the
    procedure looks something like this:
    
    * Allocate a new atomic state
    * Duplicate the atomic state of each mode object we want to mutate, and add
      the duplicated state to the new atomic state
    * Check (possibly more then once) the atomic state, possibly modifying it
      along the way
    * Commit the atomic state to software (we'll call this commit time). At
      this point no new objects can be added to the state
    * Finish committing the atomic state to hardware asynchronously
    
    With this in mind, we introduce AtomicStateMutator and AtomicStateComposer
    (along with leaky variants intended for uses in FFI calls). An
    AtomicStateMutator allows mutating an atomic state but does not allow for
    adding new objects to the state. Subsequently, an AtomicStateComposer
    allows for both mutating an atomic state and adding new mode objects. We
    control when we expose each of these types in order to implement the
    limitations required by the aforementioned example.
    
    Note as well that AtomicStateComposer is intended to eventually be usable
    directly by drivers. In this scenario, a driver will be able to create an
    AtomicStateComposer (the equivalent of allocating an atomic state in C) and
    then commit it by passing it to our DRM bindings by-value, insuring that
    once the commit process begins it is impossible to keep using the
    AtomicStateComposer.
    
    The next part of this is allowing users to modify the atomic states of all
    of the objects contained within an atomic state. Since it's an extremely
    common usecase for objects to mutate the atomic state of multiple objects
    at once in an unpredictable order, we need a mechanism that will allow us
    to hand out &mut references to each state while ensuring at runtime that we
    do not break rust's data aliasing rules (which disallow us from ever having
    more then one &mut reference to the same piece of data).
    
    We do this by introducing the concept of a "borrowed" state. This is a very
    similar concept to RefCell, where it is ensured during runtime that when a
    &mut reference is taken out another one cannot be created until the
    corresponding Ref object has been dropped. Our equivalent Ref types are
    BorrowedConnectorState, BorrowedCrtcState, and BorrowedPlaneState.
    
    Each one of these types can be used in the same manner as a Ref - no
    additional borrows for an atomic state may be taken until the existing one
    has been dropped. Subsequently, all of these types implement their
    respective AsRaw* and FromRaw* counter-parts - and allow dereferencing to
    each driver-private data structure for fully qualified borrows (like
    BorrowedCrtcState<'a, CrtcState<T>>. This allows a pretty clean way of
    mutating multiple states at once without ever breaking rust's mutability
    rules.
    
    We'll use all of these types over the next few commits to begin introducing
    various atomic modeset callbacks to each mode object type.
    
    Signed-off-by: Lyude Paul's avatarLyude Paul <lyude@redhat.com>
    
    ---
    
    V3:
    * Drop the TODO about printing a kernel error in BorrowedConnectorState
      I thought this was something we'd want early on in designing this, but
      since then I'm pretty sure we just want to return None - there are valid
      cases where we'd get None while doing connector iteration through an
      atomic state
    * Improve safety comments in BorrowedConnectorState::new()
    * Rename Borrowed*State to *StateMutator
      I think this makes things a lot clearer, as well - cleanup the
      documentation regarding this.
    * Drop plane state iterator for now. It's not that we don't need this, it's
      just that I haven't actually finished writing these up for all types so
      I'd rather focus on that later now that we've demonstrated it's a thing
      that is possible. And it at least shouldn't be needed for getting these
      bindings/rvkms upstream.
    553c6a9a
    History
    WIP: rust: drm/kms: Add drm_atomic_state bindings
    Lyude Paul authored
    
    Next up is introducing bindings that we can use to represent the global DRM
    atomic state, along with all of the various object states contained within.
    We do this by introducing a few new concepts: borrowed states, atomic state
    mutators, and atomic state composers.
    
    To understand these, we need to quickly touch upon the general life of an
    atomic commit. Assuming a driver does its own internal atomic commit, the
    procedure looks something like this:
    
    * Allocate a new atomic state
    * Duplicate the atomic state of each mode object we want to mutate, and add
      the duplicated state to the new atomic state
    * Check (possibly more then once) the atomic state, possibly modifying it
      along the way
    * Commit the atomic state to software (we'll call this commit time). At
      this point no new objects can be added to the state
    * Finish committing the atomic state to hardware asynchronously
    
    With this in mind, we introduce AtomicStateMutator and AtomicStateComposer
    (along with leaky variants intended for uses in FFI calls). An
    AtomicStateMutator allows mutating an atomic state but does not allow for
    adding new objects to the state. Subsequently, an AtomicStateComposer
    allows for both mutating an atomic state and adding new mode objects. We
    control when we expose each of these types in order to implement the
    limitations required by the aforementioned example.
    
    Note as well that AtomicStateComposer is intended to eventually be usable
    directly by drivers. In this scenario, a driver will be able to create an
    AtomicStateComposer (the equivalent of allocating an atomic state in C) and
    then commit it by passing it to our DRM bindings by-value, insuring that
    once the commit process begins it is impossible to keep using the
    AtomicStateComposer.
    
    The next part of this is allowing users to modify the atomic states of all
    of the objects contained within an atomic state. Since it's an extremely
    common usecase for objects to mutate the atomic state of multiple objects
    at once in an unpredictable order, we need a mechanism that will allow us
    to hand out &mut references to each state while ensuring at runtime that we
    do not break rust's data aliasing rules (which disallow us from ever having
    more then one &mut reference to the same piece of data).
    
    We do this by introducing the concept of a "borrowed" state. This is a very
    similar concept to RefCell, where it is ensured during runtime that when a
    &mut reference is taken out another one cannot be created until the
    corresponding Ref object has been dropped. Our equivalent Ref types are
    BorrowedConnectorState, BorrowedCrtcState, and BorrowedPlaneState.
    
    Each one of these types can be used in the same manner as a Ref - no
    additional borrows for an atomic state may be taken until the existing one
    has been dropped. Subsequently, all of these types implement their
    respective AsRaw* and FromRaw* counter-parts - and allow dereferencing to
    each driver-private data structure for fully qualified borrows (like
    BorrowedCrtcState<'a, CrtcState<T>>. This allows a pretty clean way of
    mutating multiple states at once without ever breaking rust's mutability
    rules.
    
    We'll use all of these types over the next few commits to begin introducing
    various atomic modeset callbacks to each mode object type.
    
    Signed-off-by: Lyude Paul's avatarLyude Paul <lyude@redhat.com>
    
    ---
    
    V3:
    * Drop the TODO about printing a kernel error in BorrowedConnectorState
      I thought this was something we'd want early on in designing this, but
      since then I'm pretty sure we just want to return None - there are valid
      cases where we'd get None while doing connector iteration through an
      atomic state
    * Improve safety comments in BorrowedConnectorState::new()
    * Rename Borrowed*State to *StateMutator
      I think this makes things a lot clearer, as well - cleanup the
      documentation regarding this.
    * Drop plane state iterator for now. It's not that we don't need this, it's
      just that I haven't actually finished writing these up for all types so
      I'd rather focus on that later now that we've demonstrated it's a thing
      that is possible. And it at least shouldn't be needed for getting these
      bindings/rvkms upstream.