From 7a618390eced6431389e3b9659cbac72819337a1 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 17 Aug 2021 15:02:56 +0200 Subject: [PATCH] doc: add warning about mapping DMA-BUFs A list of reasons why DMA-BUFs have to be treated specially. This should make it clearer why mmaping DMA-BUFs should be avoided and hint clients on how treat them correctly Co-authored-by: columbarius --- doc/dma-buf.dox | 49 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/doc/dma-buf.dox b/doc/dma-buf.dox index 48371dcbd..f805b26f7 100644 --- a/doc/dma-buf.dox +++ b/doc/dma-buf.dox @@ -35,12 +35,12 @@ The second stream parameter should not contain any `SPA_FORMAT_VIDEO_modifier` property. To prioritise DMA-BUFs place those `SPA_PARAM_EnumFormat` containing modifiers -first, when emitting them to PipeWire +first, when emitting them to PipeWire. ## param_changed hook When the `param_changed` hook is called for a `SPA_PARAM_Format` the client -has to parse the 'spa_pod' directly. Use +has to parse the `spa_pod` directly. Use `spa_pod_find_prop(param, NULL, SPA_FORMAT_VIDEO_modifier)` to check whether modifiers were negotiated. If they were negotiated, set the `SPA_PARAM_BUFFERS_dataType` property to `1 << SPA_DATA_DmaBuf`. If they were @@ -48,7 +48,7 @@ not negotiated, fall back to shared memory by setting the `SPA_PARAM_BUFFERS_dataType` property to `1 << SPA_DATA_MemFd`, `1 << SPA_DATA_MemPtr`, or both. -While consumers only have to parse the resulting 'SPA_PARAM_Format' for any +While consumers only have to parse the resulting `SPA_PARAM_Format` for any format related information, it's up to the producer to fixate onto a single format modifier pair. The producer is also responsible to check if all clients announce sufficient capabilities or fallback to shared memory buffers when @@ -72,23 +72,23 @@ modifier aware one, or supporting both. else fall back to SHM, if possible. - modifier-aware: In this case a list with all supported modifiers will be returned in the format. - (using 'DRM_FORMAT_MOD_INVALID' as the token for the modifier-less API). - On the 'param_changed' event check if the modifier key is present and has the flag - 'SPA_POD_PROP_FLAG_DONT_FIXATE'. attached to it. In this case extract all modifiers + (using `DRM_FORMAT_MOD_INVALID` as the token for the modifier-less API). + On the `param_changed` event check if the modifier key is present and has the flag + `SPA_POD_PROP_FLAG_DONT_FIXATE`. attached to it. In this case extract all modifiers from the list and do a test allocation with your allocator to choose the preferred - modifier. Fixate on that 'EnumFormat' by announcing a 'SPA_PARAM_EnumFormat' with - only one modifier in the 'SPA_CHOICE_Enum' and without the - 'SPA_POD_PROP_FLAG_DONT_FIXATE', followed by the previous announced - 'EnumFormat's. This will retrigger (**TBD**) the 'param_changed' event with an - 'SPA__PARAM_Format' as described below. - If the 'SPA_PARAM_Format' contains a modifier key, without the flag - 'SPA_POD_PROP_FLAG_DONT_FIXATE', it should only contain one value in the - 'SPA_CHOICE_Enum'. In this case announce the 'SPA_PARAM_Buffers' accordingly + modifier. Fixate on that `EnumFormat` by announcing a `SPA_PARAM_EnumFormat` with + only one modifier in the `SPA_CHOICE_Enum` and without the + `SPA_POD_PROP_FLAG_DONT_FIXATE`, followed by the previous announced + `EnumFormat`s. This will retrigger (**TBD**) the `param_changed` event with an + `SPA_PARAM_Format` as described below. + If the `SPA_PARAM_Format` contains a modifier key, without the flag + `SPA_POD_PROP_FLAG_DONT_FIXATE`, it should only contain one value in the + `SPA_CHOICE_Enum`. In this case announce the `SPA_PARAM_Buffers` accordingly to the selected format and modifier. It is important to query the plane count - of the used format modifier pair and set 'SPA_PARAM_BUFFERS_blocks' accordingly. + of the used format modifier pair and set `SPA_PARAM_BUFFERS_blocks` accordingly. Note: When test allocating a buffer, collect all possible modifiers, while omitting -'DRM_FORMAT_MOD_INVALID' from the `SPA_FORMAT_VIDEO_modifier` property and +`DRM_FORMAT_MOD_INVALID` from the `SPA_FORMAT_VIDEO_modifier` property and pass them all to the graphics API. If the allocation fails and the list of possible modifiers contains `DRM_FORMAT_MOD_INVALID`, fall back to allocating without an explicit modifier if the graphics API allows it. @@ -113,4 +113,21 @@ Note: Some graphics APIs have separated functions for the modifier-less case (`DRM_FORMAT_MOD_INVALID`) or are omitting the modifier, since it might be used for error handling. +# DMA-BUF mapping warning + +It's important to make sure all consumers of the PipeWire stream are prepared +to deal with DMA-BUFs. Most DMA-BUFs cannot be treated like shared memory in general +because of the following issues: + +- DMA-BUFs can use hardware-specific tiling and compression as described by + modifiers. Thus, a `mmap(3)` on the DMA-BUF FD will not give a linear view of + the buffer contents. +- DMA-BUFs need to be properly synchronized with the asynchronous reads and + writes of the hardware. A `mmap(3)` call is not enough to guarantee proper + synchronization. (Maybe add link to linux syscall doc??) +- Blindly accessing the DMA-BUFs via `mmap(3)` can be extremely slow if the + buffer has been allocated on discrete hardware. Consumers are better off + using a proper graphics API (such as EGL, Vulkan or VA-API) to process the + DMA-BUFs. + */