aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/helpers/Monitor.cpp6
-rw-r--r--src/helpers/Monitor.hpp5
-rw-r--r--src/managers/ProtocolManager.cpp3
-rw-r--r--src/protocols/CTMControl.cpp86
-rw-r--r--src/protocols/CTMControl.hpp44
-rw-r--r--src/render/Renderer.cpp5
6 files changed, 149 insertions, 0 deletions
diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp
index c6cef41f..f3e7de4e 100644
--- a/src/helpers/Monitor.cpp
+++ b/src/helpers/Monitor.cpp
@@ -813,6 +813,12 @@ void CMonitor::scheduleDone() {
});
}
+void CMonitor::setCTM(const Mat3x3& ctm_) {
+ ctm = ctm_;
+ ctmUpdated = true;
+ g_pCompositor->scheduleFrameForMonitor(this, Aquamarine::IOutput::scheduleFrameReason::AQ_SCHEDULE_NEEDS_FRAME);
+}
+
bool CMonitor::attemptDirectScanout() {
if (!mirrors.empty() || isMirror() || g_pHyprRenderer->m_bDirectScanoutBlocked)
return false; // do not DS if this monitor is being mirrored. Will break the functionality.
diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp
index 2a2edab6..f5068dba 100644
--- a/src/helpers/Monitor.hpp
+++ b/src/helpers/Monitor.hpp
@@ -131,6 +131,10 @@ class CMonitor {
CMonitor* pMirrorOf = nullptr;
std::vector<CMonitor*> mirrors;
+ // ctm
+ Mat3x3 ctm = Mat3x3::identity();
+ bool ctmUpdated = false;
+
// for tearing
PHLWINDOWREF solitaryClient;
@@ -179,6 +183,7 @@ class CMonitor {
CBox logicalBox();
void scheduleDone();
bool attemptDirectScanout();
+ void setCTM(const Mat3x3& ctm);
bool m_bEnabled = false;
bool m_bRenderingInitPassed = false;
diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp
index 6366eefe..25a34657 100644
--- a/src/managers/ProtocolManager.cpp
+++ b/src/managers/ProtocolManager.cpp
@@ -46,6 +46,7 @@
#include "../protocols/XDGDialog.hpp"
#include "../protocols/SinglePixel.hpp"
#include "../protocols/SecurityContext.hpp"
+#include "../protocols/CTMControl.hpp"
#include "../protocols/core/Seat.hpp"
#include "../protocols/core/DataDevice.hpp"
@@ -157,6 +158,7 @@ CProtocolManager::CProtocolManager() {
PROTO::xdgDialog = std::make_unique<CXDGDialogProtocol>(&xdg_dialog_v1_interface, 1, "XDGDialog");
PROTO::singlePixel = std::make_unique<CSinglePixelProtocol>(&wp_single_pixel_buffer_manager_v1_interface, 1, "SinglePixel");
PROTO::securityContext = std::make_unique<CSecurityContextProtocol>(&wp_security_context_manager_v1_interface, 1, "SecurityContext");
+ PROTO::ctm = std::make_unique<CHyprlandCTMControlProtocol>(&hyprland_ctm_control_manager_v1_interface, 1, "CTMControl");
for (auto const& b : g_pCompositor->m_pAqBackend->getImplementations()) {
if (b->type() != Aquamarine::AQ_BACKEND_DRM)
@@ -229,6 +231,7 @@ CProtocolManager::~CProtocolManager() {
PROTO::xdgDialog.reset();
PROTO::singlePixel.reset();
PROTO::securityContext.reset();
+ PROTO::ctm.reset();
PROTO::lease.reset();
PROTO::sync.reset();
diff --git a/src/protocols/CTMControl.cpp b/src/protocols/CTMControl.cpp
new file mode 100644
index 00000000..f2a54c6f
--- /dev/null
+++ b/src/protocols/CTMControl.cpp
@@ -0,0 +1,86 @@
+#include "CTMControl.hpp"
+#include "../Compositor.hpp"
+#include "core/Output.hpp"
+
+CHyprlandCTMControlResource::CHyprlandCTMControlResource(SP<CHyprlandCtmControlManagerV1> resource_) : resource(resource_) {
+ if (!good())
+ return;
+
+ resource->setDestroy([this](CHyprlandCtmControlManagerV1* pMgr) { PROTO::ctm->destroyResource(this); });
+ resource->setOnDestroy([this](CHyprlandCtmControlManagerV1* pMgr) { PROTO::ctm->destroyResource(this); });
+
+ resource->setSetCtmForOutput([this](CHyprlandCtmControlManagerV1* r, wl_resource* output, wl_fixed_t mat0, wl_fixed_t mat1, wl_fixed_t mat2, wl_fixed_t mat3, wl_fixed_t mat4,
+ wl_fixed_t mat5, wl_fixed_t mat6, wl_fixed_t mat7, wl_fixed_t mat8) {
+ const auto OUTPUTRESOURCE = CWLOutputResource::fromResource(output);
+
+ if (!OUTPUTRESOURCE)
+ return; // ?!
+
+ const auto PMONITOR = OUTPUTRESOURCE->monitor.lock();
+
+ if (!PMONITOR)
+ return; // ?!?!
+
+ const std::array<float, 9> MAT = {wl_fixed_to_double(mat0), wl_fixed_to_double(mat1), wl_fixed_to_double(mat2), wl_fixed_to_double(mat3), wl_fixed_to_double(mat4),
+ wl_fixed_to_double(mat5), wl_fixed_to_double(mat6), wl_fixed_to_double(mat7), wl_fixed_to_double(mat8)};
+
+ for (auto& el : MAT) {
+ if (el < 0.F) {
+ resource->error(HYPRLAND_CTM_CONTROL_MANAGER_V1_ERROR_INVALID_MATRIX, "a matrix component was < 0");
+ return;
+ }
+ }
+
+ ctms[PMONITOR->szName] = MAT;
+
+ LOGM(LOG, "CTM set for output {}: {}", PMONITOR->szName, ctms.at(PMONITOR->szName).toString());
+ });
+
+ resource->setCommit([this](CHyprlandCtmControlManagerV1* r) {
+ LOGM(LOG, "Committing ctms to outputs");
+
+ for (auto& m : g_pCompositor->m_vMonitors) {
+ if (!ctms.contains(m->szName)) {
+ PROTO::ctm->setCTM(m, Mat3x3::identity());
+ continue;
+ }
+
+ PROTO::ctm->setCTM(m, ctms.at(m->szName));
+ }
+ });
+}
+
+CHyprlandCTMControlResource::~CHyprlandCTMControlResource() {
+ for (auto& m : g_pCompositor->m_vMonitors) {
+ PROTO::ctm->setCTM(m, Mat3x3::identity());
+ }
+}
+
+bool CHyprlandCTMControlResource::good() {
+ return resource->resource();
+}
+
+CHyprlandCTMControlProtocol::CHyprlandCTMControlProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
+ ;
+}
+
+void CHyprlandCTMControlProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
+
+ const auto RESOURCE = m_vManagers.emplace_back(makeShared<CHyprlandCTMControlResource>(makeShared<CHyprlandCtmControlManagerV1>(client, ver, id)));
+
+ if (!RESOURCE->good()) {
+ wl_client_post_no_memory(client);
+ m_vManagers.pop_back();
+ return;
+ }
+
+ LOGM(LOG, "New CTM Manager at 0x{:x}", (uintptr_t)RESOURCE.get());
+}
+
+void CHyprlandCTMControlProtocol::destroyResource(CHyprlandCTMControlResource* res) {
+ std::erase_if(m_vManagers, [&](const auto& other) { return other.get() == res; });
+}
+
+void CHyprlandCTMControlProtocol::setCTM(SP<CMonitor> monitor, const Mat3x3& ctm) {
+ monitor->setCTM(ctm);
+}
diff --git a/src/protocols/CTMControl.hpp b/src/protocols/CTMControl.hpp
new file mode 100644
index 00000000..08f1b0e8
--- /dev/null
+++ b/src/protocols/CTMControl.hpp
@@ -0,0 +1,44 @@
+#pragma once
+
+#include <memory>
+#include <vector>
+#include <cstdint>
+#include "WaylandProtocol.hpp"
+#include "hyprland-ctm-control-v1.hpp"
+#include <unordered_map>
+
+class CMonitor;
+
+class CHyprlandCTMControlResource {
+ public:
+ CHyprlandCTMControlResource(SP<CHyprlandCtmControlManagerV1> resource_);
+ ~CHyprlandCTMControlResource();
+
+ bool good();
+
+ private:
+ SP<CHyprlandCtmControlManagerV1> resource;
+
+ std::unordered_map<std::string, Mat3x3> ctms;
+};
+
+class CHyprlandCTMControlProtocol : public IWaylandProtocol {
+ public:
+ CHyprlandCTMControlProtocol(const wl_interface* iface, const int& ver, const std::string& name);
+
+ virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id);
+
+ private:
+ void destroyResource(CHyprlandCTMControlResource* resource);
+
+ void setCTM(SP<CMonitor> monitor, const Mat3x3& ctm);
+
+ //
+ std::vector<SP<CHyprlandCTMControlResource>> m_vManagers;
+
+ friend class CHyprlandCTMControlResource;
+};
+
+namespace PROTO {
+ inline UP<CHyprlandCTMControlProtocol> ctm;
+}; \ No newline at end of file
diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp
index 310d45af..f388ec37 100644
--- a/src/render/Renderer.cpp
+++ b/src/render/Renderer.cpp
@@ -1498,6 +1498,11 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(CMonitor* pMonitor) {
if (inFD >= 0)
pMonitor->output->state->setExplicitInFence(inFD);
+ if (pMonitor->ctmUpdated) {
+ pMonitor->ctmUpdated = false;
+ pMonitor->output->state->setCTM(pMonitor->ctm);
+ }
+
bool ok = pMonitor->state.commit();
if (!ok) {
if (inFD >= 0) {