You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
182 lines
5.9 KiB
182 lines
5.9 KiB
/* |
|
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 <QList> |
|
#include <QPoint> |
|
#include <QSize> |
|
|
|
#include <chrono> |
|
#include <xf86drmMode.h> |
|
|
|
#include "core/colorpipeline.h" |
|
#include "core/colorspace.h" |
|
#include "core/output.h" |
|
#include "core/renderloop_p.h" |
|
#include "drm_blob.h" |
|
#include "drm_connector.h" |
|
#include "drm_plane.h" |
|
|
|
namespace KWin |
|
{ |
|
|
|
class DrmGpu; |
|
class DrmConnector; |
|
class DrmCrtc; |
|
class DrmConnectorMode; |
|
class DrmPipelineLayer; |
|
class DrmCommitThread; |
|
class OutputFrame; |
|
|
|
class DrmPipeline |
|
{ |
|
public: |
|
DrmPipeline(DrmConnector *conn); |
|
~DrmPipeline(); |
|
|
|
enum class Error { |
|
None, |
|
OutofMemory, |
|
InvalidArguments, |
|
NoPermission, |
|
FramePending, |
|
TestBufferFailed, |
|
Unknown, |
|
}; |
|
Q_ENUM(Error) |
|
|
|
/** |
|
* tests the pending commit first and commits it if the test passes |
|
* if the test fails, there is a guarantee for no lasting changes |
|
*/ |
|
Error present(const std::shared_ptr<OutputFrame> &frame); |
|
bool maybeModeset(const std::shared_ptr<OutputFrame> &frame); |
|
void forceLegacyModeset(); |
|
|
|
bool needsModeset() const; |
|
void applyPendingChanges(); |
|
void revertPendingChanges(); |
|
|
|
bool updateCursor(); |
|
|
|
DrmConnector *connector() const; |
|
DrmGpu *gpu() const; |
|
|
|
void pageFlipped(std::chrono::nanoseconds timestamp); |
|
bool modesetPresentPending() const; |
|
void resetModesetPresentPending(); |
|
DrmCommitThread *commitThread() const; |
|
|
|
QHash<uint32_t, QList<uint64_t>> formats(DrmPlane::TypeIndex planeType) const; |
|
bool pruneModifier(); |
|
QList<QSize> recommendedSizes(DrmPlane::TypeIndex planeType) const; |
|
|
|
void setOutput(DrmOutput *output); |
|
DrmOutput *output() const; |
|
|
|
void setLayers(const std::shared_ptr<DrmPipelineLayer> &primaryLayer, const std::shared_ptr<DrmPipelineLayer> &cursorLayer); |
|
DrmPipelineLayer *primaryLayer() const; |
|
DrmPipelineLayer *cursorLayer() const; |
|
std::chrono::nanoseconds presentationDeadline() const; |
|
|
|
DrmCrtc *crtc() const; |
|
std::shared_ptr<DrmConnectorMode> mode() const; |
|
bool active() const; |
|
bool activePending() const; |
|
bool enabled() const; |
|
PresentationMode presentationMode() const; |
|
uint32_t overscan() const; |
|
Output::RgbRange rgbRange() const; |
|
DrmConnector::DrmContentType contentType() const; |
|
const ColorDescription &colorDescription() const; |
|
const std::shared_ptr<IccProfile> &iccProfile() const; |
|
|
|
void setCrtc(DrmCrtc *crtc); |
|
void setMode(const std::shared_ptr<DrmConnectorMode> &mode); |
|
void setActive(bool active); |
|
void setEnable(bool enable); |
|
void setPresentationMode(PresentationMode mode); |
|
void setOverscan(uint32_t overscan); |
|
void setRgbRange(Output::RgbRange range); |
|
void setCrtcColorPipeline(const ColorPipeline &pipeline); |
|
void setContentType(DrmConnector::DrmContentType type); |
|
void setColorDescription(const ColorDescription &description); |
|
void setIccProfile(const std::shared_ptr<IccProfile> &profile); |
|
|
|
/** |
|
* amdgpu drops cursor updates with adaptive sync: https://gitlab.freedesktop.org/drm/amd/-/issues/2186 |
|
*/ |
|
bool amdgpuVrrWorkaroundActive() const; |
|
|
|
enum class CommitMode { |
|
Test, |
|
TestAllowModeset, |
|
CommitModeset |
|
}; |
|
Q_ENUM(CommitMode) |
|
static Error commitPipelines(const QList<DrmPipeline *> &pipelines, CommitMode mode, const QList<DrmObject *> &unusedObjects = {}); |
|
|
|
private: |
|
bool isBufferForDirectScanout() const; |
|
uint32_t calculateUnderscan(); |
|
static Error errnoToError(); |
|
std::shared_ptr<DrmBlob> createHdrMetadata(TransferFunction transferFunction) const; |
|
|
|
// legacy only |
|
Error presentLegacy(const std::shared_ptr<OutputFrame> &frame); |
|
Error legacyModeset(); |
|
Error setLegacyGamma(); |
|
Error applyPendingChangesLegacy(); |
|
bool setCursorLegacy(); |
|
static Error commitPipelinesLegacy(const QList<DrmPipeline *> &pipelines, CommitMode mode, const QList<DrmObject *> &unusedObjects); |
|
|
|
// atomic modesetting only |
|
Error prepareAtomicCommit(DrmAtomicCommit *commit, CommitMode mode, const std::shared_ptr<OutputFrame> &frame); |
|
bool prepareAtomicModeset(DrmAtomicCommit *commit); |
|
Error prepareAtomicPresentation(DrmAtomicCommit *commit, const std::shared_ptr<OutputFrame> &frame); |
|
void prepareAtomicCursor(DrmAtomicCommit *commit); |
|
void prepareAtomicDisable(DrmAtomicCommit *commit); |
|
static Error commitPipelinesAtomic(const QList<DrmPipeline *> &pipelines, CommitMode mode, const std::shared_ptr<OutputFrame> &frame, const QList<DrmObject *> &unusedObjects); |
|
|
|
DrmOutput *m_output = nullptr; |
|
DrmConnector *m_connector = nullptr; |
|
|
|
bool m_modesetPresentPending = false; |
|
ColorPipeline m_currentLegacyGamma; |
|
|
|
struct State |
|
{ |
|
DrmCrtc *crtc = nullptr; |
|
QHash<uint32_t, QList<uint64_t>> formats; |
|
bool active = true; // whether or not the pipeline should be currently used |
|
bool enabled = true; // whether or not the pipeline needs a crtc |
|
bool needsModeset = false; |
|
bool needsModesetProperties = false; |
|
std::shared_ptr<DrmConnectorMode> mode; |
|
uint32_t overscan = 0; |
|
Output::RgbRange rgbRange = Output::RgbRange::Automatic; |
|
PresentationMode presentationMode = PresentationMode::VSync; |
|
ColorPipeline crtcColorPipeline; |
|
DrmConnector::DrmContentType contentType = DrmConnector::DrmContentType::Graphics; |
|
|
|
std::shared_ptr<IccProfile> iccProfile; |
|
ColorDescription colorDescription = ColorDescription::sRGB; |
|
}; |
|
// the state that is to be tested next |
|
State m_pending; |
|
// the state that will be applied at the next real atomic commit |
|
State m_next; |
|
|
|
std::unique_ptr<DrmCommitThread> m_commitThread; |
|
std::shared_ptr<DrmPipelineLayer> m_primaryLayer; |
|
std::shared_ptr<DrmPipelineLayer> m_cursorLayer; |
|
}; |
|
|
|
}
|
|
|