mirror of
https://github.com/hyprwm/Hyprland
synced 2026-05-07 18:38:00 +02:00
render: use gpu to scale bgtex and fix missing reset on size change
This commit is contained in:
parent
6f671959de
commit
f63bff74b4
2 changed files with 51 additions and 38 deletions
|
|
@ -796,9 +796,10 @@ bool CMonitor::applyMonitorRule(Config::CMonitorRule&& pMonitorRule, bool force)
|
|||
}
|
||||
}
|
||||
|
||||
const auto WAS10B = m_enabled10bit;
|
||||
const auto OLDRES = m_pixelSize;
|
||||
bool success = false;
|
||||
const auto WAS10B = m_enabled10bit;
|
||||
const auto OLDPIXELSIZE = m_pixelSize;
|
||||
const auto OLDTRANSFORMEDSIZE = m_transformedSize;
|
||||
bool success = false;
|
||||
|
||||
// Needed in case we are switching from a custom modeline to a standard mode
|
||||
m_customDrmMode = {};
|
||||
|
|
@ -1064,17 +1065,16 @@ bool CMonitor::applyMonitorRule(Config::CMonitorRule&& pMonitorRule, bool force)
|
|||
|
||||
updateMatrix();
|
||||
|
||||
if ((WAS10B != m_enabled10bit || OLDRES != m_pixelSize)) {
|
||||
if ((WAS10B != m_enabled10bit || OLDPIXELSIZE != m_pixelSize)) {
|
||||
m_resources.reset(); // TODO skip for 10bit change and fp16?
|
||||
|
||||
if (g_pHyprRenderer && g_pHyprRenderer->glBackend())
|
||||
g_pHyprRenderer->glBackend()->destroyMonitorResources(m_self);
|
||||
}
|
||||
|
||||
// The background is pre-scaled to each monitor's resolution, so it must be reset whenever the pixel size changes
|
||||
if (OLDRES != m_pixelSize) {
|
||||
Log::logger->log(Log::DEBUG, "Pixel size changed from {} to {}, reset background for monitor {}", OLDRES, m_pixelSize, m_name);
|
||||
m_background.reset();
|
||||
}
|
||||
if (m_background && (OLDPIXELSIZE != m_pixelSize || OLDTRANSFORMEDSIZE != m_transformedSize)) {
|
||||
Log::logger->log(Log::DEBUG, "{} reset BGTex: pixelSize {} -> {}, transformedSize {} -> {}", m_name, OLDPIXELSIZE, m_pixelSize, OLDTRANSFORMEDSIZE, m_transformedSize);
|
||||
m_background.reset();
|
||||
}
|
||||
|
||||
g_pCompositor->scheduleMonitorStateRecheck();
|
||||
|
|
|
|||
|
|
@ -1233,47 +1233,60 @@ SP<ITexture> IHyprRenderer::getBackground(PHLMONITOR pMonitor) {
|
|||
return nullptr;
|
||||
|
||||
Log::logger->log(Log::DEBUG, "Creating a texture for BGTex");
|
||||
SP<ITexture> backgroundTexture = createTexture(m_backgroundResource->m_asset.cairoSurface->cairo());
|
||||
|
||||
cairo_surface_t* cairoSurface = m_backgroundResource->m_asset.cairoSurface->cairo();
|
||||
cairo_surface_t* scaledSurface = nullptr;
|
||||
if (!backgroundTexture || !backgroundTexture->ok())
|
||||
return nullptr;
|
||||
|
||||
// If the background is larger than the monitor, scale it down
|
||||
if (pMonitor->m_transformedSize.x > 0 && pMonitor->m_transformedSize.y > 0) {
|
||||
const int origW = cairo_image_surface_get_width(cairoSurface);
|
||||
const int origH = cairo_image_surface_get_height(cairoSurface);
|
||||
const int monW = (int)std::round(pMonitor->m_transformedSize.x);
|
||||
const int monH = (int)std::round(pMonitor->m_transformedSize.y);
|
||||
Log::logger->log(Log::DEBUG, "BGTex created for monitor {}", pMonitor->m_name);
|
||||
|
||||
const int monW = (int)std::round(pMonitor->m_transformedSize.x);
|
||||
const int monH = (int)std::round(pMonitor->m_transformedSize.y);
|
||||
const int origW = backgroundTexture->m_size.x;
|
||||
const int origH = backgroundTexture->m_size.y;
|
||||
|
||||
if (monW > 0 && monH > 0) {
|
||||
const double scaleX = (double)monW / origW;
|
||||
const double scaleY = (double)monH / origH;
|
||||
const double scale = std::max(scaleX, scaleY);
|
||||
|
||||
// scale the background if it's larger than the monitor
|
||||
if (scale < 1.0) {
|
||||
// Center-crop: compute offset in original-image coordinates
|
||||
const double srcX = (origW - (monW / scale)) / 2.0;
|
||||
const double srcY = (origH - (monH / scale)) / 2.0;
|
||||
auto fb = createFB("BGTex scale");
|
||||
fb->alloc(monW, monH);
|
||||
|
||||
scaledSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, monW, monH);
|
||||
cairo_t* cr = cairo_create(scaledSurface);
|
||||
cairo_scale(cr, scale, scale);
|
||||
cairo_set_source_surface(cr, cairoSurface, -srcX, -srcY);
|
||||
cairo_paint(cr);
|
||||
cairo_destroy(cr);
|
||||
cairo_surface_flush(scaledSurface);
|
||||
auto guard = bindTempFB(fb);
|
||||
|
||||
cairoSurface = scaledSurface;
|
||||
Log::logger->log(Log::INFO, "Background scaled from {}x{} to {}x{} for monitor {}", origW, origH, monW, monH, pMonitor->m_name);
|
||||
const auto oldProjType = m_renderData.projectionType;
|
||||
const auto oldFbSize = m_renderData.fbSize;
|
||||
const auto oldTransformDmg = m_renderData.transformDamage;
|
||||
|
||||
m_renderData.fbSize = Vector2D{monW, monH};
|
||||
setProjectionType(RPT_EXPORT);
|
||||
m_renderData.transformDamage = false;
|
||||
setViewport(0, 0, monW, monH);
|
||||
|
||||
draw(CClearPassElement::SClearData{{0.F, 0.F, 0.F, 0.F}});
|
||||
|
||||
const double texW = origW * scale;
|
||||
const double texH = origH * scale;
|
||||
const double offX = (monW - texW) / 2.0;
|
||||
const double offY = (monH - texH) / 2.0;
|
||||
|
||||
CRegion fullDamage = {0, 0, monW, monH};
|
||||
draw(CTexPassElement::SRenderData{.tex = backgroundTexture, .box = CBox{offX, offY, texW, texH}, .damage = fullDamage}, fullDamage);
|
||||
|
||||
m_renderData.fbSize = oldFbSize;
|
||||
m_renderData.transformDamage = oldTransformDmg;
|
||||
setProjectionType(oldProjType);
|
||||
setViewport(0, 0, (int)pMonitor->m_pixelSize.x, (int)pMonitor->m_pixelSize.y);
|
||||
|
||||
backgroundTexture = fb->getTexture();
|
||||
|
||||
Log::logger->log(Log::INFO, "BGTex scaled from {}x{} to {}x{} for monitor {}", origW, origH, monW, monH, pMonitor->m_name);
|
||||
}
|
||||
}
|
||||
|
||||
SP<ITexture> backgroundTexture = createTexture(cairoSurface);
|
||||
|
||||
if (scaledSurface)
|
||||
cairo_surface_destroy(scaledSurface);
|
||||
|
||||
if (!backgroundTexture->ok())
|
||||
return nullptr;
|
||||
Log::logger->log(Log::DEBUG, "Background created for monitor {}", pMonitor->m_name);
|
||||
|
||||
// clear the resource after we're done using it
|
||||
g_pEventLoopManager->doLater([this] { m_backgroundResource.reset(); });
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue