From e2b68a6d39eb72b6d945f0f7f47a3f317fae79ad Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Mon, 28 Aug 2023 14:41:45 +0200 Subject: [PATCH] send more meta --- src/core/PortalManager.cpp | 4 ++- src/core/PortalManager.hpp | 7 ++-- src/portals/Screencopy.cpp | 73 +++++++++++++++++++++++++++++++------- src/portals/Screencopy.hpp | 6 ++++ 4 files changed, 74 insertions(+), 16 deletions(-) diff --git a/src/core/PortalManager.cpp b/src/core/PortalManager.cpp index b4a6243..5aac211 100644 --- a/src/core/PortalManager.cpp +++ b/src/core/PortalManager.cpp @@ -29,7 +29,9 @@ inline const wl_registry_listener registryListener = { static void handleOutputGeometry(void* data, struct wl_output* wl_output, int32_t x, int32_t y, int32_t physical_width, int32_t physical_height, int32_t subpixel, const char* make, const char* model, int32_t transform) { - ; + const auto POUTPUT = (SOutput*)data; + + POUTPUT->transform = (wl_output_transform)transform; } static void handleOutputDone(void* data, struct wl_output* wl_output) { diff --git a/src/core/PortalManager.hpp b/src/core/PortalManager.hpp index 4e7f527..a11808b 100644 --- a/src/core/PortalManager.hpp +++ b/src/core/PortalManager.hpp @@ -14,9 +14,10 @@ struct pw_loop; struct SOutput { - std::string name; - wl_output* output = nullptr; - uint32_t id = 0; + std::string name; + wl_output* output = nullptr; + uint32_t id = 0; + wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; }; struct SDMABUFModifier { diff --git a/src/portals/Screencopy.cpp b/src/portals/Screencopy.cpp index c3787ab..694631c 100644 --- a/src/portals/Screencopy.cpp +++ b/src/portals/Screencopy.cpp @@ -65,7 +65,14 @@ static void wlrOnDamage(void* data, struct zwlr_screencopy_frame_v1* frame, uint Debug::log(TRACE, "[sc] wlrOnDamage for {}", (void*)PSESSION); - // todo + if (PSESSION->sharingData.damageCount > 3) { + PSESSION->sharingData.damage[0] = {0, 0, PSESSION->sharingData.frameInfoDMA.w, PSESSION->sharingData.frameInfoDMA.h}; + return; + } + + PSESSION->sharingData.damage[PSESSION->sharingData.damageCount++] = {x, y, width, height}; + + Debug::log(TRACE, "[sc] wlr damage: {} {} {} {}", x, y, width, height); } static void wlrOnDmabuf(void* data, struct zwlr_screencopy_frame_v1* frame, uint32_t format, uint32_t width, uint32_t height) { @@ -364,7 +371,7 @@ void CScreencopyPortal::startSharing(CScreencopyPortal::SSession* pSession) { wl_display_roundtrip(g_pPortalManager->m_sWaylandConnection.display); if (pSession->sharingData.frameInfoDMA.fmt == DRM_FORMAT_INVALID) { - Debug::log(ERR, "[screencopy] Couldn't obtain a format from dma"); + Debug::log(ERR, "[screencopy] Couldn't obtain a format from dma"); // todo: blocks shm return; } @@ -403,12 +410,14 @@ void CScreencopyPortal::startFrameCopy(CScreencopyPortal::SSession* pSession) { return; } - if (pSession->selection.type == TYPE_GEOMETRY) + if (pSession->selection.type == TYPE_GEOMETRY) { pSession->sharingData.frameCallback = zwlr_screencopy_manager_v1_capture_output_region(m_sState.screencopy, pSession->cursorMode, POUTPUT->output, pSession->selection.x, pSession->selection.y, pSession->selection.w, pSession->selection.h); - else if (pSession->selection.type == TYPE_OUTPUT) + pSession->sharingData.transform = POUTPUT->transform; + } else if (pSession->selection.type == TYPE_OUTPUT) { pSession->sharingData.frameCallback = zwlr_screencopy_manager_v1_capture_output(m_sState.screencopy, pSession->cursorMode, POUTPUT->output); - else { + pSession->sharingData.transform = POUTPUT->transform; + } else { Debug::log(ERR, "[screencopy] Unsupported selection {}", (int)pSession->selection.type); return; } @@ -526,7 +535,7 @@ static void pwStreamParamChanged(void* data, uint32_t id, const spa_pod* param) } spa_pod_dynamic_builder dynBuilder[3]; - const spa_pod* params[2]; + const spa_pod* params[4]; uint8_t params_buffer[3][1024]; spa_pod_dynamic_builder_init(&dynBuilder[0], params_buffer[0], sizeof(params_buffer[0]), 2048); @@ -601,8 +610,8 @@ static void pwStreamParamChanged(void* data, uint32_t id, const spa_pod* param) spa_pod_dynamic_builder_clean(&dynBuilder[1]); spa_pod_dynamic_builder_clean(&dynBuilder[2]); - Debug::log(TRACE, "[pw] Format renegotiated:"); - Debug::log(TRACE, "[pw] | buffer_type {}", "DMA"); + Debug::log(TRACE, "[pw] Format fixated:"); + Debug::log(TRACE, "[pw] | buffer_type {}", "DMA (No fixate)"); Debug::log(TRACE, "[pw] | format: {}", (int)PSTREAM->pwVideoInfo.format); Debug::log(TRACE, "[pw] | modifier: {}", PSTREAM->pwVideoInfo.modifier); Debug::log(TRACE, "[pw] | size: {}x{}", PSTREAM->pwVideoInfo.size.width, PSTREAM->pwVideoInfo.size.height); @@ -613,7 +622,7 @@ static void pwStreamParamChanged(void* data, uint32_t id, const spa_pod* param) } Debug::log(TRACE, "[pw] Format renegotiated:"); - Debug::log(TRACE, "[pw] | buffer_type {}", "SHM"); + Debug::log(TRACE, "[pw] | buffer_type {}", PSTREAM->isDMA ? "DMA" : "SHM"); Debug::log(TRACE, "[pw] | format: {}", (int)PSTREAM->pwVideoInfo.format); Debug::log(TRACE, "[pw] | modifier: {}", PSTREAM->pwVideoInfo.modifier); Debug::log(TRACE, "[pw] | size: {}x{}", PSTREAM->pwVideoInfo.size.width, PSTREAM->pwVideoInfo.size.height); @@ -623,10 +632,16 @@ static void pwStreamParamChanged(void* data, uint32_t id, const spa_pod* param) params[0] = build_buffer(&dynBuilder[0].b, blocks, PSTREAM->pSession->sharingData.frameInfoSHM.size, PSTREAM->pSession->sharingData.frameInfoSHM.stride, data_type); - params[1] = (const spa_pod*)spa_pod_builder_add_object(&dynBuilder[1].b, SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta, SPA_PARAM_META_type, SPA_POD_Id(SPA_META_Header), - SPA_PARAM_META_size, SPA_POD_Int(sizeof(struct spa_meta_header))); + params[1] = spa_pod_builder_add_object(&dynBuilder[1].b, SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta, SPA_PARAM_META_type, SPA_POD_Id(SPA_META_Header), SPA_PARAM_META_size, + SPA_POD_Int(sizeof(struct spa_meta_header))); - pw_stream_update_params(PSTREAM->stream, params, 2); + params[2] = spa_pod_builder_add_object(&dynBuilder[1].b, SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta, SPA_PARAM_META_type, SPA_POD_Id(SPA_META_VideoTransform), + SPA_PARAM_META_size, SPA_POD_Int(sizeof(struct spa_meta_videotransform))); + + params[3] = spa_pod_builder_add_object(&dynBuilder[2].b, SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta, SPA_PARAM_META_type, SPA_POD_Id(SPA_META_VideoDamage), SPA_PARAM_META_size, + SPA_POD_CHOICE_RANGE_Int(sizeof(struct spa_meta_region) * 4, sizeof(struct spa_meta_region) * 1, sizeof(struct spa_meta_region) * 4)); + + pw_stream_update_params(PSTREAM->stream, params, 4); spa_pod_dynamic_builder_clean(&dynBuilder[0]); spa_pod_dynamic_builder_clean(&dynBuilder[1]); spa_pod_dynamic_builder_clean(&dynBuilder[2]); @@ -877,6 +892,40 @@ void CPipewireConnection::enqueue(CScreencopyPortal::SSession* pSession) { Debug::log(TRACE, "[pw] | pts {}", header->pts); } + spa_meta_videotransform* vt = (spa_meta_videotransform*)spa_buffer_find_meta_data(spaBuf, SPA_META_VideoTransform, sizeof(*vt)); + if (vt) { + vt->transform = pSession->sharingData.transform; + Debug::log(TRACE, "[pw] | meta transform {}", vt->transform); + } + + spa_meta* damage = spa_buffer_find_meta(spaBuf, SPA_META_VideoDamage); + if (damage) { + Debug::log(TRACE, "[pw] | meta has damage"); + + spa_region* damageRegion = (spa_region*)spa_meta_first(damage); + uint32_t damageCounter = 0; + do { + if (damageCounter >= pSession->sharingData.damageCount) { + *damageRegion = SPA_REGION(0, 0, 0, 0); + Debug::log(TRACE, "[pw] | end damage @ {}: {} {} {} {}", damageCounter, damageRegion->position.x, damageRegion->position.y, damageRegion->size.width, + damageRegion->size.height); + break; + } + + *damageRegion = SPA_REGION(pSession->sharingData.damage[damageCounter].x, pSession->sharingData.damage[damageCounter].y, pSession->sharingData.damage[damageCounter].w, + pSession->sharingData.damage[damageCounter].h); + Debug::log(TRACE, "[pw] | damage @ {}: {} {} {} {}", damageCounter, damageRegion->position.x, damageRegion->position.y, damageRegion->size.width, + damageRegion->size.height); + damageCounter++; + } while (spa_meta_check(damageRegion + 1, damage) && damageRegion++); + + if (damageCounter < pSession->sharingData.damageCount) { + // TODO: merge damage properly + *damageRegion = SPA_REGION(0, 0, pSession->sharingData.frameInfoDMA.w, pSession->sharingData.frameInfoDMA.h); + Debug::log(TRACE, "[pw] | damage overflow, damaged whole"); + } + } + spa_data* datas = spaBuf->datas; Debug::log(TRACE, "[pw] | size {}x{}", PSTREAM->pSession->sharingData.frameInfoDMA.w, PSTREAM->pSession->sharingData.frameInfoDMA.h); diff --git a/src/portals/Screencopy.hpp b/src/portals/Screencopy.hpp index c743d5e..2ec06db 100644 --- a/src/portals/Screencopy.hpp +++ b/src/portals/Screencopy.hpp @@ -78,6 +78,7 @@ class CScreencopyPortal { uint64_t tvTimestampNs = 0; uint32_t nodeID = 0; uint32_t framerate = 60; + wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; struct { uint32_t w = 0, h = 0, size = 0, stride = 0, fmt = 0; @@ -86,6 +87,11 @@ class CScreencopyPortal { struct { uint32_t w = 0, h = 0, fmt = 0; } frameInfoDMA; + + struct { + uint32_t x = 0, y = 0, w = 0, h = 0; + } damage[4]; + uint32_t damageCount = 0; } sharingData; void onCloseRequest(sdbus::MethodCall&);