Loading...
Searching...
No Matches
DrmFourcc.hpp
1#pragma once
2
5
6// SPDX-License-Identifier: GPL-3.0-or-later
7//
8// DRM fourcc <-> AVPixelFormat <-> SPA video format mapping: the one
9// authoritative table, shared by Gfx/Pipewire, Gfx/WindowCapture and the
10// PipewireRoundtrip test in score-plugin-gfx/tests.
11//
12// Conventions (little-endian, per <drm/drm_fourcc.h>, hardware-verified by
13// the PipewireRoundtrip DMA-BUF cells):
14// - DRM fourccs name components from MSB to LSB of the packed word, so
15// memory order is reversed: DRM_FORMAT_ABGR8888 ('AB24') is
16// [R,G,B,A] bytes in memory == AV_PIX_FMT_RGBA == SPA_VIDEO_FORMAT_RGBA.
17// - 10-bit: DRM_FORMAT_ARGB2101010 ('AR30') has R in bits 29-20 ==
18// AV_PIX_FMT_X2RGB10LE == SPA_VIDEO_FORMAT_xRGB_210LE. 'AB30' is the
19// mirrored format, not RGB10A2.
20//
21// The DRM tokens are hardcoded so score builds without <drm/drm_fourcc.h>.
22// The SPA mapping is only compiled when the pipewire/SPA headers are
23// available (every current consumer is pipewire-gated anyway).
24
25extern "C" {
26#include <libavutil/pixfmt.h>
27}
28
29#include <cstdint>
30
31#if __has_include(<spa/param/video/raw.h>)
32#include <spa/param/video/raw.h>
33#define SCORE_GFX_HAS_SPA_RAW 1
34#endif
35
36namespace score::gfx::interop
37{
38
39constexpr uint32_t drmFourcc(char a, char b, char c, char d) noexcept
40{
41 return uint32_t(uint8_t(a)) | (uint32_t(uint8_t(b)) << 8)
42 | (uint32_t(uint8_t(c)) << 16) | (uint32_t(uint8_t(d)) << 24);
43}
44
45// clang-format off
46// Single- and dual-channel planes, used to import a planar frame one plane at a
47// time. DRM_FORMAT_GR1616 is fourcc_code('G','R','3','2') -- not 'GR16', which
48// is not a fourcc any kernel knows.
49inline constexpr uint32_t DRM_R8 = drmFourcc('R','8',' ',' ');
50inline constexpr uint32_t DRM_GR88 = drmFourcc('G','R','8','8');
51inline constexpr uint32_t DRM_R16 = drmFourcc('R','1','6',' ');
52inline constexpr uint32_t DRM_GR1616 = drmFourcc('G','R','3','2');
53
54static_assert(DRM_R8 == 0x20203852u, "DRM_FORMAT_R8");
55static_assert(DRM_GR88 == 0x38385247u, "DRM_FORMAT_GR88");
56static_assert(DRM_R16 == 0x20363152u, "DRM_FORMAT_R16");
57static_assert(DRM_GR1616 == 0x32335247u, "DRM_FORMAT_GR1616");
58
59inline constexpr uint32_t DRM_ABGR8888 = drmFourcc('A','B','2','4'); // [R,G,B,A] memory
60inline constexpr uint32_t DRM_ARGB8888 = drmFourcc('A','R','2','4'); // [B,G,R,A] memory
61inline constexpr uint32_t DRM_XBGR8888 = drmFourcc('X','B','2','4');
62inline constexpr uint32_t DRM_XRGB8888 = drmFourcc('X','R','2','4');
63inline constexpr uint32_t DRM_ARGB2101010 = drmFourcc('A','R','3','0'); // R bits 29-20
64inline constexpr uint32_t DRM_ABGR2101010 = drmFourcc('A','B','3','0'); // B bits 29-20
65inline constexpr uint32_t DRM_ABGR16161616F = drmFourcc('A','B','4','H');
66inline constexpr uint32_t DRM_BGR888 = drmFourcc('B','G','2','4'); // [R,G,B] memory
67inline constexpr uint32_t DRM_NV12 = drmFourcc('N','V','1','2');
68inline constexpr uint32_t DRM_P010 = drmFourcc('P','0','1','0');
69inline constexpr uint32_t DRM_P210 = drmFourcc('P','2','1','0');
70inline constexpr uint32_t DRM_YUV420 = drmFourcc('Y','U','1','2');
71inline constexpr uint32_t DRM_YVU420 = drmFourcc('Y','V','1','2');
72inline constexpr uint32_t DRM_YUYV = drmFourcc('Y','U','Y','V');
73inline constexpr uint32_t DRM_UYVY = drmFourcc('U','Y','V','Y');
74// clang-format on
75
81inline AVPixelFormat drmFourccToAv(uint32_t fourcc) noexcept
82{
83 return score::gfx::interop::toAVPixelFormat(
84 score::gfx::interop::fromDrmFourcc(fourcc));
85}
86
88inline uint32_t avToDrmFourcc(AVPixelFormat fmt) noexcept
89{
90 return score::gfx::interop::toDrmFourcc(
91 score::gfx::interop::fromAVPixelFormat(fmt));
92}
93
98drmFourccToVideoPixelFormat(uint32_t fourcc) noexcept
99{
100 return score::gfx::interop::fromDrmFourcc(fourcc);
101}
102
103#if defined(SCORE_GFX_HAS_SPA_RAW)
107spaToVideoPixelFormat(uint32_t spaFmt) noexcept;
108
110inline uint32_t spaToDrmFourcc(uint32_t spaFmt) noexcept
111{
112 switch(spaFmt)
113 {
114 case SPA_VIDEO_FORMAT_RGBA: return DRM_ABGR8888;
115 case SPA_VIDEO_FORMAT_BGRA: return DRM_ARGB8888;
116 case SPA_VIDEO_FORMAT_RGBx: return DRM_XBGR8888;
117 case SPA_VIDEO_FORMAT_BGRx: return DRM_XRGB8888;
118 case SPA_VIDEO_FORMAT_xRGB_210LE: return DRM_ARGB2101010;
119 case SPA_VIDEO_FORMAT_xBGR_210LE: return DRM_ABGR2101010;
120 case SPA_VIDEO_FORMAT_RGBA_F16: return DRM_ABGR16161616F;
121 case SPA_VIDEO_FORMAT_RGB: return DRM_BGR888;
122 case SPA_VIDEO_FORMAT_NV12: return DRM_NV12;
123 case SPA_VIDEO_FORMAT_P010_10LE: return DRM_P010;
124 case SPA_VIDEO_FORMAT_I420: return DRM_YUV420;
125 case SPA_VIDEO_FORMAT_YV12: return DRM_YVU420;
126 case SPA_VIDEO_FORMAT_YUY2: return DRM_YUYV;
127 case SPA_VIDEO_FORMAT_UYVY: return DRM_UYVY;
128 default: return 0;
129 }
130}
131
133spaToVideoPixelFormat(uint32_t spaFmt) noexcept
134{
135 return score::gfx::interop::fromDrmFourcc(spaToDrmFourcc(spaFmt));
136}
137#endif
138
139} // namespace score::gfx::interop
DRM fourcc <-> VideoPixelFormat, and the PipeWire SPA formats.
VideoPixelFormat
Definition VideoPixelFormat.hpp:229
Bridge between the wire-format enum VideoPixelFormat and libav's AVPixelFormat.