summaryrefslogtreecommitdiff
path: root/src/protocols/ToplevelExport.cpp
diff options
context:
space:
mode:
authorvaxerski <43317083+vaxerski@users.noreply.github.com>2023-07-20 12:42:25 +0200
committervaxerski <43317083+vaxerski@users.noreply.github.com>2023-07-20 12:42:25 +0200
commitb65adf8d4a0c239f5aa44425d14d1fe14f675643 (patch)
tree348fe57dc05f4111c269fabe56fee443aba97d76 /src/protocols/ToplevelExport.cpp
parent3a1496b4ebc6f66eb85e509d2e1e90ee989b47bc (diff)
toplevelexport: support dmabuf + various fixes
Diffstat (limited to 'src/protocols/ToplevelExport.cpp')
-rw-r--r--src/protocols/ToplevelExport.cpp58
1 files changed, 44 insertions, 14 deletions
diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp
index eeeaa81f..318af943 100644
--- a/src/protocols/ToplevelExport.cpp
+++ b/src/protocols/ToplevelExport.cpp
@@ -36,8 +36,6 @@ CToplevelExportProtocolManager::CToplevelExportProtocolManager() {
m_liDisplayDestroy.notify = handleDisplayDestroy;
wl_display_add_destroy_listener(g_pCompositor->m_sWLDisplay, &m_liDisplayDestroy);
- g_pHookSystem->hookDynamic("preRender", [&](void* self, std::any data) { onMonitorRender(std::any_cast<CMonitor*>(data)); });
-
Debug::log(LOG, "ToplevelExportManager started successfully!");
}
@@ -207,6 +205,12 @@ void CToplevelExportProtocolManager::captureToplevel(wl_client* client, wl_resou
PFRAME->shmStride = (PSHMINFO->bpp / 8) * PFRAME->box.width;
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);
+
+ 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);
}
void CToplevelExportProtocolManager::copyFrame(wl_client* client, wl_resource* resource, wl_resource* buffer, int32_t ignore_damage) {
@@ -278,11 +282,12 @@ void CToplevelExportProtocolManager::copyFrame(wl_client* client, wl_resource* r
m_vFramesAwaitingWrite.emplace_back(PFRAME);
}
-void CToplevelExportProtocolManager::onMonitorRender(CMonitor* pMonitor) {
-
+void CToplevelExportProtocolManager::onOutputCommit(CMonitor* pMonitor, wlr_output_event_commit* e) {
if (m_vFramesAwaitingWrite.empty())
return; // nothing to share
+ const auto PMONITOR = g_pCompositor->getMonitorFromOutput(e->output);
+
std::vector<SScreencopyFrame*> framesToRemove;
// share frame if correct output
@@ -292,6 +297,9 @@ void CToplevelExportProtocolManager::onMonitorRender(CMonitor* pMonitor) {
continue;
}
+ if (PMONITOR != g_pCompositor->getMonitorFromID(f->pWindow->m_iMonitorID))
+ continue;
+
wlr_box geometry = {f->pWindow->m_vRealPosition.vec().x, f->pWindow->m_vRealPosition.vec().y, f->pWindow->m_vRealSize.vec().x, f->pWindow->m_vRealSize.vec().y};
if (!wlr_output_layout_intersects(g_pCompositor->m_sWLROutputLayout, pMonitor->output, &geometry))
@@ -314,14 +322,12 @@ void CToplevelExportProtocolManager::shareFrame(SScreencopyFrame* frame) {
if (!frame->buffer || !g_pCompositor->windowValidMapped(frame->pWindow))
return;
- // TODO: damage
-
timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
uint32_t flags = 0;
if (frame->bufferCap == WLR_BUFFER_CAP_DMABUF) {
- if (!copyFrameDmabuf(frame)) {
+ if (!copyFrameDmabuf(frame, &now)) {
hyprland_toplevel_export_frame_v1_send_failed(frame->resource);
return;
}
@@ -333,12 +339,17 @@ void CToplevelExportProtocolManager::shareFrame(SScreencopyFrame* frame) {
}
hyprland_toplevel_export_frame_v1_send_flags(frame->resource, flags);
- // todo: send damage
+ sendDamage(frame);
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);
}
+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);
+}
+
bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* now) {
void* data;
uint32_t format;
@@ -404,8 +415,6 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times
glBindFramebuffer(GL_FRAMEBUFFER, g_pHyprOpenGL->m_RenderData.pCurrentMonData->primaryFB.m_iFb);
- glFinish(); // flush
-
glReadPixels(0, 0, frame->box.width, frame->box.height, PFORMAT->gl_format, PFORMAT->gl_type, data);
g_pHyprOpenGL->end();
@@ -420,10 +429,31 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times
return true;
}
-bool CToplevelExportProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame) {
- // todo
- Debug::log(ERR, "DMABUF copying not impl'd!");
- return false;
+bool CToplevelExportProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame, timespec* now) {
+ if (!wlr_renderer_begin_with_buffer(g_pCompositor->m_sWLRRenderer, frame->buffer))
+ return false;
+
+ const auto PMONITOR = g_pCompositor->getMonitorFromID(frame->pWindow->m_iMonitorID);
+
+ CRegion fakeDamage{0, 0, INT16_MAX, INT16_MAX};
+
+ g_pHyprOpenGL->begin(PMONITOR, &fakeDamage, true);
+
+ g_pHyprOpenGL->clear(CColor(17.0 / 255.0, 17.0 / 255.0, 17.0 / 255.0, 1.0));
+
+ g_pHyprRenderer->m_bBlockSurfaceFeedback = g_pHyprRenderer->shouldRenderWindow(frame->pWindow); // block the feedback to avoid spamming the surface if it's visible
+ g_pHyprRenderer->renderWindow(frame->pWindow, PMONITOR, now, false, RENDER_PASS_ALL, true, true);
+ g_pHyprRenderer->m_bBlockSurfaceFeedback = false;
+
+ g_pHyprOpenGL->bindWlrOutputFb();
+
+ wlr_box monbox = {0, 0, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
+ g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_RenderData.pCurrentMonData->primaryFB.m_cTex, &monbox, 1.f);
+
+ g_pHyprOpenGL->end();
+
+ wlr_renderer_end(g_pCompositor->m_sWLRRenderer);
+ return true;
}
void CToplevelExportProtocolManager::onWindowUnmap(CWindow* pWindow) {