2022-03-17 20:22:29 +01:00
# include "Renderer.hpp"
# include "../Compositor.hpp"
2023-04-27 14:55:13 +02:00
# include "linux-dmabuf-unstable-v1-protocol.h"
2023-07-19 20:09:49 +02:00
# include "../helpers/Region.hpp"
2022-03-17 20:22:29 +01:00
2023-09-28 22:48:33 +02:00
CHyprRenderer : : CHyprRenderer ( ) {
const auto ENV = getenv ( " WLR_DRM_NO_ATOMIC " ) ;
if ( ENV & & std : : string ( ENV ) = = " 1 " )
m_bTearingEnvSatisfied = true ;
}
2022-03-17 20:22:29 +01:00
void renderSurface ( struct wlr_surface * surface , int x , int y , void * data ) {
const auto TEXTURE = wlr_surface_get_texture ( surface ) ;
2022-12-16 18:17:31 +01:00
const auto RDATA = ( SRenderData * ) data ;
2022-03-17 20:22:29 +01:00
if ( ! TEXTURE )
return ;
2023-07-20 17:47:49 +02:00
TRACY_GPU_ZONE ( " RenderSurface " ) ;
2022-03-17 20:22:29 +01:00
double outputX = 0 , outputY = 0 ;
2023-01-20 19:44:30 +01:00
wlr_output_layout_output_coords ( g_pCompositor - > m_sWLROutputLayout , RDATA - > pMonitor - > output , & outputX , & outputY ) ;
2022-03-17 20:22:29 +01:00
2022-03-23 22:01:59 +01:00
wlr_box windowBox ;
2023-10-20 21:15:41 +02:00
if ( RDATA - > surface & & surface = = RDATA - > surface ) {
2022-06-29 12:54:53 +02:00
windowBox = { ( int ) outputX + RDATA - > x + x , ( int ) outputY + RDATA - > y + y , RDATA - > w , RDATA - > h } ;
2023-10-20 21:15:41 +02:00
// however, if surface buffer w / h < box, we need to adjust them
auto * const PSURFACE = CWLSurface : : surfaceFromWlr ( surface ) ;
if ( PSURFACE & & ! PSURFACE - > m_bFillIgnoreSmall & & PSURFACE - > small ( ) /* guarantees m_pOwner */ ) {
2023-10-20 21:32:47 +02:00
const auto CORRECT = PSURFACE - > correctSmallVec ( ) ;
2023-10-25 23:05:04 +02:00
const auto SIZE = PSURFACE - > getViewporterCorrectedSize ( ) ;
2023-10-20 21:32:47 +02:00
const auto INTERACTIVERESIZEINPROGRESS = g_pInputManager - > currentlyDraggedWindow = = PSURFACE - > m_pOwner & & g_pInputManager - > dragMode = = MBIND_RESIZE ;
if ( ! INTERACTIVERESIZEINPROGRESS ) {
windowBox . x + = CORRECT . x ;
windowBox . y + = CORRECT . y ;
2023-10-25 23:05:04 +02:00
windowBox . width = SIZE . x * ( PSURFACE - > m_pOwner - > m_vRealSize . vec ( ) . x / PSURFACE - > m_pOwner - > m_vReportedSize . x ) ;
windowBox . height = SIZE . y * ( PSURFACE - > m_pOwner - > m_vRealSize . vec ( ) . y / PSURFACE - > m_pOwner - > m_vReportedSize . y ) ;
2023-10-20 21:32:47 +02:00
} else {
2023-10-25 23:05:04 +02:00
windowBox . width = SIZE . x ;
windowBox . height = SIZE . y ;
2023-10-20 21:32:47 +02:00
}
2023-10-20 21:15:41 +02:00
}
} else { // here we clamp to 2, these might be some tiny specks
2022-09-26 21:10:24 +02:00
windowBox = { ( int ) outputX + RDATA - > x + x , ( int ) outputY + RDATA - > y + y , std : : max ( surface - > current . width , 2 ) , std : : max ( surface - > current . height , 2 ) } ;
2023-07-10 13:32:57 +02:00
if ( RDATA - > pWindow & & RDATA - > pWindow - > m_vRealSize . isBeingAnimated ( ) & & RDATA - > surface & & RDATA - > surface ! = surface & & RDATA - > squishOversized /* subsurface */ ) {
// adjust subsurfaces to the window
windowBox . width = ( windowBox . width / RDATA - > pWindow - > m_vReportedSize . x ) * RDATA - > pWindow - > m_vRealSize . vec ( ) . x ;
windowBox . height = ( windowBox . height / RDATA - > pWindow - > m_vReportedSize . y ) * RDATA - > pWindow - > m_vRealSize . vec ( ) . y ;
}
}
2022-09-25 20:07:48 +02:00
2022-07-11 23:38:10 +02:00
if ( RDATA - > squishOversized ) {
if ( x + windowBox . width > RDATA - > w )
windowBox . width = RDATA - > w - x ;
2022-07-15 19:07:06 +02:00
if ( y + windowBox . height > RDATA - > h )
2022-07-11 23:38:10 +02:00
windowBox . height = RDATA - > h - y ;
}
2022-08-28 10:14:43 +02:00
2023-10-21 15:20:06 +02:00
if ( windowBox . width < = 1 | | windowBox . height < = 1 )
return ; // invisible
2023-01-29 14:58:47 +01:00
g_pHyprRenderer - > calculateUVForSurface ( RDATA - > pWindow , surface , RDATA - > squishOversized ) ;
2022-09-25 20:07:48 +02:00
2023-01-20 19:44:30 +01:00
scaleBox ( & windowBox , RDATA - > pMonitor - > scale ) ;
2022-03-17 20:22:29 +01:00
2023-07-19 20:06:19 +02:00
float rounding = RDATA - > rounding ;
2022-05-28 17:48:01 +02:00
2022-08-20 22:45:30 +02:00
rounding - = 1 ; // to fix a border issue
2023-09-23 01:06:48 +02:00
if ( RDATA - > dontRound )
rounding = 0 ;
2023-10-29 21:54:14 +01:00
const bool WINDOWOPAQUE = RDATA - > pWindow & & RDATA - > pWindow - > m_pWLSurface . wlr ( ) = = surface ? RDATA - > pWindow - > opaque ( ) : false ;
const bool CANDISABLEBLEND = RDATA - > alpha * RDATA - > fadeAlpha > = 1.f & & rounding = = 0 & & ( WINDOWOPAQUE | | surface - > opaque ) ;
2023-07-20 13:49:28 +02:00
if ( CANDISABLEBLEND )
g_pHyprOpenGL - > blend ( false ) ;
else
g_pHyprOpenGL - > blend ( true ) ;
2022-06-22 15:45:56 +02:00
if ( RDATA - > surface & & surface = = RDATA - > surface ) {
2023-02-03 13:43:43 +01:00
if ( wlr_xwayland_surface_try_from_wlr_surface ( surface ) & & ! wlr_xwayland_surface_try_from_wlr_surface ( surface ) - > has_alpha & & RDATA - > fadeAlpha * RDATA - > alpha = = 1.f ) {
2022-07-06 22:12:03 +02:00
g_pHyprOpenGL - > renderTexture ( TEXTURE , & windowBox , RDATA - > fadeAlpha * RDATA - > alpha , rounding , true ) ;
2022-07-27 13:30:55 +02:00
} else {
if ( RDATA - > blur )
2023-08-23 12:03:23 +02:00
g_pHyprOpenGL - > renderTextureWithBlur ( TEXTURE , & windowBox , RDATA - > fadeAlpha * RDATA - > alpha , surface , rounding , RDATA - > blockBlurOptimization , RDATA - > fadeAlpha ) ;
2022-07-27 13:30:55 +02:00
else
g_pHyprOpenGL - > renderTexture ( TEXTURE , & windowBox , RDATA - > fadeAlpha * RDATA - > alpha , rounding , true ) ;
}
2022-12-16 18:17:31 +01:00
} else {
2022-08-28 10:14:43 +02:00
g_pHyprOpenGL - > renderTexture ( TEXTURE , & windowBox , RDATA - > fadeAlpha * RDATA - > alpha , rounding , true ) ;
2022-07-04 15:58:12 +02:00
}
2022-03-17 20:22:29 +01:00
2022-12-05 20:11:02 +01:00
if ( ! g_pHyprRenderer - > m_bBlockSurfaceFeedback ) {
wlr_surface_send_frame_done ( surface , RDATA - > when ) ;
2023-07-18 12:25:48 +02:00
wlr_presentation_surface_textured_on_output ( g_pCompositor - > m_sWLRPresentation , surface , RDATA - > pMonitor - > output ) ;
2022-12-05 20:11:02 +01:00
}
2022-08-28 10:41:47 +02:00
2023-07-20 13:49:28 +02:00
g_pHyprOpenGL - > blend ( true ) ;
2022-08-28 10:41:47 +02:00
// reset the UV, we might've set it above
2022-12-16 18:17:31 +01:00
g_pHyprOpenGL - > m_RenderData . primarySurfaceUVTopLeft = Vector2D ( - 1 , - 1 ) ;
2022-08-28 10:41:47 +02:00
g_pHyprOpenGL - > m_RenderData . primarySurfaceUVBottomRight = Vector2D ( - 1 , - 1 ) ;
2022-03-17 20:22:29 +01:00
}
2023-04-12 14:05:57 +02:00
bool CHyprRenderer : : shouldRenderWindow ( CWindow * pWindow , CMonitor * pMonitor , CWorkspace * pWorkspace ) {
2022-05-30 14:55:42 +02:00
wlr_box geometry = pWindow - > getFullWindowBoundingBox ( ) ;
2022-03-20 18:49:40 +01:00
if ( ! wlr_output_layout_intersects ( g_pCompositor - > m_sWLROutputLayout , pMonitor - > output , & geometry ) )
return false ;
2023-04-12 14:05:57 +02:00
if ( pWindow - > m_iWorkspaceID = = - 1 )
return false ;
2022-09-10 13:11:02 +02:00
if ( pWindow - > m_bPinned )
return true ;
2023-04-14 16:16:43 +02:00
const auto PWINDOWWORKSPACE = g_pCompositor - > getWorkspaceByID ( pWindow - > m_iWorkspaceID ) ;
if ( PWINDOWWORKSPACE & & PWINDOWWORKSPACE - > m_iMonitorID = = pMonitor - > ID ) {
if ( PWINDOWWORKSPACE - > m_vRenderOffset . isBeingAnimated ( ) | | PWINDOWWORKSPACE - > m_fAlpha . isBeingAnimated ( ) | | PWINDOWWORKSPACE - > m_bForceRendering ) {
2022-08-18 12:42:21 +02:00
return true ;
} else {
2023-04-14 16:16:43 +02:00
if ( ! ( ! PWINDOWWORKSPACE - > m_bHasFullscreenWindow | | pWindow - > m_bIsFullscreen | | ( pWindow - > m_bIsFloating & & pWindow - > m_bCreatedOverFullscreen ) ) )
2022-08-18 12:42:21 +02:00
return false ;
}
2022-07-28 16:33:45 +02:00
}
2023-04-12 14:05:57 +02:00
if ( pWindow - > m_iWorkspaceID = = pWorkspace - > m_iID )
2022-03-20 18:49:40 +01:00
return true ;
2022-08-18 12:41:10 +02:00
// if not, check if it maybe is active on a different monitor.
2022-10-12 19:37:11 +02:00
if ( g_pCompositor - > isWorkspaceVisible ( pWindow - > m_iWorkspaceID ) & & pWindow - > m_bIsFloating /* tiled windows can't be multi-ws */ )
2022-08-18 12:41:10 +02:00
return ! pWindow - > m_bIsFullscreen ; // Do not draw fullscreen windows on other monitors
2022-03-20 18:49:40 +01:00
2022-12-11 17:53:59 +01:00
if ( pMonitor - > specialWorkspaceID = = pWindow - > m_iWorkspaceID )
2022-05-31 14:01:00 +02:00
return true ;
2022-03-20 18:49:40 +01:00
return false ;
}
2022-05-31 22:16:13 +02:00
bool CHyprRenderer : : shouldRenderWindow ( CWindow * pWindow ) {
if ( ! g_pCompositor - > windowValidMapped ( pWindow ) )
return false ;
const auto PWORKSPACE = g_pCompositor - > getWorkspaceByID ( pWindow - > m_iWorkspaceID ) ;
2023-04-12 14:05:57 +02:00
if ( pWindow - > m_iWorkspaceID = = - 1 )
return false ;
2022-09-12 15:33:20 +02:00
if ( pWindow - > m_bPinned | | PWORKSPACE - > m_bForceRendering )
2022-09-10 13:11:02 +02:00
return true ;
2022-05-31 22:16:13 +02:00
if ( g_pCompositor - > isWorkspaceVisible ( pWindow - > m_iWorkspaceID ) )
return true ;
2022-06-30 15:44:26 +02:00
for ( auto & m : g_pCompositor - > m_vMonitors ) {
if ( PWORKSPACE & & PWORKSPACE - > m_iMonitorID = = m - > ID & & ( PWORKSPACE - > m_vRenderOffset . isBeingAnimated ( ) | | PWORKSPACE - > m_fAlpha . isBeingAnimated ( ) ) )
2022-05-31 22:16:13 +02:00
return true ;
2022-11-27 23:42:22 +01:00
if ( m - > specialWorkspaceID & & g_pCompositor - > isWorkspaceSpecial ( pWindow - > m_iWorkspaceID ) )
2022-05-31 22:16:13 +02:00
return true ;
}
return false ;
}
2023-09-04 15:07:56 +02:00
void CHyprRenderer : : renderWorkspaceWindowsFullscreen ( CMonitor * pMonitor , CWorkspace * pWorkspace , timespec * time ) {
2022-03-30 20:16:23 +02:00
CWindow * pWorkspaceWindow = nullptr ;
2023-04-18 00:45:03 +02:00
EMIT_HOOK_EVENT ( " render " , RENDER_PRE_WINDOWS ) ;
2022-09-19 18:26:11 +02:00
// loop over the tiled windows that are fading out
for ( auto & w : g_pCompositor - > m_vWindows ) {
if ( w - > m_iWorkspaceID ! = pMonitor - > activeWorkspace )
continue ;
if ( w - > m_fAlpha . fl ( ) = = 0.f )
continue ;
if ( w - > m_bIsFullscreen | | w - > m_bIsFloating )
continue ;
renderWindow ( w . get ( ) , pMonitor , time , true , RENDER_PASS_ALL ) ;
}
// and floating ones too
for ( auto & w : g_pCompositor - > m_vWindows ) {
if ( w - > m_iWorkspaceID ! = pMonitor - > activeWorkspace )
continue ;
if ( w - > m_fAlpha . fl ( ) = = 0.f )
continue ;
if ( w - > m_bIsFullscreen | | ! w - > m_bIsFloating )
continue ;
renderWindow ( w . get ( ) , pMonitor , time , true , RENDER_PASS_ALL ) ;
}
2022-06-30 15:44:26 +02:00
for ( auto & w : g_pCompositor - > m_vWindows ) {
2022-07-28 15:56:55 +02:00
const auto PWORKSPACE = g_pCompositor - > getWorkspaceByID ( w - > m_iWorkspaceID ) ;
2022-12-16 18:17:31 +01:00
if ( w - > m_iWorkspaceID ! = pWorkspace - > m_iID | | ! w - > m_bIsFullscreen ) {
2022-09-19 11:23:13 +02:00
if ( ! ( PWORKSPACE & & ( PWORKSPACE - > m_vRenderOffset . isBeingAnimated ( ) | | PWORKSPACE - > m_fAlpha . isBeingAnimated ( ) | | PWORKSPACE - > m_bForceRendering ) ) )
2022-07-28 15:56:55 +02:00
continue ;
2022-08-17 12:12:16 +02:00
if ( w - > m_iMonitorID ! = pMonitor - > ID )
continue ;
2022-07-28 15:56:55 +02:00
}
2022-03-21 19:18:33 +01:00
2022-07-28 16:33:45 +02:00
if ( w - > m_iWorkspaceID = = pMonitor - > activeWorkspace & & ! w - > m_bIsFullscreen )
continue ;
2022-07-12 09:49:56 +02:00
renderWindow ( w . get ( ) , pMonitor , time , pWorkspace - > m_efFullscreenMode ! = FULLSCREEN_FULL , RENDER_PASS_ALL ) ;
2022-03-30 20:16:23 +02:00
2022-06-30 15:44:26 +02:00
pWorkspaceWindow = w . get ( ) ;
2022-03-30 20:16:23 +02:00
}
2022-10-11 21:29:37 +02:00
if ( ! pWorkspaceWindow ) {
// ?? happens sometimes...
pWorkspace - > m_bHasFullscreenWindow = false ;
return ; // this will produce one blank frame. Oh well.
}
2022-09-19 18:26:11 +02:00
// then render windows over fullscreen.
2022-06-30 15:44:26 +02:00
for ( auto & w : g_pCompositor - > m_vWindows ) {
2023-05-10 19:36:13 +02:00
if ( w - > m_iWorkspaceID ! = pWorkspaceWindow - > m_iWorkspaceID | | ( ! w - > m_bCreatedOverFullscreen & & ! w - > m_bPinned ) | | ( ! w - > m_bIsMapped & & ! w - > m_bFadingOut ) | | w - > m_bIsFullscreen )
2022-03-30 20:16:23 +02:00
continue ;
2022-07-12 09:49:56 +02:00
renderWindow ( w . get ( ) , pMonitor , time , true , RENDER_PASS_ALL ) ;
2022-05-31 14:20:41 +02:00
}
2023-09-04 15:07:56 +02:00
}
2022-05-31 14:20:41 +02:00
2023-09-04 15:07:56 +02:00
void CHyprRenderer : : renderWorkspaceWindows ( CMonitor * pMonitor , CWorkspace * pWorkspace , timespec * time ) {
CWindow * lastWindow = nullptr ;
2022-05-31 14:20:41 +02:00
2023-09-04 15:07:56 +02:00
EMIT_HOOK_EVENT ( " render " , RENDER_PRE_WINDOWS ) ;
2022-05-31 14:20:41 +02:00
2023-09-04 15:07:56 +02:00
// Non-floating main
for ( auto & w : g_pCompositor - > m_vWindows ) {
if ( w - > isHidden ( ) & & ! w - > m_bIsMapped & & ! w - > m_bFadingOut )
continue ;
2022-05-31 14:20:41 +02:00
2023-09-04 15:07:56 +02:00
if ( w - > m_bIsFloating )
continue ; // floating are in the second pass
2022-03-31 17:25:23 +02:00
2023-09-04 15:07:56 +02:00
if ( g_pCompositor - > isWorkspaceSpecial ( w - > m_iWorkspaceID ) )
continue ; // special are in the third pass
2023-04-18 00:45:03 +02:00
2023-09-04 15:07:56 +02:00
if ( ! shouldRenderWindow ( w . get ( ) , pMonitor , pWorkspace ) )
continue ;
// render active window after all others of this pass
if ( w . get ( ) = = g_pCompositor - > m_pLastWindow ) {
lastWindow = w . get ( ) ;
continue ;
}
// render the bad boy
renderWindow ( w . get ( ) , pMonitor , time , true , RENDER_PASS_MAIN ) ;
2022-05-29 15:44:30 +02:00
}
2023-09-04 15:07:56 +02:00
if ( lastWindow )
renderWindow ( lastWindow , pMonitor , time , true , RENDER_PASS_MAIN ) ;
// Non-floating popup
for ( auto & w : g_pCompositor - > m_vWindows ) {
if ( w - > isHidden ( ) & & ! w - > m_bIsMapped & & ! w - > m_bFadingOut )
continue ;
if ( w - > m_bIsFloating )
continue ; // floating are in the second pass
if ( g_pCompositor - > isWorkspaceSpecial ( w - > m_iWorkspaceID ) )
continue ; // special are in the third pass
if ( ! shouldRenderWindow ( w . get ( ) , pMonitor , pWorkspace ) )
continue ;
// render the bad boy
renderWindow ( w . get ( ) , pMonitor , time , true , RENDER_PASS_POPUP ) ;
2022-04-25 21:49:45 +02:00
}
2023-09-04 15:07:56 +02:00
// floating on top
for ( auto & w : g_pCompositor - > m_vWindows ) {
if ( w - > isHidden ( ) & & ! w - > m_bIsMapped & & ! w - > m_bFadingOut )
continue ;
if ( ! w - > m_bIsFloating | | w - > m_bPinned )
continue ;
if ( g_pCompositor - > isWorkspaceSpecial ( w - > m_iWorkspaceID ) )
continue ;
if ( ! shouldRenderWindow ( w . get ( ) , pMonitor , pWorkspace ) )
continue ;
// render the bad boy
renderWindow ( w . get ( ) , pMonitor , time , true , RENDER_PASS_ALL ) ;
2023-09-02 20:32:10 +02:00
}
2023-09-04 15:07:56 +02:00
// pinned always above
for ( auto & w : g_pCompositor - > m_vWindows ) {
if ( w - > isHidden ( ) & & ! w - > m_bIsMapped & & ! w - > m_bFadingOut )
continue ;
2022-04-08 21:40:41 +02:00
2023-09-04 15:07:56 +02:00
if ( ! w - > m_bPinned | | ! w - > m_bIsFloating )
continue ;
2023-02-10 23:03:23 +01:00
2023-09-04 15:07:56 +02:00
if ( g_pCompositor - > isWorkspaceSpecial ( w - > m_iWorkspaceID ) )
continue ;
2023-02-10 23:03:23 +01:00
2023-09-04 15:07:56 +02:00
if ( ! shouldRenderWindow ( w . get ( ) , pMonitor , pWorkspace ) )
continue ;
// render the bad boy
renderWindow ( w . get ( ) , pMonitor , time , true , RENDER_PASS_ALL ) ;
2023-02-10 23:03:23 +01:00
}
2022-03-21 19:18:33 +01:00
}
2022-12-05 18:05:15 +01:00
void CHyprRenderer : : renderWindow ( CWindow * pWindow , CMonitor * pMonitor , timespec * time , bool decorate , eRenderPassMode mode , bool ignorePosition , bool ignoreAllGeometry ) {
2022-10-14 21:46:32 +02:00
if ( pWindow - > isHidden ( ) )
2022-04-12 16:44:18 +02:00
return ;
2022-04-05 20:49:15 +02:00
if ( pWindow - > m_bFadingOut ) {
2022-05-28 18:52:22 +02:00
if ( pMonitor - > ID = = pWindow - > m_iMonitorID ) // TODO: fix this
g_pHyprOpenGL - > renderSnapshot ( & pWindow ) ;
2022-04-05 20:49:15 +02:00
return ;
}
2022-09-25 20:07:48 +02:00
2023-07-20 17:47:49 +02:00
TRACY_GPU_ZONE ( " RenderWindow " ) ;
2023-08-17 10:13:19 +02:00
const auto PWORKSPACE = g_pCompositor - > getWorkspaceByID ( pWindow - > m_iWorkspaceID ) ;
const auto REALPOS = pWindow - > m_vRealPosition . vec ( ) + ( pWindow - > m_bPinned ? Vector2D { } : PWORKSPACE - > m_vRenderOffset . vec ( ) ) ;
static auto * const PDIMAROUND = & g_pConfigManager - > getConfigValuePtr ( " decoration:dim_around " ) - > floatValue ;
static auto * const PBORDERSIZE = & g_pConfigManager - > getConfigValuePtr ( " general:border_size " ) - > intValue ;
2023-11-03 20:07:11 +01:00
static auto * const PBLUR = & g_pConfigManager - > getConfigValuePtr ( " decoration:blur:enabled " ) - > intValue ;
2022-06-21 22:54:41 +02:00
2023-09-03 12:51:48 +02:00
SRenderData renderdata = { pMonitor , time , REALPOS . x , REALPOS . y } ;
2022-11-06 18:52:09 +01:00
if ( ignorePosition ) {
2022-11-06 18:58:56 +01:00
renderdata . x = pMonitor - > vecPosition . x ;
renderdata . y = pMonitor - > vecPosition . y ;
2022-11-06 18:52:09 +01:00
}
2022-12-05 18:05:15 +01:00
if ( ignoreAllGeometry )
decorate = false ;
2023-03-20 16:00:58 +01:00
renderdata . surface = pWindow - > m_pWLSurface . wlr ( ) ;
2023-09-03 12:51:48 +02:00
renderdata . w = std : : max ( pWindow - > m_vRealSize . vec ( ) . x , 5.0 ) ; // clamp the size to min 5,
renderdata . h = std : : max ( pWindow - > m_vRealSize . vec ( ) . y , 5.0 ) ; // otherwise we'll have issues later with invalid boxes
2022-08-01 12:57:37 +02:00
renderdata . dontRound = ( pWindow - > m_bIsFullscreen & & PWORKSPACE - > m_efFullscreenMode = = FULLSCREEN_FULL ) | | ( ! pWindow - > m_sSpecialRenderData . rounding ) ;
2023-01-05 19:25:45 +01:00
renderdata . fadeAlpha = pWindow - > m_fAlpha . fl ( ) * ( pWindow - > m_bPinned ? 1.f : PWORKSPACE - > m_fAlpha . fl ( ) ) ;
2022-12-16 18:17:31 +01:00
renderdata . alpha = pWindow - > m_fActiveInactiveAlpha . fl ( ) ;
2023-08-17 10:13:19 +02:00
renderdata . decorate = decorate & & ! pWindow - > m_bX11DoesntWantBorders & & ( ! pWindow - > m_bIsFullscreen | | PWORKSPACE - > m_efFullscreenMode ! = FULLSCREEN_FULL ) ;
renderdata . rounding = ignoreAllGeometry | | renderdata . dontRound ? 0 : pWindow - > rounding ( ) * pMonitor - > scale ;
renderdata . blur = ! ignoreAllGeometry ; // if it shouldn't, it will be ignored later
renderdata . pWindow = pWindow ;
2022-03-21 19:18:33 +01:00
2022-12-05 19:00:57 +01:00
if ( ignoreAllGeometry ) {
2022-12-16 18:17:31 +01:00
renderdata . alpha = 1.f ;
2023-01-05 19:25:45 +01:00
renderdata . fadeAlpha = 1.f ;
2022-12-05 19:00:57 +01:00
}
2022-07-28 12:07:41 +02:00
// apply opaque
if ( pWindow - > m_sAdditionalConfigData . forceOpaque )
renderdata . alpha = 1.f ;
2022-05-17 13:16:37 +02:00
g_pHyprOpenGL - > m_pCurrentWindow = pWindow ;
2022-03-21 19:18:33 +01:00
2023-05-26 13:07:45 +02:00
EMIT_HOOK_EVENT ( " render " , RENDER_PRE_WINDOW ) ;
2022-12-28 19:56:18 +01:00
if ( * PDIMAROUND & & pWindow - > m_sAdditionalConfigData . dimAround & & ! m_bRenderingSnapshot & & mode ! = RENDER_PASS_POPUP ) {
2023-01-16 16:12:22 +01:00
wlr_box monbox = { 0 , 0 , g_pHyprOpenGL - > m_RenderData . pMonitor - > vecTransformedSize . x , g_pHyprOpenGL - > m_RenderData . pMonitor - > vecTransformedSize . y } ;
2022-12-28 15:39:17 +01:00
g_pHyprOpenGL - > renderRect ( & monbox , CColor ( 0 , 0 , 0 , * PDIMAROUND * renderdata . alpha * renderdata . fadeAlpha ) ) ;
}
2022-10-07 11:35:17 +02:00
// clip box for animated offsets
2023-10-21 20:51:14 +02:00
const Vector2D PREOFFSETPOS = { renderdata . x , renderdata . y } ;
2022-12-11 17:58:29 +01:00
if ( ! ignorePosition & & pWindow - > m_bIsFloating & & ! pWindow - > m_bPinned ) {
2023-10-21 20:51:14 +02:00
Vector2D offset ;
2022-11-06 19:10:53 +01:00
if ( PWORKSPACE - > m_vRenderOffset . vec ( ) . x ! = 0 ) {
2022-12-16 18:17:31 +01:00
const auto PWSMON = g_pCompositor - > getMonitorFromID ( PWORKSPACE - > m_iMonitorID ) ;
2022-11-06 19:10:53 +01:00
const auto PROGRESS = PWORKSPACE - > m_vRenderOffset . vec ( ) . x / PWSMON - > vecSize . x ;
2022-12-16 18:17:31 +01:00
const auto WINBB = pWindow - > getFullWindowBoundingBox ( ) ;
2022-11-06 19:10:53 +01:00
if ( WINBB . x < PWSMON - > vecPosition . x ) {
offset . x = ( PWSMON - > vecPosition . x - WINBB . x ) * PROGRESS ;
2022-11-16 16:17:01 +01:00
} else if ( WINBB . x + WINBB . width > PWSMON - > vecPosition . x + PWSMON - > vecSize . x ) {
offset . x = ( WINBB . x + WINBB . width - PWSMON - > vecPosition . x - PWSMON - > vecSize . x ) * PROGRESS ;
2022-11-06 19:10:53 +01:00
}
} else if ( PWORKSPACE - > m_vRenderOffset . vec ( ) . y ) {
2022-12-16 18:17:31 +01:00
const auto PWSMON = g_pCompositor - > getMonitorFromID ( PWORKSPACE - > m_iMonitorID ) ;
2022-11-06 19:10:53 +01:00
const auto PROGRESS = PWORKSPACE - > m_vRenderOffset . vec ( ) . y / PWSMON - > vecSize . y ;
2022-12-16 18:17:31 +01:00
const auto WINBB = pWindow - > getFullWindowBoundingBox ( ) ;
2022-11-06 19:10:53 +01:00
if ( WINBB . y < PWSMON - > vecPosition . y ) {
offset . y = ( PWSMON - > vecPosition . y - WINBB . y ) * PROGRESS ;
2022-11-16 16:17:01 +01:00
} else if ( WINBB . y + WINBB . height > PWSMON - > vecPosition . y + PWSMON - > vecSize . y ) {
offset . y = ( WINBB . y + WINBB . width - PWSMON - > vecPosition . y - PWSMON - > vecSize . y ) * PROGRESS ;
2022-11-06 19:10:53 +01:00
}
2022-10-07 13:34:54 +02:00
}
2022-11-06 19:10:53 +01:00
renderdata . x + = offset . x ;
renderdata . y + = offset . y ;
}
2022-12-16 18:17:31 +01:00
2022-06-28 15:45:38 +02:00
// render window decorations first, if not fullscreen full
2022-07-12 09:49:56 +02:00
if ( mode = = RENDER_PASS_ALL | | mode = = RENDER_PASS_MAIN ) {
2023-10-21 15:15:48 +02:00
const bool TRANSFORMERSPRESENT = ! pWindow - > m_vTransformers . empty ( ) ;
2023-10-21 20:25:44 +02:00
if ( TRANSFORMERSPRESENT ) {
2023-10-21 15:15:48 +02:00
g_pHyprOpenGL - > bindOffMain ( ) ;
2023-10-21 20:25:44 +02:00
for ( auto & t : pWindow - > m_vTransformers ) {
t - > preWindowRender ( & renderdata ) ;
}
}
2022-12-16 18:17:31 +01:00
if ( ! pWindow - > m_bIsFullscreen | | PWORKSPACE - > m_efFullscreenMode ! = FULLSCREEN_FULL )
for ( auto & wd : pWindow - > m_dWindowDecorations )
2023-10-21 20:51:14 +02:00
wd - > draw ( pMonitor , renderdata . alpha * renderdata . fadeAlpha , Vector2D { renderdata . x , renderdata . y } - PREOFFSETPOS ) ;
2022-06-22 15:45:56 +02:00
2023-06-11 21:33:50 +02:00
static auto * const PXWLUSENN = & g_pConfigManager - > getConfigValuePtr ( " xwayland:use_nearest_neighbor " ) - > intValue ;
2023-10-24 22:28:55 +02:00
if ( ( pWindow - > m_bIsX11 & & * PXWLUSENN ) | | pWindow - > m_sAdditionalConfigData . nearestNeighbor . toUnderlying ( ) )
2023-06-11 21:33:50 +02:00
g_pHyprOpenGL - > m_RenderData . useNearestNeighbor = true ;
2023-11-03 20:07:11 +01:00
if ( pWindow - > m_pWLSurface . small ( ) & & ! pWindow - > m_pWLSurface . m_bFillIgnoreSmall & & renderdata . blur & & * PBLUR ) {
2023-10-30 17:20:30 +01:00
wlr_box wb = { renderdata . x - pMonitor - > vecPosition . x , renderdata . y - pMonitor - > vecPosition . y , renderdata . w , renderdata . h } ;
2023-10-25 23:38:14 +02:00
scaleBox ( & wb , pMonitor - > scale ) ;
2023-10-25 23:20:58 +02:00
g_pHyprOpenGL - > renderRectWithBlur ( & wb , CColor ( 0 , 0 , 0 , 0 ) , renderdata . dontRound ? 0 : renderdata . rounding - 1 ) ;
renderdata . blur = false ;
}
2023-03-20 16:00:58 +01:00
wlr_surface_for_each_surface ( pWindow - > m_pWLSurface . wlr ( ) , renderSurface , & renderdata ) ;
2022-07-12 09:49:56 +02:00
2023-06-11 21:33:50 +02:00
g_pHyprOpenGL - > m_RenderData . useNearestNeighbor = false ;
2022-08-16 16:19:52 +02:00
if ( renderdata . decorate & & pWindow - > m_sSpecialRenderData . border ) {
2022-12-16 18:17:31 +01:00
auto grad = g_pHyprOpenGL - > m_pCurrentWindow - > m_cRealBorderColor ;
2023-02-01 22:06:01 +01:00
const bool ANIMATED = g_pHyprOpenGL - > m_pCurrentWindow - > m_fBorderFadeAnimationProgress . isBeingAnimated ( ) ;
float a1 = renderdata . fadeAlpha * renderdata . alpha * ( ANIMATED ? g_pHyprOpenGL - > m_pCurrentWindow - > m_fBorderFadeAnimationProgress . fl ( ) : 1.f ) ;
2022-07-16 20:57:59 +02:00
2023-02-01 22:06:01 +01:00
if ( g_pHyprOpenGL - > m_pCurrentWindow - > m_fBorderAngleAnimationProgress . getConfig ( ) - > pValues - > internalEnabled ) {
grad . m_fAngle + = g_pHyprOpenGL - > m_pCurrentWindow - > m_fBorderAngleAnimationProgress . fl ( ) * M_PI * 2 ;
grad . m_fAngle = normalizeAngleRad ( grad . m_fAngle ) ;
}
wlr_box windowBox = { renderdata . x - pMonitor - > vecPosition . x , renderdata . y - pMonitor - > vecPosition . y , renderdata . w , renderdata . h } ;
2022-07-16 20:57:59 +02:00
2022-07-16 23:29:42 +02:00
scaleBox ( & windowBox , pMonitor - > scale ) ;
2023-07-18 00:11:29 +02:00
int borderSize = pWindow - > m_sSpecialRenderData . borderSize . toUnderlying ( ) = = - 1 ? * PBORDERSIZE : pWindow - > m_sSpecialRenderData . borderSize . toUnderlying ( ) ;
if ( pWindow - > m_sAdditionalConfigData . borderSize . toUnderlying ( ) ! = - 1 )
borderSize = pWindow - > m_sAdditionalConfigData . borderSize . toUnderlying ( ) ;
2023-05-01 23:28:27 +02:00
2023-07-19 16:13:55 +02:00
g_pHyprOpenGL - > renderBorder ( & windowBox , grad , renderdata . rounding , borderSize , a1 ) ;
2022-11-26 18:56:43 +01:00
if ( ANIMATED ) {
2023-02-01 22:06:01 +01:00
float a2 = renderdata . fadeAlpha * renderdata . alpha * ( 1.f - g_pHyprOpenGL - > m_pCurrentWindow - > m_fBorderFadeAnimationProgress . fl ( ) ) ;
2023-07-19 16:13:55 +02:00
g_pHyprOpenGL - > renderBorder ( & windowBox , g_pHyprOpenGL - > m_pCurrentWindow - > m_cRealBorderColorPrevious , renderdata . rounding , borderSize , a2 ) ;
2022-11-26 18:56:43 +01:00
}
2022-07-16 20:57:59 +02:00
}
2023-10-21 15:15:48 +02:00
if ( TRANSFORMERSPRESENT ) {
CFramebuffer * last = g_pHyprOpenGL - > m_RenderData . currentFB ;
for ( auto & t : pWindow - > m_vTransformers ) {
last = t - > transform ( last ) ;
}
g_pHyprOpenGL - > bindBackOnMain ( ) ;
g_pHyprOpenGL - > renderOffToMain ( last ) ;
}
2022-06-22 15:45:56 +02:00
}
2022-07-12 09:49:56 +02:00
if ( mode = = RENDER_PASS_ALL | | mode = = RENDER_PASS_POPUP ) {
if ( ! pWindow - > m_bIsX11 ) {
2022-08-28 10:14:43 +02:00
wlr_box geom ;
wlr_xdg_surface_get_geometry ( pWindow - > m_uSurface . xdg , & geom ) ;
renderdata . x - = geom . x ;
renderdata . y - = geom . y ;
2022-12-16 18:17:31 +01:00
renderdata . dontRound = true ; // don't round popups
renderdata . pMonitor = pMonitor ;
2022-07-15 19:07:06 +02:00
renderdata . squishOversized = false ; // don't squish popups
2023-10-24 22:28:55 +02:00
if ( pWindow - > m_sAdditionalConfigData . nearestNeighbor . toUnderlying ( ) )
g_pHyprOpenGL - > m_RenderData . useNearestNeighbor = true ;
2022-07-12 09:49:56 +02:00
wlr_xdg_surface_for_each_popup_surface ( pWindow - > m_uSurface . xdg , renderSurface , & renderdata ) ;
2023-10-24 22:28:55 +02:00
g_pHyprOpenGL - > m_RenderData . useNearestNeighbor = false ;
2022-07-12 09:49:56 +02:00
}
2022-05-17 13:16:37 +02:00
}
2023-05-26 13:07:45 +02:00
EMIT_HOOK_EVENT ( " render " , RENDER_POST_WINDOW ) ;
2022-12-16 18:17:31 +01:00
g_pHyprOpenGL - > m_pCurrentWindow = nullptr ;
g_pHyprOpenGL - > m_RenderData . clipBox = { 0 , 0 , 0 , 0 } ;
2022-03-21 19:18:33 +01:00
}
2022-07-27 12:32:00 +02:00
void CHyprRenderer : : renderLayer ( SLayerSurface * pLayer , CMonitor * pMonitor , timespec * time ) {
2022-05-14 17:23:46 +02:00
if ( pLayer - > fadingOut ) {
g_pHyprOpenGL - > renderSnapshot ( & pLayer ) ;
return ;
}
2023-07-20 17:47:49 +02:00
TRACY_GPU_ZONE ( " RenderLayer " ) ;
2023-01-20 19:44:30 +01:00
SRenderData renderdata = { pMonitor , time , pLayer - > geometry . x , pLayer - > geometry . y } ;
2022-12-16 18:17:31 +01:00
renderdata . fadeAlpha = pLayer - > alpha . fl ( ) ;
renderdata . blur = pLayer - > forceBlur ;
renderdata . surface = pLayer - > layerSurface - > surface ;
renderdata . decorate = false ;
2023-01-29 16:58:36 +01:00
renderdata . w = pLayer - > geometry . width ;
renderdata . h = pLayer - > geometry . height ;
2022-12-04 21:57:41 +01:00
renderdata . blockBlurOptimization = pLayer - > layer = = ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM | | pLayer - > layer = = ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND ;
2023-03-18 00:16:13 +01:00
2023-08-09 22:03:24 +02:00
g_pHyprOpenGL - > m_pCurrentLayer = pLayer ;
2023-06-11 19:30:31 +02:00
if ( pLayer - > ignoreAlpha ) {
g_pHyprOpenGL - > m_RenderData . discardMode | = DISCARD_ALPHA ;
g_pHyprOpenGL - > m_RenderData . discardOpacity = pLayer - > ignoreAlphaValue ;
}
2022-05-14 17:23:46 +02:00
wlr_surface_for_each_surface ( pLayer - > layerSurface - > surface , renderSurface , & renderdata ) ;
2023-06-11 19:30:31 +02:00
g_pHyprOpenGL - > m_RenderData . discardMode & = ~ DISCARD_ALPHA ;
2022-07-27 18:02:20 +02:00
2022-12-16 18:17:31 +01:00
renderdata . squishOversized = false ; // don't squish popups
renderdata . dontRound = true ;
2022-07-27 18:02:20 +02:00
wlr_layer_surface_v1_for_each_popup_surface ( pLayer - > layerSurface , renderSurface , & renderdata ) ;
2023-08-09 22:03:24 +02:00
g_pHyprOpenGL - > m_pCurrentLayer = nullptr ;
2022-05-14 17:23:46 +02:00
}
2022-08-05 17:07:01 +02:00
void CHyprRenderer : : renderIMEPopup ( SIMEPopup * pPopup , CMonitor * pMonitor , timespec * time ) {
2023-01-20 19:44:30 +01:00
SRenderData renderdata = { pMonitor , time , pPopup - > realX , pPopup - > realY } ;
2022-08-05 17:07:01 +02:00
2022-12-16 18:17:31 +01:00
renderdata . blur = false ;
renderdata . surface = pPopup - > pSurface - > surface ;
2022-08-05 17:07:01 +02:00
renderdata . decorate = false ;
2022-12-16 18:17:31 +01:00
renderdata . w = pPopup - > pSurface - > surface - > current . width ;
renderdata . h = pPopup - > pSurface - > surface - > current . height ;
2022-08-05 17:07:01 +02:00
wlr_surface_for_each_surface ( pPopup - > pSurface - > surface , renderSurface , & renderdata ) ;
}
2023-02-03 12:58:55 +01:00
void CHyprRenderer : : renderSessionLockSurface ( SSessionLockSurface * pSurface , CMonitor * pMonitor , timespec * time ) {
2023-02-03 15:00:23 +01:00
SRenderData renderdata = { pMonitor , time , pMonitor - > vecPosition . x , pMonitor - > vecPosition . y } ;
2023-02-03 12:58:55 +01:00
renderdata . blur = false ;
renderdata . surface = pSurface - > pWlrLockSurface - > surface ;
renderdata . decorate = false ;
renderdata . w = pMonitor - > vecSize . x ;
renderdata . h = pMonitor - > vecSize . y ;
wlr_surface_for_each_surface ( pSurface - > pWlrLockSurface - > surface , renderSurface , & renderdata ) ;
}
2023-04-12 14:05:57 +02:00
void CHyprRenderer : : renderAllClientsForWorkspace ( CMonitor * pMonitor , CWorkspace * pWorkspace , timespec * time , const Vector2D & translate , const float & scale ) {
2023-08-25 17:43:23 +02:00
static auto * const PDIMSPECIAL = & g_pConfigManager - > getConfigValuePtr ( " decoration:dim_special " ) - > floatValue ;
static auto * const PBLURSPECIAL = & g_pConfigManager - > getConfigValuePtr ( " decoration:blur:special " ) - > intValue ;
2023-08-26 11:48:01 +02:00
static auto * const PBLUR = & g_pConfigManager - > getConfigValuePtr ( " decoration:blur:enabled " ) - > intValue ;
2022-03-17 20:22:29 +01:00
2023-04-12 13:41:23 +02:00
const SRenderModifData RENDERMODIFDATA = { translate , scale } ;
if ( ! pMonitor )
2022-03-17 20:22:29 +01:00
return ;
2023-02-03 12:58:55 +01:00
if ( ! g_pCompositor - > m_sSeat . exclusiveClient & & g_pSessionLockManager - > isSessionLocked ( ) ) {
// locked with no exclusive, draw only red
wlr_box boxe = { 0 , 0 , INT16_MAX , INT16_MAX } ;
g_pHyprOpenGL - > renderRect ( & boxe , CColor ( 1.0 , 0.2 , 0.2 , 1.0 ) ) ;
return ;
}
2023-04-12 13:41:23 +02:00
// todo: matrices are buggy atm for some reason, but probably would be preferable in the long run
// g_pHyprOpenGL->saveMatrix();
// g_pHyprOpenGL->setMatrixScaleTranslate(translate, scale);
g_pHyprOpenGL - > m_RenderData . renderModif = RENDERMODIFDATA ;
2023-07-19 16:13:55 +02:00
// for storing damage when we optimize for occlusion
2023-07-19 20:09:49 +02:00
CRegion preOccludedDamage { g_pHyprOpenGL - > m_RenderData . damage } ;
2023-07-19 16:13:55 +02:00
2022-03-19 13:35:04 +01:00
// Render layer surfaces below windows for monitor
2023-04-22 13:36:50 +02:00
// if we have a fullscreen, opaque window that convers the screen, we can skip this.
// TODO: check better with solitary after MR for tearing.
const auto PFULLWINDOW = g_pCompositor - > getFullscreenWindowOnWorkspace ( pWorkspace - > m_iID ) ;
2023-04-22 13:54:57 +02:00
if ( ! pWorkspace - > m_bHasFullscreenWindow | | pWorkspace - > m_efFullscreenMode ! = FULLSCREEN_FULL | | ! PFULLWINDOW | | PFULLWINDOW - > m_vRealSize . isBeingAnimated ( ) | |
2023-07-19 16:13:55 +02:00
! PFULLWINDOW - > opaque ( ) | | pWorkspace - > m_vRenderOffset . vec ( ) ! = Vector2D { } ) {
2023-09-01 23:01:59 +02:00
if ( ! g_pHyprOpenGL - > m_RenderData . pCurrentMonData - > blurFBShouldRender )
2023-07-20 18:03:47 +02:00
setOccludedForBackLayers ( g_pHyprOpenGL - > m_RenderData . damage , pWorkspace ) ;
2023-07-19 16:13:55 +02:00
2023-04-22 13:36:50 +02:00
for ( auto & ls : pMonitor - > m_aLayerSurfaceLayers [ ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND ] ) {
renderLayer ( ls . get ( ) , pMonitor , time ) ;
}
for ( auto & ls : pMonitor - > m_aLayerSurfaceLayers [ ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM ] ) {
renderLayer ( ls . get ( ) , pMonitor , time ) ;
}
2023-07-19 16:13:55 +02:00
2023-07-19 20:09:49 +02:00
g_pHyprOpenGL - > m_RenderData . damage = preOccludedDamage ;
2022-03-19 13:35:04 +01:00
}
2022-08-01 12:23:09 +02:00
// pre window pass
g_pHyprOpenGL - > preWindowPass ( ) ;
2023-09-04 15:07:56 +02:00
if ( pWorkspace - > m_bHasFullscreenWindow )
renderWorkspaceWindowsFullscreen ( pMonitor , pWorkspace , time ) ;
else
renderWorkspaceWindows ( pMonitor , pWorkspace , time ) ;
2022-05-31 14:01:00 +02:00
2023-09-04 15:07:56 +02:00
g_pHyprOpenGL - > m_RenderData . renderModif = { } ;
2022-05-31 14:01:00 +02:00
// and then special
2023-08-25 18:05:08 +02:00
for ( auto & ws : g_pCompositor - > m_vWorkspaces ) {
if ( ws - > m_iMonitorID = = pMonitor - > ID & & ws - > m_fAlpha . fl ( ) > 0.f & & ws - > m_bIsSpecialWorkspace ) {
const auto SPECIALANIMPROGRS = ws - > m_vRenderOffset . isBeingAnimated ( ) ? ws - > m_vRenderOffset . getCurveValue ( ) : ws - > m_fAlpha . getCurveValue ( ) ;
const bool ANIMOUT = ! pMonitor - > specialWorkspaceID ;
2022-12-28 15:18:23 +01:00
2023-08-25 17:43:23 +02:00
if ( * PDIMSPECIAL ! = 0.f ) {
wlr_box monbox = { translate . x , translate . y , pMonitor - > vecTransformedSize . x * scale , pMonitor - > vecTransformedSize . y * scale } ;
2023-01-05 19:25:45 +01:00
g_pHyprOpenGL - > renderRect ( & monbox , CColor ( 0 , 0 , 0 , * PDIMSPECIAL * ( ANIMOUT ? ( 1.0 - SPECIALANIMPROGRS ) : SPECIALANIMPROGRS ) ) ) ;
2022-12-28 15:18:23 +01:00
}
2023-08-26 11:48:01 +02:00
if ( * PBLURSPECIAL & & * PBLUR ) {
2023-08-25 17:43:23 +02:00
wlr_box monbox = { translate . x , translate . y , pMonitor - > vecTransformedSize . x * scale , pMonitor - > vecTransformedSize . y * scale } ;
g_pHyprOpenGL - > renderRectWithBlur ( & monbox , CColor ( 0 , 0 , 0 , 0 ) , 0 , ( ANIMOUT ? ( 1.0 - SPECIALANIMPROGRS ) : SPECIALANIMPROGRS ) ) ;
}
2023-08-25 18:05:08 +02:00
break ;
2022-12-28 15:18:23 +01:00
}
2023-08-25 18:05:08 +02:00
}
for ( auto & w : g_pCompositor - > m_vWindows ) {
if ( w - > isHidden ( ) & & ! w - > m_bIsMapped & & ! w - > m_bFadingOut )
continue ;
if ( ! g_pCompositor - > isWorkspaceSpecial ( w - > m_iWorkspaceID ) )
continue ;
if ( ! shouldRenderWindow ( w . get ( ) , pMonitor , pWorkspace ) )
continue ;
2022-12-28 15:18:23 +01:00
2022-03-18 20:42:49 +01:00
// render the bad boy
2023-04-12 13:41:23 +02:00
renderWindow ( w . get ( ) , pMonitor , time , true , RENDER_PASS_ALL ) ;
2022-03-18 20:03:39 +01:00
}
2022-03-19 13:35:04 +01:00
2023-04-18 00:45:03 +02:00
EMIT_HOOK_EVENT ( " render " , RENDER_POST_WINDOWS ) ;
2022-03-19 13:35:04 +01:00
// Render surfaces above windows for monitor
2023-04-12 13:41:23 +02:00
for ( auto & ls : pMonitor - > m_aLayerSurfaceLayers [ ZWLR_LAYER_SHELL_V1_LAYER_TOP ] ) {
renderLayer ( ls . get ( ) , pMonitor , time ) ;
2022-03-19 13:35:04 +01:00
}
2022-08-05 17:07:01 +02:00
// Render IME popups
for ( auto & imep : g_pInputManager - > m_sIMERelay . m_lIMEPopups ) {
2023-04-12 13:41:23 +02:00
renderIMEPopup ( & imep , pMonitor , time ) ;
2022-08-05 17:07:01 +02:00
}
2023-04-12 13:41:23 +02:00
for ( auto & ls : pMonitor - > m_aLayerSurfaceLayers [ ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY ] ) {
renderLayer ( ls . get ( ) , pMonitor , time ) ;
2022-03-19 13:35:04 +01:00
}
2022-03-31 17:25:23 +02:00
2023-04-12 13:41:23 +02:00
renderDragIcon ( pMonitor , time ) ;
//g_pHyprOpenGL->restoreMatrix();
g_pHyprOpenGL - > m_RenderData . renderModif = { } ;
}
2023-02-03 12:58:55 +01:00
2023-04-12 13:41:23 +02:00
void CHyprRenderer : : renderLockscreen ( CMonitor * pMonitor , timespec * now ) {
2023-07-20 17:47:49 +02:00
TRACY_GPU_ZONE ( " RenderLockscreen " ) ;
2023-02-03 12:58:55 +01:00
if ( g_pSessionLockManager - > isSessionLocked ( ) ) {
2023-04-12 13:41:23 +02:00
const auto PSLS = g_pSessionLockManager - > getSessionLockSurfaceForMonitor ( pMonitor - > ID ) ;
2023-02-03 12:58:55 +01:00
if ( ! PSLS ) {
// locked with no surface, fill with red
wlr_box boxe = { 0 , 0 , INT16_MAX , INT16_MAX } ;
g_pHyprOpenGL - > renderRect ( & boxe , CColor ( 1.0 , 0.2 , 0.2 , 1.0 ) ) ;
} else {
2023-04-12 13:41:23 +02:00
renderSessionLockSurface ( PSLS , pMonitor , now ) ;
2023-02-03 12:58:55 +01:00
}
}
2022-03-17 20:22:29 +01:00
}
2022-03-19 14:07:18 +01:00
2023-01-29 14:58:47 +01:00
void CHyprRenderer : : calculateUVForSurface ( CWindow * pWindow , wlr_surface * pSurface , bool main ) {
if ( ! pWindow | | ! pWindow - > m_bIsX11 ) {
2022-08-28 10:14:43 +02:00
Vector2D uvTL ;
Vector2D uvBR = Vector2D ( 1 , 1 ) ;
if ( pSurface - > current . viewport . has_src ) {
2023-01-20 19:44:30 +01:00
// we stretch it to dest. if no dest, to 1,1
2022-08-28 10:14:43 +02:00
wlr_fbox bufferSource ;
wlr_surface_get_buffer_source_box ( pSurface , & bufferSource ) ;
2023-01-20 19:44:30 +01:00
Vector2D bufferSize = Vector2D ( pSurface - > buffer - > texture - > width , pSurface - > buffer - > texture - > height ) ;
2022-08-28 10:14:43 +02:00
2023-01-29 16:58:36 +01:00
// calculate UV for the basic src_box. Assume dest == size. Scale to dest later
2023-01-20 19:44:30 +01:00
uvTL = Vector2D ( bufferSource . x / bufferSize . x , bufferSource . y / bufferSize . y ) ;
uvBR = Vector2D ( ( bufferSource . x + bufferSource . width ) / bufferSize . x , ( bufferSource . y + bufferSource . height ) / bufferSize . y ) ;
2022-08-28 10:14:43 +02:00
2022-08-28 14:32:06 +02:00
if ( uvBR . x < 0.01f | | uvBR . y < 0.01f ) {
uvTL = Vector2D ( ) ;
2022-12-16 18:17:31 +01:00
uvBR = Vector2D ( 1 , 1 ) ;
2022-08-28 14:32:06 +02:00
}
2022-08-28 10:14:43 +02:00
}
2022-12-16 18:17:31 +01:00
g_pHyprOpenGL - > m_RenderData . primarySurfaceUVTopLeft = uvTL ;
2022-08-28 10:14:43 +02:00
g_pHyprOpenGL - > m_RenderData . primarySurfaceUVBottomRight = uvBR ;
if ( g_pHyprOpenGL - > m_RenderData . primarySurfaceUVTopLeft = = Vector2D ( ) & & g_pHyprOpenGL - > m_RenderData . primarySurfaceUVBottomRight = = Vector2D ( 1 , 1 ) ) {
// No special UV mods needed
2022-12-16 18:17:31 +01:00
g_pHyprOpenGL - > m_RenderData . primarySurfaceUVTopLeft = Vector2D ( - 1 , - 1 ) ;
2022-08-28 10:14:43 +02:00
g_pHyprOpenGL - > m_RenderData . primarySurfaceUVBottomRight = Vector2D ( - 1 , - 1 ) ;
}
2023-01-29 14:58:47 +01:00
if ( ! main | | ! pWindow )
2023-01-20 19:44:30 +01:00
return ;
2022-08-28 10:14:43 +02:00
2023-01-20 19:44:30 +01:00
wlr_box geom ;
wlr_xdg_surface_get_geometry ( pWindow - > m_uSurface . xdg , & geom ) ;
// ignore X and Y, adjust uv
2023-10-20 21:32:47 +02:00
if ( geom . x ! = 0 | | geom . y ! = 0 | | geom . width > pWindow - > m_vRealSize . vec ( ) . x | | geom . height > pWindow - > m_vRealSize . vec ( ) . y ) {
2023-01-20 19:44:30 +01:00
const auto XPERC = ( double ) geom . x / ( double ) pSurface - > current . width ;
const auto YPERC = ( double ) geom . y / ( double ) pSurface - > current . height ;
const auto WPERC = ( double ) ( geom . x + geom . width ) / ( double ) pSurface - > current . width ;
const auto HPERC = ( double ) ( geom . y + geom . height ) / ( double ) pSurface - > current . height ;
2022-08-28 10:14:43 +02:00
2023-01-20 19:44:30 +01:00
const auto TOADDTL = Vector2D ( XPERC * ( uvBR . x - uvTL . x ) , YPERC * ( uvBR . y - uvTL . y ) ) ;
uvBR = uvBR - Vector2D ( 1.0 - WPERC * ( uvBR . x - uvTL . x ) , 1.0 - HPERC * ( uvBR . y - uvTL . y ) ) ;
uvTL = uvTL + TOADDTL ;
2022-08-28 10:14:43 +02:00
2023-10-20 21:32:47 +02:00
if ( geom . width > pWindow - > m_vRealSize . vec ( ) . x | | geom . height > pWindow - > m_vRealSize . vec ( ) . y ) {
uvBR . x = uvBR . x * ( pWindow - > m_vRealSize . vec ( ) . x / geom . width ) ;
uvBR . y = uvBR . y * ( pWindow - > m_vRealSize . vec ( ) . y / geom . height ) ;
2023-01-20 19:44:30 +01:00
}
}
g_pHyprOpenGL - > m_RenderData . primarySurfaceUVTopLeft = uvTL ;
g_pHyprOpenGL - > m_RenderData . primarySurfaceUVBottomRight = uvBR ;
if ( g_pHyprOpenGL - > m_RenderData . primarySurfaceUVTopLeft = = Vector2D ( ) & & g_pHyprOpenGL - > m_RenderData . primarySurfaceUVBottomRight = = Vector2D ( 1 , 1 ) ) {
// No special UV mods needed
g_pHyprOpenGL - > m_RenderData . primarySurfaceUVTopLeft = Vector2D ( - 1 , - 1 ) ;
g_pHyprOpenGL - > m_RenderData . primarySurfaceUVBottomRight = Vector2D ( - 1 , - 1 ) ;
2022-08-28 10:14:43 +02:00
}
} else {
2022-12-16 18:17:31 +01:00
g_pHyprOpenGL - > m_RenderData . primarySurfaceUVTopLeft = Vector2D ( - 1 , - 1 ) ;
2022-08-28 10:14:43 +02:00
g_pHyprOpenGL - > m_RenderData . primarySurfaceUVBottomRight = Vector2D ( - 1 , - 1 ) ;
}
}
2022-11-05 13:50:47 +01:00
void countSubsurfacesIter ( wlr_surface * pSurface , int x , int y , void * data ) {
* ( int * ) data + = 1 ;
}
bool CHyprRenderer : : attemptDirectScanout ( CMonitor * pMonitor ) {
2023-04-03 18:01:05 +02:00
if ( ! pMonitor - > mirrors . empty ( ) | | pMonitor - > isMirror ( ) | | m_bDirectScanoutBlocked )
2022-11-09 11:56:36 +01:00
return false ; // do not DS if this monitor is being mirrored. Will break the functionality.
2023-04-06 22:03:53 +02:00
if ( ! wlr_output_is_direct_scanout_allowed ( pMonitor - > output ) )
return false ;
2023-09-28 22:48:33 +02:00
const auto PCANDIDATE = pMonitor - > solitaryClient ;
2022-11-05 13:50:47 +01:00
if ( ! PCANDIDATE )
return false ;
2023-09-28 22:48:33 +02:00
const auto PSURFACE = g_pXWaylandManager - > getWindowSurface ( PCANDIDATE ) ;
2022-11-05 13:50:47 +01:00
if ( ! PSURFACE | | PSURFACE - > current . scale ! = pMonitor - > output - > scale | | PSURFACE - > current . transform ! = pMonitor - > output - > transform )
return false ;
// finally, we should be GTG.
wlr_output_attach_buffer ( pMonitor - > output , & PSURFACE - > buffer - > base ) ;
2023-09-28 22:48:33 +02:00
if ( ! wlr_output_test ( pMonitor - > output ) )
2022-11-05 13:50:47 +01:00
return false ;
2022-11-06 15:20:03 +01:00
timespec now ;
clock_gettime ( CLOCK_MONOTONIC , & now ) ;
wlr_surface_send_frame_done ( PSURFACE , & now ) ;
2023-07-18 12:13:59 +02:00
wlr_presentation_surface_scanned_out_on_output ( g_pCompositor - > m_sWLRPresentation , PSURFACE , pMonitor - > output ) ;
2022-11-05 13:50:47 +01:00
if ( wlr_output_commit ( pMonitor - > output ) ) {
if ( ! m_pLastScanout ) {
m_pLastScanout = PCANDIDATE ;
2023-09-06 21:45:37 +02:00
Debug : : log ( LOG , " Entered a direct scanout to {:x}: \" {} \" " , ( uintptr_t ) PCANDIDATE , PCANDIDATE - > m_szTitle ) ;
2022-11-05 13:50:47 +01:00
}
} else {
m_pLastScanout = nullptr ;
return false ;
}
return true ;
}
2023-03-24 20:23:16 +01:00
void CHyprRenderer : : renderMonitor ( CMonitor * pMonitor ) {
static std : : chrono : : high_resolution_clock : : time_point startRender = std : : chrono : : high_resolution_clock : : now ( ) ;
static std : : chrono : : high_resolution_clock : : time_point startRenderOverlay = std : : chrono : : high_resolution_clock : : now ( ) ;
static std : : chrono : : high_resolution_clock : : time_point endRenderOverlay = std : : chrono : : high_resolution_clock : : now ( ) ;
static auto * const PDEBUGOVERLAY = & g_pConfigManager - > getConfigValuePtr ( " debug:overlay " ) - > intValue ;
static auto * const PDAMAGETRACKINGMODE = & g_pConfigManager - > getConfigValuePtr ( " debug:damage_tracking " ) - > intValue ;
static auto * const PDAMAGEBLINK = & g_pConfigManager - > getConfigValuePtr ( " debug:damage_blink " ) - > intValue ;
static auto * const PNODIRECTSCANOUT = & g_pConfigManager - > getConfigValuePtr ( " misc:no_direct_scanout " ) - > intValue ;
static auto * const PVFR = & g_pConfigManager - > getConfigValuePtr ( " misc:vfr " ) - > intValue ;
2023-04-16 15:48:38 +02:00
static auto * const PZOOMFACTOR = & g_pConfigManager - > getConfigValuePtr ( " misc:cursor_zoom_factor " ) - > floatValue ;
2023-07-20 13:49:28 +02:00
static auto * const PRENDERTEX = & g_pConfigManager - > getConfigValuePtr ( " misc:disable_hyprland_logo " ) - > intValue ;
2023-08-08 18:00:11 +02:00
static auto * const PBACKGROUNDCOLOR = & g_pConfigManager - > getConfigValuePtr ( " misc:background_color " ) - > intValue ;
2023-07-22 19:26:39 +02:00
static auto * const PANIMENABLED = & g_pConfigManager - > getConfigValuePtr ( " animations:enabled " ) - > intValue ;
2023-09-28 22:48:33 +02:00
static auto * const PTEARINGENABLED = & g_pConfigManager - > getConfigValuePtr ( " general:allow_tearing " ) - > intValue ;
2023-03-24 20:23:16 +01:00
static int damageBlinkCleanup = 0 ; // because double-buffered
if ( ! * PDAMAGEBLINK )
damageBlinkCleanup = 0 ;
2023-05-24 15:49:27 +02:00
static bool firstLaunch = true ;
static bool firstLaunchAnimActive = true ;
2023-05-01 03:49:41 +02:00
float zoomInFactorFirstLaunch = 1.f ;
if ( firstLaunch ) {
firstLaunch = false ;
m_tRenderTimer . reset ( ) ;
}
2023-05-24 15:49:27 +02:00
if ( m_tRenderTimer . getSeconds ( ) < 1.5f & & firstLaunchAnimActive ) { // TODO: make the animation system more damage-flexible so that this can be migrated to there
2023-07-22 19:26:39 +02:00
if ( ! * PANIMENABLED ) {
zoomInFactorFirstLaunch = 1.f ;
firstLaunchAnimActive = false ;
} else {
zoomInFactorFirstLaunch = 2.f - g_pAnimationManager - > getBezier ( " default " ) - > getYForPoint ( m_tRenderTimer . getSeconds ( ) / 1.5 ) ;
damageMonitor ( pMonitor ) ;
}
2023-05-24 15:49:27 +02:00
} else {
firstLaunchAnimActive = false ;
2023-05-01 03:49:41 +02:00
}
2023-03-24 20:23:16 +01:00
startRender = std : : chrono : : high_resolution_clock : : now ( ) ;
if ( * PDEBUGOVERLAY = = 1 ) {
g_pDebugOverlay - > frameData ( pMonitor ) ;
}
if ( pMonitor - > framesToSkip > 0 ) {
pMonitor - > framesToSkip - = 1 ;
if ( ! pMonitor - > noFrameSchedule )
g_pCompositor - > scheduleFrameForMonitor ( pMonitor ) ;
else {
2023-09-06 21:45:37 +02:00
Debug : : log ( LOG , " NoFrameSchedule hit for {}. " , pMonitor - > szName ) ;
2023-03-24 20:23:16 +01:00
}
g_pLayoutManager - > getCurrentLayout ( ) - > recalculateMonitor ( pMonitor - > ID ) ;
if ( pMonitor - > framesToSkip > 10 )
pMonitor - > framesToSkip = 0 ;
return ;
}
// checks //
if ( pMonitor - > ID = = m_pMostHzMonitor - > ID | |
* PVFR = = 1 ) { // unfortunately with VFR we don't have the guarantee mostHz is going to be updated all the time, so we have to ignore that
g_pCompositor - > sanityCheckWorkspaces ( ) ;
g_pConfigManager - > dispatchExecOnce ( ) ; // We exec-once when at least one monitor starts refreshing, meaning stuff has init'd
if ( g_pConfigManager - > m_bWantsMonitorReload )
g_pConfigManager - > performMonitorReload ( ) ;
ensureCursorRenderingMode ( ) ; // so that the cursor gets hidden/shown if the user requested timeouts
}
// //
if ( pMonitor - > scheduledRecalc ) {
pMonitor - > scheduledRecalc = false ;
g_pLayoutManager - > getCurrentLayout ( ) - > recalculateMonitor ( pMonitor - > ID ) ;
}
2023-06-14 13:26:47 +02:00
// gamma stuff
if ( pMonitor - > gammaChanged ) {
pMonitor - > gammaChanged = false ;
const auto PGAMMACTRL = wlr_gamma_control_manager_v1_get_control ( g_pCompositor - > m_sWLRGammaCtrlMgr , pMonitor - > output ) ;
if ( ! wlr_gamma_control_v1_apply ( PGAMMACTRL , & pMonitor - > output - > pending ) ) {
2023-09-06 21:45:37 +02:00
Debug : : log ( ERR , " Could not apply gamma control to {} " , pMonitor - > szName ) ;
2023-06-14 13:26:47 +02:00
return ;
}
if ( ! wlr_output_test ( pMonitor - > output ) ) {
2023-09-06 21:45:37 +02:00
Debug : : log ( ERR , " Output test failed for setting gamma to {} " , pMonitor - > szName ) ;
2023-06-14 13:26:47 +02:00
wlr_output_rollback ( pMonitor - > output ) ;
wlr_gamma_control_v1_send_failed_and_destroy ( PGAMMACTRL ) ;
}
}
2023-09-28 22:48:33 +02:00
// tearing and DS first
bool shouldTear = false ;
2023-09-30 18:07:50 +02:00
if ( pMonitor - > tearingState . nextRenderTorn ) {
pMonitor - > tearingState . nextRenderTorn = false ;
2023-09-28 22:48:33 +02:00
if ( ! * PTEARINGENABLED ) {
Debug : : log ( WARN , " Tearing commit requested but the master switch general:allow_tearing is off, ignoring " ) ;
return ;
}
if ( g_pHyprOpenGL - > m_RenderData . mouseZoomFactor ! = 1.0 ) {
Debug : : log ( WARN , " Tearing commit requested but scale factor is not 1, ignoring " ) ;
return ;
}
2023-09-30 18:07:50 +02:00
if ( ! pMonitor - > tearingState . canTear ) {
2023-09-28 22:48:33 +02:00
Debug : : log ( WARN , " Tearing commit requested but monitor doesn't support it, ignoring " ) ;
return ;
}
if ( pMonitor - > solitaryClient )
shouldTear = true ;
}
if ( ! * PNODIRECTSCANOUT & & ! shouldTear ) {
2023-03-24 20:23:16 +01:00
if ( attemptDirectScanout ( pMonitor ) ) {
return ;
} else if ( m_pLastScanout ) {
Debug : : log ( LOG , " Left a direct scanout. " ) ;
m_pLastScanout = nullptr ;
}
}
2023-09-30 18:07:50 +02:00
if ( pMonitor - > tearingState . activelyTearing ! = shouldTear ) {
2023-09-30 17:55:41 +02:00
// change of state
2023-09-30 18:07:50 +02:00
pMonitor - > tearingState . activelyTearing = shouldTear ;
2023-09-30 17:55:41 +02:00
}
2023-09-30 14:06:25 +02:00
2023-03-24 20:23:16 +01:00
EMIT_HOOK_EVENT ( " preRender " , pMonitor ) ;
timespec now ;
clock_gettime ( CLOCK_MONOTONIC , & now ) ;
// check the damage
2023-07-19 20:09:49 +02:00
CRegion damage ;
bool hasChanged = pMonitor - > output - > needs_frame | | pixman_region32_not_empty ( & pMonitor - > damage . current ) ;
int bufferAge ;
2023-03-24 20:23:16 +01:00
2023-04-09 18:59:24 +02:00
if ( ! hasChanged & & * PDAMAGETRACKINGMODE ! = DAMAGE_TRACKING_NONE & & pMonitor - > forceFullFrames = = 0 & & damageBlinkCleanup = = 0 )
return ;
2023-03-24 20:23:16 +01:00
if ( * PDAMAGETRACKINGMODE = = - 1 ) {
Debug : : log ( CRIT , " Damage tracking mode -1 ???? " ) ;
return ;
}
2023-04-18 00:45:03 +02:00
EMIT_HOOK_EVENT ( " render " , RENDER_PRE ) ;
2023-04-03 18:01:05 +02:00
const bool UNLOCK_SC = g_pHyprRenderer - > m_bSoftwareCursorsLocked ;
if ( UNLOCK_SC )
wlr_output_lock_software_cursors ( pMonitor - > output , true ) ;
2023-04-07 13:18:40 +02:00
if ( ! wlr_output_attach_render ( pMonitor - > output , & bufferAge ) ) {
2023-09-06 21:45:37 +02:00
Debug : : log ( ERR , " Couldn't attach render to display {} ??? " , pMonitor - > szName ) ;
2023-04-04 01:46:52 +02:00
if ( UNLOCK_SC )
wlr_output_lock_software_cursors ( pMonitor - > output , false ) ;
2023-03-24 20:23:16 +01:00
return ;
}
2023-07-19 20:09:49 +02:00
wlr_damage_ring_get_buffer_damage ( & pMonitor - > damage , bufferAge , damage . pixman ( ) ) ;
2023-04-07 13:18:40 +02:00
2023-03-24 20:23:16 +01:00
pMonitor - > renderingActive = true ;
// we need to cleanup fading out when rendering the appropriate context
g_pCompositor - > cleanupFadingOut ( pMonitor - > ID ) ;
// if we have no tracking or full tracking, invalidate the entire monitor
if ( * PDAMAGETRACKINGMODE = = DAMAGE_TRACKING_NONE | | * PDAMAGETRACKINGMODE = = DAMAGE_TRACKING_MONITOR | | pMonitor - > forceFullFrames > 0 | | damageBlinkCleanup > 0 | |
pMonitor - > isMirror ( ) /* why??? */ ) {
2023-07-19 20:09:49 +02:00
damage = { 0 , 0 , ( int ) pMonitor - > vecTransformedSize . x * 10 , ( int ) pMonitor - > vecTransformedSize . y * 10 } ;
pMonitor - > lastFrameDamage = damage ;
2023-03-24 20:23:16 +01:00
} else {
2023-08-03 15:11:10 +02:00
static auto * const PBLURENABLED = & g_pConfigManager - > getConfigValuePtr ( " decoration:blur:enabled " ) - > intValue ;
2023-03-24 20:23:16 +01:00
// if we use blur we need to expand the damage for proper blurring
if ( * PBLURENABLED = = 1 ) {
// TODO: can this be optimized?
2023-08-03 15:11:10 +02:00
static auto * const PBLURSIZE = & g_pConfigManager - > getConfigValuePtr ( " decoration:blur:size " ) - > intValue ;
static auto * const PBLURPASSES = & g_pConfigManager - > getConfigValuePtr ( " decoration:blur:passes " ) - > intValue ;
2023-03-24 20:23:16 +01:00
const auto BLURRADIUS =
* PBLURPASSES > 10 ? pow ( 2 , 15 ) : std : : clamp ( * PBLURSIZE , ( int64_t ) 1 , ( int64_t ) 40 ) * pow ( 2 , * PBLURPASSES ) ; // is this 2^pass? I don't know but it works... I think.
// now, prep the damage, get the extended damage region
2023-07-19 20:09:49 +02:00
wlr_region_expand ( damage . pixman ( ) , damage . pixman ( ) , BLURRADIUS ) ; // expand for proper blurring
2023-03-24 20:23:16 +01:00
2023-07-19 20:09:49 +02:00
pMonitor - > lastFrameDamage = damage ;
2023-03-24 20:23:16 +01:00
2023-07-19 20:09:49 +02:00
wlr_region_expand ( damage . pixman ( ) , damage . pixman ( ) , BLURRADIUS ) ; // expand for proper blurring 2
2023-03-24 20:23:16 +01:00
} else {
2023-07-19 20:09:49 +02:00
pMonitor - > lastFrameDamage = damage ;
2023-03-24 20:23:16 +01:00
}
}
if ( pMonitor - > forceFullFrames > 0 ) {
pMonitor - > forceFullFrames - = 1 ;
if ( pMonitor - > forceFullFrames > 10 )
pMonitor - > forceFullFrames = 0 ;
}
// TODO: this is getting called with extents being 0,0,0,0 should it be?
// potentially can save on resources.
2023-07-20 17:47:49 +02:00
TRACY_GPU_ZONE ( " Render " ) ;
2023-03-24 20:23:16 +01:00
g_pHyprOpenGL - > begin ( pMonitor , & damage ) ;
2023-04-18 00:45:03 +02:00
EMIT_HOOK_EVENT ( " render " , RENDER_BEGIN ) ;
2023-09-29 18:51:07 +02:00
bool renderCursor = true ;
if ( ! pMonitor - > solitaryClient ) {
if ( pMonitor - > isMirror ( ) ) {
g_pHyprOpenGL - > blend ( false ) ;
g_pHyprOpenGL - > renderMirrored ( ) ;
g_pHyprOpenGL - > blend ( true ) ;
EMIT_HOOK_EVENT ( " render " , RENDER_POST_MIRROR ) ;
renderCursor = false ;
} else {
g_pHyprOpenGL - > blend ( false ) ;
if ( ! canSkipBackBufferClear ( pMonitor ) ) {
if ( * PRENDERTEX /* inverted cfg flag */ )
g_pHyprOpenGL - > clear ( CColor ( * PBACKGROUNDCOLOR ) ) ;
else
g_pHyprOpenGL - > clearWithTex ( ) ; // will apply the hypr "wallpaper"
}
g_pHyprOpenGL - > blend ( true ) ;
2023-03-24 20:23:16 +01:00
2023-09-29 18:51:07 +02:00
wlr_box renderBox = { 0 , 0 , ( int ) pMonitor - > vecPixelSize . x , ( int ) pMonitor - > vecPixelSize . y } ;
renderWorkspace ( pMonitor , g_pCompositor - > getWorkspaceByID ( pMonitor - > activeWorkspace ) , & now , renderBox ) ;
2023-04-12 13:41:23 +02:00
2023-09-29 18:51:07 +02:00
renderLockscreen ( pMonitor , & now ) ;
2023-03-24 20:23:16 +01:00
2023-09-29 18:51:07 +02:00
if ( pMonitor = = g_pCompositor - > m_pLastMonitor ) {
g_pHyprNotificationOverlay - > draw ( pMonitor ) ;
g_pHyprError - > draw ( ) ;
}
2023-03-24 20:23:16 +01:00
2023-09-29 18:51:07 +02:00
// for drawing the debug overlay
if ( pMonitor = = g_pCompositor - > m_vMonitors . front ( ) . get ( ) & & * PDEBUGOVERLAY = = 1 ) {
startRenderOverlay = std : : chrono : : high_resolution_clock : : now ( ) ;
g_pDebugOverlay - > draw ( ) ;
endRenderOverlay = std : : chrono : : high_resolution_clock : : now ( ) ;
}
2023-03-24 20:23:16 +01:00
2023-09-29 18:51:07 +02:00
if ( * PDAMAGEBLINK & & damageBlinkCleanup = = 0 ) {
wlr_box monrect = { 0 , 0 , pMonitor - > vecTransformedSize . x , pMonitor - > vecTransformedSize . y } ;
g_pHyprOpenGL - > renderRect ( & monrect , CColor ( 1.0 , 0.0 , 1.0 , 100.0 / 255.0 ) , 0 ) ;
damageBlinkCleanup = 1 ;
} else if ( * PDAMAGEBLINK ) {
damageBlinkCleanup + + ;
if ( damageBlinkCleanup > 3 )
damageBlinkCleanup = 0 ;
}
2023-03-24 20:23:16 +01:00
}
2023-09-29 18:51:07 +02:00
} else {
g_pHyprRenderer - > renderWindow ( pMonitor - > solitaryClient , pMonitor , & now , false , RENDER_PASS_MAIN /* solitary = no popups */ ) ;
}
2023-03-24 20:23:16 +01:00
2023-09-29 18:51:07 +02:00
renderCursor = renderCursor & & shouldRenderCursor ( ) ;
if ( renderCursor & & wlr_renderer_begin ( g_pCompositor - > m_sWLRRenderer , pMonitor - > vecPixelSize . x , pMonitor - > vecPixelSize . y ) ) {
TRACY_GPU_ZONE ( " RenderCursor " ) ;
bool lockSoftware = pMonitor = = g_pCompositor - > getMonitorFromCursor ( ) & & * PZOOMFACTOR ! = 1.f ;
if ( lockSoftware ) {
wlr_output_lock_software_cursors ( pMonitor - > output , true ) ;
wlr_output_render_software_cursors ( pMonitor - > output , NULL ) ;
wlr_output_lock_software_cursors ( pMonitor - > output , false ) ;
} else
wlr_output_render_software_cursors ( pMonitor - > output , NULL ) ;
wlr_renderer_end ( g_pCompositor - > m_sWLRRenderer ) ;
2023-03-24 20:23:16 +01:00
}
2023-04-16 15:48:38 +02:00
if ( pMonitor = = g_pCompositor - > getMonitorFromCursor ( ) )
g_pHyprOpenGL - > m_RenderData . mouseZoomFactor = std : : clamp ( * PZOOMFACTOR , 1.f , INFINITY ) ;
else
g_pHyprOpenGL - > m_RenderData . mouseZoomFactor = 1.f ;
2023-04-18 00:45:03 +02:00
2023-05-01 03:49:41 +02:00
if ( zoomInFactorFirstLaunch > 1.f ) {
g_pHyprOpenGL - > m_RenderData . mouseZoomFactor = zoomInFactorFirstLaunch ;
g_pHyprOpenGL - > m_RenderData . mouseZoomUseMouse = false ;
g_pHyprOpenGL - > m_RenderData . useNearestNeighbor = false ;
}
2023-04-18 00:45:03 +02:00
EMIT_HOOK_EVENT ( " render " , RENDER_LAST_MOMENT ) ;
2023-03-24 20:23:16 +01:00
g_pHyprOpenGL - > end ( ) ;
2023-07-20 17:47:49 +02:00
TRACY_GPU_COLLECT ;
2023-03-24 20:23:16 +01:00
// calc frame damage
2023-07-19 20:09:49 +02:00
CRegion frameDamage { } ;
2023-03-24 20:23:16 +01:00
const auto TRANSFORM = wlr_output_transform_invert ( pMonitor - > output - > transform ) ;
2023-07-19 20:09:49 +02:00
wlr_region_transform ( frameDamage . pixman ( ) , pMonitor - > lastFrameDamage . pixman ( ) , TRANSFORM , ( int ) pMonitor - > vecTransformedSize . x , ( int ) pMonitor - > vecTransformedSize . y ) ;
2023-03-24 20:23:16 +01:00
if ( * PDAMAGETRACKINGMODE = = DAMAGE_TRACKING_NONE | | * PDAMAGETRACKINGMODE = = DAMAGE_TRACKING_MONITOR )
2023-07-19 20:09:49 +02:00
frameDamage . add ( 0 , 0 , ( int ) pMonitor - > vecTransformedSize . x , ( int ) pMonitor - > vecTransformedSize . y ) ;
2023-03-24 20:23:16 +01:00
if ( * PDAMAGEBLINK )
2023-07-19 20:09:49 +02:00
frameDamage . add ( damage ) ;
2023-03-24 20:23:16 +01:00
if ( ! pMonitor - > mirrors . empty ( ) )
2023-07-19 20:09:49 +02:00
g_pHyprRenderer - > damageMirrorsWith ( pMonitor , frameDamage ) ;
2023-03-24 20:23:16 +01:00
pMonitor - > renderingActive = false ;
2023-04-18 00:45:03 +02:00
EMIT_HOOK_EVENT ( " render " , RENDER_POST ) ;
2023-09-28 22:48:33 +02:00
pMonitor - > output - > pending . tearing_page_flip = shouldTear ;
2023-04-03 18:01:05 +02:00
if ( ! wlr_output_commit ( pMonitor - > output ) ) {
2023-09-29 18:51:07 +02:00
2023-04-03 18:01:05 +02:00
if ( UNLOCK_SC )
wlr_output_lock_software_cursors ( pMonitor - > output , false ) ;
2023-03-24 20:23:16 +01:00
return ;
2023-04-03 18:01:05 +02:00
}
2023-09-28 22:48:33 +02:00
if ( shouldTear )
2023-09-30 18:07:50 +02:00
pMonitor - > tearingState . busy = true ;
2023-09-28 22:48:33 +02:00
2023-07-19 20:09:49 +02:00
wlr_damage_ring_rotate ( & pMonitor - > damage ) ;
2023-04-03 18:01:05 +02:00
if ( UNLOCK_SC )
wlr_output_lock_software_cursors ( pMonitor - > output , false ) ;
2023-03-24 20:23:16 +01:00
if ( * PDAMAGEBLINK | | * PVFR = = 0 | | pMonitor - > pendingFrame )
g_pCompositor - > scheduleFrameForMonitor ( pMonitor ) ;
pMonitor - > pendingFrame = false ;
const float µ s = std : : chrono : : duration_cast < std : : chrono : : nanoseconds > ( std : : chrono : : high_resolution_clock : : now ( ) - startRender ) . count ( ) / 1000.f ;
g_pDebugOverlay - > renderData ( pMonitor , µ s ) ;
if ( * PDEBUGOVERLAY = = 1 ) {
if ( pMonitor = = g_pCompositor - > m_vMonitors . front ( ) . get ( ) ) {
const float µ sNoOverlay = µ s - std : : chrono : : duration_cast < std : : chrono : : nanoseconds > ( endRenderOverlay - startRenderOverlay ) . count ( ) / 1000.f ;
g_pDebugOverlay - > renderDataNoOverlay ( pMonitor , µ sNoOverlay ) ;
} else {
g_pDebugOverlay - > renderDataNoOverlay ( pMonitor , µ s ) ;
}
}
}
2023-04-12 13:41:23 +02:00
void CHyprRenderer : : renderWorkspace ( CMonitor * pMonitor , CWorkspace * pWorkspace , timespec * now , const wlr_box & geometry ) {
Vector2D translate = { geometry . x , geometry . y } ;
float scale = ( float ) geometry . width / pMonitor - > vecPixelSize . x ;
2023-07-20 17:47:49 +02:00
TRACY_GPU_ZONE ( " RenderWorkspace " ) ;
2023-04-12 13:50:20 +02:00
if ( ! DELTALESSTHAN ( ( double ) geometry . width / ( double ) geometry . height , pMonitor - > vecPixelSize . x / pMonitor - > vecPixelSize . y , 0.01 ) ) {
2023-04-12 13:41:23 +02:00
Debug : : log ( ERR , " Ignoring geometry in renderWorkspace: aspect ratio mismatch " ) ;
scale = 1.f ;
translate = Vector2D { } ;
}
2023-04-18 00:47:12 +02:00
g_pHyprOpenGL - > m_RenderData . pWorkspace = pWorkspace ;
2023-04-12 14:05:57 +02:00
renderAllClientsForWorkspace ( pMonitor , pWorkspace , now , translate , scale ) ;
2023-04-18 00:47:12 +02:00
g_pHyprOpenGL - > m_RenderData . pWorkspace = nullptr ;
2023-04-12 13:41:23 +02:00
}
2022-11-05 13:50:47 +01:00
void CHyprRenderer : : setWindowScanoutMode ( CWindow * pWindow ) {
2023-02-03 12:58:55 +01:00
if ( ! g_pCompositor - > m_sWLRLinuxDMABuf | | g_pSessionLockManager - > isSessionLocked ( ) )
2022-11-05 13:50:47 +01:00
return ;
if ( ! pWindow - > m_bIsFullscreen ) {
2023-03-20 16:00:58 +01:00
wlr_linux_dmabuf_v1_set_surface_feedback ( g_pCompositor - > m_sWLRLinuxDMABuf , pWindow - > m_pWLSurface . wlr ( ) , nullptr ) ;
2023-09-20 17:25:03 +02:00
Debug : : log ( LOG , " Scanout mode OFF set for {} " , pWindow ) ;
2022-11-05 13:50:47 +01:00
return ;
}
2023-03-03 22:28:22 +01:00
const auto PMONITOR = g_pCompositor - > getMonitorFromID ( pWindow - > m_iMonitorID ) ;
2022-11-05 13:50:47 +01:00
2023-03-03 22:28:22 +01:00
const wlr_linux_dmabuf_feedback_v1_init_options INIT_OPTIONS = {
. main_renderer = g_pCompositor - > m_sWLRRenderer ,
. scanout_primary_output = PMONITOR - > output ,
2022-11-05 13:50:47 +01:00
} ;
2023-03-03 22:28:22 +01:00
wlr_linux_dmabuf_feedback_v1 feedback = { 0 } ;
2022-11-05 13:50:47 +01:00
2023-03-03 22:28:22 +01:00
if ( ! wlr_linux_dmabuf_feedback_v1_init_with_options ( & feedback , & INIT_OPTIONS ) )
2022-11-05 13:50:47 +01:00
return ;
2023-03-20 16:00:58 +01:00
wlr_linux_dmabuf_v1_set_surface_feedback ( g_pCompositor - > m_sWLRLinuxDMABuf , pWindow - > m_pWLSurface . wlr ( ) , & feedback ) ;
2023-03-03 22:28:22 +01:00
wlr_linux_dmabuf_feedback_v1_finish ( & feedback ) ;
2022-11-05 13:50:47 +01:00
2023-09-20 17:25:03 +02:00
Debug : : log ( LOG , " Scanout mode ON set for {} " , pWindow ) ;
2022-11-05 13:50:47 +01:00
}
2022-03-19 14:07:18 +01:00
void CHyprRenderer : : outputMgrApplyTest ( wlr_output_configuration_v1 * config , bool test ) {
wlr_output_configuration_head_v1 * head ;
2023-09-10 14:14:27 +02:00
bool ok = true ;
2022-03-19 14:07:18 +01:00
wl_list_for_each ( head , & config - > heads , link ) {
2022-05-06 17:18:24 +02:00
std : : string commandForCfg = " " ;
2022-12-16 18:17:31 +01:00
const auto OUTPUT = head - > state . output ;
2022-03-19 14:07:18 +01:00
2022-05-06 17:18:24 +02:00
commandForCfg + = std : : string ( OUTPUT - > name ) + " , " ;
if ( ! head - > state . enabled ) {
commandForCfg + = " disabled " ;
if ( ! test )
g_pConfigManager - > parseKeyword ( " monitor " , commandForCfg , true ) ;
continue ;
2022-03-19 14:07:18 +01:00
}
2022-05-06 17:18:24 +02:00
wlr_output_enable ( OUTPUT , head - > state . enabled ) ;
if ( head - > state . mode )
2022-12-16 18:17:31 +01:00
commandForCfg + =
std : : to_string ( head - > state . mode - > width ) + " x " + std : : to_string ( head - > state . mode - > height ) + " @ " + std : : to_string ( head - > state . mode - > refresh / 1000.f ) + " , " ;
2022-05-06 17:18:24 +02:00
else
2022-12-16 18:17:31 +01:00
commandForCfg + = std : : to_string ( head - > state . custom_mode . width ) + " x " + std : : to_string ( head - > state . custom_mode . height ) + " @ " +
std : : to_string ( head - > state . custom_mode . refresh / 1000.f ) + " , " ;
2022-05-06 17:18:24 +02:00
2023-09-10 14:14:27 +02:00
commandForCfg + = std : : to_string ( head - > state . x ) + " x " + std : : to_string ( head - > state . y ) + " , " + std : : to_string ( head - > state . scale ) + " ,transform, " +
std : : to_string ( ( int ) head - > state . transform ) ;
2022-05-06 17:18:24 +02:00
2022-11-03 10:06:44 +01:00
if ( ! test ) {
2022-05-06 17:18:24 +02:00
g_pConfigManager - > parseKeyword ( " monitor " , commandForCfg , true ) ;
2023-09-10 14:14:27 +02:00
wlr_output_state_set_adaptive_sync_enabled ( & OUTPUT - > pending , head - > state . adaptive_sync_enabled ) ;
2022-11-03 10:06:44 +01:00
}
2022-05-06 17:18:24 +02:00
2023-09-10 14:14:27 +02:00
ok = wlr_output_test ( OUTPUT ) ;
2022-03-19 14:07:18 +01:00
2023-09-10 14:14:27 +02:00
if ( ! ok )
2022-03-19 14:07:18 +01:00
break ;
}
2022-05-06 17:18:24 +02:00
if ( ! test )
2022-12-16 18:17:31 +01:00
g_pConfigManager - > m_bWantsMonitorReload = true ; // for monitor keywords
2022-03-19 14:07:18 +01:00
2023-09-10 14:14:27 +02:00
if ( ok )
2022-03-19 14:07:18 +01:00
wlr_output_configuration_v1_send_succeeded ( config ) ;
else
wlr_output_configuration_v1_send_failed ( config ) ;
wlr_output_configuration_v1_destroy ( config ) ;
Debug : : log ( LOG , " OutputMgr Applied/Tested. " ) ;
2022-03-19 14:37:40 +01:00
}
2022-03-21 17:00:17 +01:00
// taken from Sway.
// this is just too much of a spaghetti for me to understand
void apply_exclusive ( struct wlr_box * usable_area , uint32_t anchor , int32_t exclusive , int32_t margin_top , int32_t margin_right , int32_t margin_bottom , int32_t margin_left ) {
if ( exclusive < = 0 ) {
return ;
}
struct {
uint32_t singular_anchor ;
uint32_t anchor_triplet ;
2022-12-16 18:17:31 +01:00
int * positive_axis ;
int * negative_axis ;
int margin ;
2022-03-21 17:00:17 +01:00
} edges [ ] = {
// Top
{
. singular_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP ,
2022-12-16 18:17:31 +01:00
. anchor_triplet = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP ,
. positive_axis = & usable_area - > y ,
. negative_axis = & usable_area - > height ,
. margin = margin_top ,
2022-03-21 17:00:17 +01:00
} ,
// Bottom
{
. singular_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM ,
2022-12-16 18:17:31 +01:00
. anchor_triplet = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM ,
. positive_axis = NULL ,
. negative_axis = & usable_area - > height ,
. margin = margin_bottom ,
2022-03-21 17:00:17 +01:00
} ,
// Left
{
. singular_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT ,
2022-12-16 18:17:31 +01:00
. anchor_triplet = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM ,
. positive_axis = & usable_area - > x ,
. negative_axis = & usable_area - > width ,
. margin = margin_left ,
2022-03-21 17:00:17 +01:00
} ,
// Right
{
. singular_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT ,
2022-12-16 18:17:31 +01:00
. anchor_triplet = ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM ,
. positive_axis = NULL ,
. negative_axis = & usable_area - > width ,
. margin = margin_right ,
2022-03-21 17:00:17 +01:00
} ,
} ;
for ( size_t i = 0 ; i < sizeof ( edges ) / sizeof ( edges [ 0 ] ) ; + + i ) {
if ( ( anchor = = edges [ i ] . singular_anchor | | anchor = = edges [ i ] . anchor_triplet ) & & exclusive + edges [ i ] . margin > 0 ) {
if ( edges [ i ] . positive_axis ) {
* edges [ i ] . positive_axis + = exclusive + edges [ i ] . margin ;
}
if ( edges [ i ] . negative_axis ) {
* edges [ i ] . negative_axis - = exclusive + edges [ i ] . margin ;
}
break ;
}
}
}
2022-03-19 14:37:40 +01:00
2022-07-27 12:32:00 +02:00
void CHyprRenderer : : arrangeLayerArray ( CMonitor * pMonitor , const std : : vector < std : : unique_ptr < SLayerSurface > > & layerSurfaces , bool exclusiveZone , wlr_box * usableArea ) {
2022-03-21 17:00:17 +01:00
wlr_box full_area = { pMonitor - > vecPosition . x , pMonitor - > vecPosition . y , pMonitor - > vecSize . x , pMonitor - > vecSize . y } ;
2022-03-19 14:37:40 +01:00
2022-03-21 17:00:17 +01:00
for ( auto & ls : layerSurfaces ) {
2022-07-18 21:16:01 +02:00
if ( ls - > fadingOut | | ls - > readyToDelete | | ! ls - > layerSurface | | ls - > noProcess )
2022-05-14 17:23:46 +02:00
continue ;
2022-03-21 17:00:17 +01:00
const auto PLAYER = ls - > layerSurface ;
const auto PSTATE = & PLAYER - > current ;
2023-10-06 15:00:05 +02:00
if ( exclusiveZone ! = ( PSTATE - > exclusive_zone > 0 ) )
2022-03-21 17:00:17 +01:00
continue ;
2022-03-19 14:37:40 +01:00
2022-03-21 17:00:17 +01:00
wlr_box bounds ;
2023-10-06 15:00:05 +02:00
if ( PSTATE - > exclusive_zone = = - 1 )
2022-03-21 17:00:17 +01:00
bounds = full_area ;
2023-10-06 15:00:05 +02:00
else
2022-03-21 17:00:17 +01:00
bounds = * usableArea ;
2022-03-19 14:37:40 +01:00
2023-10-06 15:00:05 +02:00
const Vector2D OLDSIZE = { ls - > geometry . width , ls - > geometry . height } ;
wlr_box box = { . width = PSTATE - > desired_width , . height = PSTATE - > desired_height } ;
2022-03-21 17:00:17 +01:00
// Horizontal axis
const uint32_t both_horiz = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT ;
if ( box . width = = 0 ) {
box . x = bounds . x ;
} else if ( ( PSTATE - > anchor & both_horiz ) = = both_horiz ) {
box . x = bounds . x + ( ( bounds . width / 2 ) - ( box . width / 2 ) ) ;
} else if ( ( PSTATE - > anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT ) ) {
box . x = bounds . x ;
} else if ( ( PSTATE - > anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT ) ) {
box . x = bounds . x + ( bounds . width - box . width ) ;
} else {
box . x = bounds . x + ( ( bounds . width / 2 ) - ( box . width / 2 ) ) ;
2022-03-19 14:37:40 +01:00
}
2022-03-21 17:00:17 +01:00
// Vertical axis
const uint32_t both_vert = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM ;
if ( box . height = = 0 ) {
box . y = bounds . y ;
} else if ( ( PSTATE - > anchor & both_vert ) = = both_vert ) {
box . y = bounds . y + ( ( bounds . height / 2 ) - ( box . height / 2 ) ) ;
} else if ( ( PSTATE - > anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP ) ) {
box . y = bounds . y ;
} else if ( ( PSTATE - > anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM ) ) {
box . y = bounds . y + ( bounds . height - box . height ) ;
} else {
box . y = bounds . y + ( ( bounds . height / 2 ) - ( box . height / 2 ) ) ;
2022-03-19 14:37:40 +01:00
}
2022-03-21 17:00:17 +01:00
// Margin
if ( box . width = = 0 ) {
box . x + = PSTATE - > margin . left ;
2022-12-16 18:17:31 +01:00
box . width = bounds . width - ( PSTATE - > margin . left + PSTATE - > margin . right ) ;
2022-03-21 17:00:17 +01:00
} else if ( ( PSTATE - > anchor & both_horiz ) = = both_horiz ) {
// don't apply margins
} else if ( ( PSTATE - > anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT ) ) {
box . x + = PSTATE - > margin . left ;
} else if ( ( PSTATE - > anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT ) ) {
box . x - = PSTATE - > margin . right ;
}
if ( box . height = = 0 ) {
box . y + = PSTATE - > margin . top ;
2022-12-16 18:17:31 +01:00
box . height = bounds . height - ( PSTATE - > margin . top + PSTATE - > margin . bottom ) ;
2022-03-21 17:00:17 +01:00
} else if ( ( PSTATE - > anchor & both_vert ) = = both_vert ) {
// don't apply margins
} else if ( ( PSTATE - > anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP ) ) {
box . y + = PSTATE - > margin . top ;
} else if ( ( PSTATE - > anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM ) ) {
box . y - = PSTATE - > margin . bottom ;
}
if ( box . width < = 0 | | box . height < = 0 ) {
2023-09-06 12:51:36 +02:00
Debug : : log ( ERR , " LayerSurface {:x} has a negative/zero w/h??? " , ( uintptr_t ) ls . get ( ) ) ;
2022-03-21 17:00:17 +01:00
continue ;
2022-03-20 14:52:23 +01:00
}
2022-03-21 17:00:17 +01:00
// Apply
ls - > geometry = box ;
2022-03-20 14:52:23 +01:00
2022-03-21 17:00:17 +01:00
apply_exclusive ( usableArea , PSTATE - > anchor , PSTATE - > exclusive_zone , PSTATE - > margin . top , PSTATE - > margin . right , PSTATE - > margin . bottom , PSTATE - > margin . left ) ;
2022-03-19 14:37:40 +01:00
2023-10-06 15:00:05 +02:00
if ( Vector2D { box . width , box . height } ! = OLDSIZE )
wlr_layer_surface_v1_configure ( ls - > layerSurface , box . width , box . height ) ;
2022-03-19 14:37:40 +01:00
2023-09-06 12:51:36 +02:00
Debug : : log ( LOG , " LayerSurface {:x} arranged: x: {} y: {} w: {} h: {} with margins: t: {} l: {} r: {} b: {} " , ( uintptr_t ) & ls , box . x , box . y , box . width , box . height ,
PSTATE - > margin . top , PSTATE - > margin . left , PSTATE - > margin . right , PSTATE - > margin . bottom ) ;
2022-03-19 14:37:40 +01:00
}
}
void CHyprRenderer : : arrangeLayersForMonitor ( const int & monitor ) {
const auto PMONITOR = g_pCompositor - > getMonitorFromID ( monitor ) ;
if ( ! PMONITOR )
return ;
// Reset the reserved
2022-12-16 18:17:31 +01:00
PMONITOR - > vecReservedBottomRight = Vector2D ( ) ;
PMONITOR - > vecReservedTopLeft = Vector2D ( ) ;
2022-03-19 14:37:40 +01:00
2022-03-21 17:00:17 +01:00
wlr_box usableArea = { PMONITOR - > vecPosition . x , PMONITOR - > vecPosition . y , PMONITOR - > vecSize . x , PMONITOR - > vecSize . y } ;
2023-01-22 17:03:25 +01:00
for ( auto & la : PMONITOR - > m_aLayerSurfaceLayers )
2022-03-21 17:00:17 +01:00
arrangeLayerArray ( PMONITOR , la , true , & usableArea ) ;
2023-01-22 17:03:25 +01:00
for ( auto & la : PMONITOR - > m_aLayerSurfaceLayers )
2022-03-21 17:00:17 +01:00
arrangeLayerArray ( PMONITOR , la , false , & usableArea ) ;
2022-12-16 18:17:31 +01:00
PMONITOR - > vecReservedTopLeft = Vector2D ( usableArea . x , usableArea . y ) - PMONITOR - > vecPosition ;
2022-03-21 17:00:17 +01:00
PMONITOR - > vecReservedBottomRight = PMONITOR - > vecSize - Vector2D ( usableArea . width , usableArea . height ) - PMONITOR - > vecReservedTopLeft ;
2022-10-18 00:23:01 +02:00
auto ADDITIONALRESERVED = g_pConfigManager - > m_mAdditionalReservedAreas . find ( PMONITOR - > szName ) ;
if ( ADDITIONALRESERVED = = g_pConfigManager - > m_mAdditionalReservedAreas . end ( ) ) {
2022-12-16 18:17:31 +01:00
ADDITIONALRESERVED = g_pConfigManager - > m_mAdditionalReservedAreas . find ( " " ) ; // glob wildcard
2022-10-18 00:23:01 +02:00
}
if ( ADDITIONALRESERVED ! = g_pConfigManager - > m_mAdditionalReservedAreas . end ( ) ) {
2022-12-16 18:17:31 +01:00
PMONITOR - > vecReservedTopLeft = PMONITOR - > vecReservedTopLeft + Vector2D ( ADDITIONALRESERVED - > second . left , ADDITIONALRESERVED - > second . top ) ;
2022-10-18 00:23:01 +02:00
PMONITOR - > vecReservedBottomRight = PMONITOR - > vecReservedBottomRight + Vector2D ( ADDITIONALRESERVED - > second . right , ADDITIONALRESERVED - > second . bottom ) ;
}
2022-04-27 17:46:07 +02:00
2022-05-04 15:23:30 +02:00
// damage the monitor if can
2023-04-07 13:18:40 +02:00
damageMonitor ( PMONITOR ) ;
2022-05-04 15:23:30 +02:00
2022-09-08 14:11:32 +02:00
g_pLayoutManager - > getCurrentLayout ( ) - > recalculateMonitor ( monitor ) ;
2023-09-20 17:25:03 +02:00
Debug : : log ( LOG , " Monitor {} layers arranged: reserved: {:5j} {:5j} " , PMONITOR - > szName , PMONITOR - > vecReservedTopLeft , PMONITOR - > vecReservedBottomRight ) ;
2022-03-19 16:13:19 +01:00
}
2023-06-11 21:52:13 +02:00
void CHyprRenderer : : damageSurface ( wlr_surface * pSurface , double x , double y , double scale ) {
2022-04-14 16:43:29 +02:00
if ( ! pSurface )
return ; // wut?
2022-03-21 16:13:43 +01:00
2022-08-10 23:14:53 +02:00
if ( g_pCompositor - > m_bUnsafeState )
return ;
2023-10-20 21:15:41 +02:00
auto * const PSURFACE = CWLSurface : : surfaceFromWlr ( pSurface ) ;
if ( PSURFACE & & PSURFACE - > m_pOwner & & PSURFACE - > small ( ) ) {
const auto CORRECTION = PSURFACE - > correctSmallVec ( ) ;
x + = CORRECTION . x ;
y + = CORRECTION . y ;
}
2023-07-19 20:09:49 +02:00
CRegion damageBox ;
wlr_surface_get_effective_damage ( pSurface , damageBox . pixman ( ) ) ;
2023-06-11 21:52:13 +02:00
if ( scale ! = 1.0 )
2023-07-19 20:09:49 +02:00
wlr_region_scale ( damageBox . pixman ( ) , damageBox . pixman ( ) , scale ) ;
2022-03-21 16:13:43 +01:00
2022-07-04 17:55:33 +02:00
// schedule frame events
if ( ! wl_list_empty ( & pSurface - > current . frame_callback_list ) ) {
2022-07-13 18:18:23 +02:00
g_pCompositor - > scheduleFrameForMonitor ( g_pCompositor - > getMonitorFromVector ( Vector2D ( x , y ) ) ) ;
2022-07-04 17:55:33 +02:00
}
2023-07-19 20:09:49 +02:00
if ( damageBox . empty ( ) )
2022-06-28 15:30:46 +02:00
return ;
2023-07-19 20:09:49 +02:00
CRegion damageBoxForEach ;
2022-07-28 22:15:56 +02:00
2022-06-30 15:44:26 +02:00
for ( auto & m : g_pCompositor - > m_vMonitors ) {
2023-03-16 17:32:03 +01:00
if ( ! m - > output )
continue ;
2022-04-14 16:43:29 +02:00
double lx = 0 , ly = 0 ;
2022-06-30 15:44:26 +02:00
wlr_output_layout_output_coords ( g_pCompositor - > m_sWLROutputLayout , m - > output , & lx , & ly ) ;
2022-07-28 22:15:56 +02:00
2023-07-19 20:09:49 +02:00
damageBoxForEach = damageBox ;
damageBoxForEach . translate ( { x - m - > vecPosition . x , y - m - > vecPosition . y } ) ;
wlr_region_scale ( damageBoxForEach . pixman ( ) , damageBoxForEach . pixman ( ) , m - > scale ) ;
damageBoxForEach . translate ( { lx + m - > vecPosition . x , ly + m - > vecPosition . y } ) ;
2022-07-28 22:15:56 +02:00
2022-08-23 16:07:47 +02:00
m - > addDamage ( & damageBoxForEach ) ;
2022-03-21 16:13:43 +01:00
}
2022-12-16 18:17:31 +01:00
static auto * const PLOGDAMAGE = & g_pConfigManager - > getConfigValuePtr ( " debug:log_damage " ) - > intValue ;
2022-06-07 20:41:40 +02:00
if ( * PLOGDAMAGE )
2023-09-06 12:51:36 +02:00
Debug : : log ( LOG , " Damage: Surface (extents): xy: {}, {} wh: {}, {} " , damageBox . pixman ( ) - > extents . x1 , damageBox . pixman ( ) - > extents . y1 ,
2023-07-19 20:09:49 +02:00
damageBox . pixman ( ) - > extents . x2 - damageBox . pixman ( ) - > extents . x1 , damageBox . pixman ( ) - > extents . y2 - damageBox . pixman ( ) - > extents . y1 ) ;
2022-04-14 16:43:29 +02:00
}
2022-03-21 16:13:43 +01:00
2022-04-14 16:43:29 +02:00
void CHyprRenderer : : damageWindow ( CWindow * pWindow ) {
2022-08-10 23:14:53 +02:00
if ( g_pCompositor - > m_bUnsafeState )
return ;
2022-06-29 11:21:42 +02:00
wlr_box damageBox = pWindow - > getFullWindowBoundingBox ( ) ;
2022-06-30 15:44:26 +02:00
for ( auto & m : g_pCompositor - > m_vMonitors ) {
wlr_box fixedDamageBox = { damageBox . x - m - > vecPosition . x , damageBox . y - m - > vecPosition . y , damageBox . width , damageBox . height } ;
scaleBox ( & fixedDamageBox , m - > scale ) ;
2022-08-23 16:07:47 +02:00
m - > addDamage ( & fixedDamageBox ) ;
2022-06-29 11:21:42 +02:00
}
2022-05-05 15:09:26 +02:00
2023-06-27 13:23:53 +02:00
for ( auto & wd : pWindow - > m_dWindowDecorations )
wd - > damageEntire ( ) ;
2022-12-16 18:17:31 +01:00
static auto * const PLOGDAMAGE = & g_pConfigManager - > getConfigValuePtr ( " debug:log_damage " ) - > intValue ;
2022-06-07 20:41:40 +02:00
2022-06-29 11:21:42 +02:00
if ( * PLOGDAMAGE )
2023-09-06 21:45:37 +02:00
Debug : : log ( LOG , " Damage: Window ({}): xy: {}, {} wh: {}, {} " , pWindow - > m_szTitle , damageBox . x , damageBox . y , damageBox . width , damageBox . height ) ;
2022-03-21 16:13:43 +01:00
}
2022-07-27 12:32:00 +02:00
void CHyprRenderer : : damageMonitor ( CMonitor * pMonitor ) {
2022-09-13 15:25:42 +02:00
if ( g_pCompositor - > m_bUnsafeState | | pMonitor - > isMirror ( ) )
2022-08-10 23:14:53 +02:00
return ;
2022-12-16 18:17:31 +01:00
wlr_box damageBox = { 0 , 0 , INT16_MAX , INT16_MAX } ;
2022-08-23 16:07:47 +02:00
pMonitor - > addDamage ( & damageBox ) ;
2022-05-05 15:09:26 +02:00
2022-12-16 18:17:31 +01:00
static auto * const PLOGDAMAGE = & g_pConfigManager - > getConfigValuePtr ( " debug:log_damage " ) - > intValue ;
2022-06-07 20:41:40 +02:00
if ( * PLOGDAMAGE )
2023-09-06 21:45:37 +02:00
Debug : : log ( LOG , " Damage: Monitor {} " , pMonitor - > szName ) ;
2022-04-14 16:43:29 +02:00
}
2022-03-21 16:13:43 +01:00
2022-04-14 16:43:29 +02:00
void CHyprRenderer : : damageBox ( wlr_box * pBox ) {
2022-08-10 23:14:53 +02:00
if ( g_pCompositor - > m_bUnsafeState )
return ;
2022-06-30 15:44:26 +02:00
for ( auto & m : g_pCompositor - > m_vMonitors ) {
2022-09-13 15:25:42 +02:00
if ( m - > isMirror ( ) )
continue ; // don't damage mirrors traditionally
2022-06-30 15:44:26 +02:00
wlr_box damageBox = { pBox - > x - m - > vecPosition . x , pBox - > y - m - > vecPosition . y , pBox - > width , pBox - > height } ;
scaleBox ( & damageBox , m - > scale ) ;
2022-08-23 16:07:47 +02:00
m - > addDamage ( & damageBox ) ;
2022-04-17 18:47:10 +02:00
}
2022-05-05 15:09:26 +02:00
2022-12-16 18:17:31 +01:00
static auto * const PLOGDAMAGE = & g_pConfigManager - > getConfigValuePtr ( " debug:log_damage " ) - > intValue ;
2022-06-07 20:41:40 +02:00
if ( * PLOGDAMAGE )
2023-09-06 12:51:36 +02:00
Debug : : log ( LOG , " Damage: Box: xy: {}, {} wh: {}, {} " , pBox - > x , pBox - > y , pBox - > width , pBox - > height ) ;
2022-03-31 17:25:23 +02:00
}
2022-05-05 14:02:30 +02:00
void CHyprRenderer : : damageBox ( const int & x , const int & y , const int & w , const int & h ) {
wlr_box box = { x , y , w , h } ;
damageBox ( & box ) ;
}
2023-07-19 20:09:49 +02:00
void CHyprRenderer : : damageRegion ( const CRegion & rg ) {
for ( auto & RECT : rg . getRects ( ) ) {
2022-07-16 12:44:45 +02:00
damageBox ( RECT . x1 , RECT . y1 , RECT . x2 - RECT . x1 , RECT . y2 - RECT . y1 ) ;
}
}
2023-07-19 20:09:49 +02:00
void CHyprRenderer : : damageMirrorsWith ( CMonitor * pMonitor , const CRegion & pRegion ) {
2022-09-13 15:25:42 +02:00
for ( auto & mirror : pMonitor - > mirrors ) {
2023-07-19 20:09:49 +02:00
Vector2D scale = { mirror - > vecSize . x / pMonitor - > vecSize . x , mirror - > vecSize . y / pMonitor - > vecSize . y } ;
2022-09-13 15:25:42 +02:00
2023-07-19 20:09:49 +02:00
CRegion rg { pRegion } ;
wlr_region_scale_xy ( rg . pixman ( ) , rg . pixman ( ) , scale . x , scale . y ) ;
2022-09-13 15:25:42 +02:00
pMonitor - > addDamage ( & rg ) ;
2023-03-04 01:48:02 +01:00
g_pCompositor - > scheduleFrameForMonitor ( mirror ) ;
2022-09-13 15:25:42 +02:00
}
}
2022-07-27 12:32:00 +02:00
void CHyprRenderer : : renderDragIcon ( CMonitor * pMonitor , timespec * time ) {
2022-03-31 17:25:23 +02:00
if ( ! ( g_pInputManager - > m_sDrag . dragIcon & & g_pInputManager - > m_sDrag . iconMapped & & g_pInputManager - > m_sDrag . dragIcon - > surface ) )
return ;
2023-01-20 19:44:30 +01:00
SRenderData renderdata = { pMonitor , time , g_pInputManager - > m_sDrag . pos . x , g_pInputManager - > m_sDrag . pos . y } ;
2022-12-16 18:17:31 +01:00
renderdata . surface = g_pInputManager - > m_sDrag . dragIcon - > surface ;
renderdata . w = g_pInputManager - > m_sDrag . dragIcon - > surface - > current . width ;
renderdata . h = g_pInputManager - > m_sDrag . dragIcon - > surface - > current . height ;
2022-03-31 17:25:23 +02:00
wlr_surface_for_each_surface ( g_pInputManager - > m_sDrag . dragIcon - > surface , renderSurface , & renderdata ) ;
2022-06-29 14:15:08 +02:00
2022-12-16 18:17:31 +01:00
wlr_box box = { g_pInputManager - > m_sDrag . pos . x - 2 , g_pInputManager - > m_sDrag . pos . y - 2 , g_pInputManager - > m_sDrag . dragIcon - > surface - > current . width + 4 ,
g_pInputManager - > m_sDrag . dragIcon - > surface - > current . height + 4 } ;
2022-06-29 14:15:08 +02:00
g_pHyprRenderer - > damageBox ( & box ) ;
2022-04-14 16:43:29 +02:00
}
DAMAGETRACKINGMODES CHyprRenderer : : damageTrackingModeFromStr ( const std : : string & mode ) {
if ( mode = = " full " )
return DAMAGE_TRACKING_FULL ;
if ( mode = = " monitor " )
return DAMAGE_TRACKING_MONITOR ;
if ( mode = = " none " )
return DAMAGE_TRACKING_NONE ;
return DAMAGE_TRACKING_INVALID ;
2022-04-19 19:01:23 +02:00
}
2022-07-27 12:32:00 +02:00
bool CHyprRenderer : : applyMonitorRule ( CMonitor * pMonitor , SMonitorRule * pMonitorRule , bool force ) {
2022-04-19 19:01:23 +02:00
2023-09-06 21:45:37 +02:00
Debug : : log ( LOG , " Applying monitor rule for {} " , pMonitor - > szName ) ;
2022-04-21 18:11:28 +02:00
2023-08-11 17:37:52 +02:00
pMonitor - > activeMonitorRule = * pMonitorRule ;
2022-06-30 23:50:57 +02:00
// if it's disabled, disable and ignore
if ( pMonitorRule - > disabled ) {
2022-07-27 12:32:00 +02:00
if ( pMonitor - > m_bEnabled )
pMonitor - > onDisconnect ( ) ;
2022-08-03 17:32:12 +02:00
return true ;
2022-06-30 23:50:57 +02:00
}
2023-02-15 15:50:51 +01:00
// don't touch VR headsets
if ( pMonitor - > output - > non_desktop )
return true ;
2022-07-27 12:32:00 +02:00
if ( ! pMonitor - > m_bEnabled ) {
pMonitor - > onConnect ( true ) ; // enable it.
2023-09-06 21:45:37 +02:00
Debug : : log ( LOG , " Monitor {} is disabled but is requested to be enabled " , pMonitor - > szName ) ;
2022-07-27 12:32:00 +02:00
force = true ;
}
2022-04-19 19:01:23 +02:00
// Check if the rule isn't already applied
2023-08-11 17:37:52 +02:00
// TODO: clean this up lol
2022-12-16 18:17:31 +01:00
if ( ! force & & DELTALESSTHAN ( pMonitor - > vecPixelSize . x , pMonitorRule - > resolution . x , 1 ) & & DELTALESSTHAN ( pMonitor - > vecPixelSize . y , pMonitorRule - > resolution . y , 1 ) & &
DELTALESSTHAN ( pMonitor - > refreshRate , pMonitorRule - > refreshRate , 1 ) & & pMonitor - > scale = = pMonitorRule - > scale & &
( ( DELTALESSTHAN ( pMonitor - > vecPosition . x , pMonitorRule - > offset . x , 1 ) & & DELTALESSTHAN ( pMonitor - > vecPosition . y , pMonitorRule - > offset . y , 1 ) ) | |
2023-08-16 18:16:36 +02:00
pMonitorRule - > offset = = Vector2D ( - INT32_MAX , - INT32_MAX ) ) & &
2023-05-09 15:01:45 +02:00
pMonitor - > transform = = pMonitorRule - > transform & & pMonitorRule - > enable10bit = = pMonitor - > enabled10bit & &
! memcmp ( & pMonitor - > customDrmMode , & pMonitorRule - > drmMode , sizeof ( pMonitor - > customDrmMode ) ) ) {
2022-08-04 11:10:26 +02:00
2023-09-06 21:45:37 +02:00
Debug : : log ( LOG , " Not applying a new rule to {} because it's already applied! " , pMonitor - > szName ) ;
2022-06-30 23:55:28 +02:00
return true ;
2022-04-19 19:01:23 +02:00
}
2023-05-09 15:01:45 +02:00
// Needed in case we are switching from a custom modeline to a standard mode
pMonitor - > customDrmMode = { } ;
2023-01-20 16:03:52 +01:00
if ( pMonitorRule - > scale > 0.1 ) {
2022-12-14 18:57:18 +01:00
wlr_output_set_scale ( pMonitor - > output , pMonitorRule - > scale ) ;
pMonitor - > scale = pMonitorRule - > scale ;
} else {
const auto DEFAULTSCALE = pMonitor - > getDefaultScale ( ) ;
wlr_output_set_scale ( pMonitor - > output , DEFAULTSCALE ) ;
pMonitor - > scale = DEFAULTSCALE ;
}
2022-04-19 19:01:23 +02:00
2022-11-18 15:15:19 +01:00
wlr_output_set_transform ( pMonitor - > output , pMonitorRule - > transform ) ;
pMonitor - > transform = pMonitorRule - > transform ;
2023-07-19 00:26:04 +02:00
const auto WLRREFRESHRATE = ( wlr_backend_is_wl ( pMonitor - > output - > backend ) | | wlr_backend_is_x11 ( pMonitor - > output - > backend ) ) ? 0 : pMonitorRule - > refreshRate * 1000 ;
2022-04-19 19:01:23 +02:00
// loop over modes and choose an appropriate one.
2022-12-16 18:17:31 +01:00
if ( pMonitorRule - > resolution ! = Vector2D ( ) & & pMonitorRule - > resolution ! = Vector2D ( - 1 , - 1 ) & & pMonitorRule - > resolution ! = Vector2D ( - 1 , - 2 ) ) {
2023-05-09 15:01:45 +02:00
if ( ! wl_list_empty ( & pMonitor - > output - > modes ) & & pMonitorRule - > drmMode . type ! = DRM_MODE_TYPE_USERDEF ) {
2022-07-30 22:54:29 +02:00
wlr_output_mode * mode ;
2022-12-16 18:17:31 +01:00
bool found = false ;
2022-07-30 22:54:29 +02:00
wl_list_for_each ( mode , & pMonitor - > output - > modes , link ) {
// if delta of refresh rate, w and h chosen and mode is < 1 we accept it
2022-12-16 18:17:31 +01:00
if ( DELTALESSTHAN ( mode - > width , pMonitorRule - > resolution . x , 1 ) & & DELTALESSTHAN ( mode - > height , pMonitorRule - > resolution . y , 1 ) & &
DELTALESSTHAN ( mode - > refresh / 1000.f , pMonitorRule - > refreshRate , 1 ) ) {
2022-07-30 22:54:29 +02:00
wlr_output_set_mode ( pMonitor - > output , mode ) ;
if ( ! wlr_output_test ( pMonitor - > output ) ) {
2023-09-20 17:25:03 +02:00
Debug : : log ( LOG , " Monitor {}: REJECTED available mode: {}x{}@{:2f}! " , pMonitor - > output - > name , mode - > width , mode - > height , mode - > refresh / 1000.f ) ;
2022-07-30 22:54:29 +02:00
continue ;
}
2023-09-20 17:25:03 +02:00
Debug : : log ( LOG , " Monitor {}: requested {:X0}@{:2f}, found available mode: {}x{}@{}mHz, applying. " , pMonitor - > output - > name , pMonitorRule - > resolution ,
( float ) pMonitorRule - > refreshRate , mode - > width , mode - > height , mode - > refresh ) ;
2022-04-19 19:01:23 +02:00
2022-07-30 22:54:29 +02:00
found = true ;
2022-04-19 19:01:23 +02:00
2022-07-30 22:54:29 +02:00
pMonitor - > refreshRate = mode - > refresh / 1000.f ;
2022-12-16 18:17:31 +01:00
pMonitor - > vecSize = Vector2D ( mode - > width , mode - > height ) ;
2022-04-19 19:01:23 +02:00
2022-07-30 22:54:29 +02:00
break ;
}
2022-04-19 19:01:23 +02:00
}
2022-07-30 22:54:29 +02:00
if ( ! found ) {
2023-07-19 00:26:04 +02:00
wlr_output_set_custom_mode ( pMonitor - > output , ( int ) pMonitorRule - > resolution . x , ( int ) pMonitorRule - > resolution . y , WLRREFRESHRATE ) ;
2022-12-16 18:17:31 +01:00
pMonitor - > vecSize = pMonitorRule - > resolution ;
2022-09-24 14:10:11 +02:00
pMonitor - > refreshRate = pMonitorRule - > refreshRate ;
2022-04-19 19:01:23 +02:00
2022-07-30 22:54:29 +02:00
if ( ! wlr_output_test ( pMonitor - > output ) ) {
Debug : : log ( ERR , " Custom resolution FAILED, falling back to preferred " ) ;
2022-06-28 11:12:01 +02:00
2022-07-30 22:54:29 +02:00
const auto PREFERREDMODE = wlr_output_preferred_mode ( pMonitor - > output ) ;
2022-06-28 11:12:01 +02:00
2022-07-30 22:54:29 +02:00
if ( ! PREFERREDMODE ) {
2023-09-20 17:25:03 +02:00
Debug : : log ( ERR , " Monitor {} has NO PREFERRED MODE, and an INVALID one was requested: {:X0}@{:2f} " , pMonitor - > ID , pMonitorRule - > resolution ,
( float ) pMonitorRule - > refreshRate ) ;
2022-07-30 22:54:29 +02:00
return true ;
}
2022-04-19 19:01:23 +02:00
2022-07-30 22:54:29 +02:00
// Preferred is valid
wlr_output_set_mode ( pMonitor - > output , PREFERREDMODE ) ;
2022-04-19 19:01:23 +02:00
2023-09-20 17:25:03 +02:00
Debug : : log ( ERR , " Monitor {} got an invalid requested mode: {:X0}@{:2f}, using the preferred one instead: {}x{}@{:2f} " , pMonitor - > output - > name ,
pMonitorRule - > resolution , ( float ) pMonitorRule - > refreshRate , PREFERREDMODE - > width , PREFERREDMODE - > height , PREFERREDMODE - > refresh / 1000.f ) ;
2022-04-19 19:01:23 +02:00
2022-07-30 22:54:29 +02:00
pMonitor - > refreshRate = PREFERREDMODE - > refresh / 1000.f ;
2022-12-16 18:17:31 +01:00
pMonitor - > vecSize = Vector2D ( PREFERREDMODE - > width , PREFERREDMODE - > height ) ;
2022-07-30 22:54:29 +02:00
} else {
2023-09-20 17:25:03 +02:00
Debug : : log ( LOG , " Set a custom mode {:X0}@{:2f} (mode not found in monitor modes) " , pMonitorRule - > resolution , ( float ) pMonitorRule - > refreshRate ) ;
2022-07-30 22:54:29 +02:00
}
2022-06-28 11:12:01 +02:00
}
2022-09-24 14:10:11 +02:00
} else {
2023-05-09 15:01:45 +02:00
// custom resolution
bool fail = false ;
if ( pMonitorRule - > drmMode . type = = DRM_MODE_TYPE_USERDEF ) {
if ( ! wlr_output_is_drm ( pMonitor - > output ) ) {
Debug : : log ( ERR , " Tried to set custom modeline on non-DRM output " ) ;
fail = true ;
} else {
auto * mode = wlr_drm_connector_add_mode ( pMonitor - > output , & pMonitorRule - > drmMode ) ;
if ( mode ) {
wlr_output_set_mode ( pMonitor - > output , mode ) ;
pMonitor - > customDrmMode = pMonitorRule - > drmMode ;
} else {
Debug : : log ( ERR , " wlr_drm_connector_add_mode failed " ) ;
fail = true ;
}
}
} else {
2023-07-19 00:26:04 +02:00
wlr_output_set_custom_mode ( pMonitor - > output , ( int ) pMonitorRule - > resolution . x , ( int ) pMonitorRule - > resolution . y , WLRREFRESHRATE ) ;
2023-05-09 15:01:45 +02:00
}
2022-12-16 18:17:31 +01:00
pMonitor - > vecSize = pMonitorRule - > resolution ;
2022-09-24 14:10:11 +02:00
pMonitor - > refreshRate = pMonitorRule - > refreshRate ;
2023-05-09 15:01:45 +02:00
if ( fail | | ! wlr_output_test ( pMonitor - > output ) ) {
2022-09-24 14:10:11 +02:00
Debug : : log ( ERR , " Custom resolution FAILED, falling back to preferred " ) ;
const auto PREFERREDMODE = wlr_output_preferred_mode ( pMonitor - > output ) ;
if ( ! PREFERREDMODE ) {
2023-09-20 17:25:03 +02:00
Debug : : log ( ERR , " Monitor {} has NO PREFERRED MODE, and an INVALID one was requested: {:X0}@{:2f} " , pMonitor - > output - > name , pMonitorRule - > resolution ,
( float ) pMonitorRule - > refreshRate ) ;
2022-09-24 14:10:11 +02:00
return true ;
}
// Preferred is valid
wlr_output_set_mode ( pMonitor - > output , PREFERREDMODE ) ;
2023-09-20 17:25:03 +02:00
Debug : : log ( ERR , " Monitor {} got an invalid requested mode: {:X0}@{:2f}, using the preferred one instead: {}x{}@{:2f} " , pMonitor - > output - > name ,
pMonitorRule - > resolution , ( float ) pMonitorRule - > refreshRate , PREFERREDMODE - > width , PREFERREDMODE - > height , PREFERREDMODE - > refresh / 1000.f ) ;
2022-09-24 14:10:11 +02:00
2023-05-09 15:01:45 +02:00
pMonitor - > refreshRate = PREFERREDMODE - > refresh / 1000.f ;
pMonitor - > vecSize = Vector2D ( PREFERREDMODE - > width , PREFERREDMODE - > height ) ;
pMonitor - > customDrmMode = { } ;
2022-09-24 14:10:11 +02:00
} else {
2023-09-20 17:25:03 +02:00
Debug : : log ( LOG , " Set a custom mode {:X0}@{:2f} (mode not found in monitor modes) " , pMonitorRule - > resolution , ( float ) pMonitorRule - > refreshRate ) ;
2022-09-24 14:10:11 +02:00
}
2022-09-22 00:45:56 +02:00
}
2022-09-24 12:30:41 +02:00
} else if ( pMonitorRule - > resolution ! = Vector2D ( ) ) {
2022-09-22 00:45:56 +02:00
if ( ! wl_list_empty ( & pMonitor - > output - > modes ) ) {
wlr_output_mode * mode ;
2022-12-16 18:17:31 +01:00
float currentWidth = 0 ;
float currentHeight = 0 ;
float currentRefresh = 0 ;
bool success = false ;
2022-09-22 00:45:56 +02:00
2022-09-25 20:07:48 +02:00
//(-1,-1) indicates a preference to refreshrate over resolution, (-1,-2) preference to resolution
2022-12-16 18:17:31 +01:00
if ( pMonitorRule - > resolution = = Vector2D ( - 1 , - 1 ) ) {
2022-09-22 00:45:56 +02:00
wl_list_for_each ( mode , & pMonitor - > output - > modes , link ) {
2022-12-16 18:17:31 +01:00
if ( ( mode - > width > = currentWidth & & mode - > height > = currentHeight & & mode - > refresh > = ( currentRefresh - 1000.f ) ) | | mode - > refresh > ( currentRefresh + 3000.f ) ) {
wlr_output_set_mode ( pMonitor - > output , mode ) ;
if ( wlr_output_test ( pMonitor - > output ) ) {
currentWidth = mode - > width ;
currentHeight = mode - > height ;
currentRefresh = mode - > refresh ;
success = true ;
}
}
2022-09-22 00:45:56 +02:00
}
} else {
wl_list_for_each ( mode , & pMonitor - > output - > modes , link ) {
2022-12-16 18:17:31 +01:00
if ( ( mode - > width > = currentWidth & & mode - > height > = currentHeight & & mode - > refresh > = ( currentRefresh - 1000.f ) ) | |
( mode - > width > currentWidth & & mode - > height > currentHeight ) ) {
wlr_output_set_mode ( pMonitor - > output , mode ) ;
if ( wlr_output_test ( pMonitor - > output ) ) {
currentWidth = mode - > width ;
currentHeight = mode - > height ;
currentRefresh = mode - > refresh ;
success = true ;
}
}
2022-09-21 22:29:52 +02:00
}
2022-09-22 00:45:56 +02:00
}
2022-08-07 19:28:31 +02:00
2022-09-22 00:45:56 +02:00
if ( ! success ) {
2023-09-20 17:25:03 +02:00
Debug : : log ( LOG , " Monitor {}: REJECTED mode: {:X0}@{:2f}! Falling back to preferred: {}x{}@{:2f} " , pMonitor - > output - > name , pMonitorRule - > resolution ,
( float ) pMonitorRule - > refreshRate , mode - > width , mode - > height , mode - > refresh / 1000.f ) ;
2022-09-25 20:07:48 +02:00
2022-09-22 00:45:56 +02:00
const auto PREFERREDMODE = wlr_output_preferred_mode ( pMonitor - > output ) ;
2022-09-21 22:29:52 +02:00
2022-09-22 00:45:56 +02:00
if ( ! PREFERREDMODE ) {
2023-09-20 17:25:03 +02:00
Debug : : log ( ERR , " Monitor {} has NO PREFERRED MODE, and an INVALID one was requested: {:X0}@{:2f} " , pMonitor - > ID , pMonitorRule - > resolution ,
( float ) pMonitorRule - > refreshRate ) ;
2022-09-22 00:45:56 +02:00
return true ;
}
2022-09-21 22:29:52 +02:00
2022-09-22 00:45:56 +02:00
// Preferred is valid
wlr_output_set_mode ( pMonitor - > output , PREFERREDMODE ) ;
2022-09-21 22:29:52 +02:00
2023-09-20 17:25:03 +02:00
Debug : : log ( ERR , " Monitor {} got an invalid requested mode: {:X0}@{:2f}, using the preferred one instead: {}x{}@{:2f} " , pMonitor - > output - > name ,
pMonitorRule - > resolution , ( float ) pMonitorRule - > refreshRate , PREFERREDMODE - > width , PREFERREDMODE - > height , PREFERREDMODE - > refresh / 1000.f ) ;
2022-09-21 22:29:52 +02:00
2022-09-22 00:45:56 +02:00
pMonitor - > refreshRate = PREFERREDMODE - > refresh / 1000.f ;
2022-12-16 18:17:31 +01:00
pMonitor - > vecSize = Vector2D ( PREFERREDMODE - > width , PREFERREDMODE - > height ) ;
2022-09-22 00:45:56 +02:00
} else {
2022-09-21 22:29:52 +02:00
2023-09-20 17:25:03 +02:00
Debug : : log ( LOG , " Monitor {}: Applying highest mode {}x{}@{:2f}. " , pMonitor - > output - > name , ( int ) currentWidth , ( int ) currentHeight , ( int ) currentRefresh / 1000.f ) ;
2022-09-21 22:29:52 +02:00
2022-09-22 00:45:56 +02:00
pMonitor - > refreshRate = currentRefresh / 1000.f ;
2022-12-16 18:17:31 +01:00
pMonitor - > vecSize = Vector2D ( currentWidth , currentHeight ) ;
2022-09-21 22:29:52 +02:00
}
2022-09-22 00:45:56 +02:00
}
} else {
2022-07-30 22:54:29 +02:00
const auto PREFERREDMODE = wlr_output_preferred_mode ( pMonitor - > output ) ;
if ( ! PREFERREDMODE ) {
2023-09-20 17:25:03 +02:00
Debug : : log ( ERR , " Monitor {} has NO PREFERRED MODE " , pMonitor - > output - > name ) ;
2022-07-30 22:54:29 +02:00
2022-08-02 22:20:45 +02:00
if ( ! wl_list_empty ( & pMonitor - > output - > modes ) ) {
wlr_output_mode * mode ;
wl_list_for_each ( mode , & pMonitor - > output - > modes , link ) {
wlr_output_set_mode ( pMonitor - > output , mode ) ;
if ( ! wlr_output_test ( pMonitor - > output ) ) {
2023-09-20 17:25:03 +02:00
Debug : : log ( LOG , " Monitor {}: REJECTED available mode: {}x{}@{:2f}! " , pMonitor - > output - > name , mode - > width , mode - > height , mode - > refresh / 1000.f ) ;
2022-08-02 22:20:45 +02:00
continue ;
}
2023-09-20 17:25:03 +02:00
Debug : : log ( LOG , " Monitor {}: requested {:X0}@{:2f}, found available mode: {}x{}@{}mHz, applying. " , pMonitor - > output - > name , pMonitorRule - > resolution ,
( float ) pMonitorRule - > refreshRate , mode - > width , mode - > height , mode - > refresh ) ;
2022-08-02 22:20:45 +02:00
pMonitor - > refreshRate = mode - > refresh / 1000.f ;
2022-12-16 18:17:31 +01:00
pMonitor - > vecSize = Vector2D ( mode - > width , mode - > height ) ;
2022-08-02 22:20:45 +02:00
break ;
}
}
} else {
// Preferred is valid
wlr_output_set_mode ( pMonitor - > output , PREFERREDMODE ) ;
2022-12-16 18:17:31 +01:00
pMonitor - > vecSize = Vector2D ( PREFERREDMODE - > width , PREFERREDMODE - > height ) ;
2022-08-02 22:20:45 +02:00
pMonitor - > refreshRate = PREFERREDMODE - > refresh / 1000.f ;
2022-08-07 19:28:31 +02:00
2023-09-06 12:51:36 +02:00
Debug : : log ( LOG , " Setting preferred mode for {} " , pMonitor - > output - > name ) ;
2022-08-02 22:20:45 +02:00
}
2022-04-19 19:01:23 +02:00
}
2022-09-25 20:07:48 +02:00
2022-12-16 18:17:31 +01:00
pMonitor - > vrrActive = pMonitor - > output - > pending . adaptive_sync_enabled ; // disabled here, will be tested in CConfigManager::ensureVRR()
2022-04-19 19:01:23 +02:00
2022-05-18 20:33:54 +02:00
pMonitor - > vecPixelSize = pMonitor - > vecSize ;
2023-09-22 21:15:06 +02:00
// clang-format off
static const std : : array < std : : vector < std : : pair < std : : string , uint32_t > > , 2 > formats {
std : : vector < std : : pair < std : : string , uint32_t > > { /* 10-bit */
{ " DRM_FORMAT_XRGB2101010 " , DRM_FORMAT_XRGB2101010 } , { " DRM_FORMAT_XBGR2101010 " , DRM_FORMAT_XBGR2101010 } , { " DRM_FORMAT_XRGB8888 " , DRM_FORMAT_XRGB8888 } , { " DRM_FORMAT_XBGR8888 " , DRM_FORMAT_XBGR8888 } , { " DRM_FORMAT_INVALID " , DRM_FORMAT_INVALID }
} ,
std : : vector < std : : pair < std : : string , uint32_t > > { /* 8-bit */
{ " DRM_FORMAT_XRGB8888 " , DRM_FORMAT_XRGB8888 } , { " DRM_FORMAT_XBGR8888 " , DRM_FORMAT_XBGR8888 } , { " DRM_FORMAT_INVALID " , DRM_FORMAT_INVALID }
}
} ;
// clang-format on
2022-10-27 14:26:47 +02:00
2023-10-30 16:56:02 +01:00
bool set10bit = false ;
pMonitor - > drmFormat = DRM_FORMAT_INVALID ;
2022-10-27 14:26:47 +02:00
2023-09-22 21:15:06 +02:00
for ( auto & fmt : formats [ ( int ) ! pMonitorRule - > enable10bit ] ) {
wlr_output_set_render_format ( pMonitor - > output , fmt . second ) ;
2022-10-27 14:26:47 +02:00
2023-09-22 21:15:06 +02:00
if ( ! wlr_output_test ( pMonitor - > output ) ) {
Debug : : log ( ERR , " output {} failed basic test on format {} " , pMonitor - > szName , fmt . first ) ;
2022-10-27 14:26:47 +02:00
} else {
2023-09-22 21:15:06 +02:00
Debug : : log ( LOG , " output {} succeeded basic test on format {} " , pMonitor - > szName , fmt . first ) ;
if ( pMonitorRule - > enable10bit & & fmt . first . contains ( " 101010 " ) )
set10bit = true ;
2023-10-30 16:56:02 +01:00
pMonitor - > drmFormat = fmt . second ;
2023-09-22 21:15:06 +02:00
break ;
2022-10-27 14:26:47 +02:00
}
}
2023-09-22 21:15:06 +02:00
pMonitor - > enabled10bit = set10bit ;
2022-04-19 19:01:23 +02:00
if ( ! wlr_output_commit ( pMonitor - > output ) ) {
2023-09-06 12:51:36 +02:00
Debug : : log ( ERR , " Couldn't commit output named {} " , pMonitor - > output - > name ) ;
2022-04-19 19:01:23 +02:00
}
2022-04-21 18:11:28 +02:00
2022-05-29 12:27:45 +02:00
int x , y ;
wlr_output_transformed_resolution ( pMonitor - > output , & x , & y ) ;
2022-12-16 18:17:31 +01:00
pMonitor - > vecSize = ( Vector2D ( x , y ) / pMonitor - > scale ) . floor ( ) ;
pMonitor - > vecTransformedSize = Vector2D ( x , y ) ;
2022-05-29 12:27:45 +02:00
2022-11-05 19:04:44 +01:00
if ( pMonitor - > createdByUser ) {
2022-12-16 18:17:31 +01:00
wlr_box transformedBox = { 0 , 0 , ( int ) pMonitor - > vecTransformedSize . x , ( int ) pMonitor - > vecTransformedSize . y } ;
wlr_box_transform ( & transformedBox , & transformedBox , wlr_output_transform_invert ( pMonitor - > output - > transform ) , ( int ) pMonitor - > vecTransformedSize . x ,
( int ) pMonitor - > vecTransformedSize . y ) ;
2022-11-05 19:04:44 +01:00
pMonitor - > vecPixelSize = Vector2D ( transformedBox . width , transformedBox . height ) ;
}
2022-10-07 23:19:23 +02:00
// update renderer (here because it will call rollback, so we cannot do this before committing)
g_pHyprOpenGL - > destroyMonitorResources ( pMonitor ) ;
2022-04-21 18:11:28 +02:00
// updato wlroots
2023-08-14 14:22:06 +02:00
g_pCompositor - > arrangeMonitors ( ) ;
2022-04-21 18:11:28 +02:00
2023-04-07 13:18:40 +02:00
wlr_damage_ring_set_bounds ( & pMonitor - > damage , pMonitor - > vecTransformedSize . x , pMonitor - > vecTransformedSize . y ) ;
2022-04-21 18:11:28 +02:00
// updato us
arrangeLayersForMonitor ( pMonitor - > ID ) ;
// frame skip
2022-06-06 13:48:17 +02:00
pMonitor - > framesToSkip = 1 ;
2022-06-30 23:55:28 +02:00
2022-09-13 15:25:42 +02:00
// reload to fix mirrors
g_pConfigManager - > m_bWantsMonitorReload = true ;
2023-09-20 17:25:03 +02:00
Debug : : log ( LOG , " Monitor {} data dump: res {:X}@{:.2f}Hz, scale {:.2f}, transform {}, pos {:X}, 10b {} " , pMonitor - > szName , pMonitor - > vecPixelSize , pMonitor - > refreshRate ,
pMonitor - > scale , ( int ) pMonitor - > transform , pMonitor - > vecPosition , ( int ) pMonitor - > enabled10bit ) ;
2023-01-17 11:57:36 +01:00
2023-07-18 15:30:28 +02:00
EMIT_HOOK_EVENT ( " monitorLayoutChanged " , nullptr ) ;
2023-06-23 21:14:04 +02:00
2023-09-10 14:14:27 +02:00
Events : : listener_change ( nullptr , nullptr ) ;
2022-06-30 23:55:28 +02:00
return true ;
2022-04-21 18:11:28 +02:00
}
2022-06-24 23:27:02 +02:00
2023-09-29 18:51:07 +02:00
void CHyprRenderer : : setCursorSurface ( wlr_surface * surf , int hotspotX , int hotspotY ) {
m_bCursorHasSurface = surf ;
2023-10-29 19:09:05 +01:00
if ( surf = = m_sLastCursorData . surf )
return ;
m_sLastCursorData . name = " " ;
m_sLastCursorData . surf = surf ;
2023-09-29 18:51:07 +02:00
wlr_cursor_set_surface ( g_pCompositor - > m_sWLRCursor , surf , hotspotX , hotspotY ) ;
}
void CHyprRenderer : : setCursorFromName ( const std : : string & name ) {
m_bCursorHasSurface = true ;
2023-10-29 19:09:05 +01:00
if ( name = = m_sLastCursorData . name )
return ;
m_sLastCursorData . name = name ;
2023-10-30 01:18:40 +01:00
m_sLastCursorData . surf . reset ( ) ;
2023-10-29 19:09:05 +01:00
2023-09-29 18:51:07 +02:00
wlr_cursor_set_xcursor ( g_pCompositor - > m_sWLRCursor , g_pCompositor - > m_sWLRXCursorMgr , name . c_str ( ) ) ;
}
2022-06-24 23:27:02 +02:00
void CHyprRenderer : : ensureCursorRenderingMode ( ) {
2022-12-16 18:17:31 +01:00
static auto * const PCURSORTIMEOUT = & g_pConfigManager - > getConfigValuePtr ( " general:cursor_inactive_timeout " ) - > intValue ;
2023-01-17 11:47:39 +01:00
static auto * const PHIDEONTOUCH = & g_pConfigManager - > getConfigValuePtr ( " misc:hide_cursor_on_touch " ) - > intValue ;
2022-06-24 23:27:02 +02:00
2022-12-16 18:17:31 +01:00
const auto PASSEDCURSORSECONDS = g_pInputManager - > m_tmrLastCursorMovement . getSeconds ( ) ;
2022-06-24 23:27:02 +02:00
2023-01-17 11:47:39 +01:00
if ( * PCURSORTIMEOUT > 0 | | * PHIDEONTOUCH ) {
const bool HIDE = ( * PCURSORTIMEOUT > 0 & & * PCURSORTIMEOUT < PASSEDCURSORSECONDS ) | | ( g_pInputManager - > m_bLastInputTouch & & * PHIDEONTOUCH ) ;
if ( HIDE & & m_bHasARenderedCursor ) {
2022-06-24 23:27:02 +02:00
m_bHasARenderedCursor = false ;
2023-09-29 18:51:07 +02:00
setCursorSurface ( nullptr , 0 , 0 ) ; // hide
2022-06-24 23:27:02 +02:00
Debug : : log ( LOG , " Hiding the cursor (timeout) " ) ;
2022-06-30 15:44:26 +02:00
for ( auto & m : g_pCompositor - > m_vMonitors )
2022-12-16 18:17:31 +01:00
g_pHyprRenderer - > damageMonitor ( m . get ( ) ) ; // TODO: maybe just damage the cursor area?
2023-01-17 11:47:39 +01:00
} else if ( ! HIDE & & ! m_bHasARenderedCursor ) {
2022-06-24 23:27:02 +02:00
m_bHasARenderedCursor = true ;
2022-06-26 13:43:32 +02:00
if ( ! m_bWindowRequestedCursorHide )
2023-09-29 18:51:07 +02:00
setCursorFromName ( " left_ptr " ) ;
2022-06-24 23:27:02 +02:00
Debug : : log ( LOG , " Showing the cursor (timeout) " ) ;
2022-06-30 15:44:26 +02:00
for ( auto & m : g_pCompositor - > m_vMonitors )
2022-12-16 18:17:31 +01:00
g_pHyprRenderer - > damageMonitor ( m . get ( ) ) ; // TODO: maybe just damage the cursor area?
2022-06-24 23:27:02 +02:00
}
} else {
m_bHasARenderedCursor = true ;
}
2022-06-26 13:43:32 +02:00
}
bool CHyprRenderer : : shouldRenderCursor ( ) {
2023-09-29 18:51:07 +02:00
return m_bHasARenderedCursor & & m_bCursorHasSurface ;
2022-07-11 23:38:10 +02:00
}
2023-03-24 20:23:16 +01:00
std : : tuple < float , float , float > CHyprRenderer : : getRenderTimes ( CMonitor * pMonitor ) {
const auto POVERLAY = & g_pDebugOverlay - > m_mMonitorOverlays [ pMonitor ] ;
float avgRenderTime = 0 ;
float maxRenderTime = 0 ;
float minRenderTime = 9999 ;
for ( auto & rt : POVERLAY - > m_dLastRenderTimes ) {
if ( rt > maxRenderTime )
maxRenderTime = rt ;
if ( rt < minRenderTime )
minRenderTime = rt ;
avgRenderTime + = rt ;
}
avgRenderTime / = POVERLAY - > m_dLastRenderTimes . size ( ) = = 0 ? 1 : POVERLAY - > m_dLastRenderTimes . size ( ) ;
return std : : make_tuple < > ( avgRenderTime , maxRenderTime , minRenderTime ) ;
}
2023-04-04 15:49:58 +02:00
static int handleCrashLoop ( void * data ) {
g_pHyprNotificationOverlay - > addNotification ( " Hyprland will crash in " + std : : to_string ( 10 - ( int ) ( g_pHyprRenderer - > m_fCrashingDistort * 2.f ) ) + " s. " , CColor ( 0 ) , 5000 ,
ICON_INFO ) ;
g_pHyprRenderer - > m_fCrashingDistort + = 0.5f ;
if ( g_pHyprRenderer - > m_fCrashingDistort > = 5.5f )
2023-08-31 22:52:02 +02:00
raise ( SIGABRT ) ;
2023-04-04 15:49:58 +02:00
wl_event_source_timer_update ( g_pHyprRenderer - > m_pCrashingLoop , 1000 ) ;
return 1 ;
}
void CHyprRenderer : : initiateManualCrash ( ) {
g_pHyprNotificationOverlay - > addNotification ( " Manual crash initiated. Farewell... " , CColor ( 0 ) , 5000 , ICON_INFO ) ;
m_pCrashingLoop = wl_event_loop_add_timer ( g_pCompositor - > m_sWLEventLoop , handleCrashLoop , nullptr ) ;
wl_event_source_timer_update ( m_pCrashingLoop , 1000 ) ;
m_bCrashingInProgress = true ;
m_fCrashingDistort = 0.5 ;
2023-04-04 23:04:32 +02:00
g_pHyprOpenGL - > m_tGlobalTimer . reset ( ) ;
2023-04-04 15:49:58 +02:00
g_pConfigManager - > setInt ( " debug:damage_tracking " , 0 ) ;
2023-04-14 16:16:43 +02:00
}
2023-07-19 16:13:55 +02:00
2023-07-19 20:09:49 +02:00
void CHyprRenderer : : setOccludedForBackLayers ( CRegion & region , CWorkspace * pWorkspace ) {
CRegion rg ;
2023-07-19 16:13:55 +02:00
const auto PMONITOR = g_pCompositor - > getMonitorFromID ( pWorkspace - > m_iMonitorID ) ;
for ( auto & w : g_pCompositor - > m_vWindows ) {
if ( ! w - > m_bIsMapped | | w - > isHidden ( ) | | w - > m_iWorkspaceID ! = pWorkspace - > m_iID )
continue ;
if ( ! w - > opaque ( ) )
continue ;
const auto ROUNDING = w - > rounding ( ) * PMONITOR - > scale ;
2023-08-09 22:15:37 +02:00
const Vector2D POS = w - > m_vRealPosition . vec ( ) + Vector2D { ROUNDING , ROUNDING } - PMONITOR - > vecPosition + ( w - > m_bPinned ? Vector2D { } : pWorkspace - > m_vRenderOffset . vec ( ) ) ;
2023-07-19 16:13:55 +02:00
const Vector2D SIZE = w - > m_vRealSize . vec ( ) - Vector2D { ROUNDING * 2 , ROUNDING * 2 } ;
2023-07-20 18:12:29 +02:00
wlr_box box = { POS . x , POS . y , SIZE . x , SIZE . y } ;
scaleBox ( & box , PMONITOR - > scale ) ;
rg . add ( & box ) ;
2023-07-19 16:13:55 +02:00
}
2023-07-19 20:09:49 +02:00
region . subtract ( rg ) ;
2023-07-19 16:13:55 +02:00
}
2023-07-20 14:11:05 +02:00
bool CHyprRenderer : : canSkipBackBufferClear ( CMonitor * pMonitor ) {
for ( auto & ls : pMonitor - > m_aLayerSurfaceLayers [ ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND ] ) {
if ( ! ls - > layerSurface )
continue ;
2023-07-20 18:27:14 +02:00
if ( ls - > alpha . fl ( ) < 1.f )
2023-07-20 14:11:05 +02:00
continue ;
2023-07-20 18:27:14 +02:00
if ( ls - > geometry . x ! = pMonitor - > vecPosition . x | | ls - > geometry . y ! = pMonitor - > vecPosition . y | | ls - > geometry . width ! = pMonitor - > vecSize . x | |
ls - > geometry . height ! = pMonitor - > vecSize . y )
continue ;
if ( ! ls - > layerSurface - > surface - > opaque )
continue ;
return true ;
2023-07-20 14:11:05 +02:00
}
return false ;
}
2023-09-28 22:48:33 +02:00
void CHyprRenderer : : recheckSolitaryForMonitor ( CMonitor * pMonitor ) {
pMonitor - > solitaryClient = nullptr ; // reset it, if we find one it will be set.
const auto PWORKSPACE = g_pCompositor - > getWorkspaceByID ( pMonitor - > activeWorkspace ) ;
2023-09-29 18:51:07 +02:00
if ( ! PWORKSPACE | | ! PWORKSPACE - > m_bHasFullscreenWindow | | g_pInputManager - > m_sDrag . drag | | g_pCompositor - > m_sSeat . exclusiveClient | | pMonitor - > specialWorkspaceID | |
PWORKSPACE - > m_fAlpha . fl ( ) ! = 1.f | | PWORKSPACE - > m_vRenderOffset . vec ( ) ! = Vector2D { } )
2023-09-28 22:48:33 +02:00
return ;
const auto PCANDIDATE = g_pCompositor - > getFullscreenWindowOnWorkspace ( PWORKSPACE - > m_iID ) ;
if ( ! PCANDIDATE )
return ; // ????
if ( ! PCANDIDATE - > opaque ( ) )
return ;
if ( PCANDIDATE - > m_vRealSize . vec ( ) ! = pMonitor - > vecSize | | PCANDIDATE - > m_vRealPosition . vec ( ) ! = pMonitor - > vecPosition | | PCANDIDATE - > m_vRealPosition . isBeingAnimated ( ) | |
PCANDIDATE - > m_vRealSize . isBeingAnimated ( ) )
return ;
if ( ! pMonitor - > m_aLayerSurfaceLayers [ ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY ] . empty ( ) )
return ;
for ( auto & topls : pMonitor - > m_aLayerSurfaceLayers [ ZWLR_LAYER_SHELL_V1_LAYER_TOP ] ) {
if ( topls - > alpha . fl ( ) ! = 0.f )
return ;
}
2023-10-04 10:44:03 +02:00
for ( auto & w : g_pCompositor - > m_vWindows ) {
2023-10-04 14:30:13 +02:00
if ( w - > m_iWorkspaceID = = PCANDIDATE - > m_iWorkspaceID & & w - > m_bIsFloating & & w - > m_bCreatedOverFullscreen & & ! w - > isHidden ( ) & & w - > m_bIsMapped & & w . get ( ) ! = PCANDIDATE )
2023-10-04 10:44:03 +02:00
return ;
}
if ( pMonitor - > specialWorkspaceID ! = 0 )
return ;
2023-09-28 22:48:33 +02:00
// check if it did not open any subsurfaces or shit
int surfaceCount = 0 ;
if ( PCANDIDATE - > m_bIsX11 ) {
surfaceCount = 1 ;
} else {
wlr_xdg_surface_for_each_surface ( PCANDIDATE - > m_uSurface . xdg , countSubsurfacesIter , & surfaceCount ) ;
wlr_xdg_surface_for_each_popup_surface ( PCANDIDATE - > m_uSurface . xdg , countSubsurfacesIter , & surfaceCount ) ;
}
2023-10-02 15:02:15 +02:00
if ( surfaceCount > 1 )
return ;
2023-09-28 22:48:33 +02:00
// found one!
pMonitor - > solitaryClient = PCANDIDATE ;
}