mirror of
https://github.com/hyprwm/Hyprland
synced 2025-12-20 15:50:05 +01:00
renderer: add overscan support
adds basic overscanning by squishing the image. Configurable per-side with px
This commit is contained in:
parent
251288ec59
commit
612a8d95ac
3 changed files with 64 additions and 2 deletions
|
|
@ -824,6 +824,10 @@ CConfigManager::CConfigManager() {
|
||||||
m_config->addSpecialConfigValue("monitorv2", "min_luminance", Hyprlang::FLOAT{-1.0});
|
m_config->addSpecialConfigValue("monitorv2", "min_luminance", Hyprlang::FLOAT{-1.0});
|
||||||
m_config->addSpecialConfigValue("monitorv2", "max_luminance", Hyprlang::INT{-1});
|
m_config->addSpecialConfigValue("monitorv2", "max_luminance", Hyprlang::INT{-1});
|
||||||
m_config->addSpecialConfigValue("monitorv2", "max_avg_luminance", Hyprlang::INT{-1});
|
m_config->addSpecialConfigValue("monitorv2", "max_avg_luminance", Hyprlang::INT{-1});
|
||||||
|
m_config->addSpecialConfigValue("monitorv2", "overscan_t", Hyprlang::INT{-1});
|
||||||
|
m_config->addSpecialConfigValue("monitorv2", "overscan_l", Hyprlang::INT{-1});
|
||||||
|
m_config->addSpecialConfigValue("monitorv2", "overscan_r", Hyprlang::INT{-1});
|
||||||
|
m_config->addSpecialConfigValue("monitorv2", "overscan_b", Hyprlang::INT{-1});
|
||||||
|
|
||||||
// keywords
|
// keywords
|
||||||
m_config->registerHandler(&::handleExec, "exec", {false});
|
m_config->registerHandler(&::handleExec, "exec", {false});
|
||||||
|
|
@ -1118,6 +1122,19 @@ std::optional<std::string> CConfigManager::handleMonitorv2(const std::string& ou
|
||||||
if (VAL && VAL->m_bSetByUser)
|
if (VAL && VAL->m_bSetByUser)
|
||||||
parser.rule().maxAvgLuminance = std::any_cast<Hyprlang::INT>(VAL->getValue());
|
parser.rule().maxAvgLuminance = std::any_cast<Hyprlang::INT>(VAL->getValue());
|
||||||
|
|
||||||
|
VAL = m_config->getSpecialConfigValuePtr("monitorv2", "overscan_t", output.c_str());
|
||||||
|
if (VAL && VAL->m_bSetByUser)
|
||||||
|
parser.rule().overscanTL.y = std::any_cast<Hyprlang::INT>(VAL->getValue());
|
||||||
|
VAL = m_config->getSpecialConfigValuePtr("monitorv2", "overscan_l", output.c_str());
|
||||||
|
if (VAL && VAL->m_bSetByUser)
|
||||||
|
parser.rule().overscanTL.x = std::any_cast<Hyprlang::INT>(VAL->getValue());
|
||||||
|
VAL = m_config->getSpecialConfigValuePtr("monitorv2", "overscan_r", output.c_str());
|
||||||
|
if (VAL && VAL->m_bSetByUser)
|
||||||
|
parser.rule().overscanBR.x = std::any_cast<Hyprlang::INT>(VAL->getValue());
|
||||||
|
VAL = m_config->getSpecialConfigValuePtr("monitorv2", "overscan_b", output.c_str());
|
||||||
|
if (VAL && VAL->m_bSetByUser)
|
||||||
|
parser.rule().overscanBR.y = std::any_cast<Hyprlang::INT>(VAL->getValue());
|
||||||
|
|
||||||
auto newrule = parser.rule();
|
auto newrule = parser.rule();
|
||||||
|
|
||||||
std::erase_if(m_monitorRules, [&](const auto& other) { return other.name == newrule.name; });
|
std::erase_if(m_monitorRules, [&](const auto& other) { return other.name == newrule.name; });
|
||||||
|
|
@ -3156,6 +3173,9 @@ bool CConfigManager::shouldUseSoftwareCursors(PHLMONITOR pMonitor) {
|
||||||
if (pMonitor->m_tearingState.activelyTearing)
|
if (pMonitor->m_tearingState.activelyTearing)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
if (pMonitor->m_activeMonitorRule.hasOverscan())
|
||||||
|
return true; // translating hw cursors would be annoying, fuck this.
|
||||||
|
|
||||||
if (*PINVISIBLE != 0)
|
if (*PINVISIBLE != 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -69,8 +69,16 @@ struct SMonitorRule {
|
||||||
int maxLuminance = -1; // >= 0 overrides EDID
|
int maxLuminance = -1; // >= 0 overrides EDID
|
||||||
int maxAvgLuminance = -1; // >= 0 overrides EDID
|
int maxAvgLuminance = -1; // >= 0 overrides EDID
|
||||||
|
|
||||||
|
Vector2D overscanTL = {0, 0};
|
||||||
|
Vector2D overscanBR = {0, 0};
|
||||||
|
|
||||||
drmModeModeInfo drmMode = {};
|
drmModeModeInfo drmMode = {};
|
||||||
std::optional<int> vrr;
|
std::optional<int> vrr;
|
||||||
|
|
||||||
|
//
|
||||||
|
bool hasOverscan() {
|
||||||
|
return overscanTL != Vector2D{0, 0} || overscanBR != Vector2D{0, 0};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class CMonitor;
|
class CMonitor;
|
||||||
|
|
|
||||||
|
|
@ -834,11 +834,45 @@ void CHyprOpenGLImpl::end() {
|
||||||
m_renderData.outFB->bind();
|
m_renderData.outFB->bind();
|
||||||
blend(false);
|
blend(false);
|
||||||
|
|
||||||
if (m_finalScreenShader.program < 1 && !g_pHyprRenderer->m_crashingInProgress)
|
if (m_finalScreenShader.program < 1 && !g_pHyprRenderer->m_crashingInProgress && !m_renderData.pMonitor->m_activeMonitorRule.hasOverscan())
|
||||||
renderTexturePrimitive(m_renderData.pCurrentMonData->offloadFB.getTexture(), monbox);
|
renderTexturePrimitive(m_renderData.pCurrentMonData->offloadFB.getTexture(), monbox);
|
||||||
else
|
else {
|
||||||
|
|
||||||
|
const auto DAMAGE_BACKUP = m_renderData.damage;
|
||||||
|
const auto FINAL_DAMAGE_BACKUP = m_renderData.finalDamage;
|
||||||
|
|
||||||
|
if (m_renderData.pMonitor->m_activeMonitorRule.hasOverscan()) {
|
||||||
|
|
||||||
|
// hack to clear undamaged areas
|
||||||
|
// FIXME: buffers should be cleared once, probably...
|
||||||
|
|
||||||
|
const auto OLD_MONBOX = monbox;
|
||||||
|
|
||||||
|
monbox.translate(m_renderData.pMonitor->m_activeMonitorRule.overscanTL);
|
||||||
|
monbox.w -= m_renderData.pMonitor->m_activeMonitorRule.overscanTL.x + m_renderData.pMonitor->m_activeMonitorRule.overscanBR.x;
|
||||||
|
monbox.h -= m_renderData.pMonitor->m_activeMonitorRule.overscanTL.y + m_renderData.pMonitor->m_activeMonitorRule.overscanBR.y;
|
||||||
|
|
||||||
|
m_renderData.damage = CRegion{OLD_MONBOX}.subtract(monbox);
|
||||||
|
clear(Colors::BLACK);
|
||||||
|
m_renderData.damage = DAMAGE_BACKUP;
|
||||||
|
|
||||||
|
// fix damage here, because we squish the image
|
||||||
|
m_renderData.damage.scale(
|
||||||
|
(m_renderData.pMonitor->m_pixelSize - m_renderData.pMonitor->m_activeMonitorRule.overscanTL - m_renderData.pMonitor->m_activeMonitorRule.overscanBR) /
|
||||||
|
m_renderData.pMonitor->m_pixelSize);
|
||||||
|
m_renderData.damage.translate(m_renderData.pMonitor->m_activeMonitorRule.overscanTL);
|
||||||
|
m_renderData.finalDamage.scale(
|
||||||
|
(m_renderData.pMonitor->m_pixelSize - m_renderData.pMonitor->m_activeMonitorRule.overscanTL - m_renderData.pMonitor->m_activeMonitorRule.overscanBR) /
|
||||||
|
m_renderData.pMonitor->m_pixelSize);
|
||||||
|
m_renderData.finalDamage.translate(m_renderData.pMonitor->m_activeMonitorRule.overscanTL);
|
||||||
|
}
|
||||||
|
|
||||||
renderTexture(m_renderData.pCurrentMonData->offloadFB.getTexture(), monbox, {});
|
renderTexture(m_renderData.pCurrentMonData->offloadFB.getTexture(), monbox, {});
|
||||||
|
|
||||||
|
m_renderData.damage = DAMAGE_BACKUP;
|
||||||
|
m_renderData.finalDamage = FINAL_DAMAGE_BACKUP;
|
||||||
|
}
|
||||||
|
|
||||||
blend(true);
|
blend(true);
|
||||||
|
|
||||||
m_renderData.useNearestNeighbor = false;
|
m_renderData.useNearestNeighbor = false;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue