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-06-11 17:52:16 +02:00
# include "AnimatedVariable.hpp"
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
2025-07-08 12:41:10 +02:00
class CMonitorFrameScheduler ;
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 ,
2025-05-27 15:51:59 +01:00
DIR_AUTO_RIGHT ,
DIR_AUTO_CENTER_UP ,
DIR_AUTO_CENTER_DOWN ,
DIR_AUTO_CENTER_LEFT ,
DIR_AUTO_CENTER_RIGHT
2024-04-23 00:40:03 +00:00
} ;
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
2025-06-15 13:15:18 +03:00
bool supportsWideColor = false ; // false does nothing, true overrides EDID
bool supportsHDR = false ; // false does nothing, true overrides EDID
float sdrMinLuminance = 0.2f ; // SDR -> HDR
int sdrMaxLuminance = 80 ; // SDR -> HDR
// Incorrect values will result in reduced luminance range or incorrect tonemapping. Shouldn't damage the HW. Use with care in case of a faulty monitor firmware.
float minLuminance = - 1.0f ; // >= 0 overrides EDID
int maxLuminance = - 1 ; // >= 0 overrides EDID
int maxAvgLuminance = - 1 ; // >= 0 overrides EDID
drmModeModeInfo drmMode = { } ;
std : : optional < int > vrr ;
2023-08-11 17:37:52 +02:00
} ;
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
2025-06-08 01:12:43 +05:00
eAutoDirs m_autoDir = DIR_AUTO_NONE ;
2025-04-30 23:45:20 +02:00
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 ;
2025-06-15 13:15:18 +03:00
float m_sdrMinLuminance = 0.2f ;
int m_sdrMaxLuminance = 80 ;
2025-04-30 23:45:20 +02:00
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 ;
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
2025-07-08 12:41:10 +02:00
UP < CMonitorFrameScheduler > m_frameScheduler ;
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
2025-06-11 17:52:16 +02:00
// for special fade/blur
PHLANIMVAR < float > m_specialFade ;
2025-07-01 11:33:48 +02:00
PHLANIMVAR < float > m_cursorZoom ;
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 {
2025-07-08 09:56:40 -07:00
CSignalT < > destroy ;
CSignalT < > connect ;
CSignalT < > disconnect ;
CSignalT < > dpmsChanged ;
CSignalT < > 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 ) ;
2025-06-23 15:33:09 +03:00
void applyCMType ( eCMType cmType ) ;
2025-02-26 17:56:37 +03:00
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 ) ;
2025-06-15 13:15:18 +03:00
bool supportsWideColor ( ) ;
bool supportsHDR ( ) ;
float minLuminance ( ) ;
int maxLuminance ( ) ;
int maxAvgLuminance ( ) ;
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 ;
2025-06-15 13:15:18 +03:00
bool m_supportsWideColor = false ;
bool m_supportsHDR = false ;
float m_minLuminance = - 1.0f ;
int m_maxLuminance = - 1 ;
int m_maxAvgLuminance = - 1 ;
2022-09-25 20:07:48 +02:00
} ;