2022-12-05 18:05:15 +01:00
# include "ToplevelExport.hpp"
# include "../Compositor.hpp"
2024-04-25 01:58:40 +02:00
# include "ForeignToplevelWlr.hpp"
2024-05-05 23:18:10 +02:00
# include "../managers/PointerManager.hpp"
2022-12-05 18:05:15 +01:00
# include <algorithm>
# include "ToplevelExportWlrFuncs.hpp"
2022-12-12 15:56:42 +01:00
# define TOPLEVEL_EXPORT_VERSION 2
2022-12-05 18:05:15 +01:00
static void bindManagerInt ( wl_client * client , void * data , uint32_t version , uint32_t id ) {
g_pProtocolManager - > m_pToplevelExportProtocolManager - > bindManager ( client , data , version , id ) ;
}
static void handleDisplayDestroy ( struct wl_listener * listener , void * data ) {
g_pProtocolManager - > m_pToplevelExportProtocolManager - > displayDestroy ( ) ;
}
void CToplevelExportProtocolManager : : displayDestroy ( ) {
wl_global_destroy ( m_pGlobal ) ;
}
CToplevelExportProtocolManager : : CToplevelExportProtocolManager ( ) {
# ifndef GLES32
Debug : : log ( WARN , " Toplevel sharing is not supported on LEGACY_RENDERER! " ) ;
return ;
# endif
2022-12-16 18:17:31 +01:00
m_pGlobal = wl_global_create ( g_pCompositor - > m_sWLDisplay , & hyprland_toplevel_export_manager_v1_interface , TOPLEVEL_EXPORT_VERSION , this , bindManagerInt ) ;
2022-12-05 18:05:15 +01:00
if ( ! m_pGlobal ) {
Debug : : log ( ERR , " ToplevelExportManager could not start! Sharing windows will not work! " ) ;
return ;
}
m_liDisplayDestroy . notify = handleDisplayDestroy ;
wl_display_add_destroy_listener ( g_pCompositor - > m_sWLDisplay , & m_liDisplayDestroy ) ;
Debug : : log ( LOG , " ToplevelExportManager started successfully! " ) ;
}
2023-04-03 18:01:05 +02:00
static void handleCaptureToplevel ( wl_client * client , wl_resource * resource , uint32_t frame , int32_t overlay_cursor , uint32_t handle ) {
2022-12-12 15:56:42 +01:00
g_pProtocolManager - > m_pToplevelExportProtocolManager - > captureToplevel ( client , resource , frame , overlay_cursor , g_pCompositor - > getWindowFromHandle ( handle ) ) ;
}
2023-04-03 18:01:05 +02:00
static void handleCaptureToplevelWithWlr ( wl_client * client , wl_resource * resource , uint32_t frame , int32_t overlay_cursor , wl_resource * handle ) {
2024-04-25 01:58:40 +02:00
g_pProtocolManager - > m_pToplevelExportProtocolManager - > captureToplevel ( client , resource , frame , overlay_cursor , PROTO : : foreignToplevelWlr - > windowFromHandleResource ( handle ) ) ;
2022-12-05 18:05:15 +01:00
}
2023-01-20 19:44:30 +01:00
static void handleDestroy ( wl_client * client , wl_resource * resource ) {
2022-12-05 18:05:15 +01:00
wl_resource_destroy ( resource ) ;
}
2023-04-03 18:01:05 +02:00
static void handleCopyFrame ( wl_client * client , wl_resource * resource , wl_resource * buffer , int32_t ignore_damage ) {
2022-12-05 18:05:15 +01:00
g_pProtocolManager - > m_pToplevelExportProtocolManager - > copyFrame ( client , resource , buffer , ignore_damage ) ;
}
2023-04-03 18:01:05 +02:00
static void handleDestroyFrame ( wl_client * client , wl_resource * resource ) {
2022-12-05 18:05:15 +01:00
wl_resource_destroy ( resource ) ;
}
static const struct hyprland_toplevel_export_manager_v1_interface toplevelExportManagerImpl = {
2022-12-16 18:17:31 +01:00
. capture_toplevel = handleCaptureToplevel ,
. destroy = handleDestroy ,
2022-12-12 15:56:42 +01:00
. capture_toplevel_with_wlr_toplevel_handle = handleCaptureToplevelWithWlr ,
2022-12-05 18:05:15 +01:00
} ;
2022-12-16 18:17:31 +01:00
static const struct hyprland_toplevel_export_frame_v1_interface toplevelFrameImpl = { . copy = handleCopyFrame , . destroy = handleDestroyFrame } ;
2022-12-05 18:05:15 +01:00
2023-08-08 19:10:47 +02:00
//
static CScreencopyClient * clientFromResource ( wl_resource * resource ) {
2023-02-16 23:51:34 +01:00
ASSERT ( wl_resource_instance_of ( resource , & hyprland_toplevel_export_manager_v1_interface , & toplevelExportManagerImpl ) ) ;
2023-04-16 00:43:41 +02:00
return ( CScreencopyClient * ) wl_resource_get_user_data ( resource ) ;
2022-12-05 18:05:15 +01:00
}
2023-04-16 00:43:41 +02:00
static SScreencopyFrame * frameFromResource ( wl_resource * resource ) {
2022-12-05 18:05:15 +01:00
ASSERT ( wl_resource_instance_of ( resource , & hyprland_toplevel_export_frame_v1_interface , & toplevelFrameImpl ) ) ;
2023-04-16 00:43:41 +02:00
return ( SScreencopyFrame * ) wl_resource_get_user_data ( resource ) ;
2022-12-05 18:05:15 +01:00
}
2023-04-16 00:43:41 +02:00
void CToplevelExportProtocolManager : : removeClient ( CScreencopyClient * client , bool force ) {
2022-12-05 18:05:15 +01:00
if ( ! force ) {
if ( ! client | | client - > ref < = 0 )
return ;
if ( - - client - > ref ! = 0 )
return ;
}
m_lClients . remove ( * client ) ; // TODO: this doesn't get cleaned up after sharing app exits???
}
2023-01-20 19:44:30 +01:00
static void handleManagerResourceDestroy ( wl_resource * resource ) {
2022-12-05 18:05:15 +01:00
const auto PCLIENT = clientFromResource ( resource ) ;
2022-12-06 19:58:42 +01:00
g_pProtocolManager - > m_pToplevelExportProtocolManager - > removeClient ( PCLIENT , true ) ;
2022-12-05 18:05:15 +01:00
}
void CToplevelExportProtocolManager : : bindManager ( wl_client * client , void * data , uint32_t version , uint32_t id ) {
const auto PCLIENT = & m_lClients . emplace_back ( ) ;
2023-04-16 00:43:41 +02:00
PCLIENT - > clientOwner = CLIENT_TOPLEVEL_EXPORT ;
PCLIENT - > resource = wl_resource_create ( client , & hyprland_toplevel_export_manager_v1_interface , version , id ) ;
2022-12-05 18:05:15 +01:00
if ( ! PCLIENT - > resource ) {
Debug : : log ( ERR , " ToplevelExportManager could not bind! (out of memory?) " ) ;
m_lClients . remove ( * PCLIENT ) ;
wl_client_post_no_memory ( client ) ;
return ;
}
PCLIENT - > ref = 1 ;
wl_resource_set_implementation ( PCLIENT - > resource , & toplevelExportManagerImpl , PCLIENT , handleManagerResourceDestroy ) ;
Debug : : log ( LOG , " ToplevelExportManager bound successfully! " ) ;
}
2023-04-03 18:01:05 +02:00
static void handleFrameResourceDestroy ( wl_resource * resource ) {
2022-12-05 18:05:15 +01:00
const auto PFRAME = frameFromResource ( resource ) ;
g_pProtocolManager - > m_pToplevelExportProtocolManager - > removeFrame ( PFRAME ) ;
}
2023-04-16 00:43:41 +02:00
void CToplevelExportProtocolManager : : removeFrame ( SScreencopyFrame * frame , bool force ) {
2022-12-05 18:05:15 +01:00
if ( ! frame )
return ;
2022-12-16 18:17:31 +01:00
std : : erase_if ( m_vFramesAwaitingWrite , [ & ] ( const auto & other ) { return other = = frame ; } ) ;
2022-12-05 18:05:15 +01:00
wl_resource_set_user_data ( frame - > resource , nullptr ) ;
2023-11-24 11:54:21 +01:00
if ( frame - > buffer & & frame - > buffer - > n_locks > 0 )
wlr_buffer_unlock ( frame - > buffer ) ;
2022-12-05 18:05:15 +01:00
removeClient ( frame - > client , force ) ;
m_lFrames . remove ( * frame ) ;
}
2024-04-27 13:43:12 +02:00
void CToplevelExportProtocolManager : : captureToplevel ( wl_client * client , wl_resource * resource , uint32_t frame , int32_t overlay_cursor , PHLWINDOW pWindow ) {
2022-12-05 18:05:15 +01:00
const auto PCLIENT = clientFromResource ( resource ) ;
// create a frame
2022-12-16 18:17:31 +01:00
const auto PFRAME = & m_lFrames . emplace_back ( ) ;
2022-12-05 18:05:15 +01:00
PFRAME - > overlayCursor = ! ! overlay_cursor ;
2022-12-16 18:17:31 +01:00
PFRAME - > resource = wl_resource_create ( client , & hyprland_toplevel_export_frame_v1_interface , wl_resource_get_version ( resource ) , frame ) ;
PFRAME - > pWindow = pWindow ;
2022-12-05 18:05:15 +01:00
2024-04-27 13:43:12 +02:00
if ( ! pWindow ) {
Debug : : log ( ERR , " Client requested sharing of window handle {:x} which does not exist! " , pWindow ) ;
2022-12-05 18:05:15 +01:00
hyprland_toplevel_export_frame_v1_send_failed ( PFRAME - > resource ) ;
removeFrame ( PFRAME ) ;
return ;
}
2024-04-27 13:43:12 +02:00
if ( ! pWindow - > m_bIsMapped | | pWindow - > isHidden ( ) ) {
Debug : : log ( ERR , " Client requested sharing of window handle {:x} which is not shareable! " , pWindow ) ;
2022-12-05 18:05:15 +01:00
hyprland_toplevel_export_frame_v1_send_failed ( PFRAME - > resource ) ;
removeFrame ( PFRAME ) ;
return ;
}
if ( ! PFRAME - > resource ) {
Debug : : log ( ERR , " Couldn't alloc frame for sharing! (no memory) " ) ;
m_lFrames . remove ( * PFRAME ) ;
wl_client_post_no_memory ( client ) ;
return ;
}
wl_resource_set_implementation ( PFRAME - > resource , & toplevelFrameImpl , PFRAME , handleFrameResourceDestroy ) ;
PFRAME - > client = PCLIENT ;
PCLIENT - > ref + + ;
2024-04-27 13:43:12 +02:00
const auto PMONITOR = g_pCompositor - > getMonitorFromID ( pWindow - > m_iMonitorID ) ;
2022-12-05 18:05:15 +01:00
2023-12-03 23:04:07 +01:00
g_pHyprRenderer - > makeEGLCurrent ( ) ;
2024-02-15 01:58:58 +01:00
2023-12-05 15:43:54 +01:00
PFRAME - > shmFormat = g_pHyprOpenGL - > getPreferredReadFormat ( PMONITOR ) ;
2022-12-05 18:05:15 +01:00
if ( PFRAME - > shmFormat = = DRM_FORMAT_INVALID ) {
Debug : : log ( ERR , " No format supported by renderer in capture toplevel " ) ;
hyprland_toplevel_export_frame_v1_send_failed ( resource ) ;
removeFrame ( PFRAME ) ;
return ;
}
const auto PSHMINFO = drm_get_pixel_format_info ( PFRAME - > shmFormat ) ;
if ( ! PSHMINFO ) {
Debug : : log ( ERR , " No pixel format supported by renderer in capture toplevel " ) ;
hyprland_toplevel_export_frame_v1_send_failed ( resource ) ;
removeFrame ( PFRAME ) ;
return ;
}
if ( PMONITOR - > output - > allocator & & ( PMONITOR - > output - > allocator - > buffer_caps & WLR_BUFFER_CAP_DMABUF ) ) {
PFRAME - > dmabufFormat = PMONITOR - > output - > render_format ;
} else {
PFRAME - > dmabufFormat = DRM_FORMAT_INVALID ;
}
2024-04-27 13:43:12 +02:00
PFRAME - > box = { 0 , 0 , ( int ) ( pWindow - > m_vRealSize . value ( ) . x * PMONITOR - > scale ) , ( int ) ( pWindow - > m_vRealSize . value ( ) . y * PMONITOR - > scale ) } ;
2022-12-05 18:05:15 +01:00
int ow , oh ;
wlr_output_effective_resolution ( PMONITOR - > output , & ow , & oh ) ;
2023-11-08 13:43:07 +01:00
PFRAME - > box . transform ( PMONITOR - > transform , ow , oh ) . round ( ) ;
2022-12-05 18:05:15 +01:00
2023-12-03 23:04:07 +01:00
PFRAME - > shmStride = pixel_format_info_min_stride ( PSHMINFO , PFRAME - > box . w ) ;
2022-12-05 18:05:15 +01:00
hyprland_toplevel_export_frame_v1_send_buffer ( PFRAME - > resource , convert_drm_format_to_wl_shm ( PFRAME - > shmFormat ) , PFRAME - > box . width , PFRAME - > box . height , PFRAME - > shmStride ) ;
2023-07-20 12:42:25 +02:00
if ( PFRAME - > dmabufFormat ! = DRM_FORMAT_INVALID ) {
hyprland_toplevel_export_frame_v1_send_linux_dmabuf ( PFRAME - > resource , PFRAME - > dmabufFormat , PFRAME - > box . width , PFRAME - > box . height ) ;
}
hyprland_toplevel_export_frame_v1_send_buffer_done ( PFRAME - > resource ) ;
2022-12-05 18:05:15 +01:00
}
void CToplevelExportProtocolManager : : copyFrame ( wl_client * client , wl_resource * resource , wl_resource * buffer , int32_t ignore_damage ) {
const auto PFRAME = frameFromResource ( resource ) ;
if ( ! PFRAME ) {
Debug : : log ( ERR , " No frame in copyFrame?? " ) ;
return ;
}
2024-04-27 13:43:12 +02:00
const auto PWINDOW = PFRAME - > pWindow . lock ( ) ;
if ( ! validMapped ( PWINDOW ) ) {
Debug : : log ( ERR , " Client requested sharing of window handle {:x} which is gone! " , ( uintptr_t ) PWINDOW . get ( ) ) ;
2024-02-07 01:18:47 +01:00
hyprland_toplevel_export_frame_v1_send_failed ( PFRAME - > resource ) ;
removeFrame ( PFRAME ) ;
return ;
}
2024-04-27 13:43:12 +02:00
if ( ! PWINDOW - > m_bIsMapped | | PWINDOW - > isHidden ( ) ) {
Debug : : log ( ERR , " Client requested sharing of window handle {:x} which is not shareable (2)! " , PWINDOW ) ;
2022-12-05 18:05:15 +01:00
hyprland_toplevel_export_frame_v1_send_failed ( PFRAME - > resource ) ;
2022-12-06 19:58:42 +01:00
removeFrame ( PFRAME ) ;
2022-12-05 18:05:15 +01:00
return ;
}
2023-10-25 01:27:16 +02:00
const auto PBUFFER = wlr_buffer_try_from_resource ( buffer ) ;
2022-12-05 18:05:15 +01:00
if ( ! PBUFFER ) {
wl_resource_post_error ( PFRAME - > resource , HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_INVALID_BUFFER , " invalid buffer " ) ;
2022-12-06 19:58:42 +01:00
removeFrame ( PFRAME ) ;
2022-12-05 18:05:15 +01:00
return ;
}
if ( PBUFFER - > width ! = PFRAME - > box . width | | PBUFFER - > height ! = PFRAME - > box . height ) {
wl_resource_post_error ( PFRAME - > resource , HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_INVALID_BUFFER , " invalid buffer dimensions " ) ;
2022-12-06 19:58:42 +01:00
removeFrame ( PFRAME ) ;
2022-12-05 18:05:15 +01:00
return ;
}
if ( PFRAME - > buffer ) {
wl_resource_post_error ( PFRAME - > resource , HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_ALREADY_USED , " frame already used " ) ;
2022-12-06 19:58:42 +01:00
removeFrame ( PFRAME ) ;
2022-12-05 18:05:15 +01:00
return ;
}
wlr_dmabuf_attributes dmabufAttrs ;
2022-12-16 18:17:31 +01:00
void * wlrBufferAccessData ;
uint32_t wlrBufferAccessFormat ;
size_t wlrBufferAccessStride ;
2022-12-05 18:05:15 +01:00
if ( wlr_buffer_get_dmabuf ( PBUFFER , & dmabufAttrs ) ) {
PFRAME - > bufferCap = WLR_BUFFER_CAP_DMABUF ;
if ( dmabufAttrs . format ! = PFRAME - > dmabufFormat ) {
wl_resource_post_error ( PFRAME - > resource , HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_INVALID_BUFFER , " invalid buffer format " ) ;
2022-12-06 19:58:42 +01:00
removeFrame ( PFRAME ) ;
2022-12-05 18:05:15 +01:00
return ;
}
} else if ( wlr_buffer_begin_data_ptr_access ( PBUFFER , WLR_BUFFER_DATA_PTR_ACCESS_WRITE , & wlrBufferAccessData , & wlrBufferAccessFormat , & wlrBufferAccessStride ) ) {
wlr_buffer_end_data_ptr_access ( PBUFFER ) ;
if ( wlrBufferAccessFormat ! = PFRAME - > shmFormat ) {
wl_resource_post_error ( PFRAME - > resource , HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_INVALID_BUFFER , " invalid buffer format " ) ;
2022-12-06 19:58:42 +01:00
removeFrame ( PFRAME ) ;
2022-12-05 18:05:15 +01:00
return ;
} else if ( ( int ) wlrBufferAccessStride ! = PFRAME - > shmStride ) {
wl_resource_post_error ( PFRAME - > resource , HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_INVALID_BUFFER , " invalid buffer stride " ) ;
2022-12-06 19:58:42 +01:00
removeFrame ( PFRAME ) ;
2022-12-05 18:05:15 +01:00
return ;
}
} else {
wl_resource_post_error ( PFRAME - > resource , HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_INVALID_BUFFER , " invalid buffer type " ) ;
2022-12-06 19:58:42 +01:00
removeFrame ( PFRAME ) ;
2022-12-05 18:05:15 +01:00
return ;
}
PFRAME - > buffer = PBUFFER ;
m_vFramesAwaitingWrite . emplace_back ( PFRAME ) ;
}
2023-07-20 12:42:25 +02:00
void CToplevelExportProtocolManager : : onOutputCommit ( CMonitor * pMonitor , wlr_output_event_commit * e ) {
2022-12-05 18:05:15 +01:00
if ( m_vFramesAwaitingWrite . empty ( ) )
return ; // nothing to share
2023-08-08 19:10:47 +02:00
const auto PMONITOR = g_pCompositor - > getMonitorFromOutput ( e - > output ) ;
2023-07-20 12:42:25 +02:00
2023-04-16 00:43:41 +02:00
std : : vector < SScreencopyFrame * > framesToRemove ;
2022-12-16 18:17:31 +01:00
2022-12-05 18:05:15 +01:00
// share frame if correct output
for ( auto & f : m_vFramesAwaitingWrite ) {
2024-04-27 13:43:12 +02:00
const auto PWINDOW = f - > pWindow . lock ( ) ;
if ( ! validMapped ( PWINDOW ) ) {
2022-12-05 18:05:15 +01:00
framesToRemove . push_back ( f ) ;
continue ;
}
2024-04-27 13:43:12 +02:00
if ( PMONITOR ! = g_pCompositor - > getMonitorFromID ( PWINDOW - > m_iMonitorID ) )
2023-07-20 12:42:25 +02:00
continue ;
2024-04-27 13:43:12 +02:00
CBox geometry = { PWINDOW - > m_vRealPosition . value ( ) . x , PWINDOW - > m_vRealPosition . value ( ) . y , PWINDOW - > m_vRealSize . value ( ) . x , PWINDOW - > m_vRealSize . value ( ) . y } ;
2022-12-05 18:05:15 +01:00
2024-05-05 23:18:10 +02:00
if ( geometry . intersection ( { pMonitor - > vecPosition , pMonitor - > vecSize } ) . empty ( ) )
2022-12-05 18:05:15 +01:00
continue ;
2022-12-16 18:17:31 +01:00
2022-12-05 18:05:15 +01:00
shareFrame ( f ) ;
2023-04-17 23:57:24 +02:00
f - > client - > lastFrame . reset ( ) ;
2023-04-16 00:43:41 +02:00
+ + f - > client - > frameCounter ;
2022-12-05 18:05:15 +01:00
framesToRemove . push_back ( f ) ;
}
for ( auto & f : framesToRemove ) {
removeFrame ( f ) ;
}
}
2023-04-16 00:43:41 +02:00
void CToplevelExportProtocolManager : : shareFrame ( SScreencopyFrame * frame ) {
2024-04-27 13:43:12 +02:00
if ( ! frame - > buffer | | ! validMapped ( frame - > pWindow ) )
2022-12-05 18:05:15 +01:00
return ;
timespec now ;
clock_gettime ( CLOCK_MONOTONIC , & now ) ;
uint32_t flags = 0 ;
if ( frame - > bufferCap = = WLR_BUFFER_CAP_DMABUF ) {
2023-07-20 12:42:25 +02:00
if ( ! copyFrameDmabuf ( frame , & now ) ) {
2022-12-05 18:05:15 +01:00
hyprland_toplevel_export_frame_v1_send_failed ( frame - > resource ) ;
return ;
}
} else {
if ( ! copyFrameShm ( frame , & now ) ) {
hyprland_toplevel_export_frame_v1_send_failed ( frame - > resource ) ;
return ;
}
}
hyprland_toplevel_export_frame_v1_send_flags ( frame - > resource , flags ) ;
2023-07-20 12:42:25 +02:00
sendDamage ( frame ) ;
2022-12-05 18:05:15 +01:00
uint32_t tvSecHi = ( sizeof ( now . tv_sec ) > 4 ) ? now . tv_sec > > 32 : 0 ;
uint32_t tvSecLo = now . tv_sec & 0xFFFFFFFF ;
hyprland_toplevel_export_frame_v1_send_ready ( frame - > resource , tvSecHi , tvSecLo , now . tv_nsec ) ;
}
2023-07-20 12:42:25 +02:00
void CToplevelExportProtocolManager : : sendDamage ( SScreencopyFrame * frame ) {
// TODO: send proper dmg
hyprland_toplevel_export_frame_v1_send_damage ( frame - > resource , 0 , 0 , frame - > box . width , frame - > box . height ) ;
}
2023-04-16 00:43:41 +02:00
bool CToplevelExportProtocolManager : : copyFrameShm ( SScreencopyFrame * frame , timespec * now ) {
2022-12-16 18:17:31 +01:00
void * data ;
2022-12-05 18:05:15 +01:00
uint32_t format ;
2022-12-16 18:17:31 +01:00
size_t stride ;
2022-12-05 18:05:15 +01:00
if ( ! wlr_buffer_begin_data_ptr_access ( frame - > buffer , WLR_BUFFER_DATA_PTR_ACCESS_WRITE , & data , & format , & stride ) )
return false ;
// render the client
2024-05-05 18:16:00 +02:00
const auto PMONITOR = g_pCompositor - > getMonitorFromID ( frame - > pWindow - > m_iMonitorID ) ;
2023-07-19 20:09:49 +02:00
CRegion fakeDamage { 0 , 0 , PMONITOR - > vecPixelSize . x * 10 , PMONITOR - > vecPixelSize . y * 10 } ;
2022-12-05 18:05:15 +01:00
2023-11-30 11:14:35 +01:00
g_pHyprRenderer - > makeEGLCurrent ( ) ;
CFramebuffer outFB ;
2023-12-04 02:44:06 +01:00
outFB . alloc ( PMONITOR - > vecPixelSize . x , PMONITOR - > vecPixelSize . y , g_pHyprRenderer - > isNvidia ( ) ? DRM_FORMAT_XBGR8888 : PMONITOR - > drmFormat ) ;
2023-11-30 11:14:35 +01:00
if ( ! g_pHyprRenderer - > beginRender ( PMONITOR , fakeDamage , RENDER_MODE_FULL_FAKE , nullptr , & outFB ) ) {
2023-02-16 23:51:34 +01:00
wlr_buffer_end_data_ptr_access ( frame - > buffer ) ;
return false ;
}
2024-05-05 23:18:10 +02:00
if ( frame - > overlayCursor ) {
g_pPointerManager - > lockSoftwareForMonitor ( PMONITOR - > self . lock ( ) ) ;
g_pPointerManager - > damageCursor ( PMONITOR - > self . lock ( ) ) ;
}
2023-11-24 11:54:21 +01:00
2023-01-05 19:25:45 +01:00
g_pHyprOpenGL - > clear ( CColor ( 0 , 0 , 0 , 1.0 ) ) ;
2022-12-05 18:05:15 +01:00
// render client at 0,0
2024-04-27 13:43:12 +02:00
g_pHyprRenderer - > m_bBlockSurfaceFeedback = g_pHyprRenderer - > shouldRenderWindow ( frame - > pWindow . lock ( ) ) ; // block the feedback to avoid spamming the surface if it's visible
g_pHyprRenderer - > renderWindow ( frame - > pWindow . lock ( ) , PMONITOR , now , false , RENDER_PASS_ALL , true , true ) ;
2022-12-05 20:11:02 +01:00
g_pHyprRenderer - > m_bBlockSurfaceFeedback = false ;
2022-12-05 18:05:15 +01:00
2023-11-24 11:54:21 +01:00
if ( frame - > overlayCursor )
2024-05-05 23:18:10 +02:00
g_pPointerManager - > renderSoftwareCursorsFor ( PMONITOR - > self . lock ( ) , now , fakeDamage , g_pInputManager - > getMouseCoordsInternal ( ) - frame - > pWindow - > m_vRealPosition . value ( ) ) ;
2023-04-04 01:58:30 +02:00
2023-12-04 04:52:54 +01:00
const auto PFORMAT = g_pHyprOpenGL - > getPixelFormatFromDRM ( format ) ;
if ( ! PFORMAT ) {
g_pHyprRenderer - > endRender ( ) ;
wlr_buffer_end_data_ptr_access ( frame - > buffer ) ;
return false ;
2023-12-03 23:04:07 +01:00
}
2022-12-05 18:05:15 +01:00
2024-04-03 22:35:16 +02:00
g_pHyprOpenGL - > m_RenderData . blockScreenShader = true ;
2023-12-07 18:58:13 +01:00
g_pHyprRenderer - > endRender ( ) ;
g_pHyprRenderer - > makeEGLCurrent ( ) ;
2023-12-15 22:20:13 +01:00
g_pHyprOpenGL - > m_RenderData . pMonitor = PMONITOR ;
2023-12-07 18:58:13 +01:00
outFB . bind ( ) ;
2022-12-05 18:05:15 +01:00
2023-12-15 22:04:34 +01:00
# ifndef GLES2
glBindFramebuffer ( GL_READ_FRAMEBUFFER , outFB . m_iFb ) ;
# endif
2023-12-03 23:04:07 +01:00
glPixelStorei ( GL_PACK_ALIGNMENT , 1 ) ;
2023-12-04 04:52:54 +01:00
glReadPixels ( 0 , 0 , frame - > box . width , frame - > box . height , PFORMAT - > glFormat , PFORMAT - > glType , data ) ;
2022-12-05 18:05:15 +01:00
wlr_buffer_end_data_ptr_access ( frame - > buffer ) ;
2024-05-05 23:18:10 +02:00
if ( frame - > overlayCursor ) {
g_pPointerManager - > unlockSoftwareForMonitor ( PMONITOR - > self . lock ( ) ) ;
g_pPointerManager - > damageCursor ( PMONITOR - > self . lock ( ) ) ;
}
2023-04-04 01:58:30 +02:00
2022-12-05 18:05:15 +01:00
return true ;
}
2023-07-20 12:42:25 +02:00
bool CToplevelExportProtocolManager : : copyFrameDmabuf ( SScreencopyFrame * frame , timespec * now ) {
2024-05-05 18:16:00 +02:00
const auto PMONITOR = g_pCompositor - > getMonitorFromID ( frame - > pWindow - > m_iMonitorID ) ;
2023-07-20 12:42:25 +02:00
2023-08-08 19:10:47 +02:00
CRegion fakeDamage { 0 , 0 , INT16_MAX , INT16_MAX } ;
2023-07-20 12:42:25 +02:00
2023-11-24 11:54:21 +01:00
if ( ! g_pHyprRenderer - > beginRender ( PMONITOR , fakeDamage , RENDER_MODE_TO_BUFFER , frame - > buffer ) )
return false ;
2023-07-20 12:42:25 +02:00
2023-08-08 19:10:47 +02:00
g_pHyprOpenGL - > clear ( CColor ( 0 , 0 , 0 , 1.0 ) ) ;
2023-07-20 12:42:25 +02:00
2024-04-27 13:43:12 +02:00
g_pHyprRenderer - > m_bBlockSurfaceFeedback = g_pHyprRenderer - > shouldRenderWindow ( frame - > pWindow . lock ( ) ) ; // block the feedback to avoid spamming the surface if it's visible
g_pHyprRenderer - > renderWindow ( frame - > pWindow . lock ( ) , PMONITOR , now , false , RENDER_PASS_ALL , true , true ) ;
2023-07-20 12:42:25 +02:00
g_pHyprRenderer - > m_bBlockSurfaceFeedback = false ;
2023-11-24 11:54:21 +01:00
if ( frame - > overlayCursor )
2024-05-05 23:18:10 +02:00
g_pPointerManager - > renderSoftwareCursorsFor ( PMONITOR - > self . lock ( ) , now , fakeDamage , g_pInputManager - > getMouseCoordsInternal ( ) - frame - > pWindow - > m_vRealPosition . value ( ) ) ;
2023-07-20 12:42:25 +02:00
2024-04-03 22:35:16 +02:00
g_pHyprOpenGL - > m_RenderData . blockScreenShader = true ;
2023-11-24 11:54:21 +01:00
g_pHyprRenderer - > endRender ( ) ;
2023-07-20 12:42:25 +02:00
return true ;
2022-12-05 18:05:15 +01:00
}
2024-04-27 13:43:12 +02:00
void CToplevelExportProtocolManager : : onWindowUnmap ( PHLWINDOW pWindow ) {
2022-12-05 18:05:15 +01:00
for ( auto & f : m_lFrames ) {
2024-04-27 13:43:12 +02:00
if ( f . pWindow . lock ( ) = = pWindow )
f . pWindow . reset ( ) ;
2022-12-05 18:05:15 +01:00
}
2023-02-16 23:51:34 +01:00
}