From 3058e21af0f36d78e5515cef0fe88969310fa912 Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Mon, 29 Jan 2018 15:32:55 +0100 Subject: [PATCH] eglfs_kms_vsp2: Add support for setting layer alpha Exposed through QEglFSFunctions::vsp2SetLayerAlpha. Change-Id: I2a600971d5a2aa56d4bf7cde03df3323f17249cd Reviewed-by: Laszlo Agocs --- .../eglfsfunctions/qeglfsfunctions.h | 9 +++++++++ .../qeglfskmsvsp2integration.cpp | 8 ++++++++ .../eglfs_kms_vsp2/qeglfskmsvsp2integration.h | 1 + .../eglfs_kms_vsp2/qeglfskmsvsp2screen.cpp | 6 ++++++ .../eglfs_kms_vsp2/qeglfskmsvsp2screen.h | 1 + .../eglfs_kms_vsp2/qlinuxmediadevice.cpp | 20 +++++++++++++++++++ .../eglfs_kms_vsp2/qlinuxmediadevice.h | 3 +++ .../eglfs_kms_vsp2/qvsp2blendingdevice.cpp | 12 +++++++++++ .../eglfs_kms_vsp2/qvsp2blendingdevice.h | 3 +++ 9 files changed, 63 insertions(+) diff --git a/src/platformheaders/eglfsfunctions/qeglfsfunctions.h b/src/platformheaders/eglfsfunctions/qeglfsfunctions.h index 67522ec9be..7165c3cff4 100644 --- a/src/platformheaders/eglfsfunctions/qeglfsfunctions.h +++ b/src/platformheaders/eglfsfunctions/qeglfsfunctions.h @@ -98,6 +98,15 @@ public: return func && func(screen, id, position); } + typedef bool (*Vsp2SetLayerAlphaType)(const QScreen *screen, int id, qreal alpha); + static QByteArray vsp2SetLayerAlphaTypeIdentifier() { return QByteArrayLiteral("EglFSVsp2SetLayerAlpha"); } + + static bool vsp2SetLayerAlpha(const QScreen *screen, int id, qreal alpha) + { + auto func = reinterpret_cast(QGuiApplication::platformFunction(vsp2SetLayerAlphaTypeIdentifier())); + return func && func(screen, id, alpha); + } + typedef void (*Vsp2AddBlendListenerType)(const QScreen *screen, void(*callback)()); static QByteArray vsp2AddBlendListenerTypeIdentifier() { return QByteArrayLiteral("EglFSVsp2AddBlendListener"); } diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2integration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2integration.cpp index f85d6183f6..0d9b6b6290 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2integration.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2integration.cpp @@ -133,6 +133,8 @@ QFunctionPointer QEglFSKmsVsp2Integration::platformFunction(const QByteArray &fu return QFunctionPointer(setLayerBufferStatic); if (function == QEglFSFunctions::vsp2SetLayerPositionTypeIdentifier()) return QFunctionPointer(setLayerPositionStatic); + if (function == QEglFSFunctions::vsp2SetLayerAlphaTypeIdentifier()) + return QFunctionPointer(setLayerAlphaStatic); if (function == QEglFSFunctions::vsp2AddBlendListenerTypeIdentifier()) return QFunctionPointer(addBlendListenerStatic); @@ -184,6 +186,12 @@ void QEglFSKmsVsp2Integration::setLayerPositionStatic(const QScreen *screen, int vsp2Screen->setLayerPosition(id, position); } +void QEglFSKmsVsp2Integration::setLayerAlphaStatic(const QScreen *screen, int id, qreal alpha) +{ + auto vsp2Screen = static_cast(screen->handle()); + vsp2Screen->setLayerAlpha(id, alpha); +} + void QEglFSKmsVsp2Integration::addBlendListenerStatic(const QScreen *screen, void(*callback)()) { auto vsp2Screen = static_cast(screen->handle()); diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2integration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2integration.h index c09ee205c8..b1a8a2edf3 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2integration.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2integration.h @@ -72,6 +72,7 @@ private: static bool removeLayerStatic(const QScreen *screen, int id); static void setLayerBufferStatic(const QScreen *screen, int id, int dmabufFd); static void setLayerPositionStatic(const QScreen *screen, int id, const QPoint &position); + static void setLayerAlphaStatic(const QScreen *screen, int id, qreal alpha); static void addBlendListenerStatic(const QScreen *screen, void(*callback)()); }; diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2screen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2screen.cpp index 42af93287d..88b401c920 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2screen.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2screen.cpp @@ -186,6 +186,12 @@ void QEglFSKmsVsp2Screen::setLayerPosition(int id, const QPoint &position) m_blendDevice->setInputPosition(layerIndex, position); } +void QEglFSKmsVsp2Screen::setLayerAlpha(int id, qreal alpha) +{ + int layerIndex = id; + m_blendDevice->setInputAlpha(layerIndex, alpha); +} + bool QEglFSKmsVsp2Screen::removeLayer(int id) { int layerIndex = id; diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2screen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2screen.h index 19f65e7e7d..fa03e36785 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2screen.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2screen.h @@ -65,6 +65,7 @@ public: int addLayer(int dmabufFd, const QSize &size, const QPoint &position, uint drmPixelFormat, uint bytesPerLine); void setLayerBuffer(int id, int dmabufFd); void setLayerPosition(int id, const QPoint &position); + void setLayerAlpha(int id, qreal alpha); bool removeLayer(int id); void addBlendListener(void (*callback)()); diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qlinuxmediadevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qlinuxmediadevice.cpp index 21de052b87..25b0c39050 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qlinuxmediadevice.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qlinuxmediadevice.cpp @@ -533,6 +533,14 @@ bool QLinuxMediaDevice::OutputSubDevice::streamOff() return QLinuxMediaDevice::streamOff(m_subdevFd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); } +int QLinuxMediaDevice::openVideoDevice(media_pad *pad) +{ + const char *deviceName = media_entity_get_devname(pad->entity); + int fd = open(deviceName, O_RDWR); + qCDebug(qLcEglfsKmsDebug) << "Opened video device:" << deviceName << "with fd" << fd; + return fd; +} + bool QLinuxMediaDevice::setSubdevFormat(struct media_pad *pad, const QSize &size, uint32_t mbusFormat) { Q_ASSERT(size.isValid()); @@ -556,6 +564,18 @@ bool QLinuxMediaDevice::setSubdevFormat(struct media_pad *pad, const QSize &size return true; } +bool QLinuxMediaDevice::setSubdevAlpha(int subdevFd, qreal alpha) +{ + struct v4l2_control control; + control.id = V4L2_CID_ALPHA_COMPONENT; + control.value = static_cast<__s32>(alpha * 0xff); + if (ioctl(subdevFd, VIDIOC_S_CTRL, &control) == -1) { + qErrnoWarning("Setting alpha (%d) failed", control.value); + return false; + } + return true; +} + bool QLinuxMediaDevice::setSubdevSelection(struct media_pad *pad, const QRect &geometry, uint target) { Q_ASSERT(geometry.isValid()); diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qlinuxmediadevice.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qlinuxmediadevice.h index 848099eb46..26f863214b 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qlinuxmediadevice.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qlinuxmediadevice.h @@ -95,7 +95,10 @@ public: int m_subdevFd = -1; }; + static int openVideoDevice(media_pad *pad); + static bool setSubdevFormat(struct media_pad *pad, const QSize &size, uint32_t mbusFormat = MEDIA_BUS_FMT_ARGB8888_1X32); + static bool setSubdevAlpha(int subdevFd, qreal alpha); static bool setSubdevSelection(struct media_pad *pad, const QRect &geometry, uint target); static bool setSubdevCrop(struct media_pad *pad, const QRect &geometry); diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qvsp2blendingdevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qvsp2blendingdevice.cpp index c9b9bb5b7f..58ffd31afd 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qvsp2blendingdevice.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qvsp2blendingdevice.cpp @@ -99,6 +99,7 @@ QVsp2BlendingDevice::QVsp2BlendingDevice(const QSize &screenSize) input.linkToBru = md.parseLink(QString("'%1 rpf.%2':1 -> '%1 bru':%2").arg(deviceName).arg(i)); input.inputFormatPad = md.parsePad(QString("'%1 rpf.%2':0").arg(deviceName).arg(i)); input.outputFormatPad = md.parsePad(QString("'%1 rpf.%2':1").arg(deviceName).arg(i)); + input.outputFormatFd = QLinuxMediaDevice::openVideoDevice(input.outputFormatPad); input.bruInputFormatPad = md.parsePad(QString("'%1 bru':%2").arg(deviceName).arg(i)); input.rpfInput = new QLinuxMediaDevice::OutputSubDevice(&md, QString("%1 rpf.%2 input").arg(deviceName).arg(i)); m_inputs.append(input); @@ -202,6 +203,17 @@ bool QVsp2BlendingDevice::setInputPosition(int index, const QPoint &position) return QLinuxMediaDevice::setSubdevCompose(input.bruInputFormatPad, input.geometry); } +bool QVsp2BlendingDevice::setInputAlpha(int index, qreal alpha) +{ + Input &input = m_inputs[index]; + if (input.alpha == alpha) + return true; + + m_dirty = true; + input.alpha = alpha; + return QLinuxMediaDevice::setSubdevAlpha(input.outputFormatFd, alpha); +} + bool QVsp2BlendingDevice::blend(int outputDmabufFd) { if (!m_dirty) diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qvsp2blendingdevice.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qvsp2blendingdevice.h index ff2d581d72..be48954f47 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qvsp2blendingdevice.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qvsp2blendingdevice.h @@ -59,6 +59,7 @@ public: bool disableInput(int i); bool setInputBuffer(int index, int dmabufFd); bool setInputPosition(int index, const QPoint &position); + bool setInputAlpha(int index, qreal alpha); bool blend(int outputDmabufFd); int numInputs() const; bool isDirty() const { return m_dirty; } @@ -71,6 +72,7 @@ private: struct Input { bool enabled = false; QRect geometry; + qreal alpha = 1; struct { int fd = -1; uint bytesUsed = 0; @@ -79,6 +81,7 @@ private: struct media_link *linkToBru = nullptr; //rpf.x:1 -> bru:x struct media_pad *inputFormatPad = nullptr; // rpf.x:0 struct media_pad *outputFormatPad = nullptr; // rpf.x:1 + int outputFormatFd = -1; // rpf.x:1 (again, because v4l2_subdev_* doesn't have a way to set alpha) struct media_pad *bruInputFormatPad = nullptr; // bru:x QLinuxMediaDevice::OutputSubDevice *rpfInput = nullptr; // rpf.x input };