6#include <qeglfskmshelpers_p.h>
9#include <QtCore/QLoggingCategory>
11#include <drm_fourcc.h>
15Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug)
18static inline uint drmFormatToV4l2PixelFormat(uint drmFormat) {
20 Q_ASSERT(DRM_FORMAT_ARGB8888 == V4L2_PIX_FMT_ABGR32);
27 case DRM_FORMAT_RGB888:
28 return MEDIA_BUS_FMT_RGB888_1X24;
29 case DRM_FORMAT_BGR888:
30 return MEDIA_BUS_FMT_BGR888_1X24;
31 case DRM_FORMAT_XRGB8888:
32 case DRM_FORMAT_XBGR8888:
34 case DRM_FORMAT_RGBX8888:
35 case DRM_FORMAT_BGRX8888:
36 case DRM_FORMAT_ARGB8888:
37 case DRM_FORMAT_ABGR8888:
38 case DRM_FORMAT_RGBA8888:
39 case DRM_FORMAT_BGRA8888:
40 return MEDIA_BUS_FMT_ARGB8888_1X32;
42 qWarning() <<
"Unknown drm format" << q_fourccToString(drmFormat) <<
"defaulting to argb8888";
43 return MEDIA_BUS_FMT_ARGB8888_1X32;
48 : m_mediaDevice(
"/dev/media0")
52 QString deviceName = md.deviceName();
54 if (md.model() != QString(
"VSP2"))
55 qWarning() <<
"Unsupported media device model:" << md.model();
57 if (deviceName !=
"fe960000.vsp")
58 qWarning() <<
"Unknown media device name:" << deviceName;
60 const int numInputs = 5;
62 for (
int i = 0; i < numInputs; ++i) {
64 input.linkToBru = md.parseLink(QString(
"'%1 rpf.%2':1 -> '%1 bru':%2").arg(deviceName).arg(i));
65 input.inputFormatPad = md.parsePad(QString(
"'%1 rpf.%2':0").arg(deviceName).arg(i));
66 input.outputFormatPad = md.parsePad(QString(
"'%1 rpf.%2':1").arg(deviceName).arg(i));
68 input.bruInputFormatPad = md.parsePad(QString(
"'%1 bru':%2").arg(deviceName).arg(i));
70 m_inputs.append(input);
76 md
.enableLink(md.parseLink(QString(
"'%1 bru':5 -> '%1 wpf.0':0").arg(deviceName))
);
77 md
.enableLink(md.parseLink(QString(
"'%1 wpf.0':1 -> '%1 wpf.0 output':0").arg(deviceName))
);
80 auto bruOutputFormatPad = md.parsePad(QString(
"'%1 bru':5").arg(deviceName));
81 auto wpfInputFormatPad = md.parsePad(QString(
"'%1 wpf.0':0").arg(deviceName));
82 auto wpfOutputFormatPad = md.parsePad(QString(
"'%1 wpf.0':1").arg(deviceName));
84 m_wpfOutput->setFormat(screenSize);
85 QLinuxMediaDevice::setSubdevFormat(bruOutputFormatPad, screenSize);
86 QLinuxMediaDevice::setSubdevFormat(wpfInputFormatPad, screenSize);
87 QLinuxMediaDevice::setSubdevFormat(wpfOutputFormatPad, screenSize);
94 qCDebug(qLcEglfsKmsDebug) <<
"Blend unit: Enabling input" << i;
95 if (m_inputs[i].enabled) {
96 qWarning(
"Vsp2: Input %d already enabled", i);
100 if (!bufferGeometry.isValid()) {
101 qWarning() <<
"Vsp2: Invalid buffer geometry";
105 Input &input = m_inputs[i];
109 uint pixelFormat = drmFormatToV4l2PixelFormat(drmFormat);
110 if (!setInputFormat(i, bufferGeometry, pixelFormat, bytesPerLine)) {
121 for (
int i = 0; i < m_inputs.size(); ++i) {
122 if (!m_inputs[i].enabled)
123 return enableInput(i, bufferGeometry, drmFormat, bytesPerLine) ? i : -1;
125 qWarning() <<
"Vsp2: No more inputs available in blend unit";
131 qCDebug(qLcEglfsKmsDebug) <<
"Vsp2: disabling input" << i;
132 if (!m_inputs[i].enabled) {
133 qWarning(
"Vsp2: Input %d already disabled", i);
137 m_inputs[i].rpfInput->clearBuffers();
138 m_inputs[i].enabled =
false;
144 Input &input = m_inputs[index];
146 if (!input.enabled) {
147 qWarning() <<
"Vsp2: Can't queue on disabled input" << index;
152 if (input.dmabuf.fd != dmabufFd) {
154 input.dmabuf.fd = dmabufFd;
161 Input &input = m_inputs[index];
163 if (input.geometry.topLeft() == position)
167 input.geometry.moveTopLeft(position);
173 Input &input = m_inputs[index];
174 if (input.alpha == alpha)
179 return QLinuxMediaDevice::setSubdevAlpha(input.outputFormatFd, alpha);
185 qWarning(
"Blending without being dirty, should not be necessary");
188 qWarning(
"Vsp2: Can't blend when layers are not enabled in order from 0 without gaps.");
192 bool queueingFailed =
false;
194 for (
int i=0; i < m_inputs.size(); ++i) {
195 auto &input = m_inputs[i];
197 if (!input.rpfInput->queueBuffer(input.dmabuf.fd, input.dmabuf.bytesUsed, input.dmabuf.length)) {
198 qWarning() <<
"Vsp2: Failed to queue buffer for input" << i
199 <<
"with dmabuf" << input.dmabuf.fd
200 <<
"and size" << input.geometry.size();
202 queueingFailed =
true;
207 if (queueingFailed) {
208 qWarning() <<
"Vsp2: Trying to clean up queued buffers";
209 for (
auto &input : std::as_const(m_inputs)) {
211 if (!input.rpfInput->clearBuffers())
212 qWarning() <<
"Vsp2: Failed to remove buffers after an aborted blend";
218 if (!m_wpfOutput
->queueBuffer(outputDmabufFd, m_screenSize)) {
219 qWarning() <<
"Vsp2: Failed to queue blending output buffer" << outputDmabufFd << m_screenSize;
224 qWarning() <<
"Vsp2: Failed to start streaming";
229 qWarning() <<
"Vsp2: Failed to dequeue blending output buffer";
231 qWarning() <<
"Vsp2: Failed to stop streaming when recovering after a broken blend.";
236 qWarning() <<
"Vsp2: Failed to stop streaming";
246 return m_inputs.size();
251 bool seenDisabled =
false;
252 for (
auto &input : std::as_const(m_inputs)) {
253 if (seenDisabled && input.enabled)
255 seenDisabled |= !input.enabled;
257 return m_inputs[0].enabled;
262 for (
auto &input : m_inputs) {
264 if (!input.rpfInput->streamOn()) {
277 for (
auto &input : m_inputs) {
279 succeeded &= input.rpfInput->streamOff();
284bool QVsp2BlendingDevice::setInputFormat(
int i,
const QRect &bufferGeometry, uint pixelFormat, uint bytesPerLine)
286 Input &input = m_inputs[i];
288 Q_ASSERT(bufferGeometry.isValid());
291 input.enabled =
true;
292 input.geometry = bufferGeometry;
293 input.dmabuf.bytesUsed = bpp *
static_cast<uint>(bufferGeometry.width()) *
static_cast<uint>(bufferGeometry.height());
294 input.dmabuf.length =
static_cast<uint>(bufferGeometry.height()) * bytesPerLine;
296 const QSize size = bufferGeometry.size();
298 if (!input.rpfInput->setFormat(size, pixelFormat, bytesPerLine))
301 const uint mediaBusFormat = drmFormatToMediaBusFormat(pixelFormat);
302 if (!QLinuxMediaDevice::setSubdevFormat(input.inputFormatPad, size, mediaBusFormat))
305 if (!QLinuxMediaDevice::setSubdevFormat(input.outputFormatPad, size, mediaBusFormat))
308 if (!QLinuxMediaDevice::setSubdevFormat(input.bruInputFormatPad, size, mediaBusFormat))
QVsp2BlendingDevice(const QSize &screenSize)
int enableInput(const QRect &bufferGeometry, uint drmFormat, uint bytesPerLine)
bool blend(int outputDmabufFd)
bool hasContinuousLayers() const
bool setInputBuffer(int index, int dmabufFd)
bool enableInput(int i, const QRect &bufferGeometry, uint drmFormat, uint bytesPerLine)
bool setInputPosition(int index, const QPoint &position)
bool setInputAlpha(int index, qreal alpha)
Combined button and popup list for selecting options.
static uint drmFormatToMediaBusFormat(uint drmFormat)