File indexing completed on 2024-05-12 05:31:22

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 2019 Roman Gilg <subdiff@gmail.com>
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 #pragma once
0010 
0011 #include <kwin_export.h>
0012 
0013 #include "renderloop.h"
0014 #include "utils/edid.h"
0015 
0016 #include <QDebug>
0017 #include <QList>
0018 #include <QMatrix4x4>
0019 #include <QObject>
0020 #include <QRect>
0021 #include <QSize>
0022 #include <QUuid>
0023 
0024 namespace KWin
0025 {
0026 
0027 class RenderLoop;
0028 class OutputConfiguration;
0029 class ColorTransformation;
0030 class IccProfile;
0031 class OutputChangeSet;
0032 
0033 /**
0034  * The OutputTransform type is used to describe the transform applied to the output content.
0035  */
0036 class KWIN_EXPORT OutputTransform
0037 {
0038 public:
0039     enum Kind {
0040         Normal = 0, // no rotation
0041         Rotate90 = 1, // rotate 90 degrees counterclockwise
0042         Rotate180 = 2, // rotate 180 degrees counterclockwise
0043         Rotate270 = 3, // rotate 270 degrees counterclockwise
0044         FlipX = 4, // mirror horizontally
0045         FlipX90 = 5, // mirror horizontally, then rotate 90 degrees counterclockwise
0046         FlipX180 = 6, // mirror horizontally, then rotate 180 degrees counterclockwise
0047         FlipX270 = 7, // mirror horizontally, then rotate 270 degrees counterclockwise
0048         FlipY = FlipX180, // mirror vertically
0049         FlipY90 = FlipX270, // mirror vertically, then rotate 90 degrees counterclockwise
0050         FlipY180 = FlipX, // mirror vertically, then rotate 180 degrees counterclockwise
0051         FlipY270 = FlipX90, // mirror vertically, then rotate 270 degrees counterclockwise
0052     };
0053 
0054     OutputTransform() = default;
0055     OutputTransform(Kind kind)
0056         : m_kind(kind)
0057     {
0058     }
0059 
0060     bool operator<=>(const OutputTransform &other) const = default;
0061 
0062     /**
0063      * Returns the transform kind.
0064      */
0065     Kind kind() const;
0066 
0067     /**
0068      * Returns the inverse transform. The inverse transform can be used for mapping between
0069      * surface and buffer coordinate systems.
0070      */
0071     OutputTransform inverted() const;
0072 
0073     /**
0074      * Applies the output transform to the given @a size.
0075      */
0076     QSizeF map(const QSizeF &size) const;
0077     QSize map(const QSize &size) const;
0078 
0079     /**
0080      * Applies the output transform to the given @a rect within a buffer with dimensions @a bounds.
0081      */
0082     QRectF map(const QRectF &rect, const QSizeF &bounds) const;
0083     QRect map(const QRect &rect, const QSize &bounds) const;
0084 
0085     /**
0086      * Applies the output transform to the given @a point.
0087      */
0088     QPointF map(const QPointF &point, const QSizeF &bounds) const;
0089     QPoint map(const QPoint &point, const QSize &bounds) const;
0090 
0091     /**
0092      * Returns an output transform that is equivalent to applying this transform and @a other
0093      * transform sequentially.
0094      */
0095     OutputTransform combine(OutputTransform other) const;
0096 
0097     /**
0098      * Returns the matrix corresponding to this output transform.
0099      */
0100     QMatrix4x4 toMatrix() const;
0101 
0102 private:
0103     Kind m_kind = Kind::Normal;
0104 };
0105 
0106 class KWIN_EXPORT OutputMode
0107 {
0108 public:
0109     enum class Flag : uint {
0110         Preferred = 0x1,
0111         Generated = 0x2,
0112     };
0113     Q_DECLARE_FLAGS(Flags, Flag)
0114 
0115     OutputMode(const QSize &size, uint32_t refreshRate, Flags flags = {});
0116     virtual ~OutputMode() = default;
0117 
0118     QSize size() const;
0119     uint32_t refreshRate() const;
0120     Flags flags() const;
0121 
0122 private:
0123     const QSize m_size;
0124     const uint32_t m_refreshRate;
0125     const Flags m_flags;
0126 };
0127 
0128 /**
0129  * Generic output representation.
0130  */
0131 class KWIN_EXPORT Output : public QObject
0132 {
0133     Q_OBJECT
0134     Q_PROPERTY(QRect geometry READ geometry NOTIFY geometryChanged)
0135     Q_PROPERTY(qreal devicePixelRatio READ scale NOTIFY scaleChanged)
0136     Q_PROPERTY(QString name READ name CONSTANT)
0137     Q_PROPERTY(QString manufacturer READ manufacturer CONSTANT)
0138     Q_PROPERTY(QString model READ model CONSTANT)
0139     Q_PROPERTY(QString serialNumber READ serialNumber CONSTANT)
0140 
0141 public:
0142     enum class DpmsMode {
0143         On,
0144         Standby,
0145         Suspend,
0146         Off,
0147     };
0148     Q_ENUM(DpmsMode)
0149 
0150     enum class Capability : uint {
0151         Dpms = 1,
0152         Overscan = 1 << 1,
0153         Vrr = 1 << 2,
0154         RgbRange = 1 << 3,
0155         HighDynamicRange = 1 << 4,
0156         WideColorGamut = 1 << 5,
0157         AutoRotation = 1 << 6,
0158         IccProfile = 1 << 7,
0159         Tearing = 1 << 8,
0160     };
0161     Q_DECLARE_FLAGS(Capabilities, Capability)
0162 
0163     enum class SubPixel {
0164         Unknown,
0165         None,
0166         Horizontal_RGB,
0167         Horizontal_BGR,
0168         Vertical_RGB,
0169         Vertical_BGR,
0170     };
0171     Q_ENUM(SubPixel)
0172 
0173     enum class RgbRange {
0174         Automatic = 0,
0175         Full = 1,
0176         Limited = 2,
0177     };
0178     Q_ENUM(RgbRange)
0179 
0180     enum class AutoRotationPolicy {
0181         Never = 0,
0182         InTabletMode,
0183         Always
0184     };
0185     Q_ENUM(AutoRotationPolicy);
0186 
0187     explicit Output(QObject *parent = nullptr);
0188     ~Output() override;
0189 
0190     void ref();
0191     void unref();
0192 
0193     /**
0194      * Maps the specified @a rect from the global coordinate system to the output-local coords.
0195      */
0196     QRect mapFromGlobal(const QRect &rect) const;
0197 
0198     /**
0199      * Maps the specified @a rect from the global coordinate system to the output-local coords.
0200      */
0201     QRectF mapFromGlobal(const QRectF &rect) const;
0202 
0203     /**
0204      * Maps a @a rect in this output coordinates to the global coordinate system.
0205      */
0206     QRectF mapToGlobal(const QRectF &rect) const;
0207 
0208     Q_INVOKABLE QPointF mapToGlobal(const QPointF &pos) const;
0209     Q_INVOKABLE QPointF mapFromGlobal(const QPointF &pos) const;
0210 
0211     /**
0212      * Returns a short identifiable name of this output.
0213      */
0214     QString name() const;
0215 
0216     /**
0217      * Returns the identifying uuid of this output.
0218      */
0219     QUuid uuid() const;
0220 
0221     /**
0222      * Returns @c true if the output is enabled; otherwise returns @c false.
0223      */
0224     bool isEnabled() const;
0225 
0226     /**
0227      * Returns geometry of this output in device independent pixels.
0228      */
0229     QRect geometry() const;
0230 
0231     /**
0232      * Returns geometry of this output in device independent pixels, without rounding
0233      */
0234     QRectF geometryF() const;
0235 
0236     /**
0237      * Equivalent to `QRect(QPoint(0, 0), geometry().size())`
0238      */
0239     QRect rect() const;
0240 
0241     /**
0242      * Equivalent to `QRectF(QPointF(0, 0), geometryF().size())`
0243      */
0244     QRectF rectF() const;
0245 
0246     /**
0247      * Returns the approximate vertical refresh rate of this output, in mHz.
0248      */
0249     uint32_t refreshRate() const;
0250 
0251     /**
0252      * Returns whether this output is connected through an internal connector,
0253      * e.g. LVDS, or eDP.
0254      */
0255     bool isInternal() const;
0256 
0257     /**
0258      * Returns the ratio between physical pixels and logical pixels.
0259      */
0260     qreal scale() const;
0261 
0262     /**
0263      * Returns the non-rotated physical size of this output, in millimeters.
0264      */
0265     QSize physicalSize() const;
0266 
0267     /** Returns the resolution of the output.  */
0268     QSize pixelSize() const;
0269     QSize modeSize() const;
0270 
0271     QString eisaId() const;
0272 
0273     /**
0274      * Returns the manufacturer of the screen.
0275      */
0276     QString manufacturer() const;
0277     /**
0278      * Returns the model of the screen.
0279      */
0280     QString model() const;
0281     /**
0282      * Returns the serial number of the screen.
0283      */
0284     QString serialNumber() const;
0285 
0286     /**
0287      * Returns the RenderLoop for this output. If the platform does not support per screen
0288      * rendering, all outputs will share the same render loop.
0289      * FIXME: remove this and decouple RenderLoop from Output
0290      */
0291     virtual RenderLoop *renderLoop() const = 0;
0292 
0293     void inhibitDirectScanout();
0294     void uninhibitDirectScanout();
0295 
0296     bool directScanoutInhibited() const;
0297 
0298     /**
0299      * @returns the configured time for an output to dim
0300      *
0301      * This allows the backends to coordinate with the front-end the time they
0302      * allow to decorate the dimming until the display is turned off
0303      *
0304      * @see aboutToTurnOff
0305      */
0306     static std::chrono::milliseconds dimAnimationTime();
0307 
0308     OutputTransform transform() const;
0309     /**
0310      * The transform that the user has configured, and which doesn't get changed
0311      * by automatic rotation
0312      */
0313     OutputTransform manualTransform() const;
0314     QSize orientateSize(const QSize &size) const;
0315 
0316     void applyChanges(const OutputConfiguration &config);
0317 
0318     SubPixel subPixel() const;
0319     QString description() const;
0320     Capabilities capabilities() const;
0321     const Edid &edid() const;
0322     QList<std::shared_ptr<OutputMode>> modes() const;
0323     std::shared_ptr<OutputMode> currentMode() const;
0324     DpmsMode dpmsMode() const;
0325     virtual void setDpmsMode(DpmsMode mode);
0326 
0327     uint32_t overscan() const;
0328 
0329     VrrPolicy vrrPolicy() const;
0330     RgbRange rgbRange() const;
0331 
0332     bool isPlaceholder() const;
0333     bool isNonDesktop() const;
0334     OutputTransform panelOrientation() const;
0335     bool wideColorGamut() const;
0336     bool highDynamicRange() const;
0337     uint32_t sdrBrightness() const;
0338     AutoRotationPolicy autoRotationPolicy() const;
0339     std::shared_ptr<IccProfile> iccProfile() const;
0340     QString iccProfilePath() const;
0341     /**
0342      * @returns the mst path of this output. Is empty if invalid
0343      */
0344     QByteArray mstPath() const;
0345 
0346     virtual bool setGammaRamp(const std::shared_ptr<ColorTransformation> &transformation);
0347     virtual bool setChannelFactors(const QVector3D &rgb);
0348 
0349     virtual bool updateCursorLayer();
0350 
0351     std::optional<double> maxPeakBrightness() const;
0352     std::optional<double> maxAverageBrightness() const;
0353     double minBrightness() const;
0354     std::optional<double> maxPeakBrightnessOverride() const;
0355     std::optional<double> maxAverageBrightnessOverride() const;
0356     std::optional<double> minBrightnessOverride() const;
0357 
0358     double sdrGamutWideness() const;
0359 
0360     const ColorDescription &colorDescription() const;
0361 
0362 Q_SIGNALS:
0363     /**
0364      * This signal is emitted when the geometry of this output has changed.
0365      */
0366     void geometryChanged();
0367     /**
0368      * This signal is emitted when the output has been enabled or disabled.
0369      */
0370     void enabledChanged();
0371     /**
0372      * This signal is emitted when the device pixel ratio of the output has changed.
0373      */
0374     void scaleChanged();
0375 
0376     /**
0377      * Notifies that the display will be dimmed in @p time ms. This allows
0378      * effects to plan for it and hopefully animate it
0379      */
0380     void aboutToTurnOff(std::chrono::milliseconds time);
0381 
0382     /**
0383      * Notifies that the output has been turned on and the wake can be decorated.
0384      */
0385     void wakeUp();
0386 
0387     /**
0388      * Notifies that the output is about to change configuration based on a
0389      * user interaction.
0390      *
0391      * Be it because it gets a transformation or moved around.
0392      *
0393      * Only to be used for effects
0394      */
0395     void aboutToChange(OutputChangeSet *changeSet);
0396 
0397     /**
0398      * Notifies that the output changed based on a user interaction.
0399      *
0400      * Be it because it gets a transformation or moved around.
0401      *
0402      * Only to be used for effects
0403      */
0404     void changed();
0405 
0406     void currentModeChanged();
0407     void modesChanged();
0408     void outputChange(const QRegion &damagedRegion);
0409     void transformChanged();
0410     void dpmsModeChanged();
0411     void capabilitiesChanged();
0412     void overscanChanged();
0413     void vrrPolicyChanged();
0414     void rgbRangeChanged();
0415     void wideColorGamutChanged();
0416     void sdrBrightnessChanged();
0417     void highDynamicRangeChanged();
0418     void autoRotationPolicyChanged();
0419     void iccProfileChanged();
0420     void iccProfilePathChanged();
0421     void brightnessMetadataChanged();
0422     void sdrGamutWidenessChanged();
0423     void colorDescriptionChanged();
0424 
0425 protected:
0426     struct Information
0427     {
0428         QString name;
0429         QString manufacturer;
0430         QString model;
0431         QString serialNumber;
0432         QString eisaId;
0433         QSize physicalSize;
0434         Edid edid;
0435         SubPixel subPixel = SubPixel::Unknown;
0436         Capabilities capabilities;
0437         OutputTransform panelOrientation = OutputTransform::Normal;
0438         bool internal = false;
0439         bool placeholder = false;
0440         bool nonDesktop = false;
0441         QByteArray mstPath;
0442         std::optional<double> maxPeakBrightness;
0443         std::optional<double> maxAverageBrightness;
0444         double minBrightness = 0;
0445     };
0446 
0447     struct State
0448     {
0449         QPoint position;
0450         qreal scale = 1;
0451         OutputTransform transform = OutputTransform::Normal;
0452         OutputTransform manualTransform = OutputTransform::Normal;
0453         QList<std::shared_ptr<OutputMode>> modes;
0454         std::shared_ptr<OutputMode> currentMode;
0455         DpmsMode dpmsMode = DpmsMode::On;
0456         SubPixel subPixel = SubPixel::Unknown;
0457         bool enabled = false;
0458         uint32_t overscan = 0;
0459         RgbRange rgbRange = RgbRange::Automatic;
0460         bool wideColorGamut = false;
0461         bool highDynamicRange = false;
0462         uint32_t sdrBrightness = 200;
0463         AutoRotationPolicy autoRotatePolicy = AutoRotationPolicy::InTabletMode;
0464         QString iccProfilePath;
0465         std::shared_ptr<IccProfile> iccProfile;
0466         ColorDescription colorDescription = ColorDescription::sRGB;
0467         std::optional<double> maxPeakBrightnessOverride;
0468         std::optional<double> maxAverageBrightnessOverride;
0469         std::optional<double> minBrightnessOverride;
0470         double sdrGamutWideness = 0;
0471         VrrPolicy vrrPolicy = VrrPolicy::Automatic;
0472     };
0473 
0474     void setInformation(const Information &information);
0475     void setState(const State &state);
0476 
0477     State m_state;
0478     Information m_information;
0479     QUuid m_uuid;
0480     int m_directScanoutCount = 0;
0481     int m_refCount = 1;
0482 };
0483 
0484 inline QRect Output::rect() const
0485 {
0486     return QRect(QPoint(0, 0), geometry().size());
0487 }
0488 
0489 inline QRectF Output::rectF() const
0490 {
0491     return QRectF(QPointF(0, 0), geometryF().size());
0492 }
0493 
0494 KWIN_EXPORT QDebug operator<<(QDebug debug, const Output *output);
0495 
0496 } // namespace KWin
0497 
0498 Q_DECLARE_OPERATORS_FOR_FLAGS(KWin::Output::Capabilities)