mirror of
https://github.com/hyprwm/Hyprland
synced 2026-05-07 07:38:05 +02:00
Merge 0603a354f3 into 1681bea42d
This commit is contained in:
commit
7c2ec336a3
5 changed files with 91 additions and 10 deletions
|
|
@ -2923,6 +2923,9 @@ void CCompositor::leaveUnsafeState() {
|
|||
}
|
||||
|
||||
void CCompositor::setPreferredScaleForSurface(SP<CWLSurfaceResource> pSurface, double scale) {
|
||||
if (!pSurface)
|
||||
return;
|
||||
|
||||
PROTO::fractional->sendScale(pSurface, scale);
|
||||
pSurface->sendPreferredScale(std::ceil(scale));
|
||||
|
||||
|
|
@ -2937,6 +2940,9 @@ void CCompositor::setPreferredScaleForSurface(SP<CWLSurfaceResource> pSurface, d
|
|||
}
|
||||
|
||||
void CCompositor::setPreferredTransformForSurface(SP<CWLSurfaceResource> pSurface, wl_output_transform transform) {
|
||||
if (!pSurface)
|
||||
return;
|
||||
|
||||
pSurface->sendPreferredTransform(transform);
|
||||
|
||||
const auto PSURFACE = Desktop::View::CWLSurface::fromResource(pSurface);
|
||||
|
|
|
|||
|
|
@ -264,7 +264,7 @@ SP<CWLSurfaceResource> CWLSurfaceResource::fromResource(wl_resource* res) {
|
|||
}
|
||||
|
||||
bool CWLSurfaceResource::good() {
|
||||
return m_resource->resource();
|
||||
return m_resource && m_resource->resource();
|
||||
}
|
||||
|
||||
wl_client* CWLSurfaceResource::client() {
|
||||
|
|
@ -272,6 +272,9 @@ wl_client* CWLSurfaceResource::client() {
|
|||
}
|
||||
|
||||
void CWLSurfaceResource::enter(PHLMONITOR monitor) {
|
||||
if (!good())
|
||||
return;
|
||||
|
||||
if (std::ranges::find(m_enteredOutputs, monitor) != m_enteredOutputs.end())
|
||||
return;
|
||||
|
||||
|
|
@ -304,6 +307,9 @@ void CWLSurfaceResource::enter(PHLMONITOR monitor) {
|
|||
}
|
||||
|
||||
void CWLSurfaceResource::leave(PHLMONITOR monitor) {
|
||||
if (!good())
|
||||
return;
|
||||
|
||||
if UNLIKELY (std::ranges::find(m_enteredOutputs, monitor) == m_enteredOutputs.end())
|
||||
return;
|
||||
|
||||
|
|
@ -325,12 +331,16 @@ void CWLSurfaceResource::leave(PHLMONITOR monitor) {
|
|||
}
|
||||
|
||||
void CWLSurfaceResource::sendPreferredTransform(wl_output_transform t) {
|
||||
if (!good())
|
||||
return;
|
||||
if (m_resource->version() < 6)
|
||||
return;
|
||||
m_resource->sendPreferredBufferTransform(t);
|
||||
}
|
||||
|
||||
void CWLSurfaceResource::sendPreferredScale(int32_t scale) {
|
||||
if (!good())
|
||||
return;
|
||||
if (m_resource->version() < 6)
|
||||
return;
|
||||
m_resource->sendPreferredBufferScale(scale);
|
||||
|
|
@ -471,6 +481,8 @@ std::pair<SP<CWLSurfaceResource>, Vector2D> CWLSurfaceResource::at(const Vector2
|
|||
}
|
||||
|
||||
uint32_t CWLSurfaceResource::id() {
|
||||
if (!good())
|
||||
return 0;
|
||||
return wl_resource_get_id(m_resource->resource());
|
||||
}
|
||||
|
||||
|
|
@ -505,6 +517,8 @@ void CWLSurfaceResource::releaseBuffers(bool onlyCurrent) {
|
|||
}
|
||||
|
||||
void CWLSurfaceResource::error(int code, const std::string& str) {
|
||||
if (!good())
|
||||
return;
|
||||
m_resource->error(code, str);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -664,9 +664,28 @@ EGLImageKHR CHyprOpenGLImpl::createEGLImage(const Aquamarine::SDMABUFAttrs& attr
|
|||
return image;
|
||||
}
|
||||
|
||||
bool CHyprOpenGLImpl::attemptContextReset() {
|
||||
Log::logger->log(Log::ERR, "GPU reset: attempting EGL context recovery...");
|
||||
eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
if (eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, m_eglContext) != EGL_TRUE) {
|
||||
Log::logger->log(Log::ERR, "GPU reset: eglMakeCurrent failed, context may be lost");
|
||||
return false;
|
||||
}
|
||||
m_shadersInitialized = false;
|
||||
Log::logger->log(Log::WARN, "GPU reset: EGL context re-established, shaders will reinitialize on next frame.");
|
||||
return true;
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::beginSimple(PHLMONITOR pMonitor, const CRegion& damage, SP<IRenderbuffer> rb, SP<IFramebuffer> fb) {
|
||||
g_pHyprRenderer->m_renderData.pMonitor = pMonitor;
|
||||
|
||||
if (m_gpuResetCooldown > 0) {
|
||||
m_gpuResetCooldown--;
|
||||
Log::logger->log(Log::WARN, "GPU reset recovery cooldown, skipping frame ({} remaining)", m_gpuResetCooldown);
|
||||
g_pHyprRenderer->m_renderData.pMonitor.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
const GLenum RESETSTATUS = glGetGraphicsResetStatus();
|
||||
if (RESETSTATUS != GL_NO_ERROR) {
|
||||
std::string errStr = "";
|
||||
|
|
@ -676,7 +695,14 @@ void CHyprOpenGLImpl::beginSimple(PHLMONITOR pMonitor, const CRegion& damage, SP
|
|||
case GL_UNKNOWN_CONTEXT_RESET: errStr = "GL_UNKNOWN_CONTEXT_RESET"; break;
|
||||
default: errStr = "UNKNOWN??"; break;
|
||||
}
|
||||
RASSERT(false, "Aborting, glGetGraphicsResetStatus returned {}. Cannot continue until proper GPU reset handling is implemented.", errStr);
|
||||
Log::logger->log(Log::ERR, "GPU reset detected in beginSimple: {}. Attempting EGL context recovery.", errStr);
|
||||
if (!attemptContextReset()) {
|
||||
Log::logger->log(Log::ERR, "GPU reset recovery failed. Skipping frames for cooldown.");
|
||||
m_gpuResetCooldown = 60;
|
||||
} else {
|
||||
Log::logger->log(Log::WARN, "GPU reset recovery succeeded. Skipping current frame to reinitialize.");
|
||||
}
|
||||
g_pHyprRenderer->m_renderData.pMonitor.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -715,6 +741,13 @@ void CHyprOpenGLImpl::makeEGLCurrent() {
|
|||
void CHyprOpenGLImpl::begin(PHLMONITOR pMonitor, const CRegion& damage_, SP<IFramebuffer> fb, std::optional<CRegion> finalDamage) {
|
||||
g_pHyprRenderer->m_renderData.pMonitor = pMonitor;
|
||||
|
||||
if (m_gpuResetCooldown > 0) {
|
||||
m_gpuResetCooldown--;
|
||||
Log::logger->log(Log::WARN, "GPU reset recovery cooldown, skipping frame ({} remaining)", m_gpuResetCooldown);
|
||||
g_pHyprRenderer->m_renderData.pMonitor.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
const GLenum RESETSTATUS = glGetGraphicsResetStatus();
|
||||
if (RESETSTATUS != GL_NO_ERROR) {
|
||||
std::string errStr = "";
|
||||
|
|
@ -724,7 +757,14 @@ void CHyprOpenGLImpl::begin(PHLMONITOR pMonitor, const CRegion& damage_, SP<IFra
|
|||
case GL_UNKNOWN_CONTEXT_RESET: errStr = "GL_UNKNOWN_CONTEXT_RESET"; break;
|
||||
default: errStr = "UNKNOWN??"; break;
|
||||
}
|
||||
RASSERT(false, "Aborting, glGetGraphicsResetStatus returned {}. Cannot continue until proper GPU reset handling is implemented.", errStr);
|
||||
Log::logger->log(Log::ERR, "GPU reset detected in begin: {}. Attempting EGL context recovery.", errStr);
|
||||
if (!attemptContextReset()) {
|
||||
Log::logger->log(Log::ERR, "GPU reset recovery failed. Skipping frames for cooldown.");
|
||||
m_gpuResetCooldown = 60;
|
||||
} else {
|
||||
Log::logger->log(Log::WARN, "GPU reset recovery succeeded. Skipping current frame to reinitialize.");
|
||||
}
|
||||
g_pHyprRenderer->m_renderData.pMonitor.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -858,8 +898,10 @@ void CHyprOpenGLImpl::end() {
|
|||
// check for gl errors
|
||||
const GLenum ERR = glGetError();
|
||||
|
||||
if UNLIKELY (ERR == GL_CONTEXT_LOST) /* We don't have infra to recover from this */
|
||||
RASSERT(false, "glGetError at Opengl::end() returned GL_CONTEXT_LOST. Cannot continue until proper GPU reset handling is implemented.");
|
||||
if UNLIKELY (ERR == GL_CONTEXT_LOST) {
|
||||
Log::logger->log(Log::ERR, "glGetError at Opengl::end() returned GL_CONTEXT_LOST. Recovery will trigger on next begin().");
|
||||
m_gpuResetCooldown = 60;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1048,7 +1090,12 @@ void CHyprOpenGLImpl::renderRectWithBlurInternal(const CBox& box, const CHyprCol
|
|||
CRegion damage{g_pHyprRenderer->m_renderData.damage};
|
||||
damage.intersect(box);
|
||||
|
||||
auto blurredBG = data.xray ? g_pHyprRenderer->m_renderData.pMonitor->resources()->m_blurFB->getTexture() : g_pHyprRenderer->blurMainFramebuffer(data.blurA, &damage);
|
||||
auto blurFB = g_pHyprRenderer->m_renderData.pMonitor->resources()->m_blurFB;
|
||||
auto blurredBG = data.xray ? (blurFB ? blurFB->getTexture() : nullptr) : g_pHyprRenderer->blurMainFramebuffer(data.blurA, &damage);
|
||||
if (!blurredBG) {
|
||||
Log::logger->log(Log::ERR, "renderTextureWithBlur: blur texture unavailable (likely GPU reset). Skipping blur.");
|
||||
return;
|
||||
}
|
||||
|
||||
CBox MONITORBOX = {0, 0, g_pHyprRenderer->m_renderData.pMonitor->m_transformedSize.x, g_pHyprRenderer->m_renderData.pMonitor->m_transformedSize.y};
|
||||
g_pHyprRenderer->pushMonitorTransformEnabled(true);
|
||||
|
|
@ -1439,8 +1486,13 @@ WP<CShader> CHyprOpenGLImpl::renderToFBInternal(SP<ITexture> tex, const STexture
|
|||
|
||||
void CHyprOpenGLImpl::renderTextureInternal(SP<ITexture> tex, const CBox& box, const STextureRenderData& data) {
|
||||
RASSERT(g_pHyprRenderer->m_renderData.pMonitor, "Tried to render texture without begin()!");
|
||||
RASSERT(tex, "Attempted to draw nullptr texture!");
|
||||
RASSERT(tex->ok(), "Attempted to draw invalid texture!");
|
||||
|
||||
if UNLIKELY (!tex || !tex->ok()) {
|
||||
// After a GPU reset, textures become invalid. Skip the draw
|
||||
// instead of aborting — recovery will happen on the next begin().
|
||||
Log::logger->log(Log::ERR, "renderTextureInternal: invalid texture (likely GPU reset). Skipping draw.");
|
||||
return;
|
||||
}
|
||||
|
||||
TRACY_GPU_ZONE("RenderTextureInternalWithDamage");
|
||||
|
||||
|
|
|
|||
|
|
@ -313,6 +313,8 @@ namespace Render::GL {
|
|||
bool m_applyFinalShader = false;
|
||||
bool m_blend = false;
|
||||
bool m_offloadedFramebuffer = false;
|
||||
int m_gpuResetCooldown = 0;
|
||||
bool attemptContextReset();
|
||||
bool m_cmSupported = true;
|
||||
|
||||
SP<CShader> m_finalScreenShader;
|
||||
|
|
|
|||
|
|
@ -1451,6 +1451,8 @@ SP<ITexture> IHyprRenderer::loadAsset(const std::string& filename) {
|
|||
}
|
||||
|
||||
SP<ITexture> IHyprRenderer::getBlurTexture(PHLMONITORREF pMonitor) {
|
||||
if (!pMonitor || !pMonitor->resources()->m_blurFB)
|
||||
return nullptr;
|
||||
return pMonitor->resources()->m_blurFB->getTexture();
|
||||
}
|
||||
|
||||
|
|
@ -1789,9 +1791,10 @@ Mat3x3 IHyprRenderer::projectBoxToTarget(const CBox& box, std::optional<eTransfo
|
|||
}
|
||||
|
||||
SP<ITexture> IHyprRenderer::blurMainFramebuffer(float a, CRegion* originalDamage) {
|
||||
if (!m_renderData.currentFB->getTexture()) {
|
||||
if (!m_renderData.currentFB || !m_renderData.currentFB->getTexture()) {
|
||||
Log::logger->log(Log::ERR, "BUG THIS: null fb texture while attempting to blur main fb?! (introspection off?!)");
|
||||
return m_renderData.pMonitor->resources()->m_blurFB->getTexture(); // return something to sample from at least
|
||||
auto blurFB = m_renderData.pMonitor->resources()->m_blurFB;
|
||||
return blurFB ? blurFB->getTexture() : nullptr;
|
||||
}
|
||||
|
||||
auto guard = bindTempFB(m_renderData.currentFB); // blurFramebuffer messes with FB bindings
|
||||
|
|
@ -1803,6 +1806,10 @@ void IHyprRenderer::preBlurForCurrentMonitor(CRegion* fakeDamage) {
|
|||
const auto blurredTex = blurMainFramebuffer(1, fakeDamage);
|
||||
|
||||
// render onto blurFB
|
||||
if (!m_renderData.pMonitor->resources()->m_blurFB) {
|
||||
Log::logger->log(Log::ERR, "preBlurForCurrentMonitor: blurFB is null, skipping blur.");
|
||||
return;
|
||||
}
|
||||
auto guard = bindTempFB(m_renderData.pMonitor->resources()->m_blurFB);
|
||||
const auto SAVE_TRANSFORM = blurredTex->m_transform;
|
||||
blurredTex->m_transform = Math::wlTransformToHyprutils(Math::invertTransform(m_renderData.pMonitor->m_transform));
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue