diff options
Diffstat (limited to 'src/protocols/ToplevelExport.cpp')
| -rw-r--r-- | src/protocols/ToplevelExport.cpp | 58 |
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) { |
