STRUCT DRM_CRTC_COMMIT(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

πŸ’… struct drm_crtc_commit(9) β€” the kernel API manual, but make it make sense

okay so bestie, we're in the Kernel API Manual today and the star of the show is struct drm_crtc_commit β€” it's the little guy that tracks modeset commits on a CRTC πŸŽ€


✨ NAME ✨

struct drm_crtc_commit β€” track modeset commits on a CRTC. that's it, that's the vibe πŸ’–


πŸ¦‹ SYNOPSIS πŸ¦‹

struct drm_crtc_commit {
    struct drm_crtc *crtc;
    struct kref ref;
    struct completion flip_done;
    struct completion hw_done;
    struct completion cleanup_done;
    struct list_head commit_entry;
    struct drm_pending_vblank_event *event;
    bool abort_completion;
 };

🌸 Members 🌸

okay so let's meet the cast, one by one, no skips πŸ‘‘

  • crtc β€” the DRM CRTC this commit belongs to. like, the main character of the whole operation πŸ’…
  • ref β€” the reference count for this structure. bestie, it's needed so you can block on completions without the risk of the completion just… disappearing meanwhile 😭 no cap.
  • flip_done β€” gets signaled when the hardware has flipped to the new set of buffers. it signals at the same time as when the drm event for this commit is sent to userspace, or when an out-fence is singalled. and note β€” for most hardware, in most cases, this happens after hw_done is signalled. lowkey important.

completion of this stage is signalled implicitly by calling drm_crtc_send_vblank_event on drm_crtc_state.event. 🫢

  • hw_done β€” gets signaled when all hw register changes for this commit have been written out. especially when disabling a pipe, this can be much later than flip_done, since that one can signal already when the screen goes black, whereas to fully shut down a pipe more register I/O is required. it's giving "the screen is black but the job is not done" πŸ’€

note that this does not need to include separately reference-counted resources like backing storage buffer pinning, or runtime pm management.

drivers should call drm_atomic_helper_commit_hw_done to signal completion of this stage. periodt.

  • cleanup_done β€” gets signaled after old buffers have been cleaned up by calling drm_atomic_helper_cleanup_planes. since this can only happen after a vblank wait completed, it might be a bit later. this completion is useful to throttle updates and avoid hardware updates getting ahead of the buffer cleanup too much. iconic throttling behaviour honestly πŸŽ€

drivers should call drm_atomic_helper_commit_cleanup_done to signal completion of this stage.

  • commit_entry β€” entry on the per-CRTC drm_crtc.commit_list. protected by $drm_crtc.commit_lock. πŸ”’
  • event β€” drm_pending_vblank_event pointer to clean up private events.
  • abort_completion β€” a flag that's set after drm_atomic_helper_setup_commit takes a second reference for the completion of $drm_crtc_state.event. it's used by the free code to remove the second reference if commit fails. πŸ™ˆ

🧚 Description 🧚

so this structure is used to track pending modeset changes and atomic commit on a per-CRTC basis. and since updating the list should never block, this structure is reference counted so waiters can safely wait on an event to complete without holding any locks. slay, safe concurrency πŸ’–

it has 3 different events in total to allow a fine-grained synchronization between outstanding updates πŸ‘‡

atomic commit thread                    hardware

write new state into hardware   ---->   ...
signal hw_done
                                        switch to new state on next
...                                     v/hblank

wait for buffers to show up             ...

...                                     send completion irq
                                        irq handler signals flip_done
cleanup old buffers

signal cleanup_done

wait for flip_done              <----
clean up atomic state

the important bit to know (like, the main tea β˜•) is that cleanup_done is the terminal event, but the ordering between flip_done and hw_done is entirely up to the specific driver and modeset state change. fr fr.

for an implementation of how to use this, look at drm_atomic_helper_setup_commit from the atomic helper library. go read it, i promise it's worth it 🫢

see also drm_crtc_commit_wait. πŸ’œ


πŸ‘‘ SEE ALSO πŸ‘‘

kernel file ./include/drm/drm_atomic.h struct drm_private_state_funcs(9), struct drm_private_obj(9), drm_for_each_privobj(9), struct drm_private_state(9), struct drm_atomic_commit(9), drm_crtc_commit_get(9), drm_crtc_commit_put(9), drm_atomic_commit_get(9), drm_atomic_commit_put(9), drm_atomic_get_old_crtc_state(9), drm_atomic_get_new_crtc_state(9), drm_atomic_get_old_plane_state(9), drm_atomic_get_new_plane_state(9), drm_atomic_get_old_connector_state(9), drm_atomic_get_new_connector_state(9), __drm_atomic_get_current_plane_state(9), for_each_oldnew_connector_in_state(9), for_each_old_connector_in_state(9), for_each_new_connector_in_state(9), for_each_oldnew_crtc_in_state(9), for_each_old_crtc_in_state(9), for_each_new_crtc_in_state(9), for_each_oldnew_colorop_in_state(9), for_each_new_colorop_in_state(9), for_each_oldnew_plane_in_state(9), for_each_oldnew_plane_in_state_reverse(9), for_each_new_plane_in_state_reverse(9), for_each_old_plane_in_state(9), for_each_new_plane_in_state(9), for_each_oldnew_private_obj_in_state(9), for_each_old_private_obj_in_state(9), for_each_new_private_obj_in_state(9), drm_atomic_crtc_needs_modeset(9), drm_atomic_crtc_effectively_active(9), struct drm_bus_cfg(9), struct drm_bridge_state(9)


ok that's the whole page, bestie, you ate that πŸ’…βœ¨

and yeah β€” this one lives in ./include/drm, it's the October 2026 edition of struct drm_crtc_commit(9). mwah, go read the helpers, ily πŸ«ΆπŸ’–πŸŽ€

πŸ“¦ where this page comes from