mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 01:53:24 +09:00
[Fix] (Remote): the present record presents a host-framed surface
A split client's swap reaches the server as a present record, and ServerVerbSink::OnPresent only ran the backend's Present - an eglSwapBuffers of the pbuffer the context was made with. BackendObject::SwapEGLBuffers is the only route to PresentHostFrame and a split client never takes it, so over TCP the display host was never told a frame was drawn: the app offered thousands of frames and presented none. BackendObject::PresentHostFrameIfCurrent presents the host frame when the current surface is host-framed and is a no-op otherwise; OnPresent calls it after Present and before the credit goes back, so a client released by the credit is released by a frame that is on its way to the glass.
This commit is contained in:
@@ -479,6 +479,12 @@ namespace MobileGL::MG_Backend {
|
||||
return false;
|
||||
}
|
||||
|
||||
Bool BackendObject::PresentHostFrameIfCurrent() {
|
||||
const std::lock_guard<std::recursive_mutex> lock(m_eglStateMutex);
|
||||
if (!m_eglSurfaceInitialized || m_eglSurfaceKind != SurfaceKind::HostFrame) return true;
|
||||
return PresentHostFrame();
|
||||
}
|
||||
|
||||
Bool BackendObject::IsEGLSurfaceCurrent(EGLSurface surface) const {
|
||||
if (surface == EGL_NO_SURFACE) {
|
||||
return false;
|
||||
|
||||
@@ -602,6 +602,11 @@ namespace MobileGL {
|
||||
virtual Bool CreateEGLHostFrameSurface(EGLSurface surface, Uint32 width, Uint32 height);
|
||||
virtual Bool InitHostFrameSurface(EGLint width, EGLint height);
|
||||
virtual Bool PresentHostFrame();
|
||||
// The present RECORD's half of a host-framed swap. A split client's swap reaches the
|
||||
// server as a present record (ServerVerbSink::OnPresent), never as SwapEGLBuffers, so
|
||||
// without this the host was never told a frame was drawn. True when the current
|
||||
// surface is not host-framed: there is nothing to present then.
|
||||
Bool PresentHostFrameIfCurrent();
|
||||
virtual Bool MakeEGLCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
|
||||
virtual Bool SwapEGLBuffers(EGLDisplay dpy, EGLSurface draw);
|
||||
// Forwards the app-requested eglSwapInterval to the backend's native
|
||||
|
||||
@@ -404,6 +404,15 @@ namespace MobileGL::MG_Remote::Server {
|
||||
// was wanted, recorded here so a future swap-without-present is looked for rather than
|
||||
// assumed impossible. Presents() is exposed for a lane that wants to make the comparison.
|
||||
table->Present();
|
||||
// A HOST-FRAMED SURFACE IS PRESENTED BY TELLING THE HOST, not by the swap above (which
|
||||
// swaps the pbuffer the context was made with). BackendObject::SwapEGLBuffers is the
|
||||
// only other route to PresentHostFrame and a split client never reaches it, so this is
|
||||
// where the display host learns the frame is drawn - before the credit goes back, so a
|
||||
// client released by it is released by a frame that is on its way to the glass.
|
||||
if (m_backend != nullptr) {
|
||||
if (!m_backend->PresentHostFrameIfCurrent())
|
||||
MGLOG_E_ONCE("OnPresent: the host frame was not presented (PresentHostFrame failed; see above)");
|
||||
}
|
||||
++m_presents;
|
||||
// FrameSerial 0 means "the server stamps its own" (c1-v1 8.3): P5 has no client-side
|
||||
// present credit, so the client sends 0 and the frame count on this side IS the serial.
|
||||
|
||||
Reference in New Issue
Block a user