eglfs_kms_vsp2: Add support for setting layer alpha

Exposed through QEglFSFunctions::vsp2SetLayerAlpha.

Change-Id: I2a600971d5a2aa56d4bf7cde03df3323f17249cd
Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
This commit is contained in:
Johan Klokkhammer Helsing 2018-01-29 15:32:55 +01:00 committed by Johan Helsing
parent 38c6d10bc8
commit 3058e21af0
9 changed files with 63 additions and 0 deletions

View File

@ -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<Vsp2SetLayerAlphaType>(QGuiApplication::platformFunction(vsp2SetLayerAlphaTypeIdentifier()));
return func && func(screen, id, alpha);
}
typedef void (*Vsp2AddBlendListenerType)(const QScreen *screen, void(*callback)());
static QByteArray vsp2AddBlendListenerTypeIdentifier() { return QByteArrayLiteral("EglFSVsp2AddBlendListener"); }

View File

@ -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<QEglFSKmsVsp2Screen *>(screen->handle());
vsp2Screen->setLayerAlpha(id, alpha);
}
void QEglFSKmsVsp2Integration::addBlendListenerStatic(const QScreen *screen, void(*callback)())
{
auto vsp2Screen = static_cast<QEglFSKmsVsp2Screen *>(screen->handle());

View File

@ -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)());
};

View File

@ -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;

View File

@ -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)());

View File

@ -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());

View File

@ -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);

View File

@ -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)

View File

@ -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
};