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.
 
 
 
 
 

476 lines
13 KiB

/*
KWin - the KDE window manager
This file is part of the KDE project.
SPDX-FileCopyrightText: 2019 Roman Gilg <subdiff@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include <kwin_export.h>
#include "renderloop.h"
#include "utils/edid.h"
#include <QDebug>
#include <QList>
#include <QMatrix3x3>
#include <QMatrix4x4>
#include <QObject>
#include <QRect>
#include <QSize>
#include <QUuid>
namespace KWin
{
class RenderLoop;
class OutputConfiguration;
class ColorTransformation;
class IccProfile;
class OutputChangeSet;
/**
* The OutputTransform type is used to describe the transform applied to the output content.
*/
class KWIN_EXPORT OutputTransform
{
public:
enum Kind {
Normal = 0, // no rotation
Rotated90 = 1, // rotate 90 degrees clockwise
Rotated180 = 2, // rotate 180 degrees clockwise
Rotated270 = 3, // rotate 270 degrees clockwise
Flipped = 4, // mirror horizontally
Flipped90 = 5, // rotate 90 degrees clockwise, then mirror horizontally
Flipped180 = 6, // rotate 180 degrees clockwise, then mirror horizontally
Flipped270 = 7, // rotate 270 degrees clockwise, then mirror horizontally
};
OutputTransform() = default;
OutputTransform(Kind kind)
: m_kind(kind)
{
}
bool operator<=>(const OutputTransform &other) const = default;
/**
* Returns the transform kind.
*/
Kind kind() const;
/**
* Returns the inverse transform. The inverse transform can be used for mapping between
* surface and buffer coordinate systems.
*/
OutputTransform inverted() const;
/**
* Applies the output transform to the given @a size.
*/
QSizeF map(const QSizeF &size) const;
/**
* Applies the output transform to the given @a rect within a buffer with dimensions @a bounds.
*/
QRectF map(const QRectF &rect, const QSizeF &bounds) const;
/**
* Returns an output transform that is equivalent to applying this transform and @a other
* transform sequentially.
*/
OutputTransform combine(OutputTransform other) const;
private:
Kind m_kind = Kind::Normal;
};
class KWIN_EXPORT OutputMode
{
public:
enum class Flag : uint {
Preferred = 0x1,
Generated = 0x2,
};
Q_DECLARE_FLAGS(Flags, Flag)
OutputMode(const QSize &size, uint32_t refreshRate, Flags flags = {});
virtual ~OutputMode() = default;
QSize size() const;
uint32_t refreshRate() const;
Flags flags() const;
private:
const QSize m_size;
const uint32_t m_refreshRate;
const Flags m_flags;
};
/**
* Generic output representation.
*/
class KWIN_EXPORT Output : public QObject
{
Q_OBJECT
Q_PROPERTY(QRect geometry READ geometry NOTIFY geometryChanged)
Q_PROPERTY(qreal devicePixelRatio READ scale NOTIFY scaleChanged)
Q_PROPERTY(QString name READ name CONSTANT)
Q_PROPERTY(QString manufacturer READ manufacturer CONSTANT)
Q_PROPERTY(QString model READ model CONSTANT)
Q_PROPERTY(QString serialNumber READ serialNumber CONSTANT)
public:
enum class DpmsMode {
On,
Standby,
Suspend,
Off,
};
Q_ENUM(DpmsMode)
enum class Capability : uint {
Dpms = 1,
Overscan = 1 << 1,
Vrr = 1 << 2,
RgbRange = 1 << 3,
HighDynamicRange = 1 << 4,
WideColorGamut = 1 << 5,
AutoRotation = 1 << 6,
IccProfile = 1 << 7,
Tearing = 1 << 8,
};
Q_DECLARE_FLAGS(Capabilities, Capability)
enum class SubPixel {
Unknown,
None,
Horizontal_RGB,
Horizontal_BGR,
Vertical_RGB,
Vertical_BGR,
};
Q_ENUM(SubPixel)
enum class RgbRange {
Automatic = 0,
Full = 1,
Limited = 2,
};
Q_ENUM(RgbRange)
enum class AutoRotationPolicy {
Never = 0,
InTabletMode,
Always
};
Q_ENUM(AutoRotationPolicy);
explicit Output(QObject *parent = nullptr);
~Output() override;
void ref();
void unref();
/**
* Maps the specified @a rect from the global coordinate system to the output-local coords.
*/
QRect mapFromGlobal(const QRect &rect) const;
/**
* Maps the specified @a rect from the global coordinate system to the output-local coords.
*/
QRectF mapFromGlobal(const QRectF &rect) const;
/**
* Maps a @a rect in this output coordinates to the global coordinate system.
*/
QRectF mapToGlobal(const QRectF &rect) const;
Q_INVOKABLE QPointF mapToGlobal(const QPointF &pos) const;
Q_INVOKABLE QPointF mapFromGlobal(const QPointF &pos) const;
/**
* Returns a short identifiable name of this output.
*/
QString name() const;
/**
* Returns the identifying uuid of this output.
*/
QUuid uuid() const;
/**
* Returns @c true if the output is enabled; otherwise returns @c false.
*/
bool isEnabled() const;
/**
* Returns geometry of this output in device independent pixels.
*/
QRect geometry() const;
/**
* Returns geometry of this output in device independent pixels, without rounding
*/
QRectF fractionalGeometry() const;
/**
* Equivalent to `QRect(QPoint(0, 0), geometry().size())`
*/
QRect rect() const;
/**
* Returns the approximate vertical refresh rate of this output, in mHz.
*/
uint32_t refreshRate() const;
/**
* Returns whether this output is connected through an internal connector,
* e.g. LVDS, or eDP.
*/
bool isInternal() const;
/**
* Returns the ratio between physical pixels and logical pixels.
*/
qreal scale() const;
/**
* Returns the non-rotated physical size of this output, in millimeters.
*/
QSize physicalSize() const;
/** Returns the resolution of the output. */
QSize pixelSize() const;
QSize modeSize() const;
QString eisaId() const;
/**
* Returns the manufacturer of the screen.
*/
QString manufacturer() const;
/**
* Returns the model of the screen.
*/
QString model() const;
/**
* Returns the serial number of the screen.
*/
QString serialNumber() const;
/**
* Returns the RenderLoop for this output. If the platform does not support per screen
* rendering, all outputs will share the same render loop.
* FIXME: remove this and decouple RenderLoop from Output
*/
virtual RenderLoop *renderLoop() const = 0;
void inhibitDirectScanout();
void uninhibitDirectScanout();
bool directScanoutInhibited() const;
/**
* @returns the configured time for an output to dim
*
* This allows the backends to coordinate with the front-end the time they
* allow to decorate the dimming until the display is turned off
*
* @see aboutToTurnOff
*/
static std::chrono::milliseconds dimAnimationTime();
OutputTransform transform() const;
/**
* The transform that the user has configured, and which doesn't get changed
* by automatic rotation
*/
OutputTransform manualTransform() const;
QSize orientateSize(const QSize &size) const;
void applyChanges(const OutputConfiguration &config);
SubPixel subPixel() const;
QString description() const;
Capabilities capabilities() const;
const Edid &edid() const;
QList<std::shared_ptr<OutputMode>> modes() const;
std::shared_ptr<OutputMode> currentMode() const;
DpmsMode dpmsMode() const;
virtual void setDpmsMode(DpmsMode mode);
uint32_t overscan() const;
/**
* Returns a matrix that can translate into the display's coordinates system
*/
static QMatrix4x4 logicalToNativeMatrix(const QRectF &rect, qreal scale, OutputTransform transform);
VrrPolicy vrrPolicy() const;
RgbRange rgbRange() const;
bool isPlaceholder() const;
bool isNonDesktop() const;
OutputTransform panelOrientation() const;
bool wideColorGamut() const;
bool highDynamicRange() const;
uint32_t sdrBrightness() const;
AutoRotationPolicy autoRotationPolicy() const;
std::shared_ptr<IccProfile> iccProfile() const;
QString iccProfilePath() const;
/**
* @returns the mst path of this output. Is empty if invalid
*/
QByteArray mstPath() const;
virtual bool setGammaRamp(const std::shared_ptr<ColorTransformation> &transformation);
virtual bool setChannelFactors(const QVector3D &rgb);
virtual bool updateCursorLayer();
std::optional<double> maxPeakBrightness() const;
std::optional<double> maxAverageBrightness() const;
double minBrightness() const;
std::optional<double> maxPeakBrightnessOverride() const;
std::optional<double> maxAverageBrightnessOverride() const;
std::optional<double> minBrightnessOverride() const;
double sdrGamutWideness() const;
const ColorDescription &colorDescription() const;
Q_SIGNALS:
/**
* This signal is emitted when the geometry of this output has changed.
*/
void geometryChanged();
/**
* This signal is emitted when the output has been enabled or disabled.
*/
void enabledChanged();
/**
* This signal is emitted when the device pixel ratio of the output has changed.
*/
void scaleChanged();
/**
* Notifies that the display will be dimmed in @p time ms. This allows
* effects to plan for it and hopefully animate it
*/
void aboutToTurnOff(std::chrono::milliseconds time);
/**
* Notifies that the output has been turned on and the wake can be decorated.
*/
void wakeUp();
/**
* Notifies that the output is about to change configuration based on a
* user interaction.
*
* Be it because it gets a transformation or moved around.
*
* Only to be used for effects
*/
void aboutToChange(OutputChangeSet *changeSet);
/**
* Notifies that the output changed based on a user interaction.
*
* Be it because it gets a transformation or moved around.
*
* Only to be used for effects
*/
void changed();
void currentModeChanged();
void modesChanged();
void outputChange(const QRegion &damagedRegion);
void transformChanged();
void dpmsModeChanged();
void capabilitiesChanged();
void overscanChanged();
void vrrPolicyChanged();
void rgbRangeChanged();
void wideColorGamutChanged();
void sdrBrightnessChanged();
void highDynamicRangeChanged();
void autoRotationPolicyChanged();
void iccProfileChanged();
void iccProfilePathChanged();
void brightnessMetadataChanged();
void sdrGamutWidenessChanged();
protected:
struct Information
{
QString name;
QString manufacturer;
QString model;
QString serialNumber;
QString eisaId;
QSize physicalSize;
Edid edid;
SubPixel subPixel = SubPixel::Unknown;
Capabilities capabilities;
OutputTransform panelOrientation = OutputTransform::Normal;
bool internal = false;
bool placeholder = false;
bool nonDesktop = false;
QByteArray mstPath;
std::optional<double> maxPeakBrightness;
std::optional<double> maxAverageBrightness;
double minBrightness = 0;
};
struct State
{
QPoint position;
qreal scale = 1;
OutputTransform transform = OutputTransform::Normal;
OutputTransform manualTransform = OutputTransform::Normal;
QList<std::shared_ptr<OutputMode>> modes;
std::shared_ptr<OutputMode> currentMode;
DpmsMode dpmsMode = DpmsMode::On;
SubPixel subPixel = SubPixel::Unknown;
bool enabled = false;
uint32_t overscan = 0;
RgbRange rgbRange = RgbRange::Automatic;
bool wideColorGamut = false;
bool highDynamicRange = false;
uint32_t sdrBrightness = 200;
AutoRotationPolicy autoRotatePolicy = AutoRotationPolicy::InTabletMode;
QString iccProfilePath;
std::shared_ptr<IccProfile> iccProfile;
ColorDescription colorDescription = ColorDescription::sRGB;
std::optional<double> maxPeakBrightnessOverride;
std::optional<double> maxAverageBrightnessOverride;
std::optional<double> minBrightnessOverride;
double sdrGamutWideness = 0;
VrrPolicy vrrPolicy = VrrPolicy::Automatic;
};
void setInformation(const Information &information);
void setState(const State &state);
State m_state;
Information m_information;
QUuid m_uuid;
int m_directScanoutCount = 0;
int m_refCount = 1;
};
inline QRect Output::rect() const
{
return QRect(QPoint(0, 0), geometry().size());
}
KWIN_EXPORT QDebug operator<<(QDebug debug, const Output *output);
} // namespace KWin
Q_DECLARE_OPERATORS_FOR_FLAGS(KWin::Output::Capabilities)