mirror of
https://github.com/hyprwm/xdg-desktop-portal-hyprland.git
synced 2024-11-25 07:35:57 +01:00
parent
0fe840441e
commit
12af841341
4 changed files with 34 additions and 17 deletions
|
@ -41,7 +41,8 @@ static void handleOutputDone(void* data, struct wl_output* wl_output) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handleOutputMode(void* data, struct wl_output* wl_output, uint32_t flags, int32_t width, int32_t height, int32_t refresh) {
|
static void handleOutputMode(void* data, struct wl_output* wl_output, uint32_t flags, int32_t width, int32_t height, int32_t refresh) {
|
||||||
;
|
const auto POUTPUT = (SOutput*)data;
|
||||||
|
POUTPUT->refreshRate = std::round(refresh / 1000.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handleOutputScale(void* data, struct wl_output* wl_output, int32_t factor) {
|
static void handleOutputScale(void* data, struct wl_output* wl_output, int32_t factor) {
|
||||||
|
@ -422,7 +423,7 @@ void CPortalManager::startEventLoop() {
|
||||||
// wait for being awakened
|
// wait for being awakened
|
||||||
std::unique_lock lk(m_sEventLoopInternals.loopMutex);
|
std::unique_lock lk(m_sEventLoopInternals.loopMutex);
|
||||||
if (m_sEventLoopInternals.shouldProcess == false) // avoid a lock if a thread managed to request something already since we .unlock()ed
|
if (m_sEventLoopInternals.shouldProcess == false) // avoid a lock if a thread managed to request something already since we .unlock()ed
|
||||||
m_sEventLoopInternals.loopSignal.wait(lk, [this] { return m_sEventLoopInternals.shouldProcess == true; }); // wait for events
|
m_sEventLoopInternals.loopSignal.wait_for(lk, std::chrono::seconds(5), [this] { return m_sEventLoopInternals.shouldProcess == true; }); // wait for events
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lg(m_sEventLoopInternals.loopRequestMutex);
|
std::lock_guard<std::mutex> lg(m_sEventLoopInternals.loopRequestMutex);
|
||||||
|
|
||||||
|
@ -464,7 +465,6 @@ void CPortalManager::startEventLoop() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// finalize wayland dispatching. Dispatch pending on the queue
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
do {
|
do {
|
||||||
ret = wl_display_dispatch_pending(m_sWaylandConnection.display);
|
ret = wl_display_dispatch_pending(m_sWaylandConnection.display);
|
||||||
|
|
|
@ -19,9 +19,10 @@ struct pw_loop;
|
||||||
|
|
||||||
struct SOutput {
|
struct SOutput {
|
||||||
std::string name;
|
std::string name;
|
||||||
wl_output* output = nullptr;
|
wl_output* output = nullptr;
|
||||||
uint32_t id = 0;
|
uint32_t id = 0;
|
||||||
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
float refreshRate = 60.0;
|
||||||
|
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SDMABUFModifier {
|
struct SDMABUFModifier {
|
||||||
|
|
|
@ -488,6 +488,11 @@ void CScreencopyPortal::onSelectSources(sdbus::MethodCall& call) {
|
||||||
if (SHAREDATA.type == TYPE_WINDOW && !m_sState.toplevel) {
|
if (SHAREDATA.type == TYPE_WINDOW && !m_sState.toplevel) {
|
||||||
Debug::log(ERR, "[screencopy] Requested type window for no toplevel export protocol!");
|
Debug::log(ERR, "[screencopy] Requested type window for no toplevel export protocol!");
|
||||||
SHAREDATA.type = TYPE_INVALID;
|
SHAREDATA.type = TYPE_INVALID;
|
||||||
|
} else if (SHAREDATA.type == TYPE_OUTPUT || SHAREDATA.type == TYPE_GEOMETRY) {
|
||||||
|
const auto POUTPUT = g_pPortalManager->getOutputFromName(SHAREDATA.output);
|
||||||
|
|
||||||
|
if (POUTPUT)
|
||||||
|
PSESSION->sharingData.framerate = POUTPUT->refreshRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
PSESSION->selection = SHAREDATA;
|
PSESSION->selection = SHAREDATA;
|
||||||
|
@ -670,7 +675,15 @@ void CScreencopyPortal::queueNextShareFrame(CScreencopyPortal::SSession* pSessio
|
||||||
if (PSTREAM && !PSTREAM->streamState)
|
if (PSTREAM && !PSTREAM->streamState)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
g_pPortalManager->addTimer({1000.0 / pSession->sharingData.framerate, [pSession]() { g_pPortalManager->m_sPortals.screencopy->startFrameCopy(pSession); }});
|
// calculate frame delta and queue next frame
|
||||||
|
const auto FRAMETOOKMS = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now() - pSession->sharingData.begunFrame).count() / 1000.0;
|
||||||
|
const auto MSTILNEXTREFRESH = 1000.0 / (pSession->sharingData.framerate) - FRAMETOOKMS;
|
||||||
|
pSession->sharingData.begunFrame = std::chrono::system_clock::now();
|
||||||
|
|
||||||
|
Debug::log(TRACE, "[screencopy] set fps {}, ms till next refresh {:.2f}, estimated actual fps: {:.2f}", pSession->sharingData.framerate, MSTILNEXTREFRESH,
|
||||||
|
std::clamp(1000.0 / FRAMETOOKMS, 1.0, (double)pSession->sharingData.framerate));
|
||||||
|
|
||||||
|
g_pPortalManager->addTimer({std::clamp(MSTILNEXTREFRESH, 1.0, 1000.0), [pSession]() { g_pPortalManager->m_sPortals.screencopy->startFrameCopy(pSession); }});
|
||||||
}
|
}
|
||||||
bool CScreencopyPortal::hasToplevelCapabilities() {
|
bool CScreencopyPortal::hasToplevelCapabilities() {
|
||||||
return m_sState.toplevel;
|
return m_sState.toplevel;
|
||||||
|
@ -804,6 +817,7 @@ static void pwStreamParamChanged(void* data, uint32_t id, const spa_pod* param)
|
||||||
spa_pod_dynamic_builder_init(&dynBuilder[2], params_buffer[2], sizeof(params_buffer[2]), 2048);
|
spa_pod_dynamic_builder_init(&dynBuilder[2], params_buffer[2], sizeof(params_buffer[2]), 2048);
|
||||||
|
|
||||||
spa_format_video_raw_parse(param, &PSTREAM->pwVideoInfo);
|
spa_format_video_raw_parse(param, &PSTREAM->pwVideoInfo);
|
||||||
|
Debug::log(TRACE, "[pw] Framerate: {}/{}", PSTREAM->pwVideoInfo.max_framerate.num, PSTREAM->pwVideoInfo.max_framerate.denom);
|
||||||
PSTREAM->pSession->sharingData.framerate = PSTREAM->pwVideoInfo.max_framerate.num / PSTREAM->pwVideoInfo.max_framerate.denom;
|
PSTREAM->pSession->sharingData.framerate = PSTREAM->pwVideoInfo.max_framerate.num / PSTREAM->pwVideoInfo.max_framerate.denom;
|
||||||
|
|
||||||
uint32_t data_type = 1 << SPA_DATA_MemFd;
|
uint32_t data_type = 1 << SPA_DATA_MemFd;
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "../shared/ScreencopyShared.hpp"
|
#include "../shared/ScreencopyShared.hpp"
|
||||||
#include <gbm.h>
|
#include <gbm.h>
|
||||||
#include "../shared/Session.hpp"
|
#include "../shared/Session.hpp"
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
enum cursorModes {
|
enum cursorModes {
|
||||||
HIDDEN = 1,
|
HIDDEN = 1,
|
||||||
|
@ -69,16 +70,17 @@ class CScreencopyPortal {
|
||||||
SSelectionData selection;
|
SSelectionData selection;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
bool active = false;
|
bool active = false;
|
||||||
zwlr_screencopy_frame_v1* frameCallback = nullptr;
|
zwlr_screencopy_frame_v1* frameCallback = nullptr;
|
||||||
hyprland_toplevel_export_frame_v1* windowFrameCallback = nullptr;
|
hyprland_toplevel_export_frame_v1* windowFrameCallback = nullptr;
|
||||||
frameStatus status = FRAME_NONE;
|
frameStatus status = FRAME_NONE;
|
||||||
uint64_t tvSec = 0;
|
uint64_t tvSec = 0;
|
||||||
uint32_t tvNsec = 0;
|
uint32_t tvNsec = 0;
|
||||||
uint64_t tvTimestampNs = 0;
|
uint64_t tvTimestampNs = 0;
|
||||||
uint32_t nodeID = 0;
|
uint32_t nodeID = 0;
|
||||||
uint32_t framerate = 60;
|
uint32_t framerate = 60;
|
||||||
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||||
|
std::chrono::system_clock::time_point begunFrame = std::chrono::system_clock::now();
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
uint32_t w = 0, h = 0, size = 0, stride = 0, fmt = 0;
|
uint32_t w = 0, h = 0, size = 0, stride = 0, fmt = 0;
|
||||||
|
|
Loading…
Reference in a new issue