Commit 995437f5 authored by Xaver Hugl's avatar Xaver Hugl
Browse files

decouple DRM planes from DrmOutput

parent 7c2c213f
......@@ -72,7 +72,6 @@ private Q_SLOTS:
void testId();
void testFd_data();
void testFd();
void testOutput();
void testInitProperties();
};
......@@ -120,18 +119,6 @@ public:
};
}
void ObjectTest::testOutput()
{
MockDrmObject object{0, 1};
QVERIFY(!object.output());
KWin::DrmOutput output{2};
object.setOutput(&output);
QCOMPARE(object.output(), &output);
QCOMPARE(object.output()->foo, 2);
}
void ObjectTest::testInitProperties()
{
MockDrmObject object{0, 20};
......
......@@ -182,7 +182,7 @@ void DrmBackend::reactivate()
DrmOutput *o = *it;
// only relevant in atomic mode
o->m_modesetRequested = true;
o->m_crtc->blank();
o->m_crtc->blank(o);
o->showCursor();
o->moveCursor();
}
......
......@@ -85,47 +85,29 @@ void DrmGpu::tryAMS()
{
m_atomicModeSetting = false;
if (drmSetClientCap(m_fd, DRM_CLIENT_CAP_ATOMIC, 1) == 0) {
bool ams = true;
QVector<DrmPlane*> planes, overlayPlanes;
DrmScopedPointer<drmModePlaneRes> planeResources(drmModeGetPlaneResources(m_fd));
if (!planeResources) {
qCWarning(KWIN_DRM) << "Failed to get plane resources. Falling back to legacy mode on GPU " << m_devNode;
ams = false;
m_atomicModeSetting = false;
return;
}
if (ams) {
qCDebug(KWIN_DRM) << "Using Atomic Mode Setting on gpu" << m_devNode;
qCDebug(KWIN_DRM) << "Number of planes on GPU" << m_devNode << ":" << planeResources->count_planes;
// create the plane objects
for (unsigned int i = 0; i < planeResources->count_planes; ++i) {
DrmScopedPointer<drmModePlane> kplane(drmModeGetPlane(m_fd, planeResources->planes[i]));
DrmPlane *p = new DrmPlane(kplane->plane_id, m_fd);
if (p->init()) {
planes << p;
if (p->type() == DrmPlane::TypeIndex::Overlay) {
overlayPlanes << p;
}
} else {
delete p;
}
}
if (planes.isEmpty()) {
qCWarning(KWIN_DRM) << "Failed to create any plane. Falling back to legacy mode on GPU " << m_devNode;
ams = false;
}
}
if (!ams) {
for (auto p : planes) {
qCDebug(KWIN_DRM) << "Using Atomic Mode Setting on gpu" << m_devNode;
qCDebug(KWIN_DRM) << "Number of planes on GPU" << m_devNode << ":" << planeResources->count_planes;
// create the plane objects
for (unsigned int i = 0; i < planeResources->count_planes; ++i) {
DrmScopedPointer<drmModePlane> kplane(drmModeGetPlane(m_fd, planeResources->planes[i]));
DrmPlane *p = new DrmPlane(kplane->plane_id, m_fd);
if (p->init()) {
m_planes << p;
} else {
delete p;
}
planes.clear();
overlayPlanes.clear();
}
m_atomicModeSetting = ams;
m_planes = planes;
m_overlayPlanes = overlayPlanes;
if (m_planes.isEmpty()) {
qCWarning(KWIN_DRM) << "Failed to create any plane. Falling back to legacy mode on GPU " << m_devNode;
m_atomicModeSetting = false;
}
m_unusedPlanes = m_planes;
} else {
qCWarning(KWIN_DRM) << "drmSetClientCap for Atomic Mode Setting failed. Using legacy mode on GPU" << m_devNode;
}
......@@ -254,11 +236,11 @@ bool DrmGpu::updateOutputs()
}
DrmOutput *output = new DrmOutput(this->m_backend, this);
con->setOutput(output);
output->m_conn = con;
crtc->setOutput(output);
output->m_crtc = crtc;
output->m_mode = connector->modes[0];
output->m_primaryPlane = getCompatiblePlane(DrmPlane::TypeIndex::Primary, crtc);
output->m_cursorPlane = getCompatiblePlane(DrmPlane::TypeIndex::Cursor, crtc);
qCDebug(KWIN_DRM) << "For new output use mode " << output->m_mode.name << output->m_mode.hdisplay << output->m_mode.vdisplay;
if (!output->init(connector.data())) {
......@@ -291,6 +273,9 @@ bool DrmGpu::updateOutputs()
m_connectors.removeOne(removedOutput->m_conn);
delete removedOutput->m_conn;
removedOutput->m_conn = nullptr;
if (removedOutput->m_primaryPlane) {
m_unusedPlanes << removedOutput->m_primaryPlane;
}
}
qDeleteAll(oldConnectors);
......@@ -309,4 +294,18 @@ DrmOutput *DrmGpu::findOutput(quint32 connector)
return nullptr;
}
DrmPlane *DrmGpu::getCompatiblePlane(DrmPlane::TypeIndex typeIndex, DrmCrtc *crtc)
{
for (auto plane : m_unusedPlanes) {
if (plane->type() != typeIndex) {
continue;
}
if (plane->isCrtcSupported(crtc->resIndex())) {
m_unusedPlanes.removeOne(plane);
return plane;
}
}
return nullptr;
}
}
......@@ -16,6 +16,7 @@
#include <epoxy/egl.h>
#include "drm_buffer.h"
#include "drm_object_plane.h"
struct gbm_device;
......@@ -23,7 +24,6 @@ namespace KWin
{
class DrmOutput;
class DrmPlane;
class DrmCrtc;
class DrmConnector;
class DrmBackend;
......@@ -73,10 +73,6 @@ public:
return m_eglDisplay;
}
QVector<DrmPlane*> planes() const {
return m_planes;
}
AbstractEglBackend *eglBackend() {
return m_eglBackend;
}
......@@ -120,6 +116,7 @@ protected:
bool updateOutputs();
private:
DrmPlane *getCompatiblePlane(DrmPlane::TypeIndex typeIndex, DrmCrtc *crtc);
DrmOutput *findOutput(quint32 connector);
DrmBackend* const m_backend;
......@@ -136,9 +133,9 @@ private:
EGLDisplay m_eglDisplay = EGL_NO_DISPLAY;
clockid_t m_presentationClock;
// all available planes: primarys, cursors and overlays
// all planes: primarys, cursors and overlays
QVector<DrmPlane*> m_planes;
QVector<DrmPlane*> m_overlayPlanes;
QVector<DrmPlane*> m_unusedPlanes;
// crtcs
QVector<DrmCrtc*> m_crtcs;
// connectors
......
......@@ -177,5 +177,5 @@ void DrmObject::Property::initEnumMap(drmModePropertyRes *prop)
QDebug& operator<<(QDebug& s, const KWin::DrmObject* obj)
{
return s.nospace() << "DrmObject(" << obj->id() << ", output:" << obj->output() << ", fd: "<< obj->fd() << ')';
return s.nospace() << "DrmObject(" << obj->id() << ", fd: "<< obj->fd() << ')';
}
......@@ -42,13 +42,6 @@ public:
return m_id;
}
DrmOutput *output() const {
return m_output;
}
void setOutput(DrmOutput* output) {
m_output = output;
}
int fd() const {
return m_fd;
}
......@@ -83,7 +76,6 @@ protected:
int m_fd;
const uint32_t m_id;
DrmOutput *m_output = nullptr;
// for comparison with received name of DRM object
QVector<Property *> m_props;
......
......@@ -77,18 +77,14 @@ void DrmCrtc::flipBuffer()
m_blackBuffer = nullptr;
}
bool DrmCrtc::blank()
bool DrmCrtc::blank(DrmOutput *output)
{
if (!m_output) {
return false;
}
if (m_gpu->atomicModeSetting()) {
return false;
}
if (!m_blackBuffer) {
DrmDumbBuffer *blackBuffer = m_gpu->createBuffer(m_output->pixelSize());
DrmDumbBuffer *blackBuffer = m_gpu->createBuffer(output->pixelSize());
if (!blackBuffer->map()) {
delete blackBuffer;
return false;
......@@ -97,7 +93,7 @@ bool DrmCrtc::blank()
m_blackBuffer = blackBuffer;
}
if (m_output->setModeLegacy(m_blackBuffer)) {
if (output->setModeLegacy(m_blackBuffer)) {
if (m_currentBuffer && m_gpu->deleteBufferAfterPageFlip()) {
delete m_currentBuffer;
delete m_nextBuffer;
......
......@@ -52,7 +52,7 @@ public:
}
void flipBuffer();
bool blank();
bool blank(DrmOutput *output);
int gammaRampSize() const {
return m_gammaRampSize;
......
......@@ -66,23 +66,15 @@ void DrmOutput::teardown()
}
m_deleted = true;
hideCursor();
m_crtc->blank();
m_crtc->blank(this);
if (m_primaryPlane) {
// TODO: when having multiple planes, also clean up these
m_primaryPlane->setOutput(nullptr);
if (m_gpu->deleteBufferAfterPageFlip()) {
delete m_primaryPlane->current();
}
m_primaryPlane->setCurrent(nullptr);
}
if (m_cursorPlane) {
m_cursorPlane->setOutput(nullptr);
}
m_crtc->setOutput(nullptr);
m_conn->setOutput(nullptr);
m_cursor[0].reset(nullptr);
m_cursor[1].reset(nullptr);
......@@ -233,10 +225,8 @@ bool DrmOutput::init(drmModeConnector *connector)
initEdid(connector);
initDpms(connector);
initUuid();
if (m_gpu->atomicModeSetting()) {
if (!initPrimaryPlane()) {
return false;
}
if (m_gpu->atomicModeSetting() && !m_primaryPlane) {
return false;
}
setInternal(connector->connector_type == DRM_MODE_CONNECTOR_LVDS || connector->connector_type == DRM_MODE_CONNECTOR_eDP
......@@ -244,7 +234,7 @@ bool DrmOutput::init(drmModeConnector *connector)
setDpmsSupported(true);
initOutputDevice(connector);
if (!m_gpu->atomicModeSetting() && !m_crtc->blank()) {
if (!m_gpu->atomicModeSetting() && !m_crtc->blank(this)) {
// We use legacy mode and the initial output blank failed.
return false;
}
......@@ -369,61 +359,6 @@ void DrmOutput::initEdid(drmModeConnector *connector)
}
}
bool DrmOutput::initPrimaryPlane()
{
for (int i = 0; i < m_gpu->planes().size(); ++i) {
DrmPlane *p = m_gpu->planes()[i];
if (!p) {
continue;
}
if (p->type() != DrmPlane::TypeIndex::Primary) {
continue;
}
if (p->output()) { // Plane already has an output
continue;
}
if (m_primaryPlane) { // Output already has a primary plane
continue;
}
if (!p->isCrtcSupported(m_crtc->resIndex())) {
continue;
}
p->setOutput(this);
m_primaryPlane = p;
qCDebug(KWIN_DRM) << "Initialized primary plane" << p->id() << "on CRTC" << m_crtc->id();
return true;
}
qCCritical(KWIN_DRM) << "Failed to initialize primary plane.";
return false;
}
bool DrmOutput::initCursorPlane() // TODO: Add call in init (but needs layer support in general first)
{
for (int i = 0; i < m_gpu->planes().size(); ++i) {
DrmPlane *p = m_gpu->planes()[i];
if (!p) {
continue;
}
if (p->type() != DrmPlane::TypeIndex::Cursor) {
continue;
}
if (p->output()) { // Plane already has an output
continue;
}
if (m_cursorPlane) { // Output already has a cursor plane
continue;
}
if (!p->isCrtcSupported(m_crtc->resIndex())) {
continue;
}
p->setOutput(this);
m_cursorPlane = p;
qCDebug(KWIN_DRM) << "Initialized cursor plane" << p->id() << "on CRTC" << m_crtc->id();
return true;
}
return false;
}
bool DrmOutput::initCursor(const QSize &cursorSize)
{
auto createCursor = [this, cursorSize] (int index) {
......@@ -579,9 +514,7 @@ void DrmOutput::dpmsFinishOn()
waylandOutput()->setDpmsMode(toWaylandDpmsMode(DpmsMode::On));
m_backend->checkOutputsAreOn();
if (!m_gpu->atomicModeSetting()) {
m_crtc->blank();
}
m_crtc->blank(this);
if (Compositor *compositor = Compositor::self()) {
compositor->addRepaintFull();
}
......
......@@ -121,8 +121,6 @@ private:
bool isCurrentMode(const drmModeModeInfo *mode) const;
void initUuid();
bool initPrimaryPlane();
bool initCursorPlane();
void atomicEnable();
void atomicDisable();
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment