From bf7fc6bf6bb76092c5c312cb775503794bd6f910 Mon Sep 17 00:00:00 2001 From: BZLZHH Date: Thu, 1 Oct 2026 09:47:32 -0400 Subject: [PATCH] [Fix] (DirectGLES): an imported external texture is attached as the host frame canvas The arms that bind the display host's frame in place of an imported texture were gated on the attach target being 0x8D65, but an external texture is attached through the GL_TEXTURE_2D upload target, so they never ran. The texture's twin on the server has no storage - the dma-buf behind it never crosses - and kwin's framebuffers over it were incomplete (status 0x8cd7, every draw GL_INVALID_FRAMEBUFFER_OPERATION), so nothing it drew landed anywhere. The record arm (SyncAttachmentSurface) now recognises a texture point whose target is TextureExternalOES and attaches the host frame canvas before any twin adoption or storage sync, which have nothing to offer a texture with no storage; it takes the host frame first if none is held yet. The legacy object arm keys on the texture object's own target the same way. Measured: all four of kwin's daemon-buffer framebuffers complete, and the desktop it draws reaches the glass. --- MobileGL/MG_Backend/DirectGLES/Managers.cpp | 28 +++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/MobileGL/MG_Backend/DirectGLES/Managers.cpp b/MobileGL/MG_Backend/DirectGLES/Managers.cpp index 69e99868..a0705bc4 100644 --- a/MobileGL/MG_Backend/DirectGLES/Managers.cpp +++ b/MobileGL/MG_Backend/DirectGLES/Managers.cpp @@ -11283,7 +11283,14 @@ namespace MobileGL::MG_Backend::DirectGLES { const Bool isCubeFace = glTextureTarget >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && glTextureTarget <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; backendTextureObject->Bind(isCubeFace ? GL_TEXTURE_CUBE_MAP : glTextureTarget); - if (glTextureTarget == 0x8D65 && g_hostFrameRenderbuffer == 0) { + // THE TEXTURE'S OWN TARGET, not the attach target: an external texture is attached + // through the GL_TEXTURE_2D upload target (TextureEnumConverter maps 0x8D65 there so the + // attach validates), so glTextureTarget is never 0x8D65 here and the arms below were + // dead - kwin's framebuffers got a storage-less texture and every draw into them failed + // with GL_INVALID_FRAMEBUFFER_OPERATION. + const Bool externalTexture = + glTextureTarget == 0x8D65 || textureObject->GetTarget() == TextureTarget::TextureExternalOES; + if (externalTexture && g_hostFrameRenderbuffer == 0) { // NOBODY ELSE TAKES THE FRAME ON THIS ROUTE (DirectGLES.h): the compositor // here never creates a window surface, so this attachment is the first place // the display host's frame is known to be wanted. A failed take leaves the @@ -11294,7 +11301,7 @@ namespace MobileGL::MG_Backend::DirectGLES { // this route exists to fill. (void)TakeHostFrameForExternalTexture(1440, 3200); } - if (glTextureTarget == 0x8D65 && g_hostFrameRenderbuffer != 0) { + if (externalTexture && g_hostFrameRenderbuffer != 0) { // THE IMPORTED dma-buf IS THE DISPLAY HOST'S FRAME. Measured, and the whole reason // this branch exists: kwin_wayland in the container imports the display daemon's // dma-buf as an EGLImage ("taking target 0x8d65 over an EGLImage of 1440x2937 @@ -11630,6 +11637,23 @@ namespace MobileGL::MG_Backend::DirectGLES { // nothing here is the whole of the agreement. (The legacy arm does the same.) return true; } + // AN IMPORTED dma-buf AT A COLOUR POINT IS THE DISPLAY HOST'S FRAME. The client marks the + // texture it bound an imported EGLImage to as GL_TEXTURE_EXTERNAL_OES (TextureObject2D's + // target), the server never received that dma-buf's storage, and the compositor's + // framebuffer over it was incomplete (measured: status 0x8cd7, every draw + // GL_INVALID_FRAMEBUFFER_OPERATION). It is bound to the host frame canvas instead - the + // storage the display host's frames are copied out of at present - before any twin or + // storage sync, which have nothing to offer a texture with no storage. + if (surface.Kind == MG_Pipe::kMGPipeSurfaceKindTexture && + surface.TextureTarget == + static_cast(TextureTarget::TextureExternalOES)) { + if (g_hostFrameRenderbuffer == 0) (void)TakeHostFrameForExternalTexture(1440, 3200); + if (g_hostFrameRenderbuffer != 0) { + g_GLESFuncs.glFramebufferRenderbuffer(glFBOTarget, glBackendAttachment, GL_RENDERBUFFER, + g_hostFrameRenderbuffer); + return true; + } + } if (surface.Kind == MG_Pipe::kMGPipeSurfaceKindTexture) { // The record's handle is validated BEFORE the frontend is consulted (N-3): it is // the untrusted half, the frontend cross-check below is the corroboration, and