Small refactor in the drm backends

This commit is contained in:
Xaver Hugl 2020-12-01 16:58:24 +00:00
parent d56d4370b2
commit b460909212
6 changed files with 45 additions and 98 deletions

View file

@ -11,6 +11,7 @@
#include "drm_backend.h"
#include "drm_gpu.h"
#include "drm_output.h"
using namespace KWin;
@ -20,6 +21,8 @@ AbstractEglDrmBackend::AbstractEglDrmBackend(DrmBackend *drmBackend, DrmGpu *gpu
// Egl is always direct rendering.
setIsDirectRendering(true);
setSyncsToVBlank(true);
connect(m_gpu, &DrmGpu::outputEnabled, this, &AbstractEglDrmBackend::addOutput);
connect(m_gpu, &DrmGpu::outputDisabled, this, &AbstractEglDrmBackend::removeOutput);
}
AbstractEglDrmBackend::~AbstractEglDrmBackend()

View file

@ -17,6 +17,7 @@ namespace KWin
class DrmBackend;
class DrmGpu;
class DrmOutput;
class AbstractEglDrmBackend : public AbstractEglBackend
{
@ -28,9 +29,8 @@ public:
void screenGeometryChanged(const QSize &size) override;
virtual int screenCount() const = 0;
virtual void addSecondaryGpuOutput(AbstractOutput *output) {
Q_UNUSED(output)
}
virtual void addOutput(DrmOutput *output) = 0;
virtual void removeOutput(DrmOutput *output) = 0;
virtual int getDmabufForSecondaryGpuOutput(AbstractOutput *output, uint32_t *format, uint32_t *stride) {
Q_UNUSED(output)
Q_UNUSED(format)
@ -40,16 +40,10 @@ public:
virtual void cleanupDmabufForSecondaryGpuOutput(AbstractOutput *output) {
Q_UNUSED(output)
}
virtual void removeSecondaryGpuOutput(AbstractOutput *output) {
Q_UNUSED(output)
}
virtual QRegion beginFrameForSecondaryGpu(AbstractOutput *output) {
Q_UNUSED(output)
return QRegion();
}
virtual void renderFramebufferToSurface(AbstractOutput *output) {
Q_UNUSED(output)
}
static AbstractEglDrmBackend *renderingBackend() {
return static_cast<AbstractEglDrmBackend*>(primaryBackend());

View file

@ -30,8 +30,6 @@ namespace KWin
EglGbmBackend::EglGbmBackend(DrmBackend *drmBackend, DrmGpu *gpu)
: AbstractEglDrmBackend(drmBackend, gpu)
{
connect(m_gpu, &DrmGpu::outputEnabled, this, &EglGbmBackend::createOutput);
connect(m_gpu, &DrmGpu::outputDisabled, this, &EglGbmBackend::removeOutput);
}
void EglGbmBackend::cleanupSurfaces()
@ -139,7 +137,7 @@ bool EglGbmBackend::initRenderingContext()
const auto outputs = m_gpu->outputs();
for (DrmOutput *drmOutput: outputs) {
createOutput(drmOutput);
addOutput(drmOutput);
}
if (m_outputs.isEmpty() && !outputs.isEmpty()) {
@ -213,73 +211,52 @@ bool EglGbmBackend::resetOutput(Output &output, DrmOutput *drmOutput)
return true;
}
void EglGbmBackend::createOutput(DrmOutput *drmOutput)
void EglGbmBackend::addOutput(DrmOutput *drmOutput)
{
if (isPrimary()) {
Output newOutput;
if (resetOutput(newOutput, drmOutput)) {
QVector<Output> &outputs = drmOutput->gpu() == m_gpu ? m_outputs : m_secondaryGpuOutputs;
connect(drmOutput, &DrmOutput::modeChanged, this,
[drmOutput, this] {
auto it = std::find_if(m_outputs.begin(), m_outputs.end(),
[drmOutput, &outputs, this] {
auto it = std::find_if(outputs.begin(), outputs.end(),
[drmOutput] (const auto &output) {
return output.output == drmOutput;
}
);
if (it == m_outputs.end()) {
if (it == outputs.end()) {
return;
}
resetOutput(*it, drmOutput);
}
);
m_outputs << newOutput;
outputs << newOutput;
}
} else {
Output newOutput;
newOutput.output = drmOutput;
renderingBackend()->addSecondaryGpuOutput(drmOutput);
renderingBackend()->addOutput(drmOutput);
m_outputs << newOutput;
}
}
void EglGbmBackend::removeOutput(DrmOutput *drmOutput)
{
auto it = std::find_if(m_outputs.begin(), m_outputs.end(),
QVector<Output> &outputs = drmOutput->gpu() == m_gpu ? m_outputs : m_secondaryGpuOutputs;
auto it = std::find_if(outputs.begin(), outputs.end(),
[drmOutput] (const Output &output) {
return output.output == drmOutput;
}
);
if (it == m_outputs.end()) {
if (it == outputs.end()) {
return;
}
if (this != primaryBackend()) {
renderingBackend()->removeSecondaryGpuOutput((*it).output);
} else {
if (isPrimary()) {
cleanupOutput(*it);
} else {
renderingBackend()->removeOutput((*it).output);
}
m_outputs.erase(it);
}
void EglGbmBackend::addSecondaryGpuOutput(AbstractOutput *output)
{
DrmOutput *drmOutput = static_cast<DrmOutput*>(output);
Output newOutput;
newOutput.onSecondaryGPU = true;
if (resetOutput(newOutput, drmOutput)) {
connect(drmOutput, &DrmOutput::modeChanged, this,
[drmOutput, this] {
auto it = std::find_if(m_secondaryGpuOutputs.begin(), m_secondaryGpuOutputs.end(),
[drmOutput] (const auto &output) {
return output.output == drmOutput;
}
);
if (it == m_secondaryGpuOutputs.end()) {
return;
}
resetOutput(*it, drmOutput);
}
);
m_secondaryGpuOutputs << newOutput;
}
outputs.erase(it);
}
int EglGbmBackend::getDmabufForSecondaryGpuOutput(AbstractOutput *output, uint32_t *format, uint32_t *stride)
@ -293,6 +270,7 @@ int EglGbmBackend::getDmabufForSecondaryGpuOutput(AbstractOutput *output, uint32
if (it == m_secondaryGpuOutputs.end()) {
return -1;
}
renderFramebufferToSurface(*it);
auto error = eglSwapBuffers(eglDisplay(), it->eglSurface);
if (error != EGL_TRUE) {
qCDebug(KWIN_DRM) << "an error occurred while swapping buffers" << error;
@ -331,21 +309,6 @@ void EglGbmBackend::cleanupDmabufForSecondaryGpuOutput(AbstractOutput *output)
}
}
void EglGbmBackend::removeSecondaryGpuOutput(AbstractOutput *output)
{
DrmOutput *drmOutput = static_cast<DrmOutput*>(output);
auto it = std::find_if(m_secondaryGpuOutputs.begin(), m_secondaryGpuOutputs.end(),
[drmOutput] (const Output &output) {
return output.output == drmOutput;
}
);
if (it == m_secondaryGpuOutputs.end()) {
return;
}
cleanupOutput(*it);
m_secondaryGpuOutputs.erase(it);
}
QRegion EglGbmBackend::beginFrameForSecondaryGpu(AbstractOutput *output)
{
DrmOutput *drmOutput = static_cast<DrmOutput*>(output);
@ -360,20 +323,6 @@ QRegion EglGbmBackend::beginFrameForSecondaryGpu(AbstractOutput *output)
return prepareRenderingForOutput(*it);
}
void EglGbmBackend::renderFramebufferToSurface(AbstractOutput *output)
{
DrmOutput *drmOutput = static_cast<DrmOutput*>(output);
auto it = std::find_if(m_secondaryGpuOutputs.begin(), m_secondaryGpuOutputs.end(),
[drmOutput] (const Output &output) {
return output.output == drmOutput;
}
);
if (it == m_secondaryGpuOutputs.end()) {
return;
}
renderFramebufferToSurface(*it);
}
const float vertices[] = {
-1.0f, 1.0f,
-1.0f, -1.0f,
@ -503,7 +452,6 @@ void EglGbmBackend::renderFramebufferToSurface(Output &output)
glBindTexture(GL_TEXTURE_2D, 0);
} else {
// secondary GPU: render on primary and import framebuffer
renderingBackend()->renderFramebufferToSurface(output.output);
uint32_t stride = 0;
uint32_t format = 0;
int fd = renderingBackend()->getDmabufForSecondaryGpuOutput(output.output, &format, &stride);

View file

@ -43,12 +43,11 @@ public:
return m_outputs.count();
}
void addSecondaryGpuOutput(AbstractOutput *output) override;
void addOutput(DrmOutput *output) override;
void removeOutput(DrmOutput *output) override;
int getDmabufForSecondaryGpuOutput(AbstractOutput *output, uint32_t *format, uint32_t *stride) override;
void cleanupDmabufForSecondaryGpuOutput(AbstractOutput *output) override;
void removeSecondaryGpuOutput(AbstractOutput *output) override;
QRegion beginFrameForSecondaryGpu(AbstractOutput *output) override;
void renderFramebufferToSurface(AbstractOutput *output) override;
protected:
void present() override;
@ -83,7 +82,6 @@ private:
gbm_bo *importedGbmBo = nullptr;
};
void createOutput(DrmOutput *drmOutput);
bool resetOutput(Output &output, DrmOutput *drmOutput);
std::shared_ptr<GbmSurface> createGbmSurface(const QSize &size, const bool linear) const;
EGLSurface createEglSurface(std::shared_ptr<GbmSurface> gbmSurface) const;
@ -100,7 +98,6 @@ private:
void presentOnOutput(Output &output, const QRegion &damagedRegion);
void removeOutput(DrmOutput *drmOutput);
void cleanupOutput(Output &output);
void cleanupFramebuffer(Output &output);

View file

@ -72,19 +72,6 @@ PFNEGLQUERYWAYLANDBUFFERWL pEglQueryWaylandBufferWL = nullptr;
EglStreamBackend::EglStreamBackend(DrmBackend *drmBackend, DrmGpu *gpu)
: AbstractEglDrmBackend(drmBackend, gpu)
{
connect(m_gpu, &DrmGpu::outputEnabled, this, &EglStreamBackend::createOutput);
connect(m_gpu, &DrmGpu::outputDisabled, this,
[this] (DrmOutput *output) {
auto it = std::find_if(m_outputs.begin(), m_outputs.end(),
[output] (const Output &o) {
return o.output == output;
});
if (it == m_outputs.end()) {
return;
}
cleanupOutput(*it);
m_outputs.erase(it);
});
}
void EglStreamBackend::cleanupSurfaces()
@ -280,7 +267,7 @@ bool EglStreamBackend::initRenderingContext()
const auto outputs = m_gpu->outputs();
for (DrmOutput *drmOutput : outputs) {
createOutput(drmOutput);
addOutput(drmOutput);
}
if (m_outputs.isEmpty()) {
qCCritical(KWIN_DRM) << "Failed to create output surface";
@ -358,8 +345,9 @@ bool EglStreamBackend::resetOutput(Output &o, DrmOutput *drmOutput)
return true;
}
void EglStreamBackend::createOutput(DrmOutput *drmOutput)
void EglStreamBackend::addOutput(DrmOutput *drmOutput)
{
Q_ASSERT(drmOutput->gpu() == m_gpu);
Output o;
if (!resetOutput(o, drmOutput)) {
return;
@ -381,6 +369,21 @@ void EglStreamBackend::createOutput(DrmOutput *drmOutput)
m_outputs << o;
}
void EglStreamBackend::removeOutput(DrmOutput *drmOutput)
{
Q_ASSERT(drmOutput->gpu() == m_gpu);
auto it = std::find_if(m_outputs.begin(), m_outputs.end(),
[drmOutput] (const Output &o) {
return o.output == drmOutput;
}
);
if (it == m_outputs.end()) {
return;
}
cleanupOutput(*it);
m_outputs.erase(it);
}
bool EglStreamBackend::makeContextCurrent(const Output &output)
{
const EGLSurface surface = output.eglSurface;

View file

@ -36,6 +36,9 @@ public:
return m_outputs.count();
}
void addOutput(DrmOutput *output) override;
void removeOutput(DrmOutput *output) override;
protected:
void present() override;
void cleanupSurfaces() override;
@ -64,7 +67,6 @@ private:
bool makeContextCurrent(const Output &output);
void presentOnOutput(Output &output);
void cleanupOutput(const Output &output);
void createOutput(DrmOutput *output);
QVector<Output> m_outputs;
KWaylandServer::EglStreamControllerInterface *m_eglStreamControllerInterface;