aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorVaxry <[email protected]>2024-02-14 22:05:36 +0000
committerVaxry <[email protected]>2024-02-14 22:05:41 +0000
commit305b1419c8ff463836324168946bc34417dc0310 (patch)
treeb99facc5a1b33356477778168e012c9a05682d29
parentd5950f7719d3c9ec5305208265366df5ce81b6c3 (diff)
downloadHyprland-305b1419c8ff463836324168946bc34417dc0310.tar.gz
Hyprland-305b1419c8ff463836324168946bc34417dc0310.zip
renderer: accept custom state requests for fake outputs
-rw-r--r--src/events/Monitors.cpp16
-rw-r--r--src/helpers/Monitor.hpp55
-rw-r--r--src/render/Renderer.cpp102
3 files changed, 94 insertions, 79 deletions
diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp
index ddbc81f7..f54c2d37 100644
--- a/src/events/Monitors.cpp
+++ b/src/events/Monitors.cpp
@@ -209,10 +209,20 @@ void Events::listener_monitorDestroy(void* owner, void* data) {
}
void Events::listener_monitorStateRequest(void* owner, void* data) {
- //const auto PMONITOR = (CMonitor*)owner;
- //const auto E = (wlr_output_event_request_state*)data;
+ const auto PMONITOR = (CMonitor*)owner;
+ const auto E = (wlr_output_event_request_state*)data;
+
+ if (!PMONITOR->createdByUser)
+ return;
+
+ const auto SIZE = E->state->mode ? Vector2D{E->state->mode->width, E->state->mode->height} : Vector2D{E->state->custom_mode.width, E->state->custom_mode.height};
+
+ PMONITOR->forceSize = SIZE;
+
+ SMonitorRule rule = PMONITOR->activeMonitorRule;
+ rule.resolution = SIZE;
- // TODO: maybe don't ignore?
+ g_pHyprRenderer->applyMonitorRule(PMONITOR, &rule);
}
void Events::listener_monitorDamage(void* owner, void* data) {
diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp
index d5aba751..c5eb70a0 100644
--- a/src/helpers/Monitor.hpp
+++ b/src/helpers/Monitor.hpp
@@ -73,33 +73,34 @@ class CMonitor {
CMonitorState state;
// WLR stuff
- wlr_damage_ring damage;
- wlr_output* output = nullptr;
- float refreshRate = 60;
- int framesToSkip = 0;
- int forceFullFrames = 0;
- bool noFrameSchedule = false;
- bool scheduledRecalc = false;
- wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
- bool gammaChanged = false;
- float xwaylandScale = 1.f;
- std::array<float, 9> projMatrix = {0};
-
- bool dpmsStatus = true;
- bool vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it.
- bool enabled10bit = false; // as above, this can be TRUE even if 10 bit failed.
- bool createdByUser = false;
- uint32_t drmFormat = DRM_FORMAT_INVALID;
- bool isUnsafeFallback = false;
-
- bool pendingFrame = false; // if we schedule a frame during rendering, reschedule it after
- bool renderingActive = false;
-
- wl_event_source* renderTimer = nullptr; // for RAT
- bool RATScheduled = false;
- CTimer lastPresentationTimer;
-
- SMonitorRule activeMonitorRule;
+ wlr_damage_ring damage;
+ wlr_output* output = nullptr;
+ float refreshRate = 60;
+ int framesToSkip = 0;
+ int forceFullFrames = 0;
+ bool noFrameSchedule = false;
+ bool scheduledRecalc = false;
+ wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
+ bool gammaChanged = false;
+ float xwaylandScale = 1.f;
+ std::array<float, 9> projMatrix = {0};
+ std::optional<Vector2D> forceSize;
+
+ bool dpmsStatus = true;
+ bool vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it.
+ bool enabled10bit = false; // as above, this can be TRUE even if 10 bit failed.
+ bool createdByUser = false;
+ uint32_t drmFormat = DRM_FORMAT_INVALID;
+ bool isUnsafeFallback = false;
+
+ bool pendingFrame = false; // if we schedule a frame during rendering, reschedule it after
+ bool renderingActive = false;
+
+ wl_event_source* renderTimer = nullptr; // for RAT
+ bool RATScheduled = false;
+ CTimer lastPresentationTimer;
+
+ SMonitorRule activeMonitorRule;
// mirroring
CMonitor* pMirrorOf = nullptr;
diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp
index 65477b31..55d11303 100644
--- a/src/render/Renderer.cpp
+++ b/src/render/Renderer.cpp
@@ -1736,8 +1736,13 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
pMonitor->activeMonitorRule = *pMonitorRule;
+ if (pMonitor->forceSize.has_value())
+ pMonitor->activeMonitorRule.resolution = pMonitor->forceSize.value();
+
+ const auto RULE = &pMonitor->activeMonitorRule;
+
// if it's disabled, disable and ignore
- if (pMonitorRule->disabled) {
+ if (RULE->disabled) {
if (pMonitor->m_bEnabled)
pMonitor->onDisconnect();
@@ -1756,12 +1761,12 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
// Check if the rule isn't already applied
// TODO: clean this up lol
- if (!force && DELTALESSTHAN(pMonitor->vecPixelSize.x, pMonitorRule->resolution.x, 1) && DELTALESSTHAN(pMonitor->vecPixelSize.y, pMonitorRule->resolution.y, 1) &&
- DELTALESSTHAN(pMonitor->refreshRate, pMonitorRule->refreshRate, 1) && pMonitor->setScale == pMonitorRule->scale &&
- ((DELTALESSTHAN(pMonitor->vecPosition.x, pMonitorRule->offset.x, 1) && DELTALESSTHAN(pMonitor->vecPosition.y, pMonitorRule->offset.y, 1)) ||
- pMonitorRule->offset == Vector2D(-INT32_MAX, -INT32_MAX)) &&
- pMonitor->transform == pMonitorRule->transform && pMonitorRule->enable10bit == pMonitor->enabled10bit &&
- !memcmp(&pMonitor->customDrmMode, &pMonitorRule->drmMode, sizeof(pMonitor->customDrmMode))) {
+ if (!force && DELTALESSTHAN(pMonitor->vecPixelSize.x, RULE->resolution.x, 1) && DELTALESSTHAN(pMonitor->vecPixelSize.y, RULE->resolution.y, 1) &&
+ DELTALESSTHAN(pMonitor->refreshRate, RULE->refreshRate, 1) && pMonitor->setScale == RULE->scale &&
+ ((DELTALESSTHAN(pMonitor->vecPosition.x, RULE->offset.x, 1) && DELTALESSTHAN(pMonitor->vecPosition.y, RULE->offset.y, 1)) ||
+ RULE->offset == Vector2D(-INT32_MAX, -INT32_MAX)) &&
+ pMonitor->transform == RULE->transform && RULE->enable10bit == pMonitor->enabled10bit &&
+ !memcmp(&pMonitor->customDrmMode, &RULE->drmMode, sizeof(pMonitor->customDrmMode))) {
Debug::log(LOG, "Not applying a new rule to {} because it's already applied!", pMonitor->szName);
return true;
@@ -1774,8 +1779,8 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
pMonitor->customDrmMode = {};
bool autoScale = false;
- if (pMonitorRule->scale > 0.1) {
- pMonitor->scale = pMonitorRule->scale;
+ if (RULE->scale > 0.1) {
+ pMonitor->scale = RULE->scale;
} else {
autoScale = true;
const auto DEFAULTSCALE = pMonitor->getDefaultScale();
@@ -1785,21 +1790,21 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
wlr_output_state_set_scale(pMonitor->state.wlr(), pMonitor->scale);
pMonitor->setScale = pMonitor->scale;
- wlr_output_state_set_transform(pMonitor->state.wlr(), pMonitorRule->transform);
- pMonitor->transform = pMonitorRule->transform;
+ wlr_output_state_set_transform(pMonitor->state.wlr(), RULE->transform);
+ pMonitor->transform = RULE->transform;
- const auto WLRREFRESHRATE = (wlr_backend_is_wl(pMonitor->output->backend) || wlr_backend_is_x11(pMonitor->output->backend)) ? 0 : pMonitorRule->refreshRate * 1000;
+ const auto WLRREFRESHRATE = (wlr_backend_is_wl(pMonitor->output->backend) || wlr_backend_is_x11(pMonitor->output->backend)) ? 0 : RULE->refreshRate * 1000;
// loop over modes and choose an appropriate one.
- if (pMonitorRule->resolution != Vector2D() && pMonitorRule->resolution != Vector2D(-1, -1) && pMonitorRule->resolution != Vector2D(-1, -2)) {
- if (!wl_list_empty(&pMonitor->output->modes) && pMonitorRule->drmMode.type != DRM_MODE_TYPE_USERDEF) {
+ if (RULE->resolution != Vector2D() && RULE->resolution != Vector2D(-1, -1) && RULE->resolution != Vector2D(-1, -2)) {
+ if (!wl_list_empty(&pMonitor->output->modes) && RULE->drmMode.type != DRM_MODE_TYPE_USERDEF) {
wlr_output_mode* mode;
bool found = false;
wl_list_for_each(mode, &pMonitor->output->modes, link) {
// if delta of refresh rate, w and h chosen and mode is < 1 we accept it
- if (DELTALESSTHAN(mode->width, pMonitorRule->resolution.x, 1) && DELTALESSTHAN(mode->height, pMonitorRule->resolution.y, 1) &&
- DELTALESSTHAN(mode->refresh / 1000.f, pMonitorRule->refreshRate, 1)) {
+ if (DELTALESSTHAN(mode->width, RULE->resolution.x, 1) && DELTALESSTHAN(mode->height, RULE->resolution.y, 1) &&
+ DELTALESSTHAN(mode->refresh / 1000.f, RULE->refreshRate, 1)) {
wlr_output_state_set_mode(pMonitor->state.wlr(), mode);
if (!wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) {
@@ -1807,8 +1812,8 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
continue;
}
- Debug::log(LOG, "Monitor {}: requested {:X0}@{:2f}, found available mode: {}x{}@{}mHz, applying.", pMonitor->output->name, pMonitorRule->resolution,
- (float)pMonitorRule->refreshRate, mode->width, mode->height, mode->refresh);
+ Debug::log(LOG, "Monitor {}: requested {:X0}@{:2f}, found available mode: {}x{}@{}mHz, applying.", pMonitor->output->name, RULE->resolution,
+ (float)RULE->refreshRate, mode->width, mode->height, mode->refresh);
found = true;
@@ -1820,9 +1825,9 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
}
if (!found) {
- wlr_output_state_set_custom_mode(pMonitor->state.wlr(), (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, WLRREFRESHRATE);
- pMonitor->vecSize = pMonitorRule->resolution;
- pMonitor->refreshRate = pMonitorRule->refreshRate;
+ wlr_output_state_set_custom_mode(pMonitor->state.wlr(), (int)RULE->resolution.x, (int)RULE->resolution.y, WLRREFRESHRATE);
+ pMonitor->vecSize = RULE->resolution;
+ pMonitor->refreshRate = RULE->refreshRate;
if (!wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) {
Debug::log(ERR, "Custom resolution FAILED, falling back to preferred");
@@ -1830,47 +1835,47 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output);
if (!PREFERREDMODE) {
- Debug::log(ERR, "Monitor {} has NO PREFERRED MODE, and an INVALID one was requested: {:X0}@{:2f}", pMonitor->ID, pMonitorRule->resolution,
- (float)pMonitorRule->refreshRate);
+ Debug::log(ERR, "Monitor {} has NO PREFERRED MODE, and an INVALID one was requested: {:X0}@{:2f}", pMonitor->ID, RULE->resolution,
+ (float)RULE->refreshRate);
return true;
}
// Preferred is valid
wlr_output_state_set_mode(pMonitor->state.wlr(), PREFERREDMODE);
- Debug::log(ERR, "Monitor {} got an invalid requested mode: {:X0}@{:2f}, using the preferred one instead: {}x{}@{:2f}", pMonitor->output->name,
- pMonitorRule->resolution, (float)pMonitorRule->refreshRate, PREFERREDMODE->width, PREFERREDMODE->height, PREFERREDMODE->refresh / 1000.f);
+ Debug::log(ERR, "Monitor {} got an invalid requested mode: {:X0}@{:2f}, using the preferred one instead: {}x{}@{:2f}", pMonitor->output->name, RULE->resolution,
+ (float)RULE->refreshRate, PREFERREDMODE->width, PREFERREDMODE->height, PREFERREDMODE->refresh / 1000.f);
pMonitor->refreshRate = PREFERREDMODE->refresh / 1000.f;
pMonitor->vecSize = Vector2D(PREFERREDMODE->width, PREFERREDMODE->height);
} else {
- Debug::log(LOG, "Set a custom mode {:X0}@{:2f} (mode not found in monitor modes)", pMonitorRule->resolution, (float)pMonitorRule->refreshRate);
+ Debug::log(LOG, "Set a custom mode {:X0}@{:2f} (mode not found in monitor modes)", RULE->resolution, (float)RULE->refreshRate);
}
}
} else {
// custom resolution
bool fail = false;
- if (pMonitorRule->drmMode.type == DRM_MODE_TYPE_USERDEF) {
+ if (RULE->drmMode.type == DRM_MODE_TYPE_USERDEF) {
if (!wlr_output_is_drm(pMonitor->output)) {
Debug::log(ERR, "Tried to set custom modeline on non-DRM output");
fail = true;
} else {
- auto* mode = wlr_drm_connector_add_mode(pMonitor->output, &pMonitorRule->drmMode);
+ auto* mode = wlr_drm_connector_add_mode(pMonitor->output, &RULE->drmMode);
if (mode) {
wlr_output_state_set_mode(pMonitor->state.wlr(), mode);
- pMonitor->customDrmMode = pMonitorRule->drmMode;
+ pMonitor->customDrmMode = RULE->drmMode;
} else {
Debug::log(ERR, "wlr_drm_connector_add_mode failed");
fail = true;
}
}
} else {
- wlr_output_state_set_custom_mode(pMonitor->state.wlr(), (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, WLRREFRESHRATE);
+ wlr_output_state_set_custom_mode(pMonitor->state.wlr(), (int)RULE->resolution.x, (int)RULE->resolution.y, WLRREFRESHRATE);
}
- pMonitor->vecSize = pMonitorRule->resolution;
- pMonitor->refreshRate = pMonitorRule->refreshRate;
+ pMonitor->vecSize = RULE->resolution;
+ pMonitor->refreshRate = RULE->refreshRate;
if (fail || !wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) {
Debug::log(ERR, "Custom resolution FAILED, falling back to preferred");
@@ -1878,25 +1883,25 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output);
if (!PREFERREDMODE) {
- Debug::log(ERR, "Monitor {} has NO PREFERRED MODE, and an INVALID one was requested: {:X0}@{:2f}", pMonitor->output->name, pMonitorRule->resolution,
- (float)pMonitorRule->refreshRate);
+ Debug::log(ERR, "Monitor {} has NO PREFERRED MODE, and an INVALID one was requested: {:X0}@{:2f}", pMonitor->output->name, RULE->resolution,
+ (float)RULE->refreshRate);
return true;
}
// Preferred is valid
wlr_output_state_set_mode(pMonitor->state.wlr(), PREFERREDMODE);
- Debug::log(ERR, "Monitor {} got an invalid requested mode: {:X0}@{:2f}, using the preferred one instead: {}x{}@{:2f}", pMonitor->output->name,
- pMonitorRule->resolution, (float)pMonitorRule->refreshRate, PREFERREDMODE->width, PREFERREDMODE->height, PREFERREDMODE->refresh / 1000.f);
+ Debug::log(ERR, "Monitor {} got an invalid requested mode: {:X0}@{:2f}, using the preferred one instead: {}x{}@{:2f}", pMonitor->output->name, RULE->resolution,
+ (float)RULE->refreshRate, PREFERREDMODE->width, PREFERREDMODE->height, PREFERREDMODE->refresh / 1000.f);
pMonitor->refreshRate = PREFERREDMODE->refresh / 1000.f;
pMonitor->vecSize = Vector2D(PREFERREDMODE->width, PREFERREDMODE->height);
pMonitor->customDrmMode = {};
} else {
- Debug::log(LOG, "Set a custom mode {:X0}@{:2f} (mode not found in monitor modes)", pMonitorRule->resolution, (float)pMonitorRule->refreshRate);
+ Debug::log(LOG, "Set a custom mode {:X0}@{:2f} (mode not found in monitor modes)", RULE->resolution, (float)RULE->refreshRate);
}
}
- } else if (pMonitorRule->resolution != Vector2D()) {
+ } else if (RULE->resolution != Vector2D()) {
if (!wl_list_empty(&pMonitor->output->modes)) {
wlr_output_mode* mode;
float currentWidth = 0;
@@ -1905,7 +1910,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
bool success = false;
//(-1,-1) indicates a preference to refreshrate over resolution, (-1,-2) preference to resolution
- if (pMonitorRule->resolution == Vector2D(-1, -1)) {
+ if (RULE->resolution == Vector2D(-1, -1)) {
wl_list_for_each(mode, &pMonitor->output->modes, link) {
if ((mode->width >= currentWidth && mode->height >= currentHeight && mode->refresh >= (currentRefresh - 1000.f)) || mode->refresh > (currentRefresh + 3000.f)) {
wlr_output_state_set_mode(pMonitor->state.wlr(), mode);
@@ -1933,22 +1938,21 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
}
if (!success) {
- Debug::log(LOG, "Monitor {}: REJECTED mode: {:X0}@{:2f}! Falling back to preferred: {}x{}@{:2f}", pMonitor->output->name, pMonitorRule->resolution,
- (float)pMonitorRule->refreshRate, mode->width, mode->height, mode->refresh / 1000.f);
+ Debug::log(LOG, "Monitor {}: REJECTED mode: {:X0}@{:2f}! Falling back to preferred: {}x{}@{:2f}", pMonitor->output->name, RULE->resolution,
+ (float)RULE->refreshRate, mode->width, mode->height, mode->refresh / 1000.f);
const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output);
if (!PREFERREDMODE) {
- Debug::log(ERR, "Monitor {} has NO PREFERRED MODE, and an INVALID one was requested: {:X0}@{:2f}", pMonitor->ID, pMonitorRule->resolution,
- (float)pMonitorRule->refreshRate);
+ Debug::log(ERR, "Monitor {} has NO PREFERRED MODE, and an INVALID one was requested: {:X0}@{:2f}", pMonitor->ID, RULE->resolution, (float)RULE->refreshRate);
return true;
}
// Preferred is valid
wlr_output_state_set_mode(pMonitor->state.wlr(), PREFERREDMODE);
- Debug::log(ERR, "Monitor {} got an invalid requested mode: {:X0}@{:2f}, using the preferred one instead: {}x{}@{:2f}", pMonitor->output->name,
- pMonitorRule->resolution, (float)pMonitorRule->refreshRate, PREFERREDMODE->width, PREFERREDMODE->height, PREFERREDMODE->refresh / 1000.f);
+ Debug::log(ERR, "Monitor {} got an invalid requested mode: {:X0}@{:2f}, using the preferred one instead: {}x{}@{:2f}", pMonitor->output->name, RULE->resolution,
+ (float)RULE->refreshRate, PREFERREDMODE->width, PREFERREDMODE->height, PREFERREDMODE->refresh / 1000.f);
pMonitor->refreshRate = PREFERREDMODE->refresh / 1000.f;
pMonitor->vecSize = Vector2D(PREFERREDMODE->width, PREFERREDMODE->height);
@@ -1977,8 +1981,8 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
continue;
}
- Debug::log(LOG, "Monitor {}: requested {:X0}@{:2f}, found available mode: {}x{}@{}mHz, applying.", pMonitor->output->name, pMonitorRule->resolution,
- (float)pMonitorRule->refreshRate, mode->width, mode->height, mode->refresh);
+ Debug::log(LOG, "Monitor {}: requested {:X0}@{:2f}, found available mode: {}x{}@{}mHz, applying.", pMonitor->output->name, RULE->resolution,
+ (float)RULE->refreshRate, mode->width, mode->height, mode->refresh);
pMonitor->refreshRate = mode->refresh / 1000.f;
pMonitor->vecSize = Vector2D(mode->width, mode->height);
@@ -2076,14 +2080,14 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
bool set10bit = false;
pMonitor->drmFormat = DRM_FORMAT_INVALID;
- for (auto& fmt : formats[(int)!pMonitorRule->enable10bit]) {
+ for (auto& fmt : formats[(int)!RULE->enable10bit]) {
wlr_output_state_set_render_format(pMonitor->state.wlr(), fmt.second);
if (!wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) {
Debug::log(ERR, "output {} failed basic test on format {}", pMonitor->szName, fmt.first);
} else {
Debug::log(LOG, "output {} succeeded basic test on format {}", pMonitor->szName, fmt.first);
- if (pMonitorRule->enable10bit && fmt.first.contains("101010"))
+ if (RULE->enable10bit && fmt.first.contains("101010"))
set10bit = true;
pMonitor->drmFormat = fmt.second;