EGL-Registry
EGL-Registry copied to clipboard
Add EGL_EXT_display_alloc extension
This is an EGL extension that allows you to allocate private EGLDisplays and destroy them when they're no longer needed.
The default semantics of eglGetPlatformDisplay have a few inherent problems:
First, if two modules (applications, libraries, etc) both try to use EGL internally, then they have to sharing the same EGLDisplay, and they risk clobbering each other. EGL_KHR_display_reference
can at least make the problem less catastrophic when something calls eglTerminate
, but it's not a complete solution -- an extra call to eglTerminate
would still break everything, and you can't rely on using eglTerminate to clean up any remaining display-owned objects.
Likewise, the fact that EGLDisplay handles stick around forever means that it's literally impossible to write an EGL application (or implementation) that doesn't leak memory.
Perhaps most importantly, the default semantics make no sense at all in X11 or Wayland applications, because the EGLDisplay will necessarily last longer than the display connection under it, leading to a dangling pointer.
So, this extension adds a new EGL_PRIVATE_DISPLAY_EXT attribute for eglGetPlatformDIsplay, which tells it to allocate a brand new EGLDisplay handle, even if another EGLDisplay would otherwise match the native display. Different modules can thus use their own private EGLDisplays without risk of clobbering each other.
It also adds a new eglDestroyDisplayEXT function, which will fully destroy an EGLDisplay handle that was created with EGL_PRIVATE_DISPLAY_EXT. That way, you can actually clean up properly, or deal with cases where a native display is no longer valid.
This would also make it possible to implement new client extensions such as EGL_KHR_display_reference entirely within libglvnd.
https://www.khronos.org/registry/EGL/extensions/KHR/EGL_KHR_display_reference.txt - is not sufficient then? We had a lot of discussion at one time for that. Just curious, who is part of this EXT?
EGL_KHR_display_reference is not sufficient, no. In terms of utility, it's effectively a strict subset of EGL_EXT_display_alloc.
With EGL_KHR_display_reference, you can have multiple libraries that call eglInitialize and eglTerminate independently without clobbering each other, which is arguably the worst problem with EGL's normal semantics. That also requires that you don't have any bugs that would lead to an extra eglTerminate call, and that each library cleans up every display-owned resource manually.
With EGL_EXT_display_alloc, multiple libraries can still call eglInitialize and eglTerminate independently because they would operate on separate EGLDisplay handles. If a library has an extra eglTerminate call, it doesn't matter. And a library could use eglTerminate to handle cleanup.
EGL_KHR_display_reference also doesn't fix the fact that everything that ever uses EGL has to leak memory, and it doesn't fix the dangling pointers when you call XCloseDisplay or wl_display_disconnect.
Perhaps most interestingly, EGL_EXT_display_alloc would make it possible to implement extensions like EGL_KHR_display_reference entirely within libglvnd. Libglvnd could implement reference tracking for an EGLDisplay internally pretty easily, but without EGL_EXT_display_alloc, it couldn't get separate EGLDisplay handles for different values of EGL_TRACK_REFERENCES_KHR.
As for the use of EXT, there's nothing hardware- or vendor-specific about this. It's just a change in a driver's bookkeeping, so any driver could implement it. I did float the general idea in a discussion a while ago with favorable response from someone on the Mesa side, though I don't remember who -- @nwnk maybe?
Sorry my comment was not push back. I got a better read and I get it.
Should I rebase this on top of #157, or just wait until #157 is merged and then rebase onto ToT?
Not sure if rebasing on other work in progress has turned out without issue. Not sure.
Okay. Easy enough to just wait for #156 to merge and then rebase on ToT, then.
@kbrenneman you don't need to rebase, just please take out the generated files (eglext.h / index.php) to avoid conflicts. I will fix any XML conflicts (unlikely) and extension number issues prior to merging.
Done.
Rebased and renumbered. I also updated the issues section to say "Resolved" instead of "Proposed resolution."
Please add other reviewers. Jon and I can says its well formed, but +1 from experts is reassuring.
I was looking to implement similar functionality to this - I want to be able to force a new allocation of a display. I would want my one to be destroyed the normal way using eglTerminate
, and interact with EGL_KHR_display_reference
to have additional logic for deleting. I also do not fully understand the purpose of eglDestroyDisplayEXT
- is this just to provide different behaviour depending on EGL_KHR_display_reference
- if so, would it be more logical to only require it be included it when both extensions are present? Would this extension do what I want?
Edit: ignore that bit about private, I can't read lol
In practice, I expect that most applications and libraries would use EGL_EXT_display_alloc
instead of EGL_KHR_display_reference
, not use the two of them together. The main purpose of EGL_KHR_display_reference
is so that two libraries which end up getting the same EGLDisplay when they call eglGetPlatformDisplay
won't clobber each other when one of them calls eglTerminate
(assuming no bugs in either, of course). With EGL_EXT_display_alloc
, you can simply not share an EGLDisplay in the first place.
The reason I added a separate eglDestroyDisplayEXT
function is so that eglInitialize
and eglTerminate
would not have different behavior. Once you've got an EGLDisplay handle, calling eglInitialize
and eglTerminate
would do exactly the same thing regardless of whether you set EGL_PRIVATE_DISPLAY_EXT
or not, including being able to reinitialize an EGLDisplay.
That also means that this extension is logically orthogonal to EGL_KHR_display_reference
. This extension only cares about whether an EGLDisplay is initialized, not how many times you'd have to call eglTerminate
to uninitialize it.
In addition, you can easily get the behavior that you want, too: Just call eglDestroyDisplayEXT
immediately after eglInitialize
. It'll mark the EGLDisplay for deletion, but since it treats an initialized EGLDisplay is "in use", it'll wait until eglTerminate
to actually destroy it.
Cool, sounds good.
Just checking, the difference between eglDestroyDisplayEXT
and eglTerminate
is that it doesn't allow reviving the display? If so, that's exactly what I wanted I think. Thanks!
Edit: out of curiosity, what codebase are you implementing this on? I was hoping to implement it on my fork of ANGLE.
Cool, sounds good. Just checking, the difference between
eglDestroyDisplayEXT
andeglTerminate
is that it doesn't allow reviving the display? If so, that's exactly what I wanted I think. Thanks!
In effect, yeah. Every EGL function would do exactly the same thing that it does now. eglTerminate
basically reverts the EGLDisplay to the same uninitialized state that it was in before you called eglInitialize
. Trying to pass it to any other function would produce an EGL_NOT_INITIALIZED
error, but the EGLDisplay handle still exists, so you can pass it to eglInitialize
. If you call eglGetPlatformDisplay
with EGL_PRIVATE_DISPLAY_EXT
set to true, then it will not return that EGLDisplay handle.
When you call eglDestroyDisplayEXT
, it destroys the EGLDisplay handle entirely, with the same semantics you'd expect out of eglDestroyContext
. You can't reinitialize it because it no longer exists, and a call to eglGetPlatformDisplay
is free to re-use that handle.
Edit: out of curiosity, what codebase are you implementing this on? I was hoping to implement it on my fork of ANGLE.
Libglvnd first, since that'll be needed for anything else to work. After that, the NVIDIA driver.
I've started sketching this up for Mesa and it's looking pretty sane. I might have some questions about exactly what gets destroyed when but I think the discussion above has most of the answers. I'll link to a merge request once I've got it working but I think the spec gets a +1 from me.
Mesa merge review is now up. @kbrenneman if you have any tests for this you could share that'd be cool. (I do not, yet, they'll be in piglit once I do though.)
Any news about this ext?
What should happen if I create 2 displays (A
and B
) using the same platform display (e.g. wl_display'). And then use
EGLSurfacefrom display
Ain a
EGLContextfrom display
B`.
Do I understand correctly, that unshared
means that I can't use anything from A
with the B
entirely even though, they have exactly the same platform display under the hood?
Each EGLDisplay would have its own wl_display
, and Wayland objects cannot be shared across two wl_display
s.
Each EGLDisplay would have its own wl_display, and Wayland objects cannot be shared across two wl_displays.
I don't think I understand with wl_display
(you don't wl_display_connect
you just get the handle from the user), but I think you've meant that they will have different queues under the hood and you can't mix the objects between the queues.
However on X11 where everything is a XID, I think you could be able to do so, given that.
If the EGL_PRIVATE_DISPLAY_EXT attribute is set to EGL_TRUE, then eglGetPlatformDisplay returns a new EGLDisplay handle, even if the platform, native_display, and attributes would match an existing display.
It would be nice to be more explicit here, so the libraries could do runtime asserts just in case.
Oh, hm, right. You should be able to use wl_display
objects from multiple queues… Assuming the per-queue wrappers are properly created.
You can create two EGLDisplays from the same wl_display, but they're still separate EGLDisplays.
Remember, an EGLDisplay is the namespace that EGLContexts, EGLSurfaces, and other EGL objects belong to. Every other EGL object is only valid with the EGLDisplay that created it. So, if you try to call eglMakeCurrent with EGLDisplay A, but you pass it an EGLContext from EGLDisplay B, then that's an error.
That much is not new behavior. You can already create multiple EGLDisplays from the same native display just by passing different attributes to eglGetPlatformDisplay. I think Mesa will hand back different EGLDisplays even if the attribute lists are logically equivalent:
wl_display *wdpy = wl_display_connect(NULL);
EGLAttrib attribs1[] = [ EGL_TRACK_REFERENCES_KHR, EGL_TRUE, EGL_NONE ]
EGLDisplay dpy1 = eglGetPlatformDisplay(EGL_PLATFORM_WAYLAND_KHR, wdpy, attribs1);
EGLAttrib attribs2[] = [ EGL_TRACK_REFERENCES_KHR, EGL_FALSE, EGL_NONE ]
EGLDisplay dpy2 = eglGetPlatformDisplay(EGL_PLATFORM_WAYLAND_KHR, wdpy, attribs2);
EGLAttrib attribs3[] = [ EGL_TRACK_REFERENCES_KHR, EGL_FALSE, EGL_NONE ]
EGLDisplay dpy3 = eglGetPlatformDisplay(EGL_PLATFORM_WAYLAND_KHR, wdpy, attribs3);
EGLAttrib attribs4[] = [ EGL_NONE ]
EGLDisplay dpy4 = eglGetPlatformDisplay(EGL_PLATFORM_WAYLAND_KHR, wdpy, attribs4);
if (dpy1 != dpy2) {
// This will be true on all drivers, because we used different attribute lists.
}
if (dpy2 == dpy3) {
// This will be true on all drivers, because we used the same attribute list.
}
if (dpy3 != dpy4) {
// This could be true or false depending on the driver.
// EGL_TRACK_REFERENCES_KHR defaults to false, so the attribute lists are
// different, but logically equivalent. The EGL spec allows either behavior.
}
EGLContext ctx = eglCreateContext(dpy1, ...);
eglMakeCurrent(dpy2, NULL, NULL, ctx); // ERROR: ctx came from dpy1, not dpy2
What this extension adds is a way to guarantee that you get a different EGLDisplay when you call eglGetPlatformDisplay, even if the attribute list is otherwise identical. It also gives you a way to destroy an EGLDisplay afterward instead of leaking it.
When you say "private" EGL_PRIVATE_DISPLAY_EXT, private to what? Is this private to a single thread (TLS space for implementation)? or private by some other context? That would need to be clear in the spec.
I guess the point is that "eglGetPlatformDisplay" will not return the same handle twice.
"Private" in this case means private to whatever called eglGetPlatformDisplay, rather than the default behavior where everything that calls eglGetPlatformDisplay would end up with the same shared EGLDisplay object.
The use I was thinking about initially was for libraries that use EGL as an internal implementation detail, where they'd want their own private EGLDisplay so that they don't interfere with the application or with other libraries.
The name "EGL_PRIVATE_DISPLAY" is left over from that, but it's definitely not the best choice of enum name.
Maybe something like "EGL_ALLOC_NEW_DISPLAY_EXT" instead? That would more clearly describe what it does, rather than what it might be used for.
I'm open to other suggestions, if anyone's got any.
Is "UNIQUE" any clearer?
I just wanted to be sure that it wasn't private to a thread. eglGetPlatformDisplay" with EGL_PRIVATE_DISPLAY_EXT set EGL_TRUE - will not return the same EGLDisplay handle twice, so private by unknown/obscure by any other EGL user.
Yeah, that's correct.
Looking at your current EGL_EXT_display_alloc.txt lines 62-64 Good Line 88, may I suggest add "unique" handle. That might cover James' suggestion and would cover my desire for clarity for users and implementers.
Can do.
For the enum name, would something like "EGL_UNIQUE_DISPLAY_EXT" or "EGL_ALLOC_DISPLAY_EXT" read better than "EGL_PRIVATE_DISPLAY_EXT"?
PRIVATE is OK with me. In all cases what that means needs to be clear.