Module dmabuf

Module dmabuf 

Source
Available on crate feature wayland_frontend only.
Expand description

Linux DMABUF protocol

This module provides helper to handle the linux-dmabuf protocol, which allows clients to submit their contents as dmabuf file descriptors. These handlers automate the aggregation of the metadata associated with a dma buffer, and do some basic checking of the sanity of what the client sends.

§How to use

To setup the dmabuf global, you will need to provide 2 things:

The list of supported formats is a Vec<Format>, where you will enter all the (code, modifier) pairs you support. You can typically receive a list of supported formats for one renderer by calling ImportDma::dmabuf_formats.

use smithay::{
    delegate_dmabuf,
    backend::allocator::dmabuf::{Dmabuf},
    reexports::{
        wayland_server::protocol::{
            wl_buffer::WlBuffer,
            wl_surface::WlSurface,
        }
    },
    wayland::{
        buffer::BufferHandler,
        dmabuf::{DmabufFeedback, DmabufFeedbackBuilder, DmabufGlobal, DmabufHandler, DmabufState, ImportNotifier}
    },
};

pub struct State {
    dmabuf_state: DmabufState,
    dmabuf_global: DmabufGlobal,
}

// Smithay's "DmabufHandler" also requires the buffer management utilities, you need to implement
// "BufferHandler".
impl BufferHandler for State {
    fn buffer_destroyed(&mut self, buffer: &wayland_server::protocol::wl_buffer::WlBuffer) {
        // All renderers can handle buffer destruction at this point. Some parts of window management may
        // also use this function.
        //
        // If you need to mark a dmabuf elsewhere in your state as destroyed, you use the "get_dmabuf"
        // function defined in this module to access the dmabuf associated the "Buffer".
    }
}

impl DmabufHandler for State {
    fn dmabuf_state(&mut self) -> &mut DmabufState {
        &mut self.dmabuf_state
    }

    fn dmabuf_imported(&mut self, global: &DmabufGlobal, dmabuf: Dmabuf, notifier: ImportNotifier) {
        // Here you should import the dmabuf into your renderer.
        //
        // The notifier is used to communicate whether import was successful. In this example we
        // call successful to notify the client import was successful.
        notifier.successful::<State>();
    }

    fn new_surface_feedback(
        &mut self,
        surface: &WlSurface,
        global: &DmabufGlobal,
    ) -> Option<DmabufFeedback> {
        // Here you can override the initial feedback sent to a client requesting feedback for a specific
        // surface. Returning `None` instructs the global to return the default feedback to the client which
        // is also the default implementation for this function when not overridden
        None
    }
}

// Delegate dmabuf handling for State to DmabufState.
delegate_dmabuf!(State);

// First a DmabufState must be created. This type is used to create some "DmabufGlobal"s
let mut dmabuf_state = DmabufState::new();

// ...identify primary render node and load dmabuf formats supported for rendering...

// Build the default feedback from the device node of the primary render node and
// the supported dmabuf formats
let default_feedback = DmabufFeedbackBuilder::new(main_device, formats).build().unwrap();

// And create the dmabuf global.
let dmabuf_global = dmabuf_state.create_global_with_default_feedback::<State>(
    &display_handle,
    &default_feedback,
);

let state = State {
    dmabuf_state,
    dmabuf_global,
};

// Rest of the compositor goes here...

Accessing a Dmabuf associated with a WlBuffer may be achieved using get_dmabuf.

§Notes on supporting per surface feedback

If a client requests DmabufFeedback for a specific WlSurface it can be used to inform the client about sub-optimal buffer allocations. This is especially important to support direct scan-out over drm planes that typically only support a subset of supported formats from the rendering formats.

The DmabufFeedback of a specific WlSurface can be updated by retrieving the SurfaceDmabufFeedbackState with SurfaceDmabufFeedbackState::from_states and setting the feedback with SurfaceDmabufFeedbackState::set_feedback.

DmabufFeedback uses preference tranches to inform the client about formats that could result on more optimal buffer placement. Preference tranches can be added to the feedback during initialization with DmabufFeedbackBuilder::add_preference_tranche. Note that the order of formats within a tranche (target_device + flags) is undefined, if you want to communicate preference of a specific format you have to split the formats into multiple tranches. A tranche can additionally define TrancheFlags which can give clients additional context what the tranche represents. As an example formats gathered from drm planes should define TrancheFlags::Scanout to communicate that buffers should be allocated so that they support scan-out by the device specified as the target device.

Note: Surface feedback only represents an optimization and the fallback path using compositing should always be supported, so typically you do not want to announce formats in a preference tranche that are not supported by the main device for rendering.

§Notes on clients binding version 3 or lower

During instantiation the global will automatically build a format list from the provided DmabufFeedback consisting of all formats that are part of a tranche having the target device equal the main device and defining no special TrancheFlags.

§Without feedback (v3)

It is also possible to initialize the Global without support for DmabufFeedback by using DmabufState::create_global which will then only advertise version 3 to clients. This is mostly meant to guarantee an easy update path for compositors already supporting dmabuf version 3 without breakage.

// define your supported formats
let formats = vec![
    /* ... */
];

// And create the dmabuf global.
let dmabuf_global = dmabuf_state.create_global::<State>(
    &display_handle,
    formats,
);

let state = State {
    dmabuf_state,
    dmabuf_global,
};

// Rest of the compositor goes here...

Structs§

DmabufData
Data associated with a dmabuf global protocol object.
DmabufFeedback
Feedback for dmabuf allocation
DmabufFeedbackBuilder
Builder for DmabufFeedback
DmabufFeedbackData
Data associated with a dmabuf global protocol object.
DmabufGlobal
A handle to a registered dmabuf global.
DmabufGlobalData
Data associated with a dmabuf global.
DmabufParamsData
Data associated with a pending Dmabuf import.
DmabufState
Delegate type for all dmabuf globals.
ImportNotifier
An object to allow asynchronous creation of a Dmabuf backed WlBuffer.
SurfaceDmabufFeedbackState
Feedback state for a surface

Traits§

DmabufHandler
Handler trait for Dmabuf import from the compositor.

Functions§

get_dmabuf
Gets the contents of a Dmabuf backed WlBuffer.