mirror of
https://github.com/hyprwm/Hyprland
synced 2025-12-20 06:50:10 +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", "max_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
|
||||
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)
|
||||
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();
|
||||
|
||||
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)
|
||||
return true;
|
||||
|
||||
if (pMonitor->m_activeMonitorRule.hasOverscan())
|
||||
return true; // translating hw cursors would be annoying, fuck this.
|
||||
|
||||
if (*PINVISIBLE != 0)
|
||||
return true;
|
||||
|
||||
|
|
|
|||
|
|
@ -69,8 +69,16 @@ struct SMonitorRule {
|
|||
int maxLuminance = -1; // >= 0 overrides EDID
|
||||
int maxAvgLuminance = -1; // >= 0 overrides EDID
|
||||
|
||||
Vector2D overscanTL = {0, 0};
|
||||
Vector2D overscanBR = {0, 0};
|
||||
|
||||
drmModeModeInfo drmMode = {};
|
||||
std::optional<int> vrr;
|
||||
|
||||
//
|
||||
bool hasOverscan() {
|
||||
return overscanTL != Vector2D{0, 0} || overscanBR != Vector2D{0, 0};
|
||||
}
|
||||
};
|
||||
|
||||
class CMonitor;
|
||||
|
|
|
|||
|
|
@ -834,11 +834,45 @@ void CHyprOpenGLImpl::end() {
|
|||
m_renderData.outFB->bind();
|
||||
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);
|
||||
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, {});
|
||||
|
||||
m_renderData.damage = DAMAGE_BACKUP;
|
||||
m_renderData.finalDamage = FINAL_DAMAGE_BACKUP;
|
||||
}
|
||||
|
||||
blend(true);
|
||||
|
||||
m_renderData.useNearestNeighbor = false;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue