mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 01:53:24 +09:00
[Fix] (EGL, DirectGLES): keep a lost context's release off the fresh session, bind no surfaceless context natively, and keep the display while surfaces remain.
This commit is contained in:
@@ -17110,7 +17110,14 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
tuple->Read = EGL_NO_SURFACE;
|
||||
g_nativeRegistryEpoch.fetch_add(1, std::memory_order_acq_rel);
|
||||
if (g_displayUsers > 0) --g_displayUsers;
|
||||
if (g_displayUsers == 0 && g_Display != EGL_NO_DISPLAY && g_EGLFuncs.eglTerminate) {
|
||||
// NOT WHILE A SESSION STILL HOLDS SURFACES. eglTerminate destroys them with the display, and
|
||||
// the session keeps naming them: the next context made current on one (an application that
|
||||
// destroys its only context and creates another on the same surface, as eglinfo does with
|
||||
// its surfaceless stand-in) bound a surface the driver no longer had. The session's own
|
||||
// teardown terminates the display once its surfaces are gone (DestroyNativeStateOfSession).
|
||||
Bool surfacesRemain = false;
|
||||
for (const auto* session : NativeSessions()) surfacesRemain = surfacesRemain || !session->Surfaces.empty();
|
||||
if (g_displayUsers == 0 && !surfacesRemain && g_Display != EGL_NO_DISPLAY && g_EGLFuncs.eglTerminate) {
|
||||
g_EGLFuncs.eglTerminate(g_Display);
|
||||
NoteDisplayTerminated();
|
||||
g_Display = EGL_NO_DISPLAY;
|
||||
@@ -17139,9 +17146,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// surface drew one window's frame into the other.
|
||||
NativeSessionState& session = ActiveNativeSession();
|
||||
// Nothing to make it current on yet: a context bound for the records of its own creation
|
||||
// (EGLImpl's CreateContext) before the session has any surface. Its first make-current
|
||||
// gives it one.
|
||||
if (tuple.Draw == EGL_NO_SURFACE && session.Draw == EGL_NO_SURFACE) return true;
|
||||
// (EGLImpl's CreateContext), which no make-current has given a surface (or whose surface
|
||||
// is gone). Binding it to whichever surface the session holds would hand it another
|
||||
// context's surface - one the driver may not even have any more. Its first make-current
|
||||
// binds it natively.
|
||||
if (tuple.Draw == EGL_NO_SURFACE) return true;
|
||||
if (tuple.Draw != session.Draw && SessionOwnsSurface(session, tuple.Draw)) {
|
||||
session.Draw = tuple.Draw;
|
||||
session.Read = SessionOwnsSurface(session, tuple.Read) ? tuple.Read : tuple.Draw;
|
||||
|
||||
@@ -938,6 +938,9 @@ namespace MobileGL::MG_Impl::EGLImpl {
|
||||
// knows it. Read here because `state->MakeCurrent` below has already committed the
|
||||
// new one by the time the emission points are reached.
|
||||
const Uint64 oldContextToken = state->GetContextClientToken(oldContext);
|
||||
// Read before the release too: a thread letting go of a context lost with an ended session
|
||||
// says nothing to the fresh one (its binding never named that context).
|
||||
const Bool oldContextLost = ContextIsLost(state, oldContext);
|
||||
#endif
|
||||
const String threadId = CurrentThreadIdString();
|
||||
|
||||
@@ -981,7 +984,11 @@ namespace MobileGL::MG_Impl::EGLImpl {
|
||||
}
|
||||
MGLOG_D("eglMakeCurrent release succeeded thread=%s", threadId.c_str());
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
EmitContextBinding(state, EGL_NO_CONTEXT, oldContextToken);
|
||||
{
|
||||
std::optional<ClientSession::ScopedWireMute> silence;
|
||||
if (oldContextLost) silence.emplace();
|
||||
EmitContextBinding(state, EGL_NO_CONTEXT, oldContextToken);
|
||||
}
|
||||
#endif
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user