494ef1c930
The cursor being set out-of-band with atomic commits creates problems because it can create false positive for atomic tests, if the cursor state gets changed in between an atomic test and its matching commit. This commit also ports the cursor to a swapchain instead of only one image. This is not strictly required but may prevent artifacts and will be needed for future optimisations.
142 lines
3.7 KiB
C++
142 lines
3.7 KiB
C++
/*
|
|
KWin - the KDE window manager
|
|
This file is part of the KDE project.
|
|
|
|
SPDX-FileCopyrightText: 2021 Xaver Hugl <xaver.hugl@gmail.com>
|
|
|
|
SPDX-License-Identifier: GPL-2.0-or-later
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <QPoint>
|
|
#include <QSize>
|
|
#include <QVector>
|
|
#include <QSharedPointer>
|
|
|
|
#include <xf86drmMode.h>
|
|
#include <chrono>
|
|
|
|
#include "drm_object_plane.h"
|
|
#include "renderloop_p.h"
|
|
#include "abstract_wayland_output.h"
|
|
|
|
namespace KWin
|
|
{
|
|
|
|
class DrmGpu;
|
|
class DrmConnector;
|
|
class DrmCrtc;
|
|
class DrmBuffer;
|
|
class DrmDumbBuffer;
|
|
class GammaRamp;
|
|
|
|
class DrmGammaRamp
|
|
{
|
|
public:
|
|
DrmGammaRamp(DrmGpu *gpu, const GammaRamp &lut);
|
|
~DrmGammaRamp();
|
|
|
|
uint32_t size() const;
|
|
uint16_t *red() const;
|
|
uint16_t *green() const;
|
|
uint16_t *blue() const;
|
|
uint32_t blobId() const;
|
|
|
|
private:
|
|
DrmGpu *m_gpu;
|
|
const GammaRamp m_lut;
|
|
uint32_t m_blobId = 0;
|
|
};
|
|
|
|
class DrmPipeline
|
|
{
|
|
public:
|
|
DrmPipeline(DrmConnector *conn);
|
|
~DrmPipeline();
|
|
|
|
/**
|
|
* tests the pending commit first and commits it if the test passes
|
|
* if the test fails, there is a guarantee for no lasting changes
|
|
*/
|
|
bool present(const QSharedPointer<DrmBuffer> &buffer);
|
|
|
|
bool needsModeset() const;
|
|
bool needsCommit() const;
|
|
void prepareModeset();
|
|
void applyPendingChanges();
|
|
void revertPendingChanges();
|
|
|
|
bool setCursor(const QSharedPointer<DrmDumbBuffer> &buffer, const QPoint &hotspot = QPoint());
|
|
bool moveCursor(QPoint pos);
|
|
|
|
DrmConnector *connector() const;
|
|
DrmCrtc *currentCrtc() const;
|
|
DrmGpu *gpu() const;
|
|
|
|
void pageFlipped(std::chrono::nanoseconds timestamp);
|
|
bool pageflipPending() const;
|
|
bool modesetPresentPending() const;
|
|
void resetModesetPresentPending();
|
|
void printDebugInfo() const;
|
|
QSize sourceSize() const;
|
|
|
|
bool isFormatSupported(uint32_t drmFormat) const;
|
|
QVector<uint64_t> supportedModifiers(uint32_t drmFormat) const;
|
|
|
|
void setOutput(DrmOutput *output);
|
|
DrmOutput *output() const;
|
|
|
|
struct State {
|
|
DrmCrtc *crtc = nullptr;
|
|
bool active = true; // whether or not the pipeline should be currently used
|
|
bool enabled = true;// whether or not the pipeline needs a crtc
|
|
int modeIndex = 0;
|
|
uint32_t overscan = 0;
|
|
AbstractWaylandOutput::RgbRange rgbRange = AbstractWaylandOutput::RgbRange::Automatic;
|
|
RenderLoopPrivate::SyncMode syncMode = RenderLoopPrivate::SyncMode::Fixed;
|
|
QSharedPointer<DrmGammaRamp> gamma;
|
|
DrmPlane::Transformations transformation = DrmPlane::Transformation::Rotate0;
|
|
|
|
QPoint cursorPos;
|
|
QSharedPointer<DrmDumbBuffer> cursorBo;
|
|
};
|
|
State pending;
|
|
|
|
enum class CommitMode {
|
|
Test,
|
|
Commit,
|
|
CommitModeset
|
|
};
|
|
Q_ENUM(CommitMode);
|
|
static bool commitPipelines(const QVector<DrmPipeline*> &pipelines, CommitMode mode, const QVector<DrmObject*> &unusedObjects = {});
|
|
|
|
private:
|
|
bool populateAtomicValues(drmModeAtomicReq *req, uint32_t &flags);
|
|
bool presentLegacy();
|
|
bool checkTestBuffer();
|
|
bool activePending() const;
|
|
bool isCursorVisible() const;
|
|
|
|
bool applyPendingChangesLegacy();
|
|
bool legacyModeset();
|
|
|
|
static void printFlags(uint32_t flags);
|
|
enum class PrintMode { OnlyChanged, All };
|
|
static void printProps(DrmObject *object, PrintMode mode);
|
|
|
|
DrmOutput *m_output = nullptr;
|
|
DrmConnector *m_connector = nullptr;
|
|
|
|
QSharedPointer<DrmBuffer> m_primaryBuffer;
|
|
QSharedPointer<DrmBuffer> m_oldTestBuffer;
|
|
bool m_pageflipPending = false;
|
|
bool m_modesetPresentPending = false;
|
|
|
|
// the state that will be applied at the next real atomic commit
|
|
State m_next;
|
|
// the state that is already committed
|
|
State m_current;
|
|
};
|
|
|
|
}
|