summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorvaxerski <43317083+vaxerski@users.noreply.github.com>2023-04-12 21:40:51 +0100
committervaxerski <43317083+vaxerski@users.noreply.github.com>2023-04-12 21:40:51 +0100
commita22e1174ee8b61bce400265206010cd52c5bace7 (patch)
treed9fc484b058d3b22cb2e22f5c70a63dccbcf44b7 /src
parent985764c8db01ff8f23461ed860eaacf3d52ee813 (diff)
screencopy: implement dmabuf
Diffstat (limited to 'src')
-rw-r--r--src/events/Events.hpp1
-rw-r--r--src/events/Monitors.cpp8
-rw-r--r--src/helpers/Monitor.cpp3
-rw-r--r--src/helpers/Monitor.hpp1
-rw-r--r--src/protocols/Screencopy.cpp57
-rw-r--r--src/protocols/Screencopy.hpp4
6 files changed, 65 insertions, 9 deletions
diff --git a/src/events/Events.hpp b/src/events/Events.hpp
index d0a1df39..e0f44727 100644
--- a/src/events/Events.hpp
+++ b/src/events/Events.hpp
@@ -100,6 +100,7 @@ namespace Events {
DYNLISTENFUNC(monitorStateRequest);
DYNLISTENFUNC(monitorDamage);
DYNLISTENFUNC(monitorNeedsFrame);
+ DYNLISTENFUNC(monitorCommit);
// XWayland
LISTENER(readyXWayland);
diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp
index fab7fc89..111076d5 100644
--- a/src/events/Monitors.cpp
+++ b/src/events/Monitors.cpp
@@ -212,3 +212,11 @@ void Events::listener_monitorNeedsFrame(void* owner, void* data) {
g_pCompositor->scheduleFrameForMonitor(PMONITOR);
}
+
+void Events::listener_monitorCommit(void* owner, void* data) {
+ const auto PMONITOR = (CMonitor*)owner;
+
+ const auto E = (wlr_output_event_commit*)data;
+
+ g_pProtocolManager->m_pScreencopyProtocolManager->onOutputCommit(PMONITOR, E);
+}
diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp
index e1cf54cd..cae76e8b 100644
--- a/src/helpers/Monitor.cpp
+++ b/src/helpers/Monitor.cpp
@@ -22,11 +22,13 @@ void CMonitor::onConnect(bool noRule) {
hyprListener_monitorStateRequest.removeCallback();
hyprListener_monitorDamage.removeCallback();
hyprListener_monitorNeedsFrame.removeCallback();
+ hyprListener_monitorCommit.removeCallback();
hyprListener_monitorFrame.initCallback(&output->events.frame, &Events::listener_monitorFrame, this);
hyprListener_monitorDestroy.initCallback(&output->events.destroy, &Events::listener_monitorDestroy, this);
hyprListener_monitorStateRequest.initCallback(&output->events.request_state, &Events::listener_monitorStateRequest, this);
hyprListener_monitorDamage.initCallback(&output->events.damage, &Events::listener_monitorDamage, this);
hyprListener_monitorNeedsFrame.initCallback(&output->events.needs_frame, &Events::listener_monitorNeedsFrame, this);
+ hyprListener_monitorCommit.initCallback(&output->events.commit, &Events::listener_monitorCommit, this);
if (m_bEnabled) {
wlr_output_enable(output, 1);
@@ -221,6 +223,7 @@ void CMonitor::onDisconnect() {
hyprListener_monitorFrame.removeCallback();
hyprListener_monitorDamage.removeCallback();
hyprListener_monitorNeedsFrame.removeCallback();
+ hyprListener_monitorCommit.removeCallback();
for (size_t i = 0; i < 4; ++i) {
for (auto& ls : m_aLayerSurfaceLayers[i]) {
diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp
index bb475189..25753687 100644
--- a/src/helpers/Monitor.hpp
+++ b/src/helpers/Monitor.hpp
@@ -67,6 +67,7 @@ class CMonitor {
DYNLISTENER(monitorStateRequest);
DYNLISTENER(monitorDamage);
DYNLISTENER(monitorNeedsFrame);
+ DYNLISTENER(monitorCommit);
// hack: a group = workspaces on a monitor.
// I don't really care lol :P
diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp
index a697abc9..2dca96bb 100644
--- a/src/protocols/Screencopy.cpp
+++ b/src/protocols/Screencopy.cpp
@@ -51,11 +51,20 @@ static void handleDestroy(wl_client* client, wl_resource* resource) {
}
static void handleCopyFrame(wl_client* client, wl_resource* resource, wl_resource* buffer) {
+ const auto PFRAME = frameFromResource(resource);
+
+ if (!PFRAME)
+ return;
+
g_pProtocolManager->m_pScreencopyProtocolManager->copyFrame(client, resource, buffer);
}
static void handleCopyWithDamage(wl_client* client, wl_resource* resource, wl_resource* buffer) {
- const auto PFRAME = frameFromResource(resource);
+ const auto PFRAME = frameFromResource(resource);
+
+ if (!PFRAME)
+ return;
+
PFRAME->withDamage = true;
handleCopyFrame(client, resource, buffer);
}
@@ -206,10 +215,9 @@ void CScreencopyProtocolManager::captureOutput(wl_client* client, wl_resource* r
zwlr_screencopy_frame_v1_send_buffer(PFRAME->resource, convert_drm_format_to_wl_shm(PFRAME->shmFormat), PFRAME->box.width, PFRAME->box.height, PFRAME->shmStride);
if (wl_resource_get_version(resource) >= 3) {
- // todo
- // if (PFRAME->dmabufFormat != DRM_FORMAT_INVALID) {
- // zwlr_screencopy_frame_v1_send_linux_dmabuf(PFRAME->resource, PFRAME->dmabufFormat, PFRAME->box.width, PFRAME->box.height);
- // }
+ if (PFRAME->dmabufFormat != DRM_FORMAT_INVALID) {
+ zwlr_screencopy_frame_v1_send_linux_dmabuf(PFRAME->resource, PFRAME->dmabufFormat, PFRAME->box.width, PFRAME->box.height);
+ }
zwlr_screencopy_frame_v1_send_buffer_done(PFRAME->resource);
}
@@ -284,7 +292,17 @@ void CScreencopyProtocolManager::copyFrame(wl_client* client, wl_resource* resou
g_pCompositor->scheduleFrameForMonitor(PFRAME->pMonitor);
}
+void CScreencopyProtocolManager::onOutputCommit(CMonitor* pMonitor, wlr_output_event_commit* e) {
+ m_pLastMonitorBackBuffer = e->buffer;
+ shareAllFrames(pMonitor, true);
+ m_pLastMonitorBackBuffer = nullptr;
+}
+
void CScreencopyProtocolManager::onRenderEnd(CMonitor* pMonitor) {
+ shareAllFrames(pMonitor, false);
+}
+
+void CScreencopyProtocolManager::shareAllFrames(CMonitor* pMonitor, bool dmabuf) {
if (m_vFramesAwaitingWrite.empty())
return; // nothing to share
@@ -297,7 +315,7 @@ void CScreencopyProtocolManager::onRenderEnd(CMonitor* pMonitor) {
continue;
}
- if (f->pMonitor != pMonitor)
+ if (f->pMonitor != pMonitor || dmabuf != (f->bufferCap == WLR_BUFFER_CAP_DMABUF))
continue;
shareFrame(f);
@@ -349,6 +367,7 @@ void CScreencopyProtocolManager::shareFrame(SScreencopyFrame* frame) {
uint32_t tvSecLo = now.tv_sec & 0xFFFFFFFF;
zwlr_screencopy_frame_v1_send_ready(frame->resource, tvSecHi, tvSecLo, now.tv_nsec);
}
+
void CScreencopyProtocolManager::sendFrameDamage(SScreencopyFrame* frame) {
if (!frame->withDamage)
return;
@@ -408,7 +427,27 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec*
}
bool CScreencopyProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame) {
- // todo
- Debug::log(ERR, "DMABUF copying not impl'd!");
- return false;
+ wlr_texture* sourceTex = wlr_texture_from_buffer(g_pCompositor->m_sWLRRenderer, m_pLastMonitorBackBuffer);
+ if (!sourceTex)
+ return false;
+
+ float glMatrix[9];
+ wlr_matrix_identity(glMatrix);
+ wlr_matrix_scale(glMatrix, frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y);
+ wlr_matrix_translate(glMatrix, -frame->box.x, -frame->box.y);
+
+ if (!wlr_renderer_begin_with_buffer(g_pCompositor->m_sWLRRenderer, frame->buffer)) {
+ wlr_texture_destroy(sourceTex);
+ return false;
+ }
+
+ float color[] = {0, 0, 0, 0};
+ wlr_renderer_clear(g_pCompositor->m_sWLRRenderer, color);
+ wlr_render_texture_with_matrix(g_pCompositor->m_sWLRRenderer, sourceTex, glMatrix, 1.0f);
+
+ wlr_texture_destroy(sourceTex);
+
+ wlr_renderer_end(g_pCompositor->m_sWLRRenderer);
+
+ return true;
}
diff --git a/src/protocols/Screencopy.hpp b/src/protocols/Screencopy.hpp
index d854c3bd..77d2b5c3 100644
--- a/src/protocols/Screencopy.hpp
+++ b/src/protocols/Screencopy.hpp
@@ -54,6 +54,7 @@ class CScreencopyProtocolManager {
void copyFrame(wl_client* client, wl_resource* resource, wl_resource* buffer);
void onRenderEnd(CMonitor* pMonitor);
+ void onOutputCommit(CMonitor* pMonitor, wlr_output_event_commit* e);
private:
wl_global* m_pGlobal = nullptr;
@@ -64,6 +65,9 @@ class CScreencopyProtocolManager {
std::vector<SScreencopyFrame*> m_vFramesAwaitingWrite;
+ wlr_buffer* m_pLastMonitorBackBuffer = nullptr;
+
+ void shareAllFrames(CMonitor* pMonitor, bool dmabuf);
void shareFrame(SScreencopyFrame* frame);
void sendFrameDamage(SScreencopyFrame* frame);
bool copyFrameDmabuf(SScreencopyFrame* frame);