summaryrefslogtreecommitdiff
path: root/src/helpers/MonitorResources.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/helpers/MonitorResources.cpp')
-rw-r--r--src/helpers/MonitorResources.cpp94
1 files changed, 94 insertions, 0 deletions
diff --git a/src/helpers/MonitorResources.cpp b/src/helpers/MonitorResources.cpp
new file mode 100644
index 00000000..6f5c4d33
--- /dev/null
+++ b/src/helpers/MonitorResources.cpp
@@ -0,0 +1,94 @@
+#include "MonitorResources.hpp"
+#include "./cm/ColorManagement.hpp"
+#include "../render/Renderer.hpp"
+#include <algorithm>
+#include <format>
+
+using namespace Monitor;
+using namespace NColorManagement;
+
+static const int MAX_WORK_BUFFERS = 8;
+static const int MAX_UNUSED_SECONDS = 5;
+
+CMonitorResources::CMonitorResources(WP<CMonitor> monitor, DRMFormat format, Vector2D size, NColorManagement::PImageDescription imageDescription) :
+ m_stencilTex(g_pHyprRenderer->createStencilTexture(monitor->m_pixelSize.x, monitor->m_pixelSize.y)),
+ m_blurFB(g_pHyprRenderer->createFB(std::format("Monitor {} blur FB", monitor->m_name))), m_monitor(monitor), m_drmFormat(format), m_size(size),
+ m_imageDescription(imageDescription) {
+ initFB(m_blurFB);
+}
+
+void CMonitorResources::initFB(SP<Render::IFramebuffer> fb) {
+ fb->addStencil(m_stencilTex);
+ fb->alloc(m_size.x, m_size.y, m_drmFormat);
+ fb->setImageDescription(m_imageDescription);
+}
+
+SP<Render::IFramebuffer> CMonitorResources::getUnusedWorkBuffer() {
+ std::erase_if(m_workBuffers, [](const auto& res) { return res.lastUsed.getSeconds() >= MAX_UNUSED_SECONDS; });
+
+ auto found = std::ranges::find_if(m_workBuffers, [](const auto& res) { return res.buffer.strongRef() < 2; });
+ if (found != m_workBuffers.end()) {
+ found->lastUsed.reset();
+ return found->buffer;
+ }
+ if (m_workBuffers.size() >= MAX_WORK_BUFFERS)
+ return nullptr;
+
+ auto& res = m_workBuffers.emplace_back(g_pHyprRenderer->createFB(std::format("Monitor {} workbuffer", m_monitor->m_name)));
+ initFB(res.buffer);
+ res.lastUsed.reset();
+ return res.buffer;
+}
+
+void CMonitorResources::forEachUnusedFB(std::function<void(SP<Render::IFramebuffer>)> callback, bool includeNamed) {
+ for (const auto& res : m_workBuffers) {
+ if (res.buffer.strongRef() > 1)
+ continue;
+
+ callback(res.buffer);
+ }
+ if (includeNamed) {
+ if (m_blurFB && m_blurFB->isAllocated() && m_blurFB.strongRef() < 2)
+ callback(m_blurFB);
+ if (hasMirrorFB() && m_monitorMirrorFB.strongRef() < 2)
+ callback(m_monitorMirrorFB);
+ }
+}
+
+bool CMonitorResources::hasMirrorFB() {
+ return m_monitorMirrorFB && m_monitorMirrorFB->isAllocated();
+}
+
+SP<Render::IFramebuffer> CMonitorResources::mirrorFB() {
+ if (!m_monitorMirrorFB)
+ m_monitorMirrorFB = g_pHyprRenderer->createFB(std::format("Monitor {} mirror FB", m_monitor->m_name));
+
+ if (!m_monitorMirrorFB->isAllocated()) {
+ m_monitorMirrorFB->alloc(m_size.x, m_size.y, DRM_FORMAT_XRGB8888);
+ m_monitorMirrorFB->setImageDescription(NColorManagement::DEFAULT_IMAGE_DESCRIPTION);
+ }
+
+ return m_monitorMirrorFB;
+}
+
+SP<Render::ITexture> CMonitorResources::getMirrorTexture() {
+ return hasMirrorFB() ? mirrorFB()->getTexture() : nullptr;
+}
+
+void CMonitorResources::enableMirror() {
+ if (m_mirrorTex)
+ return;
+ m_mirrorTex = g_pHyprRenderer->createTexture();
+ m_mirrorTex->allocate({m_size.x, m_size.y}, DRM_FORMAT_XRGB8888);
+ m_mirrorTex->m_imageDescription = CImageDescription::from(SImageDescription{
+ .transferFunction = NColorManagement::CM_TRANSFER_FUNCTION_GAMMA22,
+ .primariesNameSet = m_imageDescription->value().primariesNameSet,
+ .primariesNamed = m_imageDescription->value().primariesNamed,
+ .primaries = m_imageDescription->value().primaries,
+ .luminances = {.min = SDR_MIN_LUMINANCE, .max = 80, .reference = 80},
+ });
+}
+
+void CMonitorResources::disableMirror() {
+ m_mirrorTex.reset();
+}