127 lines
3.3 KiB
C++
127 lines
3.3 KiB
C++
|
/*
|
||
|
KWin - the KDE window manager
|
||
|
This file is part of the KDE project.
|
||
|
|
||
|
SPDX-FileCopyrightText: 2020 Xaver Hugl <xaver.hugl@gmail.com>
|
||
|
|
||
|
SPDX-License-Identifier: GPL-2.0-or-later
|
||
|
*/
|
||
|
|
||
|
#include "egl_multi_backend.h"
|
||
|
#include "logging.h"
|
||
|
|
||
|
namespace KWin
|
||
|
{
|
||
|
|
||
|
EglMultiBackend::EglMultiBackend(AbstractEglDrmBackend *backend0) : OpenGLBackend()
|
||
|
{
|
||
|
m_backends.append(backend0);
|
||
|
setIsDirectRendering(true);
|
||
|
}
|
||
|
|
||
|
EglMultiBackend::~EglMultiBackend()
|
||
|
{
|
||
|
for (int i = 1; i < m_backends.count(); i++) {
|
||
|
delete m_backends[i];
|
||
|
}
|
||
|
// delete primary backend last, or this will crash!
|
||
|
delete m_backends[0];
|
||
|
}
|
||
|
|
||
|
void EglMultiBackend::init()
|
||
|
{
|
||
|
for (auto b : qAsConst(m_backends)) {
|
||
|
b->init();
|
||
|
}
|
||
|
// if any don't support it set it to not supported
|
||
|
setSupportsBufferAge(true);
|
||
|
setSupportsPartialUpdate(true);
|
||
|
setSupportsSwapBuffersWithDamage(true);
|
||
|
for (auto b : qAsConst(m_backends)) {
|
||
|
if (!b->supportsBufferAge()) {
|
||
|
setSupportsBufferAge(false);
|
||
|
}
|
||
|
if (!b->supportsPartialUpdate()) {
|
||
|
setSupportsPartialUpdate(false);
|
||
|
}
|
||
|
if (!b->supportsSwapBuffersWithDamage()) {
|
||
|
setSupportsSwapBuffersWithDamage(false);
|
||
|
}
|
||
|
}
|
||
|
// we only care about the rendering GPU here
|
||
|
setSupportsSurfacelessContext(m_backends[0]->supportsSurfacelessContext());
|
||
|
// these are client extensions and the same for all egl backends
|
||
|
setExtensions(m_backends[0]->extensions());
|
||
|
|
||
|
m_backends[0]->makeCurrent();
|
||
|
}
|
||
|
|
||
|
QRegion EglMultiBackend::beginFrame(int screenId)
|
||
|
{
|
||
|
int internalScreenId;
|
||
|
AbstractEglBackend *backend = findBackend(screenId, internalScreenId);
|
||
|
Q_ASSERT(backend != nullptr);
|
||
|
return backend->beginFrame(internalScreenId);
|
||
|
}
|
||
|
|
||
|
void EglMultiBackend::endFrame(int screenId, const QRegion &damage, const QRegion &damagedRegion)
|
||
|
{
|
||
|
int internalScreenId;
|
||
|
AbstractEglBackend *backend = findBackend(screenId, internalScreenId);
|
||
|
Q_ASSERT(backend != nullptr);
|
||
|
backend->endFrame(internalScreenId, damage, damagedRegion);
|
||
|
}
|
||
|
|
||
|
bool EglMultiBackend::makeCurrent()
|
||
|
{
|
||
|
return m_backends[0]->makeCurrent();
|
||
|
}
|
||
|
|
||
|
void EglMultiBackend::doneCurrent()
|
||
|
{
|
||
|
m_backends[0]->doneCurrent();
|
||
|
}
|
||
|
|
||
|
SceneOpenGLTexturePrivate *EglMultiBackend::createBackendTexture(SceneOpenGLTexture *texture)
|
||
|
{
|
||
|
return m_backends[0]->createBackendTexture(texture);
|
||
|
}
|
||
|
|
||
|
QSharedPointer<GLTexture> EglMultiBackend::textureForOutput(AbstractOutput *requestedOutput) const
|
||
|
{
|
||
|
// this assumes that the wrong backends return {}
|
||
|
for (auto backend : qAsConst(m_backends)) {
|
||
|
auto texture = backend->textureForOutput(requestedOutput);
|
||
|
if (!texture.isNull()) {
|
||
|
return texture;
|
||
|
}
|
||
|
}
|
||
|
return {};
|
||
|
}
|
||
|
|
||
|
void EglMultiBackend::screenGeometryChanged(const QSize &size)
|
||
|
{
|
||
|
Q_UNUSED(size)
|
||
|
}
|
||
|
|
||
|
AbstractEglDrmBackend *EglMultiBackend::findBackend(int screenId, int& internalScreenId)
|
||
|
{
|
||
|
int screens = 0;
|
||
|
for (int i = 0; i < m_backends.count(); i++) {
|
||
|
if (screenId < screens + m_backends[i]->screenCount()) {
|
||
|
internalScreenId = screenId - screens;
|
||
|
return m_backends[i];
|
||
|
}
|
||
|
screens += m_backends[i]->screenCount();
|
||
|
}
|
||
|
qCDebug(KWIN_DRM) << "could not find backend!" << screenId << "/" << screens;
|
||
|
return nullptr;
|
||
|
}
|
||
|
|
||
|
void EglMultiBackend::addBackend(AbstractEglDrmBackend *backend)
|
||
|
{
|
||
|
m_backends.append(backend);
|
||
|
}
|
||
|
|
||
|
}
|