mirror of
https://github.com/hyprwm/Hyprland
synced 2024-12-23 09:29:49 +01:00
screencopy: implement dmabuf
This commit is contained in:
parent
985764c8db
commit
a22e1174ee
6 changed files with 65 additions and 9 deletions
|
@ -100,6 +100,7 @@ namespace Events {
|
||||||
DYNLISTENFUNC(monitorStateRequest);
|
DYNLISTENFUNC(monitorStateRequest);
|
||||||
DYNLISTENFUNC(monitorDamage);
|
DYNLISTENFUNC(monitorDamage);
|
||||||
DYNLISTENFUNC(monitorNeedsFrame);
|
DYNLISTENFUNC(monitorNeedsFrame);
|
||||||
|
DYNLISTENFUNC(monitorCommit);
|
||||||
|
|
||||||
// XWayland
|
// XWayland
|
||||||
LISTENER(readyXWayland);
|
LISTENER(readyXWayland);
|
||||||
|
|
|
@ -212,3 +212,11 @@ void Events::listener_monitorNeedsFrame(void* owner, void* data) {
|
||||||
|
|
||||||
g_pCompositor->scheduleFrameForMonitor(PMONITOR);
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -22,11 +22,13 @@ void CMonitor::onConnect(bool noRule) {
|
||||||
hyprListener_monitorStateRequest.removeCallback();
|
hyprListener_monitorStateRequest.removeCallback();
|
||||||
hyprListener_monitorDamage.removeCallback();
|
hyprListener_monitorDamage.removeCallback();
|
||||||
hyprListener_monitorNeedsFrame.removeCallback();
|
hyprListener_monitorNeedsFrame.removeCallback();
|
||||||
|
hyprListener_monitorCommit.removeCallback();
|
||||||
hyprListener_monitorFrame.initCallback(&output->events.frame, &Events::listener_monitorFrame, this);
|
hyprListener_monitorFrame.initCallback(&output->events.frame, &Events::listener_monitorFrame, this);
|
||||||
hyprListener_monitorDestroy.initCallback(&output->events.destroy, &Events::listener_monitorDestroy, this);
|
hyprListener_monitorDestroy.initCallback(&output->events.destroy, &Events::listener_monitorDestroy, this);
|
||||||
hyprListener_monitorStateRequest.initCallback(&output->events.request_state, &Events::listener_monitorStateRequest, this);
|
hyprListener_monitorStateRequest.initCallback(&output->events.request_state, &Events::listener_monitorStateRequest, this);
|
||||||
hyprListener_monitorDamage.initCallback(&output->events.damage, &Events::listener_monitorDamage, this);
|
hyprListener_monitorDamage.initCallback(&output->events.damage, &Events::listener_monitorDamage, this);
|
||||||
hyprListener_monitorNeedsFrame.initCallback(&output->events.needs_frame, &Events::listener_monitorNeedsFrame, 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) {
|
if (m_bEnabled) {
|
||||||
wlr_output_enable(output, 1);
|
wlr_output_enable(output, 1);
|
||||||
|
@ -221,6 +223,7 @@ void CMonitor::onDisconnect() {
|
||||||
hyprListener_monitorFrame.removeCallback();
|
hyprListener_monitorFrame.removeCallback();
|
||||||
hyprListener_monitorDamage.removeCallback();
|
hyprListener_monitorDamage.removeCallback();
|
||||||
hyprListener_monitorNeedsFrame.removeCallback();
|
hyprListener_monitorNeedsFrame.removeCallback();
|
||||||
|
hyprListener_monitorCommit.removeCallback();
|
||||||
|
|
||||||
for (size_t i = 0; i < 4; ++i) {
|
for (size_t i = 0; i < 4; ++i) {
|
||||||
for (auto& ls : m_aLayerSurfaceLayers[i]) {
|
for (auto& ls : m_aLayerSurfaceLayers[i]) {
|
||||||
|
|
|
@ -67,6 +67,7 @@ class CMonitor {
|
||||||
DYNLISTENER(monitorStateRequest);
|
DYNLISTENER(monitorStateRequest);
|
||||||
DYNLISTENER(monitorDamage);
|
DYNLISTENER(monitorDamage);
|
||||||
DYNLISTENER(monitorNeedsFrame);
|
DYNLISTENER(monitorNeedsFrame);
|
||||||
|
DYNLISTENER(monitorCommit);
|
||||||
|
|
||||||
// hack: a group = workspaces on a monitor.
|
// hack: a group = workspaces on a monitor.
|
||||||
// I don't really care lol :P
|
// I don't really care lol :P
|
||||||
|
|
|
@ -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) {
|
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);
|
g_pProtocolManager->m_pScreencopyProtocolManager->copyFrame(client, resource, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handleCopyWithDamage(wl_client* client, wl_resource* resource, wl_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;
|
PFRAME->withDamage = true;
|
||||||
handleCopyFrame(client, resource, buffer);
|
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);
|
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) {
|
if (wl_resource_get_version(resource) >= 3) {
|
||||||
// todo
|
if (PFRAME->dmabufFormat != DRM_FORMAT_INVALID) {
|
||||||
// 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_linux_dmabuf(PFRAME->resource, PFRAME->dmabufFormat, PFRAME->box.width, PFRAME->box.height);
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
zwlr_screencopy_frame_v1_send_buffer_done(PFRAME->resource);
|
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);
|
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) {
|
void CScreencopyProtocolManager::onRenderEnd(CMonitor* pMonitor) {
|
||||||
|
shareAllFrames(pMonitor, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CScreencopyProtocolManager::shareAllFrames(CMonitor* pMonitor, bool dmabuf) {
|
||||||
if (m_vFramesAwaitingWrite.empty())
|
if (m_vFramesAwaitingWrite.empty())
|
||||||
return; // nothing to share
|
return; // nothing to share
|
||||||
|
|
||||||
|
@ -297,7 +315,7 @@ void CScreencopyProtocolManager::onRenderEnd(CMonitor* pMonitor) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (f->pMonitor != pMonitor)
|
if (f->pMonitor != pMonitor || dmabuf != (f->bufferCap == WLR_BUFFER_CAP_DMABUF))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
shareFrame(f);
|
shareFrame(f);
|
||||||
|
@ -349,6 +367,7 @@ void CScreencopyProtocolManager::shareFrame(SScreencopyFrame* frame) {
|
||||||
uint32_t tvSecLo = now.tv_sec & 0xFFFFFFFF;
|
uint32_t tvSecLo = now.tv_sec & 0xFFFFFFFF;
|
||||||
zwlr_screencopy_frame_v1_send_ready(frame->resource, tvSecHi, tvSecLo, now.tv_nsec);
|
zwlr_screencopy_frame_v1_send_ready(frame->resource, tvSecHi, tvSecLo, now.tv_nsec);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CScreencopyProtocolManager::sendFrameDamage(SScreencopyFrame* frame) {
|
void CScreencopyProtocolManager::sendFrameDamage(SScreencopyFrame* frame) {
|
||||||
if (!frame->withDamage)
|
if (!frame->withDamage)
|
||||||
return;
|
return;
|
||||||
|
@ -408,7 +427,27 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec*
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CScreencopyProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame) {
|
bool CScreencopyProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame) {
|
||||||
// todo
|
wlr_texture* sourceTex = wlr_texture_from_buffer(g_pCompositor->m_sWLRRenderer, m_pLastMonitorBackBuffer);
|
||||||
Debug::log(ERR, "DMABUF copying not impl'd!");
|
if (!sourceTex)
|
||||||
return false;
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,7 @@ class CScreencopyProtocolManager {
|
||||||
void copyFrame(wl_client* client, wl_resource* resource, wl_resource* buffer);
|
void copyFrame(wl_client* client, wl_resource* resource, wl_resource* buffer);
|
||||||
|
|
||||||
void onRenderEnd(CMonitor* pMonitor);
|
void onRenderEnd(CMonitor* pMonitor);
|
||||||
|
void onOutputCommit(CMonitor* pMonitor, wlr_output_event_commit* e);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
wl_global* m_pGlobal = nullptr;
|
wl_global* m_pGlobal = nullptr;
|
||||||
|
@ -64,6 +65,9 @@ class CScreencopyProtocolManager {
|
||||||
|
|
||||||
std::vector<SScreencopyFrame*> m_vFramesAwaitingWrite;
|
std::vector<SScreencopyFrame*> m_vFramesAwaitingWrite;
|
||||||
|
|
||||||
|
wlr_buffer* m_pLastMonitorBackBuffer = nullptr;
|
||||||
|
|
||||||
|
void shareAllFrames(CMonitor* pMonitor, bool dmabuf);
|
||||||
void shareFrame(SScreencopyFrame* frame);
|
void shareFrame(SScreencopyFrame* frame);
|
||||||
void sendFrameDamage(SScreencopyFrame* frame);
|
void sendFrameDamage(SScreencopyFrame* frame);
|
||||||
bool copyFrameDmabuf(SScreencopyFrame* frame);
|
bool copyFrameDmabuf(SScreencopyFrame* frame);
|
||||||
|
|
Loading…
Reference in a new issue