[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.
This commit is contained in:
BZLZHH
2026-10-01 09:46:57 -04:00
parent b2ce268c86
commit 08e45dc9c6
7 changed files with 35 additions and 3 deletions
@@ -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;
}
}
@@ -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;
}
@@ -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<GenericErrorInfo>(
@@ -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<GenericErrorInfo>(
@@ -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<GenericErrorInfo>(
@@ -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,
@@ -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<TextureUploadTarget>& GetUploadTargets() const override { return m_uploadTargets; }
protected:
@@ -35,6 +35,14 @@ namespace MobileGL::MG_State::GLState {
return MakeShared<TextureObject2DCube>(index);
case TextureTarget::Texture2D:
return MakeShared<TextureObject2D>(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<TextureObject2D>(index, TextureTarget::TextureExternalOES);
case TextureTarget::Texture3D:
return MakeShared<TextureObject3D>(index);
case TextureTarget::TextureBuffer:
@@ -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: