backends/drm: rework how atomic commits are tracked
Pending buffers for drm planes and crtcs are no longer tracked in the planes and crtcs themselves, but instead in a DrmCommit object that is used as the user data for the pageflip handler. This way multiple commits can be pending at the same time without causing conflicts, and the handling of pending buffers is simplified as well.
This commit is contained in:
parent
fcf24d98bf
commit
7d02bc17d6
16 changed files with 217 additions and 170 deletions
|
@ -1,10 +1,10 @@
|
|||
set(mockDRM_SRCS
|
||||
mock_drm.cpp
|
||||
../../src/backends/drm/drm_abstract_output.cpp
|
||||
../../src/backends/drm/drm_atomic_commit.cpp
|
||||
../../src/backends/drm/drm_backend.cpp
|
||||
../../src/backends/drm/drm_blob.cpp
|
||||
../../src/backends/drm/drm_buffer.cpp
|
||||
../../src/backends/drm/drm_commit.cpp
|
||||
../../src/backends/drm/drm_commit_thread.cpp
|
||||
../../src/backends/drm/drm_connector.cpp
|
||||
../../src/backends/drm/drm_crtc.cpp
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
target_sources(kwin PRIVATE
|
||||
drm_abstract_output.cpp
|
||||
drm_atomic_commit.cpp
|
||||
drm_backend.cpp
|
||||
drm_blob.cpp
|
||||
drm_buffer.cpp
|
||||
drm_commit.cpp
|
||||
drm_commit_thread.cpp
|
||||
drm_connector.cpp
|
||||
drm_crtc.cpp
|
||||
|
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
SPDX-FileCopyrightText: 2023 Xaver Hugl <xaver.hugl@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#include "drm_atomic_commit.h"
|
||||
#include "drm_blob.h"
|
||||
#include "drm_gpu.h"
|
||||
#include "drm_object.h"
|
||||
#include "drm_property.h"
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
DrmAtomicCommit::DrmAtomicCommit(DrmGpu *gpu)
|
||||
: m_gpu(gpu)
|
||||
, m_req(drmModeAtomicAlloc())
|
||||
{
|
||||
}
|
||||
|
||||
void DrmAtomicCommit::addProperty(const DrmProperty &prop, uint64_t value)
|
||||
{
|
||||
drmModeAtomicAddProperty(m_req.get(), prop.drmObject()->id(), prop.propId(), value);
|
||||
}
|
||||
|
||||
void DrmAtomicCommit::addBlob(const DrmProperty &prop, const std::shared_ptr<DrmBlob> &blob)
|
||||
{
|
||||
addProperty(prop, blob ? blob->blobId() : 0);
|
||||
m_blobs[&prop] = blob;
|
||||
}
|
||||
|
||||
bool DrmAtomicCommit::test()
|
||||
{
|
||||
return drmModeAtomicCommit(m_gpu->fd(), m_req.get(), DRM_MODE_ATOMIC_TEST_ONLY | DRM_MODE_ATOMIC_NONBLOCK, m_gpu) == 0;
|
||||
}
|
||||
|
||||
bool DrmAtomicCommit::testAllowModeset()
|
||||
{
|
||||
return drmModeAtomicCommit(m_gpu->fd(), m_req.get(), DRM_MODE_ATOMIC_TEST_ONLY | DRM_MODE_ATOMIC_ALLOW_MODESET, m_gpu) == 0;
|
||||
}
|
||||
|
||||
bool DrmAtomicCommit::commit()
|
||||
{
|
||||
return drmModeAtomicCommit(m_gpu->fd(), m_req.get(), DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT, m_gpu) == 0;
|
||||
}
|
||||
|
||||
bool DrmAtomicCommit::commitModeset()
|
||||
{
|
||||
return drmModeAtomicCommit(m_gpu->fd(), m_req.get(), DRM_MODE_ATOMIC_ALLOW_MODESET, m_gpu) == 0;
|
||||
}
|
||||
|
||||
drmModeAtomicReq *DrmAtomicCommit::req() const
|
||||
{
|
||||
return m_req.get();
|
||||
}
|
||||
|
||||
}
|
126
src/backends/drm/drm_commit.cpp
Normal file
126
src/backends/drm/drm_commit.cpp
Normal file
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
SPDX-FileCopyrightText: 2023 Xaver Hugl <xaver.hugl@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#include "drm_commit.h"
|
||||
#include "drm_blob.h"
|
||||
#include "drm_buffer.h"
|
||||
#include "drm_connector.h"
|
||||
#include "drm_crtc.h"
|
||||
#include "drm_gpu.h"
|
||||
#include "drm_object.h"
|
||||
#include "drm_property.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QThread>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
DrmCommit::DrmCommit(DrmGpu *gpu)
|
||||
: m_gpu(gpu)
|
||||
{
|
||||
}
|
||||
|
||||
DrmCommit::~DrmCommit()
|
||||
{
|
||||
}
|
||||
|
||||
DrmGpu *DrmCommit::gpu() const
|
||||
{
|
||||
return m_gpu;
|
||||
}
|
||||
|
||||
DrmAtomicCommit::DrmAtomicCommit(DrmGpu *gpu)
|
||||
: DrmCommit(gpu)
|
||||
, m_req(drmModeAtomicAlloc())
|
||||
{
|
||||
}
|
||||
|
||||
DrmAtomicCommit::~DrmAtomicCommit()
|
||||
{
|
||||
Q_ASSERT(QThread::currentThread() == QApplication::instance()->thread());
|
||||
if (m_commitSuccessful) {
|
||||
for (const auto &[plane, buffer] : m_buffers) {
|
||||
plane->setCurrentBuffer(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DrmAtomicCommit::addProperty(const DrmProperty &prop, uint64_t value)
|
||||
{
|
||||
drmModeAtomicAddProperty(m_req.get(), prop.drmObject()->id(), prop.propId(), value);
|
||||
}
|
||||
|
||||
void DrmAtomicCommit::addBlob(const DrmProperty &prop, const std::shared_ptr<DrmBlob> &blob)
|
||||
{
|
||||
addProperty(prop, blob ? blob->blobId() : 0);
|
||||
m_blobs[&prop] = blob;
|
||||
}
|
||||
|
||||
void DrmAtomicCommit::addBuffer(DrmPlane *plane, const std::shared_ptr<DrmFramebuffer> &buffer)
|
||||
{
|
||||
addProperty(plane->fbId, buffer ? buffer->framebufferId() : 0);
|
||||
m_buffers[plane] = buffer;
|
||||
}
|
||||
|
||||
bool DrmAtomicCommit::test()
|
||||
{
|
||||
return drmModeAtomicCommit(m_gpu->fd(), m_req.get(), DRM_MODE_ATOMIC_TEST_ONLY | DRM_MODE_ATOMIC_NONBLOCK, this) == 0;
|
||||
}
|
||||
|
||||
bool DrmAtomicCommit::testAllowModeset()
|
||||
{
|
||||
return drmModeAtomicCommit(m_gpu->fd(), m_req.get(), DRM_MODE_ATOMIC_TEST_ONLY | DRM_MODE_ATOMIC_ALLOW_MODESET, this) == 0;
|
||||
}
|
||||
|
||||
bool DrmAtomicCommit::commit()
|
||||
{
|
||||
m_commitSuccessful = (drmModeAtomicCommit(m_gpu->fd(), m_req.get(), DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT, this) == 0);
|
||||
return m_commitSuccessful;
|
||||
}
|
||||
|
||||
bool DrmAtomicCommit::commitModeset()
|
||||
{
|
||||
m_commitSuccessful = (drmModeAtomicCommit(m_gpu->fd(), m_req.get(), DRM_MODE_ATOMIC_ALLOW_MODESET, this) == 0);
|
||||
return m_commitSuccessful;
|
||||
}
|
||||
|
||||
drmModeAtomicReq *DrmAtomicCommit::req() const
|
||||
{
|
||||
return m_req.get();
|
||||
}
|
||||
|
||||
DrmLegacyCommit::DrmLegacyCommit(DrmCrtc *crtc, const std::shared_ptr<DrmFramebuffer> &buffer)
|
||||
: DrmCommit(crtc->gpu())
|
||||
, m_crtc(crtc)
|
||||
, m_buffer(buffer)
|
||||
{
|
||||
}
|
||||
|
||||
DrmLegacyCommit::~DrmLegacyCommit()
|
||||
{
|
||||
Q_ASSERT(QThread::currentThread() == QApplication::instance()->thread());
|
||||
if (m_success) {
|
||||
m_crtc->setCurrent(m_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
bool DrmLegacyCommit::doModeset(DrmConnector *connector, DrmConnectorMode *mode)
|
||||
{
|
||||
uint32_t connectorId = connector->id();
|
||||
m_success = (drmModeSetCrtc(gpu()->fd(), m_crtc->id(), m_buffer->framebufferId(), 0, 0, &connectorId, 1, mode->nativeMode()) == 0);
|
||||
return m_success;
|
||||
}
|
||||
|
||||
bool DrmLegacyCommit::doPageflip(uint32_t flags)
|
||||
{
|
||||
m_success = (drmModePageFlip(gpu()->fd(), m_crtc->id(), m_buffer->framebufferId(), flags, this) == 0);
|
||||
return m_success;
|
||||
}
|
||||
|
||||
}
|
|
@ -12,6 +12,7 @@
|
|||
#include <xf86drmMode.h>
|
||||
|
||||
#include <QHash>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "drm_pointer.h"
|
||||
#include "drm_property.h"
|
||||
|
@ -19,14 +20,33 @@
|
|||
namespace KWin
|
||||
{
|
||||
|
||||
class DrmGpu;
|
||||
class DrmProperty;
|
||||
class DrmBlob;
|
||||
class DrmConnector;
|
||||
class DrmConnectorMode;
|
||||
class DrmCrtc;
|
||||
class DrmFramebuffer;
|
||||
class DrmGpu;
|
||||
class DrmPlane;
|
||||
class DrmProperty;
|
||||
|
||||
class DrmAtomicCommit
|
||||
class DrmCommit
|
||||
{
|
||||
public:
|
||||
virtual ~DrmCommit();
|
||||
|
||||
DrmGpu *gpu() const;
|
||||
|
||||
protected:
|
||||
DrmCommit(DrmGpu *gpu);
|
||||
|
||||
DrmGpu *const m_gpu;
|
||||
};
|
||||
|
||||
class DrmAtomicCommit : public DrmCommit
|
||||
{
|
||||
public:
|
||||
DrmAtomicCommit(DrmGpu *gpu);
|
||||
~DrmAtomicCommit() override;
|
||||
|
||||
void addProperty(const DrmProperty &prop, uint64_t value);
|
||||
template<typename T>
|
||||
|
@ -35,6 +55,7 @@ public:
|
|||
addProperty(prop, prop.valueForEnum(enumValue));
|
||||
}
|
||||
void addBlob(const DrmProperty &prop, const std::shared_ptr<DrmBlob> &blob);
|
||||
void addBuffer(DrmPlane *plane, const std::shared_ptr<DrmFramebuffer> &buffer);
|
||||
|
||||
bool test();
|
||||
bool testAllowModeset();
|
||||
|
@ -44,9 +65,25 @@ public:
|
|||
drmModeAtomicReq *req() const;
|
||||
|
||||
private:
|
||||
DrmGpu *const m_gpu;
|
||||
DrmUniquePtr<drmModeAtomicReq> m_req;
|
||||
QHash<const DrmProperty *, std::shared_ptr<DrmBlob>> m_blobs;
|
||||
std::unordered_map<DrmPlane *, std::shared_ptr<DrmFramebuffer>> m_buffers;
|
||||
bool m_commitSuccessful = false;
|
||||
};
|
||||
|
||||
class DrmLegacyCommit : public DrmCommit
|
||||
{
|
||||
public:
|
||||
DrmLegacyCommit(DrmCrtc *crtc, const std::shared_ptr<DrmFramebuffer> &buffer);
|
||||
~DrmLegacyCommit() override;
|
||||
|
||||
bool doModeset(DrmConnector *connector, DrmConnectorMode *mode);
|
||||
bool doPageflip(uint32_t flags);
|
||||
|
||||
private:
|
||||
DrmCrtc *const m_crtc;
|
||||
const std::shared_ptr<DrmFramebuffer> m_buffer;
|
||||
bool m_success = false;
|
||||
};
|
||||
|
||||
}
|
|
@ -7,7 +7,7 @@
|
|||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#include "drm_commit_thread.h"
|
||||
#include "drm_atomic_commit.h"
|
||||
#include "drm_commit.h"
|
||||
#include "drm_gpu.h"
|
||||
#include "utils/realtime.h"
|
||||
|
||||
|
@ -38,10 +38,14 @@ DrmCommitThread::DrmCommitThread()
|
|||
}
|
||||
// the other thread may replace the commit, but not erase it
|
||||
Q_ASSERT(m_commit);
|
||||
if (!m_commit->commit()) {
|
||||
if (m_commit->commit()) {
|
||||
// the atomic commit takes ownership of the object
|
||||
m_commit.release();
|
||||
} else {
|
||||
m_droppedCommits.push_back(std::move(m_commit));
|
||||
QMetaObject::invokeMethod(this, &DrmCommitThread::commitFailed, Qt::ConnectionType::QueuedConnection);
|
||||
QMetaObject::invokeMethod(this, &DrmCommitThread::clearDroppedCommits, Qt::ConnectionType::QueuedConnection);
|
||||
}
|
||||
m_commit.reset();
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
@ -75,4 +79,9 @@ bool DrmCommitThread::replaceCommit(std::unique_ptr<DrmAtomicCommit> &&commit)
|
|||
}
|
||||
}
|
||||
|
||||
void DrmCommitThread::clearDroppedCommits()
|
||||
{
|
||||
std::unique_lock lock(m_mutex);
|
||||
m_droppedCommits.clear();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <QThread>
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
@ -33,11 +34,14 @@ Q_SIGNALS:
|
|||
void commitFailed();
|
||||
|
||||
private:
|
||||
void clearDroppedCommits();
|
||||
|
||||
std::unique_ptr<DrmAtomicCommit> m_commit;
|
||||
std::unique_ptr<QThread> m_thread;
|
||||
std::mutex m_mutex;
|
||||
std::condition_variable m_commitPending;
|
||||
std::chrono::nanoseconds m_targetPageflipTime;
|
||||
std::vector<std::unique_ptr<DrmAtomicCommit>> m_droppedCommits;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#include "drm_connector.h"
|
||||
#include "drm_atomic_commit.h"
|
||||
#include "drm_commit.h"
|
||||
#include "drm_crtc.h"
|
||||
#include "drm_gpu.h"
|
||||
#include "drm_logging.h"
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#include "drm_crtc.h"
|
||||
#include "drm_atomic_commit.h"
|
||||
#include "drm_backend.h"
|
||||
#include "drm_buffer.h"
|
||||
#include "drm_commit.h"
|
||||
#include "drm_gpu.h"
|
||||
#include "drm_logging.h"
|
||||
#include "drm_output.h"
|
||||
|
@ -54,12 +54,6 @@ bool DrmCrtc::updateProperties()
|
|||
return !gpu()->atomicModeSetting() || (modeId.isValid() && active.isValid());
|
||||
}
|
||||
|
||||
void DrmCrtc::flipBuffer()
|
||||
{
|
||||
m_currentBuffer = m_nextBuffer;
|
||||
m_nextBuffer = nullptr;
|
||||
}
|
||||
|
||||
drmModeModeInfo DrmCrtc::queryCurrentMode()
|
||||
{
|
||||
m_crtc.reset(drmModeGetCrtc(gpu()->fd(), id()));
|
||||
|
@ -76,21 +70,11 @@ std::shared_ptr<DrmFramebuffer> DrmCrtc::current() const
|
|||
return m_currentBuffer;
|
||||
}
|
||||
|
||||
std::shared_ptr<DrmFramebuffer> DrmCrtc::next() const
|
||||
{
|
||||
return m_nextBuffer;
|
||||
}
|
||||
|
||||
void DrmCrtc::setCurrent(const std::shared_ptr<DrmFramebuffer> &buffer)
|
||||
{
|
||||
m_currentBuffer = buffer;
|
||||
}
|
||||
|
||||
void DrmCrtc::setNext(const std::shared_ptr<DrmFramebuffer> &buffer)
|
||||
{
|
||||
m_nextBuffer = buffer;
|
||||
}
|
||||
|
||||
int DrmCrtc::gammaRampSize() const
|
||||
{
|
||||
if (gpu()->atomicModeSetting()) {
|
||||
|
@ -118,11 +102,8 @@ void DrmCrtc::disable(DrmAtomicCommit *commit)
|
|||
commit->addProperty(modeId, 0);
|
||||
}
|
||||
|
||||
void DrmCrtc::releaseBuffers()
|
||||
void DrmCrtc::releaseCurrentBuffer()
|
||||
{
|
||||
if (m_nextBuffer) {
|
||||
m_nextBuffer->releaseBuffer();
|
||||
}
|
||||
if (m_currentBuffer) {
|
||||
m_currentBuffer->releaseBuffer();
|
||||
}
|
||||
|
|
|
@ -37,11 +37,8 @@ public:
|
|||
drmModeModeInfo queryCurrentMode();
|
||||
|
||||
std::shared_ptr<DrmFramebuffer> current() const;
|
||||
std::shared_ptr<DrmFramebuffer> next() const;
|
||||
void setCurrent(const std::shared_ptr<DrmFramebuffer> &buffer);
|
||||
void setNext(const std::shared_ptr<DrmFramebuffer> &buffer);
|
||||
void flipBuffer();
|
||||
void releaseBuffers();
|
||||
void releaseCurrentBuffer();
|
||||
|
||||
DrmProperty modeId;
|
||||
DrmProperty active;
|
||||
|
@ -55,7 +52,6 @@ public:
|
|||
private:
|
||||
DrmUniquePtr<drmModeCrtc> m_crtc;
|
||||
std::shared_ptr<DrmFramebuffer> m_currentBuffer;
|
||||
std::shared_ptr<DrmFramebuffer> m_nextBuffer;
|
||||
int m_pipeIndex;
|
||||
DrmPlane *m_primaryPlane;
|
||||
DrmPlane *m_cursorPlane;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "core/session.h"
|
||||
#include "drm_backend.h"
|
||||
#include "drm_buffer.h"
|
||||
#include "drm_commit.h"
|
||||
#include "drm_connector.h"
|
||||
#include "drm_crtc.h"
|
||||
#include "drm_egl_backend.h"
|
||||
|
@ -539,7 +540,8 @@ static std::chrono::nanoseconds convertTimestamp(clockid_t sourceClock, clockid_
|
|||
|
||||
void DrmGpu::pageFlipHandler(int fd, unsigned int sequence, unsigned int sec, unsigned int usec, unsigned int crtc_id, void *user_data)
|
||||
{
|
||||
DrmGpu *gpu = static_cast<DrmGpu *>(user_data);
|
||||
const auto commit = static_cast<DrmCommit *>(user_data);
|
||||
const auto gpu = commit->gpu();
|
||||
|
||||
// The static_cast<> here are for a 32-bit environment where
|
||||
// sizeof(time_t) == sizeof(unsigned int) == 4 . Putting @p sec
|
||||
|
@ -562,6 +564,7 @@ void DrmGpu::pageFlipHandler(int fd, unsigned int sequence, unsigned int sec, un
|
|||
} else {
|
||||
(*it)->pageFlipped(timestamp);
|
||||
}
|
||||
delete commit;
|
||||
}
|
||||
|
||||
void DrmGpu::dispatchEvents()
|
||||
|
@ -803,10 +806,10 @@ QSize DrmGpu::cursorSize() const
|
|||
void DrmGpu::releaseBuffers()
|
||||
{
|
||||
for (const auto &plane : std::as_const(m_planes)) {
|
||||
plane->releaseBuffers();
|
||||
plane->releaseCurrentBuffer();
|
||||
}
|
||||
for (const auto &crtc : std::as_const(m_crtcs)) {
|
||||
crtc->releaseBuffers();
|
||||
crtc->releaseCurrentBuffer();
|
||||
}
|
||||
for (const auto &pipeline : std::as_const(m_pipelines)) {
|
||||
pipeline->primaryLayer()->releaseBuffers();
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
#include <errno.h>
|
||||
|
||||
#include "drm_atomic_commit.h"
|
||||
#include "drm_commit.h"
|
||||
#include "drm_gpu.h"
|
||||
#include "drm_logging.h"
|
||||
#include "drm_pointer.h"
|
||||
|
|
|
@ -12,9 +12,9 @@
|
|||
#include <errno.h>
|
||||
|
||||
#include "core/session.h"
|
||||
#include "drm_atomic_commit.h"
|
||||
#include "drm_backend.h"
|
||||
#include "drm_buffer.h"
|
||||
#include "drm_commit.h"
|
||||
#include "drm_commit_thread.h"
|
||||
#include "drm_connector.h"
|
||||
#include "drm_crtc.h"
|
||||
|
@ -139,19 +139,12 @@ DrmPipeline::Error DrmPipeline::commitPipelinesAtomic(const QVector<DrmPipeline
|
|||
// The kernel fails commits with DRM_MODE_PAGE_FLIP_EVENT when a crtc is disabled in the commit
|
||||
// and already was disabled before, to work around some quirks in old userspace.
|
||||
// Instead of using DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_NONBLOCK, do the modeset in a blocking
|
||||
// fashion without page flip events and directly call the pageFlipped method afterwards
|
||||
// fashion without page flip events
|
||||
if (!commit->commitModeset()) {
|
||||
qCCritical(KWIN_DRM) << "Atomic modeset commit failed!" << strerror(errno);
|
||||
return errnoToError();
|
||||
}
|
||||
std::for_each(pipelines.begin(), pipelines.end(), std::mem_fn(&DrmPipeline::atomicModesetSuccessful));
|
||||
for (const auto &obj : unusedObjects) {
|
||||
if (auto crtc = dynamic_cast<DrmCrtc *>(obj)) {
|
||||
crtc->flipBuffer();
|
||||
} else if (auto plane = dynamic_cast<DrmPlane *>(obj)) {
|
||||
plane->flipBuffer();
|
||||
}
|
||||
}
|
||||
return Error::None;
|
||||
}
|
||||
case CommitMode::Test: {
|
||||
|
@ -221,15 +214,15 @@ bool DrmPipeline::prepareAtomicPresentation(DrmAtomicCommit *commit)
|
|||
return false;
|
||||
}
|
||||
|
||||
const auto fb = m_pending.layer->currentBuffer().get();
|
||||
const auto fb = m_pending.layer->currentBuffer();
|
||||
m_pending.crtc->primaryPlane()->set(commit, QPoint(0, 0), fb->buffer()->size(), centerBuffer(fb->buffer()->size(), m_pending.mode->size()));
|
||||
commit->addProperty(m_pending.crtc->primaryPlane()->fbId, fb->framebufferId());
|
||||
commit->addBuffer(m_pending.crtc->primaryPlane(), fb);
|
||||
|
||||
if (auto plane = m_pending.crtc->cursorPlane()) {
|
||||
const auto layer = cursorLayer();
|
||||
plane->set(commit, QPoint(0, 0), gpu()->cursorSize(), QRect(layer->position(), gpu()->cursorSize()));
|
||||
commit->addProperty(plane->crtcId, layer->isVisible() ? m_pending.crtc->id() : 0);
|
||||
commit->addProperty(plane->fbId, layer->isVisible() ? layer->currentBuffer()->framebufferId() : 0);
|
||||
commit->addBuffer(plane, layer->isVisible() ? layer->currentBuffer() : nullptr);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -350,12 +343,6 @@ void DrmPipeline::atomicCommitSuccessful()
|
|||
if (activePending()) {
|
||||
m_pageflipPending = true;
|
||||
}
|
||||
if (m_pending.crtc) {
|
||||
m_pending.crtc->primaryPlane()->setNext(m_pending.layer->currentBuffer());
|
||||
if (m_pending.crtc->cursorPlane()) {
|
||||
m_pending.crtc->cursorPlane()->setNext(cursorLayer()->currentBuffer());
|
||||
}
|
||||
}
|
||||
m_current = m_pending;
|
||||
}
|
||||
|
||||
|
@ -426,13 +413,6 @@ DrmGpu *DrmPipeline::gpu() const
|
|||
|
||||
void DrmPipeline::pageFlipped(std::chrono::nanoseconds timestamp)
|
||||
{
|
||||
m_current.crtc->flipBuffer();
|
||||
if (m_current.crtc->primaryPlane()) {
|
||||
m_current.crtc->primaryPlane()->flipBuffer();
|
||||
}
|
||||
if (m_current.crtc->cursorPlane()) {
|
||||
m_current.crtc->cursorPlane()->flipBuffer();
|
||||
}
|
||||
m_pageflipPending = false;
|
||||
if (m_output) {
|
||||
m_output->pageFlipped(timestamp);
|
||||
|
|
|
@ -7,8 +7,9 @@
|
|||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "drm_buffer.h"
|
||||
#include "core/graphicsbuffer.h"
|
||||
#include "drm_buffer.h"
|
||||
#include "drm_commit.h"
|
||||
#include "drm_connector.h"
|
||||
#include "drm_crtc.h"
|
||||
#include "drm_gpu.h"
|
||||
|
@ -35,12 +36,14 @@ DrmPipeline::Error DrmPipeline::presentLegacy()
|
|||
if (m_pending.syncMode == RenderLoopPrivate::SyncMode::Async || m_pending.syncMode == RenderLoopPrivate::SyncMode::AdaptiveAsync) {
|
||||
flags |= DRM_MODE_PAGE_FLIP_ASYNC;
|
||||
}
|
||||
if (drmModePageFlip(gpu()->fd(), m_pending.crtc->id(), buffer->framebufferId(), flags, gpu()) != 0) {
|
||||
auto commit = std::make_unique<DrmLegacyCommit>(m_pending.crtc, buffer);
|
||||
if (!commit->doPageflip(flags)) {
|
||||
qCWarning(KWIN_DRM) << "Page flip failed:" << strerror(errno);
|
||||
return errnoToError();
|
||||
}
|
||||
// the pageflip takes ownership of the object
|
||||
commit.release();
|
||||
m_pageflipPending = true;
|
||||
m_pending.crtc->setNext(buffer);
|
||||
return Error::None;
|
||||
}
|
||||
|
||||
|
@ -51,21 +54,14 @@ void DrmPipeline::forceLegacyModeset()
|
|||
|
||||
DrmPipeline::Error DrmPipeline::legacyModeset()
|
||||
{
|
||||
uint32_t connId = m_connector->id();
|
||||
if (!m_pending.layer->checkTestBuffer()) {
|
||||
return Error::TestBufferFailed;
|
||||
}
|
||||
const auto buffer = m_pending.layer->currentBuffer();
|
||||
if (drmModeSetCrtc(gpu()->fd(), m_pending.crtc->id(), buffer->framebufferId(), 0, 0, &connId, 1, m_pending.mode->nativeMode()) != 0) {
|
||||
auto commit = std::make_unique<DrmLegacyCommit>(m_pending.crtc, m_pending.layer->currentBuffer());
|
||||
if (!commit->doModeset(m_connector, m_pending.mode.get())) {
|
||||
qCWarning(KWIN_DRM) << "Modeset failed!" << strerror(errno);
|
||||
return errnoToError();
|
||||
}
|
||||
// make sure the buffer gets kept alive, or the modeset gets reverted by the kernel
|
||||
if (m_pending.crtc->current()) {
|
||||
m_pending.crtc->setNext(buffer);
|
||||
} else {
|
||||
m_pending.crtc->setCurrent(buffer);
|
||||
}
|
||||
return Error::None;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,8 +11,8 @@
|
|||
|
||||
#include "config-kwin.h"
|
||||
|
||||
#include "drm_atomic_commit.h"
|
||||
#include "drm_buffer.h"
|
||||
#include "drm_commit.h"
|
||||
#include "drm_gpu.h"
|
||||
#include "drm_logging.h"
|
||||
#include "drm_pointer.h"
|
||||
|
@ -107,17 +107,6 @@ bool DrmPlane::updateProperties()
|
|||
return true;
|
||||
}
|
||||
|
||||
void DrmPlane::setNext(const std::shared_ptr<DrmFramebuffer> &b)
|
||||
{
|
||||
m_next = b;
|
||||
}
|
||||
|
||||
void DrmPlane::flipBuffer()
|
||||
{
|
||||
m_current = m_next;
|
||||
m_next = nullptr;
|
||||
}
|
||||
|
||||
void DrmPlane::set(DrmAtomicCommit *commit, const QPoint &srcPos, const QSize &srcSize, const QRect &dst)
|
||||
{
|
||||
// Src* are in 16.16 fixed point format
|
||||
|
@ -142,17 +131,12 @@ QMap<uint32_t, QVector<uint64_t>> DrmPlane::formats() const
|
|||
return m_supportedFormats;
|
||||
}
|
||||
|
||||
std::shared_ptr<DrmFramebuffer> DrmPlane::current() const
|
||||
std::shared_ptr<DrmFramebuffer> DrmPlane::currentBuffer() const
|
||||
{
|
||||
return m_current;
|
||||
}
|
||||
|
||||
std::shared_ptr<DrmFramebuffer> DrmPlane::next() const
|
||||
{
|
||||
return m_next;
|
||||
}
|
||||
|
||||
void DrmPlane::setCurrent(const std::shared_ptr<DrmFramebuffer> &b)
|
||||
void DrmPlane::setCurrentBuffer(const std::shared_ptr<DrmFramebuffer> &b)
|
||||
{
|
||||
m_current = b;
|
||||
}
|
||||
|
@ -160,15 +144,11 @@ void DrmPlane::setCurrent(const std::shared_ptr<DrmFramebuffer> &b)
|
|||
void DrmPlane::disable(DrmAtomicCommit *commit)
|
||||
{
|
||||
commit->addProperty(crtcId, 0);
|
||||
commit->addProperty(fbId, 0);
|
||||
m_next = nullptr;
|
||||
commit->addBuffer(this, nullptr);
|
||||
}
|
||||
|
||||
void DrmPlane::releaseBuffers()
|
||||
void DrmPlane::releaseCurrentBuffer()
|
||||
{
|
||||
if (m_next) {
|
||||
m_next->releaseBuffer();
|
||||
}
|
||||
if (m_current) {
|
||||
m_current->releaseBuffer();
|
||||
}
|
||||
|
|
|
@ -35,16 +35,12 @@ public:
|
|||
bool isCrtcSupported(int pipeIndex) const;
|
||||
QMap<uint32_t, QVector<uint64_t>> formats() const;
|
||||
|
||||
std::shared_ptr<DrmFramebuffer> current() const;
|
||||
std::shared_ptr<DrmFramebuffer> next() const;
|
||||
void setCurrent(const std::shared_ptr<DrmFramebuffer> &b);
|
||||
void setNext(const std::shared_ptr<DrmFramebuffer> &b);
|
||||
void flipBuffer();
|
||||
std::shared_ptr<DrmFramebuffer> currentBuffer() const;
|
||||
void setCurrentBuffer(const std::shared_ptr<DrmFramebuffer> &b);
|
||||
void releaseCurrentBuffer();
|
||||
|
||||
void set(DrmAtomicCommit *commit, const QPoint &srcPos, const QSize &srcSize, const QRect &dst);
|
||||
|
||||
void releaseBuffers();
|
||||
|
||||
enum class TypeIndex : uint64_t {
|
||||
Overlay = 0,
|
||||
Primary = 1,
|
||||
|
@ -86,7 +82,6 @@ public:
|
|||
|
||||
private:
|
||||
std::shared_ptr<DrmFramebuffer> m_current;
|
||||
std::shared_ptr<DrmFramebuffer> m_next;
|
||||
|
||||
QMap<uint32_t, QVector<uint64_t>> m_supportedFormats;
|
||||
uint32_t m_possibleCrtcs;
|
||||
|
|
Loading…
Reference in a new issue