mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-15 22:13:24 +09:00
[Fix] (EGL, Remote): a server-owned surface is re-created at the size it asked for, and a lost session's image reference is never released on the fresh one.
This commit is contained in:
@@ -1643,8 +1643,16 @@ namespace MobileGL::MG_Impl::EGLImpl {
|
||||
state->SetError(EGL_BAD_MATCH);
|
||||
return EGL_NO_IMAGE;
|
||||
}
|
||||
const EGLImage image = state->CreateSharedImage(
|
||||
dpy, {.Id = sharedImageId, .Width = request.Width, .Height = request.Height, .Fourcc = request.Fourcc});
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
const Uint64 wireEpoch = MG_State::CurrentWireEpoch();
|
||||
#else
|
||||
const Uint64 wireEpoch = 0;
|
||||
#endif
|
||||
const EGLImage image = state->CreateSharedImage(dpy, {.Id = sharedImageId,
|
||||
.Width = request.Width,
|
||||
.Height = request.Height,
|
||||
.Fourcc = request.Fourcc,
|
||||
.WireEpoch = wireEpoch});
|
||||
if (image == EGL_NO_IMAGE) (void)backendObject->ReleaseSharedImage(sharedImageId);
|
||||
return image;
|
||||
}
|
||||
@@ -1654,10 +1662,20 @@ namespace MobileGL::MG_Impl::EGLImpl {
|
||||
if (!state) {
|
||||
return EGL_FALSE;
|
||||
}
|
||||
// The session the image's reference was taken on: a reference of a session that has ended
|
||||
// died with it, and the same image imported again on the fresh session has the same id - a
|
||||
// release of the old one sent there would drop the new one's reference.
|
||||
MG_State::EGLState::EGLContext::SharedImageInfo shared;
|
||||
const Bool sharedImage = state->GetSharedImage(image, &shared);
|
||||
Uint64 sharedImageId = 0;
|
||||
if (!state->DestroyImage(dpy, image, &sharedImageId)) {
|
||||
return EGL_FALSE;
|
||||
}
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
if (sharedImage && shared.WireEpoch != MG_State::CurrentWireEpoch()) sharedImageId = 0;
|
||||
#else
|
||||
(void)sharedImage;
|
||||
#endif
|
||||
// A texture the image was bound to keeps its own reference on the server (EGLImage
|
||||
// siblings outlive the image), so only this handle's goes.
|
||||
if (sharedImageId != 0) {
|
||||
|
||||
@@ -238,8 +238,12 @@ namespace MobileGL::MG_Remote::Client {
|
||||
// into its registration only; it is re-created at that size when it is next used.
|
||||
{
|
||||
const std::lock_guard<std::recursive_mutex> lock(m_eglStateMutex);
|
||||
if (GetRegisteredEGLSurface(surface) != nullptr && m_homedSurfaces.count(surface) == 0)
|
||||
if (GetRegisteredEGLSurface(surface) != nullptr && m_homedSurfaces.count(surface) == 0) {
|
||||
// A server-owned one asks the fresh session's window for this size, as a resize would.
|
||||
if (ClientSession::IsServerOwnedWindowSurface(surface))
|
||||
m_serverOwnedRequests[surface] = {width, height};
|
||||
return MG_Backend::BackendObject::ResizeEGLWindowSurface(surface, width, height);
|
||||
}
|
||||
}
|
||||
// P12 review fix: a surface on the SERVER's window is resized by resizing that window. The
|
||||
// server asks its display for the size and answers with the extent the window really took,
|
||||
@@ -254,6 +258,7 @@ namespace MobileGL::MG_Remote::Client {
|
||||
width, height, static_cast<int>(reply.transport), Server::SurfaceRefusalCodeName(reply.refusal));
|
||||
return false;
|
||||
}
|
||||
NoteServerOwnedRequest(surface, width, height);
|
||||
const Uint32 realWidth = reply.width != 0 ? reply.width : width;
|
||||
const Uint32 realHeight = reply.height != 0 ? reply.height : height;
|
||||
if (MG_State::pEGLContext) {
|
||||
@@ -392,6 +397,7 @@ namespace MobileGL::MG_Remote::Client {
|
||||
local.Width = reply.width;
|
||||
local.Height = reply.height;
|
||||
if (!MG_Backend::BackendObject::CreateEGLWindowSurface(surface, local)) return false;
|
||||
NoteServerOwnedRequest(surface, handle.Width, handle.Height);
|
||||
NoteHomed(surface);
|
||||
return true;
|
||||
}
|
||||
@@ -481,6 +487,7 @@ namespace MobileGL::MG_Remote::Client {
|
||||
const std::lock_guard<std::recursive_mutex> lock(m_eglStateMutex);
|
||||
homed = m_homedSurfaces.erase(surface) != 0;
|
||||
m_standInSurfaces.erase(surface);
|
||||
m_serverOwnedRequests.erase(surface);
|
||||
}
|
||||
if (homed && !ClientSession::SessionLatchedLost()) Server::ServerReleaseEGLSurface(surface);
|
||||
MG_Backend::BackendObject::ReleaseEGLSurface(surface);
|
||||
@@ -534,8 +541,13 @@ namespace MobileGL::MG_Remote::Client {
|
||||
recreated = Server::ServerCreateEGLPbufferSurface(surface, state.Width, state.Height, nullptr, flags);
|
||||
} else if (ClientSession::IsServerOwnedWindowSurface(surface)) {
|
||||
kind = "server-owned window";
|
||||
// The window is asked for what the application asked for (its own size for a surface
|
||||
// created without one), not for the extent it had: that would fix its size for good.
|
||||
const auto requested = m_serverOwnedRequests.find(surface);
|
||||
const Uint32 wantWidth = requested != m_serverOwnedRequests.end() ? requested->second.first : 0u;
|
||||
const Uint32 wantHeight = requested != m_serverOwnedRequests.end() ? requested->second.second : 0u;
|
||||
const Server::ServerOwnedWindowReply reply =
|
||||
Server::ServerCreateServerOwnedWindowSurface(surface, state.Window.Width, state.Window.Height);
|
||||
Server::ServerCreateServerOwnedWindowSurface(surface, wantWidth, wantHeight);
|
||||
recreated = reply.ok;
|
||||
if (recreated && reply.width != 0 && reply.height != 0) {
|
||||
if (MG_State::pEGLContext) {
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
|
||||
namespace MobileGL::MG_Remote::Client {
|
||||
|
||||
@@ -156,6 +157,15 @@ namespace MobileGL::MG_Remote::Client {
|
||||
std::unordered_map<Uint64, Uint32> m_sessionSharedImages; // id -> references taken
|
||||
// The ids a replaced session held: releasing one is a success with nothing sent.
|
||||
std::unordered_set<Uint64> m_lostSessionSharedImages;
|
||||
// The size each server-owned window surface ASKED for (0x0: the window's own), which is what a
|
||||
// fresh session is asked for again when the surface is re-created there - not the extent the
|
||||
// window happened to have, which would fix the window's size for good. Guarded by
|
||||
// m_eglStateMutex.
|
||||
std::unordered_map<EGLSurface, std::pair<Uint32, Uint32>> m_serverOwnedRequests;
|
||||
void NoteServerOwnedRequest(EGLSurface surface, Uint32 width, Uint32 height) {
|
||||
const std::lock_guard<std::recursive_mutex> lock(m_eglStateMutex);
|
||||
m_serverOwnedRequests[surface] = {width, height};
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace MobileGL::MG_Remote::Client
|
||||
|
||||
@@ -342,7 +342,14 @@ namespace MobileGL {
|
||||
|
||||
for (auto imageIt = m_images.begin(); imageIt != m_images.end();) {
|
||||
if (imageIt->second.Display == display) {
|
||||
if (imageIt->second.Shared.Id != 0) m_orphanedSharedImages.push_back(imageIt->second.Shared.Id);
|
||||
// Only a reference the current session holds is owed a release there.
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
const Bool currentSession = imageIt->second.Shared.WireEpoch == CurrentWireEpoch();
|
||||
#else
|
||||
constexpr Bool currentSession = true;
|
||||
#endif
|
||||
if (imageIt->second.Shared.Id != 0 && currentSession)
|
||||
m_orphanedSharedImages.push_back(imageIt->second.Shared.Id);
|
||||
imageIt = m_images.erase(imageIt);
|
||||
} else {
|
||||
++imageIt;
|
||||
|
||||
@@ -197,6 +197,10 @@ namespace MobileGL {
|
||||
EGLint Width = 0;
|
||||
EGLint Height = 0;
|
||||
Uint32 Fourcc = 0;
|
||||
// The server session the reference was taken on (MG_State::CurrentWireEpoch() at the
|
||||
// import). A reference of an ended session died with it and is never released on
|
||||
// another: the same image imported again on the fresh session has the same Id.
|
||||
Uint64 WireEpoch = 0;
|
||||
};
|
||||
static constexpr Uint32 kDrmFourccAbgr8888 = 0x34324241u; // 'AB24'
|
||||
static constexpr Uint32 kDrmFourccXbgr8888 = 0x34324258u; // 'XB24'
|
||||
|
||||
Reference in New Issue
Block a user