Commit cdab4be1 authored by Xaver Hugl's avatar Xaver Hugl Committed by Vlad Zahorodnii

Automatically detect the proprietary NVidia driver and use EGLStreams accordingly

parent 6b940c12
......@@ -67,11 +67,6 @@ DrmBackend::DrmBackend(QObject *parent)
, m_udevMonitor(m_udev->monitor())
, m_dpmsFilter()
{
#if HAVE_EGL_STREAMS
if (qEnvironmentVariableIsSet("KWIN_DRM_USE_EGL_STREAMS")) {
m_useEglStreams = true;
}
#endif
setSupportsGammaControl(true);
supportsOutputChanges();
}
......@@ -482,7 +477,7 @@ DrmOutput *DrmBackend::findOutput(quint32 connector)
bool DrmBackend::present(DrmBuffer *buffer, DrmOutput *output)
{
if (!buffer || buffer->bufferId() == 0) {
if (m_deleteBufferAfterPageFlip) {
if (output->gpu()->deleteBufferAfterPageFlip()) {
delete buffer;
}
return false;
......@@ -494,7 +489,7 @@ bool DrmBackend::present(DrmBuffer *buffer, DrmOutput *output)
Compositor::self()->aboutToSwapBuffers();
}
return true;
} else if (m_deleteBufferAfterPageFlip) {
} else if (output->gpu()->deleteBufferAfterPageFlip()) {
delete buffer;
}
return false;
......@@ -506,9 +501,14 @@ void DrmBackend::initCursor()
#if HAVE_EGL_STREAMS
// Hardware cursors aren't currently supported with EGLStream backend,
// possibly an NVIDIA driver bug
if (m_useEglStreams) {
setSoftWareCursor(true);
bool needsSoftwareCursor = false;
for (auto gpu : qAsConst(m_gpus)) {
if (gpu->useEglStreams()) {
needsSoftwareCursor = true;
break;
}
}
setSoftWareCursor(needsSoftwareCursor);
#endif
m_cursorEnabled = waylandServer()->seat()->hasPointer();
......@@ -604,21 +604,19 @@ Screens *DrmBackend::createScreens(QObject *parent)
QPainterBackend *DrmBackend::createQPainterBackend()
{
m_deleteBufferAfterPageFlip = false;
m_gpus.at(0)->setDeleteBufferAfterPageFlip(false);
return new DrmQPainterBackend(this, m_gpus.at(0));
}
OpenGLBackend *DrmBackend::createOpenGLBackend()
{
#if HAVE_EGL_STREAMS
if (m_useEglStreams) {
m_deleteBufferAfterPageFlip = false;
if (m_gpus.at(0)->useEglStreams()) {
return new EglStreamBackend(this, m_gpus.at(0));
}
#endif
#if HAVE_GBM
m_deleteBufferAfterPageFlip = true;
return new EglGbmBackend(this, m_gpus.at(0));
#else
return Platform::createOpenGLBackend();
......@@ -642,7 +640,7 @@ QVector<CompositingType> DrmBackend::supportedCompositors() const
#if HAVE_GBM
return QVector<CompositingType>{OpenGLCompositing, QPainterCompositing};
#elif HAVE_EGL_STREAMS
return m_useEglStreams ?
return m_gpus.at(0)->useEglStreams() ?
QVector<CompositingType>{OpenGLCompositing, QPainterCompositing} :
QVector<CompositingType>{QPainterCompositing};
#else
......@@ -661,7 +659,7 @@ QString DrmBackend::supportInformation() const
s << "Atomic Mode Setting on GPU " << g << ": " << m_gpus.at(g)->atomicModeSetting() << Qt::endl;
}
#if HAVE_EGL_STREAMS
s << "Using EGL Streams: " << m_useEglStreams << Qt::endl;
s << "Using EGL Streams: " << m_gpus.at(0)->useEglStreams() << Qt::endl;
#endif
return supportInfo;
}
......
......@@ -78,17 +78,6 @@ public:
void createDpmsFilter();
void checkOutputsAreOn();
// QPainter reuses buffers
bool deleteBufferAfterPageFlip() const {
return m_deleteBufferAfterPageFlip;
}
#if HAVE_EGL_STREAMS
bool useEglStreams() const {
return m_useEglStreams;
}
#endif
QVector<CompositingType> supportedCompositors() const override;
QString supportInformation() const override;
......@@ -130,13 +119,9 @@ private:
// active and enabled pipelines (above + wl_output)
QVector<DrmOutput*> m_enabledOutputs;
bool m_deleteBufferAfterPageFlip;
bool m_cursorEnabled = false;
int m_pageFlipsPending = 0;
bool m_active = false;
#if HAVE_EGL_STREAMS
bool m_useEglStreams = false;
#endif
QVector<DrmGpu*> m_gpus;
QScopedPointer<DpmsInputEventFilter> m_dpmsFilter;
};
......
......@@ -32,7 +32,7 @@
namespace KWin
{
DrmGpu::DrmGpu(DrmBackend *backend, QByteArray devNode, int fd, int drmId) : m_backend(backend), m_devNode(devNode), m_fd(fd), m_drmId(drmId), m_atomicModeSetting(false), m_useEglStreams(false), m_gbmDevice(nullptr)
DrmGpu::DrmGpu(DrmBackend *backend, QByteArray devNode, int fd, int drmId) : m_backend(backend), m_devNode(devNode), m_fd(fd), m_drmId(drmId), m_atomicModeSetting(false), m_gbmDevice(nullptr)
{
uint64_t capability = 0;
......@@ -47,6 +47,12 @@ DrmGpu::DrmGpu(DrmBackend *backend, QByteArray devNode, int fd, int drmId) : m_b
} else {
m_cursorSize.setHeight(64);
}
// find out if this GPU is using the NVidia proprietary driver
DrmScopedPointer<drmVersion> version(drmGetVersion(fd));
m_useEglStreams = strstr(version->name, "nvidia-drm");
m_deleteBufferAfterPageFlip = !m_useEglStreams;
}
DrmGpu::~DrmGpu()
......
......@@ -54,6 +54,14 @@ public:
return m_atomicModeSetting;
}
bool useEglStreams() const {
return m_useEglStreams;
}
bool deleteBufferAfterPageFlip() const {
return m_deleteBufferAfterPageFlip;
}
QByteArray devNode() const {
return m_devNode;
}
......@@ -78,6 +86,10 @@ public:
m_eglDisplay = display;
}
void setDeleteBufferAfterPageFlip(bool deleteBuffer) {
m_deleteBufferAfterPageFlip = deleteBuffer;
}
DrmDumbBuffer *createBuffer(const QSize &size) const {
return new DrmDumbBuffer(m_fd, size);
}
......@@ -105,6 +117,7 @@ private:
const int m_drmId;
bool m_atomicModeSetting;
bool m_useEglStreams;
bool m_deleteBufferAfterPageFlip;
gbm_device* m_gbmDevice;
EGLDisplay m_eglDisplay = EGL_NO_DISPLAY;
......
......@@ -67,7 +67,7 @@ bool DrmCrtc::initProps()
void DrmCrtc::flipBuffer()
{
if (m_currentBuffer && m_backend->deleteBufferAfterPageFlip() && m_currentBuffer != m_nextBuffer) {
if (m_currentBuffer && m_gpu->deleteBufferAfterPageFlip() && m_currentBuffer != m_nextBuffer) {
delete m_currentBuffer;
}
m_currentBuffer = m_nextBuffer;
......@@ -98,7 +98,7 @@ bool DrmCrtc::blank()
}
if (m_output->setModeLegacy(m_blackBuffer)) {
if (m_currentBuffer && m_backend->deleteBufferAfterPageFlip()) {
if (m_currentBuffer && m_gpu->deleteBufferAfterPageFlip()) {
delete m_currentBuffer;
delete m_nextBuffer;
}
......
......@@ -65,7 +65,7 @@ void DrmOutput::teardown()
// TODO: when having multiple planes, also clean up these
m_primaryPlane->setOutput(nullptr);
if (m_backend->deleteBufferAfterPageFlip()) {
if (m_gpu->deleteBufferAfterPageFlip()) {
delete m_primaryPlane->current();
}
m_primaryPlane->setCurrent(nullptr);
......@@ -694,7 +694,7 @@ void DrmOutput::pageFlipped()
}
// Egl based surface buffers get destroyed, QPainter based dumb buffers not
// TODO: split up DrmOutput in two for dumb and egl/gbm surface buffer compatible subclasses completely?
if (m_backend->deleteBufferAfterPageFlip()) {
if (m_gpu->deleteBufferAfterPageFlip()) {
if (m_gpu->atomicModeSetting()) {
if (!m_primaryPlane->next()) {
// on manual vt switch
......@@ -784,7 +784,7 @@ bool DrmOutput::presentAtomically(DrmBuffer *buffer)
}
#if HAVE_EGL_STREAMS
if (m_backend->useEglStreams() && !m_modesetRequested) {
if (m_gpu->useEglStreams() && !m_modesetRequested) {
// EglStreamBackend queues normal page flips through EGL,
// modesets are still performed through DRM-KMS
m_pageFlipPending = true;
......@@ -935,7 +935,7 @@ bool DrmOutput::doAtomicCommit(AtomicCommitMode mode)
}
#if HAVE_EGL_STREAMS
if (!m_backend->useEglStreams())
if (!m_gpu->useEglStreams())
// EglStreamBackend uses the NV_output_drm_flip_event EGL extension
// to register the flip event through eglStreamConsumerAcquireAttribNV
#endif
......@@ -988,7 +988,7 @@ bool DrmOutput::atomicReqModesetPopulate(drmModeAtomicReq *req, bool enable)
m_primaryPlane->setValue(int(DrmPlane::PropertyIndex::CrtcH), mSize.height());
m_primaryPlane->setValue(int(DrmPlane::PropertyIndex::CrtcId), m_crtc->id());
} else {
if (m_backend->deleteBufferAfterPageFlip()) {
if (m_gpu->deleteBufferAfterPageFlip()) {
delete m_primaryPlane->current();
delete m_primaryPlane->next();
}
......
......@@ -13,6 +13,7 @@
#include <QScopedPointer>
#include <xf86drmMode.h>
#include <xf86drm.h>
namespace KWin
{
......@@ -20,6 +21,15 @@ namespace KWin
template <typename T>
struct DrmDeleter;
template <>
struct DrmDeleter<drmVersion>
{
static void cleanup(drmVersion *version)
{
drmFreeVersion(version);
}
};
template <>
struct DrmDeleter<drmModeAtomicReq>
{
......
Markdown is supported
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