2022-03-17 16:56:33 +01:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include "../defines.hpp"
|
2025-01-11 19:05:53 +03:00
|
|
|
#include <stack>
|
2024-12-16 15:58:19 +00:00
|
|
|
#include <vector>
|
2025-01-12 16:35:10 +00:00
|
|
|
#include "../SharedDefs.hpp"
|
2025-01-17 15:21:35 +00:00
|
|
|
#include "MiscFunctions.hpp"
|
2022-03-17 18:25:16 +01:00
|
|
|
#include "WLClasses.hpp"
|
2022-03-19 13:54:24 +01:00
|
|
|
#include <array>
|
2025-01-23 21:55:41 +01:00
|
|
|
|
2023-05-09 15:01:45 +02:00
|
|
|
#include <xf86drmMode.h>
|
2025-04-16 01:37:48 +01:00
|
|
|
#include "time/Timer.hpp"
|
2024-06-19 16:20:06 +02:00
|
|
|
#include "math/Math.hpp"
|
2023-08-11 17:37:52 +02:00
|
|
|
#include <optional>
|
2025-02-27 00:56:11 +01:00
|
|
|
#include "../protocols/types/ColorManagement.hpp"
|
2024-04-22 18:21:03 +01:00
|
|
|
#include "signal/Signal.hpp"
|
2024-06-19 18:25:20 +02:00
|
|
|
#include "DamageRing.hpp"
|
2024-07-21 13:09:54 +02:00
|
|
|
#include <aquamarine/output/Output.hpp>
|
|
|
|
|
#include <aquamarine/allocator/Swapchain.hpp>
|
2025-01-30 12:30:12 +01:00
|
|
|
#include <hyprutils/os/FileDescriptor.hpp>
|
2024-04-22 18:21:03 +01:00
|
|
|
|
2024-04-23 00:40:03 +00:00
|
|
|
// Enum for the different types of auto directions, e.g. auto-left, auto-up.
|
2024-12-07 18:51:18 +01:00
|
|
|
enum eAutoDirs : uint8_t {
|
2024-05-24 20:56:42 +02:00
|
|
|
DIR_AUTO_NONE = 0, /* None will be treated as right. */
|
2024-04-23 00:40:03 +00:00
|
|
|
DIR_AUTO_UP,
|
|
|
|
|
DIR_AUTO_DOWN,
|
|
|
|
|
DIR_AUTO_LEFT,
|
|
|
|
|
DIR_AUTO_RIGHT
|
|
|
|
|
};
|
|
|
|
|
|
2025-03-14 02:15:18 +03:00
|
|
|
enum eCMType : uint8_t {
|
|
|
|
|
CM_AUTO = 0, // subject to change. srgb for 8bpc, wide for 10bpc if supported
|
|
|
|
|
CM_SRGB, // default, sRGB primaries
|
|
|
|
|
CM_WIDE, // wide color gamut, BT2020 primaries
|
|
|
|
|
CM_EDID, // primaries from edid (known to be inaccurate)
|
|
|
|
|
CM_HDR, // wide color gamut and HDR PQ transfer function
|
|
|
|
|
CM_HDR_EDID, // same as CM_HDR with edid primaries
|
|
|
|
|
};
|
|
|
|
|
|
2023-08-11 17:37:52 +02:00
|
|
|
struct SMonitorRule {
|
2025-03-14 02:15:18 +03:00
|
|
|
eAutoDirs autoDir = DIR_AUTO_NONE;
|
|
|
|
|
std::string name = "";
|
|
|
|
|
Vector2D resolution = Vector2D(1280, 720);
|
|
|
|
|
Vector2D offset = Vector2D(0, 0);
|
|
|
|
|
float scale = 1;
|
|
|
|
|
float refreshRate = 60; // Hz
|
|
|
|
|
bool disabled = false;
|
|
|
|
|
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
|
|
|
|
std::string mirrorOf = "";
|
|
|
|
|
bool enable10bit = false;
|
|
|
|
|
eCMType cmType = CM_SRGB;
|
|
|
|
|
float sdrSaturation = 1.0f; // SDR -> HDR
|
|
|
|
|
float sdrBrightness = 1.0f; // SDR -> HDR
|
|
|
|
|
drmModeModeInfo drmMode = {};
|
2023-08-11 17:37:52 +02:00
|
|
|
std::optional<int> vrr;
|
|
|
|
|
};
|
2022-09-13 15:25:42 +02:00
|
|
|
|
2024-01-28 01:57:13 +00:00
|
|
|
class CMonitor;
|
2024-07-21 13:09:54 +02:00
|
|
|
class CSyncTimeline;
|
2025-03-20 11:39:55 +01:00
|
|
|
class CEGLSync;
|
2024-01-28 01:57:13 +00:00
|
|
|
|
|
|
|
|
class CMonitorState {
|
|
|
|
|
public:
|
|
|
|
|
CMonitorState(CMonitor* owner);
|
2025-01-30 16:07:06 +05:00
|
|
|
~CMonitorState() = default;
|
2024-01-28 01:57:13 +00:00
|
|
|
|
|
|
|
|
bool commit();
|
|
|
|
|
bool test();
|
2024-07-21 13:09:54 +02:00
|
|
|
bool updateSwapchain();
|
2024-01-28 01:57:13 +00:00
|
|
|
|
|
|
|
|
private:
|
2024-07-21 13:09:54 +02:00
|
|
|
void ensureBufferPresent();
|
|
|
|
|
|
2025-04-30 23:45:20 +02:00
|
|
|
CMonitor* m_owner = nullptr;
|
2024-01-28 01:57:13 +00:00
|
|
|
};
|
|
|
|
|
|
2022-07-27 12:32:00 +02:00
|
|
|
class CMonitor {
|
2022-12-16 17:17:31 +00:00
|
|
|
public:
|
2024-08-19 18:44:22 +02:00
|
|
|
CMonitor(SP<Aquamarine::IOutput> output);
|
2023-04-07 12:18:40 +01:00
|
|
|
~CMonitor();
|
|
|
|
|
|
2025-04-30 23:45:20 +02:00
|
|
|
Vector2D m_position = Vector2D(-1, -1); // means unset
|
|
|
|
|
Vector2D m_xwaylandPosition = Vector2D(-1, -1); // means unset
|
|
|
|
|
Vector2D m_size = Vector2D(0, 0);
|
|
|
|
|
Vector2D m_pixelSize = Vector2D(0, 0);
|
|
|
|
|
Vector2D m_transformedSize = Vector2D(0, 0);
|
|
|
|
|
|
|
|
|
|
MONITORID m_id = MONITOR_INVALID;
|
|
|
|
|
PHLWORKSPACE m_activeWorkspace = nullptr;
|
|
|
|
|
PHLWORKSPACE m_activeSpecialWorkspace = nullptr;
|
|
|
|
|
float m_setScale = 1; // scale set by cfg
|
|
|
|
|
float m_scale = 1; // real scale
|
|
|
|
|
|
|
|
|
|
std::string m_name = "";
|
|
|
|
|
std::string m_description = "";
|
|
|
|
|
std::string m_shortDescription = "";
|
|
|
|
|
|
|
|
|
|
Vector2D m_reservedTopLeft = Vector2D(0, 0);
|
|
|
|
|
Vector2D m_reservedBottomRight = Vector2D(0, 0);
|
|
|
|
|
|
|
|
|
|
drmModeModeInfo m_customDrmMode = {};
|
|
|
|
|
|
|
|
|
|
CMonitorState m_state;
|
|
|
|
|
CDamageRing m_damage;
|
|
|
|
|
|
|
|
|
|
SP<Aquamarine::IOutput> m_output;
|
|
|
|
|
float m_refreshRate = 60; // Hz
|
|
|
|
|
int m_forceFullFrames = 0;
|
|
|
|
|
bool m_scheduledRecalc = false;
|
|
|
|
|
wl_output_transform m_transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
|
|
|
|
float m_xwaylandScale = 1.f;
|
|
|
|
|
Mat3x3 m_projMatrix;
|
|
|
|
|
std::optional<Vector2D> m_forceSize;
|
|
|
|
|
SP<Aquamarine::SOutputMode> m_currentMode;
|
|
|
|
|
SP<Aquamarine::CSwapchain> m_cursorSwapchain;
|
|
|
|
|
uint32_t m_drmFormat = DRM_FORMAT_INVALID;
|
|
|
|
|
uint32_t m_prevDrmFormat = DRM_FORMAT_INVALID;
|
|
|
|
|
|
|
|
|
|
bool m_dpmsStatus = true;
|
|
|
|
|
bool m_vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it.
|
|
|
|
|
bool m_enabled10bit = false; // as above, this can be TRUE even if 10 bit failed.
|
|
|
|
|
eCMType m_cmType = CM_SRGB;
|
|
|
|
|
float m_sdrSaturation = 1.0f;
|
|
|
|
|
float m_sdrBrightness = 1.0f;
|
|
|
|
|
bool m_createdByUser = false;
|
|
|
|
|
bool m_isUnsafeFallback = false;
|
|
|
|
|
|
|
|
|
|
bool m_pendingFrame = false; // if we schedule a frame during rendering, reschedule it after
|
|
|
|
|
bool m_renderingActive = false;
|
|
|
|
|
|
|
|
|
|
wl_event_source* m_renderTimer = nullptr; // for RAT
|
|
|
|
|
bool m_ratsScheduled = false;
|
|
|
|
|
CTimer m_lastPresentationTimer;
|
|
|
|
|
|
|
|
|
|
bool m_isBeingLeased = false;
|
|
|
|
|
|
|
|
|
|
SMonitorRule m_activeMonitorRule;
|
2023-08-11 17:37:52 +02:00
|
|
|
|
2024-07-21 13:09:54 +02:00
|
|
|
// explicit sync
|
2025-04-30 23:45:20 +02:00
|
|
|
Hyprutils::OS::CFileDescriptor m_inFence; // TODO: remove when aq uses CFileDescriptor
|
2024-07-21 13:09:54 +02:00
|
|
|
|
2025-04-30 23:45:20 +02:00
|
|
|
PHLMONITORREF m_self;
|
2024-05-05 22:18:10 +01:00
|
|
|
|
2022-09-13 15:25:42 +02:00
|
|
|
// mirroring
|
2025-04-30 23:45:20 +02:00
|
|
|
PHLMONITORREF m_mirrorOf;
|
|
|
|
|
std::vector<PHLMONITORREF> m_mirrors;
|
2022-09-13 15:25:42 +02:00
|
|
|
|
2024-10-08 16:59:15 +01:00
|
|
|
// ctm
|
2025-04-30 23:45:20 +02:00
|
|
|
Mat3x3 m_ctm = Mat3x3::identity();
|
|
|
|
|
bool m_ctmUpdated = false;
|
2024-10-08 16:59:15 +01:00
|
|
|
|
2023-09-28 21:48:33 +01:00
|
|
|
// for tearing
|
2025-04-30 23:45:20 +02:00
|
|
|
PHLWINDOWREF m_solitaryClient;
|
2023-09-30 17:07:50 +01:00
|
|
|
|
2024-07-21 13:09:54 +02:00
|
|
|
// for direct scanout
|
2025-04-30 23:45:20 +02:00
|
|
|
PHLWINDOWREF m_lastScanout;
|
|
|
|
|
bool m_scanoutNeedsCursorUpdate = false;
|
2024-07-21 13:09:54 +02:00
|
|
|
|
2023-09-30 17:07:50 +01:00
|
|
|
struct {
|
|
|
|
|
bool canTear = false;
|
|
|
|
|
bool nextRenderTorn = false;
|
|
|
|
|
bool activelyTearing = false;
|
|
|
|
|
|
|
|
|
|
bool busy = false;
|
|
|
|
|
bool frameScheduledWhileBusy = false;
|
2025-04-30 23:45:20 +02:00
|
|
|
} m_tearingState;
|
2023-09-28 21:48:33 +01:00
|
|
|
|
2024-04-22 18:21:03 +01:00
|
|
|
struct {
|
|
|
|
|
CSignal destroy;
|
|
|
|
|
CSignal connect;
|
|
|
|
|
CSignal disconnect;
|
2024-04-29 01:28:26 +01:00
|
|
|
CSignal dpmsChanged;
|
|
|
|
|
CSignal modeChanged;
|
2025-04-30 23:45:20 +02:00
|
|
|
} m_events;
|
2024-04-22 18:21:03 +01:00
|
|
|
|
2025-04-30 23:45:20 +02:00
|
|
|
std::array<std::vector<PHLLSREF>, 4> m_layerSurfaceLayers;
|
2022-03-17 18:25:16 +01:00
|
|
|
|
2022-07-27 12:32:00 +02:00
|
|
|
// methods
|
2025-02-26 17:56:37 +03:00
|
|
|
void onConnect(bool noRule);
|
|
|
|
|
void onDisconnect(bool destroy = false);
|
|
|
|
|
bool applyMonitorRule(SMonitorRule* pMonitorRule, bool force = false);
|
|
|
|
|
void addDamage(const pixman_region32_t* rg);
|
|
|
|
|
void addDamage(const CRegion& rg);
|
|
|
|
|
void addDamage(const CBox& box);
|
|
|
|
|
bool shouldSkipScheduleFrameOnMouseEvent();
|
|
|
|
|
void setMirror(const std::string&);
|
|
|
|
|
bool isMirror();
|
|
|
|
|
bool matchesStaticSelector(const std::string& selector) const;
|
|
|
|
|
float getDefaultScale();
|
|
|
|
|
void changeWorkspace(const PHLWORKSPACE& pWorkspace, bool internal = false, bool noMouseMove = false, bool noFocus = false);
|
|
|
|
|
void changeWorkspace(const WORKSPACEID& id, bool internal = false, bool noMouseMove = false, bool noFocus = false);
|
|
|
|
|
void setSpecialWorkspace(const PHLWORKSPACE& pWorkspace);
|
|
|
|
|
void setSpecialWorkspace(const WORKSPACEID& id);
|
|
|
|
|
void moveTo(const Vector2D& pos);
|
|
|
|
|
Vector2D middle();
|
|
|
|
|
void updateMatrix();
|
|
|
|
|
WORKSPACEID activeWorkspaceID();
|
|
|
|
|
WORKSPACEID activeSpecialWorkspaceID();
|
|
|
|
|
CBox logicalBox();
|
|
|
|
|
void scheduleDone();
|
|
|
|
|
bool attemptDirectScanout();
|
|
|
|
|
void setCTM(const Mat3x3& ctm);
|
|
|
|
|
void onCursorMovedOnMonitor();
|
|
|
|
|
|
|
|
|
|
void debugLastPresentation(const std::string& message);
|
|
|
|
|
void onMonitorFrame();
|
|
|
|
|
|
2025-04-30 23:45:20 +02:00
|
|
|
bool m_enabled = false;
|
|
|
|
|
bool m_renderingInitPassed = false;
|
2025-02-26 17:56:37 +03:00
|
|
|
WP<CWindow> m_previousFSWindow;
|
2025-04-30 23:45:20 +02:00
|
|
|
NColorManagement::SImageDescription m_imageDescription;
|
2022-07-27 12:32:00 +02:00
|
|
|
|
2022-03-18 22:35:51 +01:00
|
|
|
// For the list lookup
|
|
|
|
|
|
2022-07-27 12:32:00 +02:00
|
|
|
bool operator==(const CMonitor& rhs) {
|
2025-04-30 23:45:20 +02:00
|
|
|
return m_position == rhs.m_position && m_size == rhs.m_size && m_name == rhs.m_name;
|
2022-03-18 22:35:51 +01:00
|
|
|
}
|
2022-09-13 15:25:42 +02:00
|
|
|
|
2025-01-11 19:05:53 +03:00
|
|
|
// workspace previous per monitor functionality
|
|
|
|
|
SWorkspaceIDName getPrevWorkspaceIDName(const WORKSPACEID id);
|
|
|
|
|
void addPrevWorkspaceID(const WORKSPACEID id);
|
|
|
|
|
|
2022-12-16 17:17:31 +00:00
|
|
|
private:
|
2025-01-11 19:05:53 +03:00
|
|
|
void setupDefaultWS(const SMonitorRule&);
|
|
|
|
|
WORKSPACEID findAvailableDefaultWS();
|
2024-07-21 13:09:54 +02:00
|
|
|
|
2025-04-30 23:45:20 +02:00
|
|
|
bool m_doneScheduled = false;
|
|
|
|
|
std::stack<WORKSPACEID> m_prevWorkSpaces;
|
2024-07-21 13:09:54 +02:00
|
|
|
|
|
|
|
|
struct {
|
|
|
|
|
CHyprSignalListener frame;
|
|
|
|
|
CHyprSignalListener destroy;
|
|
|
|
|
CHyprSignalListener state;
|
|
|
|
|
CHyprSignalListener needsFrame;
|
|
|
|
|
CHyprSignalListener presented;
|
|
|
|
|
CHyprSignalListener commit;
|
2025-04-30 23:45:20 +02:00
|
|
|
} m_listeners;
|
2022-09-25 20:07:48 +02:00
|
|
|
};
|