From 08e45dc9c6ef92f3a49fe61ac47fc3b99cc9753f Mon Sep 17 00:00:00 2001 From: BZLZHH Date: Thu, 1 Oct 2026 09:46:57 -0400 Subject: [PATCH] [Fix] (GLState): an external texture is a 2D texture that remembers it is external GL_TEXTURE_EXTERNAL_OES had a target of its own but nothing behind it: the texture factory had no row for it (the compositor died on "Unimplemented texture type" the moment it bound one), the attach path had no upload target for 0x8D65 (validation failed, the attachment was never recorded and the compositor read GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT), and nothing downstream could tell an imported texture from an ordinary one. An external texture is now a TextureObject2D created with the TextureExternalOES target, attached through the 2D upload target - which the three framebuffer-texture validations accept for an external object - and the target crosses the pipe (TexExternalOES maps back on the server) so the render server can recognise it. To the driver it stays a 2D texture: MapToBackendTextureTarget folds it to Texture2D like the other targets ES does not have. --- MobileGL/MG_Backend/DirectGLES/Managers.cpp | 1 + MobileGL/MG_Backend/DirectGLES/Managers.h | 3 +++ .../MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.cpp | 12 +++++++++--- .../GLState/TextureState/TextureObject2D.cpp | 3 +++ .../MG_State/GLState/TextureState/TextureObject2D.h | 3 +++ .../MG_State/GLState/TextureState/TextureState.cpp | 8 ++++++++ .../Converters/GLToMG/TextureEnumConverter.cpp | 8 ++++++++ 7 files changed, 35 insertions(+), 3 deletions(-) diff --git a/MobileGL/MG_Backend/DirectGLES/Managers.cpp b/MobileGL/MG_Backend/DirectGLES/Managers.cpp index 57db0774..69e99868 100644 --- a/MobileGL/MG_Backend/DirectGLES/Managers.cpp +++ b/MobileGL/MG_Backend/DirectGLES/Managers.cpp @@ -3183,6 +3183,7 @@ namespace MobileGL::MG_Backend::DirectGLES { case MG_Pipe::MGPipeResourceTarget::Tex2DMSArray: return TextureTarget::Texture2DMultisampleArray; case MG_Pipe::MGPipeResourceTarget::TexRect: return TextureTarget::TextureRectangle; case MG_Pipe::MGPipeResourceTarget::TexBuffer: return TextureTarget::TextureBuffer; + case MG_Pipe::MGPipeResourceTarget::TexExternalOES: return TextureTarget::TextureExternalOES; default: return TextureTarget::Unknown; } } diff --git a/MobileGL/MG_Backend/DirectGLES/Managers.h b/MobileGL/MG_Backend/DirectGLES/Managers.h index 463829f5..1d1008ad 100644 --- a/MobileGL/MG_Backend/DirectGLES/Managers.h +++ b/MobileGL/MG_Backend/DirectGLES/Managers.h @@ -1879,6 +1879,9 @@ namespace MobileGL::MG_Backend::DirectGLES { return TextureTarget::Texture2D; case TextureTarget::Texture1DArray: return TextureTarget::Texture2DArray; + // An external texture's storage is an imported EGLImage; to the driver it is 2D. + case TextureTarget::TextureExternalOES: + return TextureTarget::Texture2D; default: return target; } diff --git a/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.cpp b/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.cpp index 32a4072d..ed1dee3d 100644 --- a/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.cpp +++ b/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.cpp @@ -618,7 +618,9 @@ namespace MobileGL::MG_Impl::GLImpl { const auto expectedTextureTarget = MG_Util::ConvertTextureUploadTargetToTextureTarget(textureUploadTarget); if (expectedTextureTarget == TextureTarget::Unknown || - textureObject->GetTarget() != expectedTextureTarget) { + (textureObject->GetTarget() != expectedTextureTarget && + !(textureObject->GetTarget() == TextureTarget::TextureExternalOES && + expectedTextureTarget == TextureTarget::Texture2D))) { MG_State::pGLContext->RecordError( ErrorCode::InvalidOperation, MakeUnique( @@ -1389,7 +1391,9 @@ namespace MobileGL::MG_Impl::GLImpl { const auto expectedTextureTarget = MG_Util::ConvertTextureUploadTargetToTextureTarget(textureUploadTarget); if (expectedTextureTarget == TextureTarget::Unknown || - textureObject->GetTarget() != expectedTextureTarget) { + (textureObject->GetTarget() != expectedTextureTarget && + !(textureObject->GetTarget() == TextureTarget::TextureExternalOES && + expectedTextureTarget == TextureTarget::Texture2D))) { MG_State::pGLContext->RecordError( ErrorCode::InvalidOperation, MakeUnique( @@ -1539,7 +1543,9 @@ namespace MobileGL::MG_Impl::GLImpl { const auto expectedTextureTarget = MG_Util::ConvertTextureUploadTargetToTextureTarget(textureUploadTarget); if (expectedTextureTarget == TextureTarget::Unknown || - textureObject->GetTarget() != expectedTextureTarget) { + (textureObject->GetTarget() != expectedTextureTarget && + !(textureObject->GetTarget() == TextureTarget::TextureExternalOES && + expectedTextureTarget == TextureTarget::Texture2D))) { MG_State::pGLContext->RecordError( ErrorCode::InvalidOperation, MakeUnique( diff --git a/MobileGL/MG_State/GLState/TextureState/TextureObject2D.cpp b/MobileGL/MG_State/GLState/TextureState/TextureObject2D.cpp index 2ec90c79..9632f1ba 100644 --- a/MobileGL/MG_State/GLState/TextureState/TextureObject2D.cpp +++ b/MobileGL/MG_State/GLState/TextureState/TextureObject2D.cpp @@ -14,6 +14,9 @@ namespace MobileGL { TextureObject2D::TextureObject2D(Uint externalIndex) : TextureObjectWithOneMipmap(TextureTarget::Texture2D, externalIndex) {} + TextureObject2D::TextureObject2D(Uint externalIndex, TextureTarget target) + : TextureObjectWithOneMipmap(target, externalIndex) {} + Uint TextureObject2D::GetIndexOfTextureUploadTarget(TextureUploadTarget target) const { MOBILEGL_ASSERT(target == TextureUploadTarget::Texture2D || target == TextureUploadTarget::ProxyTexture2D, diff --git a/MobileGL/MG_State/GLState/TextureState/TextureObject2D.h b/MobileGL/MG_State/GLState/TextureState/TextureObject2D.h index ecb009f0..f5ecc65d 100644 --- a/MobileGL/MG_State/GLState/TextureState/TextureObject2D.h +++ b/MobileGL/MG_State/GLState/TextureState/TextureObject2D.h @@ -15,6 +15,9 @@ namespace MobileGL { class TextureObject2D : public TextureObjectWithOneMipmap { public: explicit TextureObject2D(Uint externalIndex); + // An external texture (GL_TEXTURE_EXTERNAL_OES) is a 2D texture whose storage is an + // imported EGLImage; it keeps that target so the render server can tell it apart. + TextureObject2D(Uint externalIndex, TextureTarget target); const Vector& GetUploadTargets() const override { return m_uploadTargets; } protected: diff --git a/MobileGL/MG_State/GLState/TextureState/TextureState.cpp b/MobileGL/MG_State/GLState/TextureState/TextureState.cpp index 60d249d5..076d1c30 100644 --- a/MobileGL/MG_State/GLState/TextureState/TextureState.cpp +++ b/MobileGL/MG_State/GLState/TextureState/TextureState.cpp @@ -35,6 +35,14 @@ namespace MobileGL::MG_State::GLState { return MakeShared(index); case TextureTarget::Texture2D: return MakeShared(index); + // GL_TEXTURE_EXTERNAL_OES: an external texture IS a 2D texture whose storage comes from an + // imported EGLImage (the compositor's display-daemon dma-buf). The object is the 2D one; what + // differs is where the storage comes from, and the import path records that. Without this row + // the factory asserted "Unimplemented texture type when creating texture object!" the moment + // kwin bound one (measured: the compositor died on Trace/breakpoint trap right after the bind + // was accepted). + case TextureTarget::TextureExternalOES: + return MakeShared(index, TextureTarget::TextureExternalOES); case TextureTarget::Texture3D: return MakeShared(index); case TextureTarget::TextureBuffer: diff --git a/MobileGL/MG_Util/Converters/GLToMG/TextureEnumConverter.cpp b/MobileGL/MG_Util/Converters/GLToMG/TextureEnumConverter.cpp index bea1d21e..ee3c038a 100644 --- a/MobileGL/MG_Util/Converters/GLToMG/TextureEnumConverter.cpp +++ b/MobileGL/MG_Util/Converters/GLToMG/TextureEnumConverter.cpp @@ -404,6 +404,14 @@ namespace MobileGL { return TextureUploadTarget::Texture1D; case GL_TEXTURE_2D: return TextureUploadTarget::Texture2D; + // GL_TEXTURE_EXTERNAL_OES (0x8D65), an upload target of its own right: the compositor + // attaches the imported dma-buf texture to a framebuffer through this enum, and the attach + // path validates the target here. Left unmapped it became Unknown, the validation failed, + // the attachment was never recorded, and the compositor's own check then read + // GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT. External textures ARE two-dimensional, so + // the upload target is the 2D one. + case 0x8D65: + return TextureUploadTarget::Texture2D; case GL_TEXTURE_3D: return TextureUploadTarget::Texture3D; case GL_PROXY_TEXTURE_2D: