From fab9961c4912f2ddd3e35ce9c6d66dd3851b8742 Mon Sep 17 00:00:00 2001 From: Geoffrey McRae Date: Fri, 31 Jul 2026 14:15:17 +1000 Subject: [PATCH] [client] egl: fix streamed texture post-processing race --- client/renderers/EGL/desktop.c | 18 +++++++++++------- client/renderers/EGL/egltypes.h | 1 + client/renderers/EGL/texture_buffer.c | 2 +- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/client/renderers/EGL/desktop.c b/client/renderers/EGL/desktop.c index 9f1d7415..ffaf36a3 100644 --- a/client/renderers/EGL/desktop.c +++ b/client/renderers/EGL/desktop.c @@ -431,12 +431,14 @@ bool egl_desktopUpdate(EGL_Desktop * desktop, const FrameBuffer * frame, int dma return false; } + /* + * Streamed textures trigger post-processing when the render context submits + * the upload. Signalling here can race with that submission and process the + * previous texture contents instead. + */ if (likely(egl_textureUpdateFromFrame(desktop->texture, frame, damageRects, damageRectsCount))) - { - atomic_store(&desktop->processFrame, true); return true; - } return false; } @@ -474,8 +476,9 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth, if (unlikely(outputWidth == 0 || outputHeight == 0)) DEBUG_FATAL("outputWidth || outputHeight == 0"); - enum EGL_TexStatus status; - if (unlikely((status = egl_textureProcess(tex)) != EGL_TEX_STATUS_OK)) + const enum EGL_TexStatus status = egl_textureProcess(tex); + const bool textureUpdated = status == EGL_TEX_STATUS_UPDATED; + if (unlikely(status != EGL_TEX_STATUS_OK && !textureUpdated)) { if (status != EGL_TEX_STATUS_NOTREADY) DEBUG_ERROR("Failed to process the desktop texture"); @@ -501,8 +504,9 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth, HDR_PEAK_LUMINANCE_MIN, HDR_PEAK_LUMINANCE_MAX); } - const bool processFrame = atomic_exchange(&desktop->processFrame, false) || - egl_postProcessConfigModified(desktop->pp); + bool processFrame = textureUpdated; + processFrame |= atomic_exchange(&desktop->processFrame, false); + processFrame |= egl_postProcessConfigModified(desktop->pp); if (processFrame && egl_postProcessRun(desktop->pp, tex, desktop->mesh, width, height, outputWidth, outputHeight, dma, diff --git a/client/renderers/EGL/egltypes.h b/client/renderers/EGL/egltypes.h index 7990e9ed..1967ecef 100644 --- a/client/renderers/EGL/egltypes.h +++ b/client/renderers/EGL/egltypes.h @@ -48,6 +48,7 @@ typedef enum EGL_TexStatus { EGL_TEX_STATUS_NOTREADY, EGL_TEX_STATUS_OK, + EGL_TEX_STATUS_UPDATED, EGL_TEX_STATUS_ERROR } EGL_TexStatus; diff --git a/client/renderers/EGL/texture_buffer.c b/client/renderers/EGL/texture_buffer.c index 11de3c2b..6d17d427 100644 --- a/client/renderers/EGL/texture_buffer.c +++ b/client/renderers/EGL/texture_buffer.c @@ -325,7 +325,7 @@ EGL_TexStatus egl_texBufferStreamProcess(EGL_Texture * texture) if (keepLocked) LG_UNLOCK(this->copyLock); - return EGL_TEX_STATUS_OK; + return EGL_TEX_STATUS_UPDATED; } EGL_TexStatus egl_texBufferStreamGet(EGL_Texture * texture, GLuint * tex,