kms: Discover all available planes
Task-number: QTBUG-63058 Change-Id: I655384916bedbeb0da516e2eaa177d1128272d1c Reviewed-by: Andy Nichols <andy.nichols@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
parent
a31b5bf5da
commit
93dd85141b
@ -384,6 +384,20 @@ QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources,
|
|||||||
output.drm_format = drmFormat;
|
output.drm_format = drmFormat;
|
||||||
output.clone_source = cloneSource;
|
output.clone_source = cloneSource;
|
||||||
|
|
||||||
|
QString planeListStr;
|
||||||
|
for (const QKmsPlane &plane : qAsConst(m_planes)) {
|
||||||
|
if (plane.possibleCrtcs & (1 << output.crtc_index)) {
|
||||||
|
output.available_planes.append(plane);
|
||||||
|
planeListStr.append(QString::number(plane.id));
|
||||||
|
planeListStr.append(QLatin1Char(' '));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
qCDebug(qLcKmsDebug, "Output %s can use %d planes: %s",
|
||||||
|
connectorName.constData(), output.available_planes.count(), qPrintable(planeListStr));
|
||||||
|
|
||||||
|
// This is for the EGLDevice/EGLStream backend. On some of those devices one
|
||||||
|
// may want to target a pre-configured plane. It is probably useless for
|
||||||
|
// eglfs_kms and others. Do not confuse with generic plane support (available_planes).
|
||||||
bool ok;
|
bool ok;
|
||||||
int idx = qEnvironmentVariableIntValue("QT_QPA_EGLFS_KMS_PLANE_INDEX", &ok);
|
int idx = qEnvironmentVariableIntValue("QT_QPA_EGLFS_KMS_PLANE_INDEX", &ok);
|
||||||
if (ok) {
|
if (ok) {
|
||||||
@ -504,12 +518,16 @@ void QKmsDevice::createScreens()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
drmSetClientCap(m_dri_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
|
||||||
|
|
||||||
drmModeResPtr resources = drmModeGetResources(m_dri_fd);
|
drmModeResPtr resources = drmModeGetResources(m_dri_fd);
|
||||||
if (!resources) {
|
if (!resources) {
|
||||||
qErrnoWarning(errno, "drmModeGetResources failed");
|
qErrnoWarning(errno, "drmModeGetResources failed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
discoverPlanes();
|
||||||
|
|
||||||
QVector<OrderedScreen> screens;
|
QVector<OrderedScreen> screens;
|
||||||
|
|
||||||
int wantedConnectorIndex = -1;
|
int wantedConnectorIndex = -1;
|
||||||
@ -628,6 +646,116 @@ void QKmsDevice::registerScreenCloning(QPlatformScreen *screen,
|
|||||||
Q_UNUSED(screensCloningThisScreen);
|
Q_UNUSED(screensCloningThisScreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// drm_property_type_is is not available in old headers
|
||||||
|
static inline bool propTypeIs(drmModePropertyPtr prop, uint32_t type)
|
||||||
|
{
|
||||||
|
if (prop->flags & DRM_MODE_PROP_EXTENDED_TYPE)
|
||||||
|
return (prop->flags & DRM_MODE_PROP_EXTENDED_TYPE) == type;
|
||||||
|
return prop->flags & type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QKmsDevice::enumerateProperties(drmModeObjectPropertiesPtr objProps, PropCallback callback)
|
||||||
|
{
|
||||||
|
for (uint32_t propIdx = 0; propIdx < objProps->count_props; ++propIdx) {
|
||||||
|
drmModePropertyPtr prop = drmModeGetProperty(m_dri_fd, objProps->props[propIdx]);
|
||||||
|
if (!prop)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const quint64 value = objProps->prop_values[propIdx];
|
||||||
|
qCDebug(qLcKmsDebug, " property %d: id = %u name = '%s'", propIdx, prop->prop_id, prop->name);
|
||||||
|
|
||||||
|
if (propTypeIs(prop, DRM_MODE_PROP_SIGNED_RANGE)) {
|
||||||
|
qCDebug(qLcKmsDebug, " type is SIGNED_RANGE, value is %lld, possible values are:", qint64(value));
|
||||||
|
for (int i = 0; i < prop->count_values; ++i)
|
||||||
|
qCDebug(qLcKmsDebug, " %lld", qint64(prop->values[i]));
|
||||||
|
} else if (propTypeIs(prop, DRM_MODE_PROP_RANGE)) {
|
||||||
|
qCDebug(qLcKmsDebug, " type is RANGE, value is %llu, possible values are:", value);
|
||||||
|
for (int i = 0; i < prop->count_values; ++i)
|
||||||
|
qCDebug(qLcKmsDebug, " %llu", quint64(prop->values[i]));
|
||||||
|
} else if (propTypeIs(prop, DRM_MODE_PROP_ENUM)) {
|
||||||
|
qCDebug(qLcKmsDebug, " type is ENUM, value is %llu, possible values are:", value);
|
||||||
|
for (int i = 0; i < prop->count_enums; ++i)
|
||||||
|
qCDebug(qLcKmsDebug, " enum %d: %s - %llu", i, prop->enums[i].name, prop->enums[i].value);
|
||||||
|
} else if (propTypeIs(prop, DRM_MODE_PROP_BITMASK)) {
|
||||||
|
qCDebug(qLcKmsDebug, " type is BITMASK, value is %llu, possible bits are:", value);
|
||||||
|
for (int i = 0; i < prop->count_enums; ++i)
|
||||||
|
qCDebug(qLcKmsDebug, " bitmask %d: %s - %u", i, prop->enums[i].name, 1 << prop->enums[i].value);
|
||||||
|
} else if (propTypeIs(prop, DRM_MODE_PROP_BLOB)) {
|
||||||
|
qCDebug(qLcKmsDebug, " type is BLOB");
|
||||||
|
} else if (propTypeIs(prop, DRM_MODE_PROP_OBJECT)) {
|
||||||
|
qCDebug(qLcKmsDebug, " type is OBJECT");
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(prop, value);
|
||||||
|
|
||||||
|
drmModeFreeProperty(prop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QKmsDevice::discoverPlanes()
|
||||||
|
{
|
||||||
|
m_planes.clear();
|
||||||
|
|
||||||
|
drmModePlaneResPtr planeResources = drmModeGetPlaneResources(m_dri_fd);
|
||||||
|
if (!planeResources)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const int countPlanes = planeResources->count_planes;
|
||||||
|
qCDebug(qLcKmsDebug, "Found %d planes", countPlanes);
|
||||||
|
for (int planeIdx = 0; planeIdx < countPlanes; ++planeIdx) {
|
||||||
|
drmModePlanePtr drmplane = drmModeGetPlane(m_dri_fd, planeResources->planes[planeIdx]);
|
||||||
|
if (!drmplane) {
|
||||||
|
qCDebug(qLcKmsDebug, "Failed to query plane %d, ignoring", planeIdx);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
QKmsPlane plane;
|
||||||
|
plane.id = drmplane->plane_id;
|
||||||
|
plane.possibleCrtcs = drmplane->possible_crtcs;
|
||||||
|
|
||||||
|
const int countFormats = drmplane->count_formats;
|
||||||
|
QString formatStr;
|
||||||
|
for (int i = 0; i < countFormats; ++i) {
|
||||||
|
uint32_t f = drmplane->formats[i];
|
||||||
|
plane.supportedFormats.append(f);
|
||||||
|
QString s;
|
||||||
|
s.sprintf("%c%c%c%c ", f, f >> 8, f >> 16, f >> 24);
|
||||||
|
formatStr += s;
|
||||||
|
}
|
||||||
|
|
||||||
|
qCDebug(qLcKmsDebug, "plane %d: id = %u countFormats = %d possibleCrtcs = 0x%x supported formats = %s",
|
||||||
|
planeIdx, plane.id, countFormats, plane.possibleCrtcs, qPrintable(formatStr));
|
||||||
|
|
||||||
|
drmModeFreePlane(drmplane);
|
||||||
|
|
||||||
|
drmModeObjectPropertiesPtr objProps = drmModeObjectGetProperties(m_dri_fd, plane.id, DRM_MODE_OBJECT_PLANE);
|
||||||
|
if (!objProps) {
|
||||||
|
qCDebug(qLcKmsDebug, "Failed to query plane %d object properties, ignoring", planeIdx);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
enumerateProperties(objProps, [this, &plane](drmModePropertyPtr prop, quint64 value) {
|
||||||
|
if (!strcmp(prop->name, "type")) {
|
||||||
|
plane.type = QKmsPlane::Type(value);
|
||||||
|
} else if (!strcmp(prop->name, "rotation")) {
|
||||||
|
plane.initialRotation = QKmsPlane::Rotations(int(value));
|
||||||
|
plane.availableRotations = 0;
|
||||||
|
if (propTypeIs(prop, DRM_MODE_PROP_BITMASK)) {
|
||||||
|
for (int i = 0; i < prop->count_enums; ++i)
|
||||||
|
plane.availableRotations |= QKmsPlane::Rotation(1 << prop->enums[i].value);
|
||||||
|
}
|
||||||
|
plane.rotationPropertyId = prop->prop_id;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
m_planes.append(plane);
|
||||||
|
|
||||||
|
drmModeFreeObjectProperties(objProps);
|
||||||
|
}
|
||||||
|
|
||||||
|
drmModeFreePlaneResources(planeResources);
|
||||||
|
}
|
||||||
|
|
||||||
int QKmsDevice::fd() const
|
int QKmsDevice::fd() const
|
||||||
{
|
{
|
||||||
return m_dri_fd;
|
return m_dri_fd;
|
||||||
|
@ -61,6 +61,41 @@
|
|||||||
#include <xf86drmMode.h>
|
#include <xf86drmMode.h>
|
||||||
#include <drm_fourcc.h>
|
#include <drm_fourcc.h>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
// In less fortunate cases one may need to build on a system with dev headers
|
||||||
|
// from the dark ages. Let's pull a GL and define the missing stuff outselves.
|
||||||
|
|
||||||
|
#ifndef DRM_PLANE_TYPE_OVERLAY
|
||||||
|
#define DRM_PLANE_TYPE_OVERLAY 0
|
||||||
|
#endif
|
||||||
|
#ifndef DRM_PLANE_TYPE_PRIMARY
|
||||||
|
#define DRM_PLANE_TYPE_PRIMARY 1
|
||||||
|
#endif
|
||||||
|
#ifndef DRM_PLANE_TYPE_CURSOR
|
||||||
|
#define DRM_PLANE_TYPE_CURSOR 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef DRM_CLIENT_CAP_UNIVERSAL_PLANES
|
||||||
|
#define DRM_CLIENT_CAP_UNIVERSAL_PLANES 2
|
||||||
|
#endif
|
||||||
|
#ifndef DRM_CLIENT_CAP_ATOMIC
|
||||||
|
#define DRM_CLIENT_CAP_ATOMIC 3
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef DRM_MODE_PROP_EXTENDED_TYPE
|
||||||
|
#define DRM_MODE_PROP_EXTENDED_TYPE 0x0000ffc0
|
||||||
|
#endif
|
||||||
|
#ifndef DRM_MODE_PROP_TYPE
|
||||||
|
#define DRM_MODE_PROP_TYPE(n) ((n) << 6)
|
||||||
|
#endif
|
||||||
|
#ifndef DRM_MODE_PROP_OBJECT
|
||||||
|
#define DRM_MODE_PROP_OBJECT DRM_MODE_PROP_TYPE(1)
|
||||||
|
#endif
|
||||||
|
#ifndef DRM_MODE_PROP_SIGNED_RANGE
|
||||||
|
#define DRM_MODE_PROP_SIGNED_RANGE DRM_MODE_PROP_TYPE(2)
|
||||||
|
#endif
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
class QKmsDevice;
|
class QKmsDevice;
|
||||||
@ -99,6 +134,42 @@ private:
|
|||||||
QMap<QString, QVariantMap> m_outputSettings;
|
QMap<QString, QVariantMap> m_outputSettings;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// NB! QKmsPlane does not store the current state and offers no functions to
|
||||||
|
// change object properties. Any such functionality belongs to subclasses since
|
||||||
|
// in some cases atomic operations will be desired where a mere
|
||||||
|
// drmModeObjectSetProperty would not be acceptable.
|
||||||
|
struct QKmsPlane
|
||||||
|
{
|
||||||
|
enum Type {
|
||||||
|
OverlayPlane = DRM_PLANE_TYPE_OVERLAY,
|
||||||
|
PrimaryPlane = DRM_PLANE_TYPE_PRIMARY,
|
||||||
|
CursorPlane = DRM_PLANE_TYPE_CURSOR
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Rotation {
|
||||||
|
Rotation0 = 1 << 0,
|
||||||
|
Rotation90 = 1 << 1,
|
||||||
|
Rotation180 = 1 << 2,
|
||||||
|
Rotation270 = 1 << 3,
|
||||||
|
RotationReflectX = 1 << 4,
|
||||||
|
RotationReflectY = 1 << 5
|
||||||
|
};
|
||||||
|
Q_DECLARE_FLAGS(Rotations, Rotation)
|
||||||
|
|
||||||
|
uint32_t id = 0;
|
||||||
|
Type type = OverlayPlane;
|
||||||
|
|
||||||
|
int possibleCrtcs = 0;
|
||||||
|
|
||||||
|
QVector<uint32_t> supportedFormats;
|
||||||
|
|
||||||
|
Rotations initialRotation = Rotation0;
|
||||||
|
Rotations availableRotations = Rotation0;
|
||||||
|
uint32_t rotationPropertyId = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
Q_DECLARE_OPERATORS_FOR_FLAGS(QKmsPlane::Rotations)
|
||||||
|
|
||||||
struct QKmsOutput
|
struct QKmsOutput
|
||||||
{
|
{
|
||||||
QString name;
|
QString name;
|
||||||
@ -119,6 +190,7 @@ struct QKmsOutput
|
|||||||
bool forced_plane_set = false;
|
bool forced_plane_set = false;
|
||||||
uint32_t drm_format = DRM_FORMAT_XRGB8888;
|
uint32_t drm_format = DRM_FORMAT_XRGB8888;
|
||||||
QString clone_source;
|
QString clone_source;
|
||||||
|
QVector<QKmsPlane> available_planes;
|
||||||
|
|
||||||
void restoreMode(QKmsDevice *device);
|
void restoreMode(QKmsDevice *device);
|
||||||
void cleanup(QKmsDevice *device);
|
void cleanup(QKmsDevice *device);
|
||||||
@ -168,6 +240,9 @@ protected:
|
|||||||
ScreenInfo *vinfo);
|
ScreenInfo *vinfo);
|
||||||
drmModePropertyPtr connectorProperty(drmModeConnectorPtr connector, const QByteArray &name);
|
drmModePropertyPtr connectorProperty(drmModeConnectorPtr connector, const QByteArray &name);
|
||||||
drmModePropertyBlobPtr connectorPropertyBlob(drmModeConnectorPtr connector, const QByteArray &name);
|
drmModePropertyBlobPtr connectorPropertyBlob(drmModeConnectorPtr connector, const QByteArray &name);
|
||||||
|
typedef std::function<void(drmModePropertyPtr, quint64)> PropCallback;
|
||||||
|
void enumerateProperties(drmModeObjectPropertiesPtr objProps, PropCallback callback);
|
||||||
|
void discoverPlanes();
|
||||||
|
|
||||||
QKmsScreenConfig *m_screenConfig;
|
QKmsScreenConfig *m_screenConfig;
|
||||||
QString m_path;
|
QString m_path;
|
||||||
@ -175,6 +250,8 @@ protected:
|
|||||||
|
|
||||||
quint32 m_crtc_allocator;
|
quint32 m_crtc_allocator;
|
||||||
|
|
||||||
|
QVector<QKmsPlane> m_planes;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Q_DISABLE_COPY(QKmsDevice)
|
Q_DISABLE_COPY(QKmsDevice)
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user