Add RenderThreadInfoGl
... and move the GL decoders into a RenderThreadInfoGl which, for
now, is always initialized. This is useful for upcoming changes to
eventually turn off the GL bits when running in Vulkan only mode.
Bug: b/233939967
Test: cvd start --gpu_mode=gfxstream
Test: cvd start --gpu_mode=gfxstream --enable_gpu_angle=true
Change-Id: Id7dd0b078d4870e51dff5a5e7ad2e012f55a1c8b
diff --git a/stream-servers/Android.bp b/stream-servers/Android.bp
index c1969e6..96416d1 100644
--- a/stream-servers/Android.bp
+++ b/stream-servers/Android.bp
@@ -68,14 +68,15 @@
"ReadBuffer.cpp",
"render_api.cpp",
"RenderChannelImpl.cpp",
+ "RenderThread.cpp",
"RenderThreadInfo.cpp",
+ "RenderThreadInfoGl.cpp",
"RingStream.cpp",
"SyncThread.cpp",
"TextureDraw.cpp",
"TextureResize.cpp",
"WindowSurface.cpp",
"YUVConverter.cpp",
- "RenderThread.cpp",
"RenderContext.cpp",
"RenderControl.cpp",
"RenderWindow.cpp",
diff --git a/stream-servers/CMakeLists.txt b/stream-servers/CMakeLists.txt
index f72cacc..ad5e7e7 100644
--- a/stream-servers/CMakeLists.txt
+++ b/stream-servers/CMakeLists.txt
@@ -38,6 +38,7 @@
render_api.cpp
RenderChannelImpl.cpp
RenderThreadInfo.cpp
+ RenderThreadInfoGl.cpp
RingStream.cpp
SyncThread.cpp
TextureDraw.cpp
diff --git a/stream-servers/ColorBuffer.cpp b/stream-servers/ColorBuffer.cpp
index f5ad397..f301f7f 100644
--- a/stream-servers/ColorBuffer.cpp
+++ b/stream-servers/ColorBuffer.cpp
@@ -23,7 +23,7 @@
#include "Debug.h"
#include "OpenGLESDispatch/DispatchTables.h"
#include "OpenGLESDispatch/EGLDispatch.h"
-#include "RenderThreadInfo.h"
+#include "RenderThreadInfoGl.h"
#include "TextureDraw.h"
#include "TextureResize.h"
#include "YUVConverter.h"
@@ -645,7 +645,12 @@
}
bool ColorBuffer::blitFromCurrentReadBuffer() {
- RenderThreadInfo* tInfo = RenderThreadInfo::get();
+ RenderThreadInfoGl* const tInfo = RenderThreadInfoGl::get();
+ if (!tInfo) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "Render thread GL not available.";
+ }
+
if (!tInfo->currContext.get()) {
// no Current context
return false;
@@ -808,7 +813,12 @@
return false;
}
- RenderThreadInfo* tInfo = RenderThreadInfo::get();
+ RenderThreadInfoGl* const tInfo = RenderThreadInfoGl::get();
+ if (!tInfo) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "Render thread GL not available.";
+ }
+
if (!tInfo->currContext.get()) {
return false;
}
@@ -835,7 +845,13 @@
if (!m_eglImage) {
return false;
}
- RenderThreadInfo* tInfo = RenderThreadInfo::get();
+
+ RenderThreadInfoGl* const tInfo = RenderThreadInfoGl::get();
+ if (!tInfo) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "Render thread GL not available.";
+ }
+
if (!tInfo->currContext.get()) {
return false;
}
diff --git a/stream-servers/FrameBuffer.cpp b/stream-servers/FrameBuffer.cpp
index 9b76f80..95cdd8e 100644
--- a/stream-servers/FrameBuffer.cpp
+++ b/stream-servers/FrameBuffer.cpp
@@ -31,6 +31,8 @@
#include "OpenGLESDispatch/EGLDispatch.h"
#include "RenderControl.h"
#include "RenderThreadInfo.h"
+#include "RenderThreadInfoGl.h"
+#include "SyncThread.h"
#include "YUVConverter.h"
#include "base/LayoutResolver.h"
#include "base/Lock.h"
@@ -1731,7 +1733,11 @@
if (puid) {
m_procOwnedRenderContext[puid].insert(ret);
} else { // legacy path to manage context lifetime by threads
- tinfo->m_contextSet.insert(ret);
+ if (!tinfo->m_glInfo) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "Render thread GL not available.";
+ }
+ tinfo->m_glInfo->m_contextSet.insert(ret);
}
} else {
ret = 0;
@@ -1764,19 +1770,46 @@
if (puid) {
m_procOwnedWindowSurfaces[puid].insert(ret);
} else { // legacy path to manage window surface lifetime by threads
- tInfo->m_windowSet.insert(ret);
+ if (!tInfo->m_glInfo) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "Render thread GL not available.";
+ }
+ tInfo->m_glInfo->m_windowSet.insert(ret);
}
}
return ret;
}
-void FrameBuffer::drainRenderContext() {
- if (m_shuttingDown) {
+void FrameBuffer::drainRenderThreadResources() {
+ // If we're already exiting then snapshot should not contain
+ // this thread information at all.
+ if (isShuttingDown()) {
return;
}
- RenderThreadInfo* const tinfo = RenderThreadInfo::get();
+ // Release references to the current thread's context/surfaces if any
+ bindContext(0, 0, 0);
+
+ drainRenderThreadWindowSurfaces();
+ drainRenderThreadContexts();
+
+ if (!s_egl.eglReleaseThread()) {
+ ERR("Error: RenderThread @%p failed to eglReleaseThread()", this);
+ }
+}
+
+void FrameBuffer::drainRenderThreadContexts() {
+ if (isShuttingDown()) {
+ return;
+ }
+
+ RenderThreadInfoGl* const tinfo = RenderThreadInfoGl::get();
+ if (!tinfo) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "Render thread GL not available.";
+ }
+
if (tinfo->m_contextSet.empty()) {
return;
}
@@ -1789,11 +1822,17 @@
tinfo->m_contextSet.clear();
}
-void FrameBuffer::drainWindowSurface() {
- if (m_shuttingDown) {
+void FrameBuffer::drainRenderThreadWindowSurfaces() {
+ if (isShuttingDown()) {
return;
}
- RenderThreadInfo* const tinfo = RenderThreadInfo::get();
+
+ RenderThreadInfoGl* const tinfo = RenderThreadInfoGl::get();
+ if (!tinfo) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "Render thread GL not available.";
+ }
+
if (tinfo->m_windowSet.empty()) {
return;
}
@@ -1847,7 +1886,11 @@
ite->second.erase(p_context);
}
} else {
- tinfo->m_contextSet.erase(p_context);
+ if (!tinfo->m_glInfo) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "Render thread GL not available.";
+ }
+ tinfo->m_glInfo->m_contextSet.erase(p_context);
}
}
@@ -1890,7 +1933,11 @@
ite->second.erase(p_surface);
}
} else {
- tinfo->m_windowSet.erase(p_surface);
+ if (!tinfo->m_glInfo) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "Render thread GL not available.";
+ }
+ tinfo->m_glInfo->m_windowSet.erase(p_surface);
}
}
return colorBuffersToCleanUp;
@@ -2626,7 +2673,12 @@
//
// Bind the surface(s) to the context
//
- RenderThreadInfo* tinfo = RenderThreadInfo::get();
+ RenderThreadInfoGl* const tinfo = RenderThreadInfoGl::get();
+ if (!tinfo) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "Render thread GL not available.";
+ }
+
WindowSurfacePtr bindDraw, bindRead;
if (draw.get() == NULL && read.get() == NULL) {
// Unbind the current read and draw surfaces from the context
diff --git a/stream-servers/FrameBuffer.h b/stream-servers/FrameBuffer.h
index a06023d..ffeb1a9 100644
--- a/stream-servers/FrameBuffer.h
+++ b/stream-servers/FrameBuffer.h
@@ -252,14 +252,19 @@
void createBufferWithHandle(uint64_t size, HandleType handle);
// Call this function when a render thread terminates to destroy all
- // the remaining contexts it created. Necessary to avoid leaking host
- // contexts when a guest application crashes, for example.
- void drainRenderContext();
+ // resources it created. Necessary to avoid leaking host resources
+ // when a guest application crashes, for example.
+ void drainRenderThreadResources();
// Call this function when a render thread terminates to destroy all
- // remaining window surfqce it created. Necessary to avoid leaking
+ // the remaining contexts it created. Necessary to avoid leaking host
+ // contexts when a guest application crashes, for example.
+ void drainRenderThreadContexts();
+
+ // Call this function when a render thread terminates to destroy all
+ // remaining window surface it created. Necessary to avoid leaking
// host buffers when a guest application crashes, for example.
- void drainWindowSurface();
+ void drainRenderThreadWindowSurfaces();
// Destroy a given RenderContext instance. |p_context| is its handle
// value as returned by createRenderContext().
diff --git a/stream-servers/RenderControl.cpp b/stream-servers/RenderControl.cpp
index f950ec3..44786f8 100644
--- a/stream-servers/RenderControl.cpp
+++ b/stream-servers/RenderControl.cpp
@@ -31,6 +31,7 @@
#include "OpenGLESDispatch/EGLDispatch.h"
#include "RenderContext.h"
#include "RenderThreadInfo.h"
+#include "RenderThreadInfoGl.h"
#include "SyncThread.h"
#include "base/Tracing.h"
#include "host-common/dma_device.h"
@@ -426,7 +427,7 @@
}
static EGLint rcGetGLString(EGLenum name, void* buffer, EGLint bufferSize) {
- RenderThreadInfo *tInfo = RenderThreadInfo::get();
+ RenderThreadInfoGl* const tInfo = RenderThreadInfoGl::get();
// whatever we end up returning,
// it will have a terminating \0,
@@ -1163,7 +1164,11 @@
// rcTriggerWait is registered.
emugl_sync_register_trigger_wait(rcTriggerWait);
- RenderThreadInfo *tInfo = RenderThreadInfo::get();
+ RenderThreadInfoGl* const tInfo = RenderThreadInfoGl::get();
+ if (!tInfo) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "Render thread GL not available.";
+ }
if (!tInfo->currContext) {
auto fb = FrameBuffer::getFB();
@@ -1200,7 +1205,12 @@
static EGLint rcClientWaitSyncKHR(uint64_t handle,
EGLint flags,
uint64_t timeout) {
- RenderThreadInfo *tInfo = RenderThreadInfo::get();
+ RenderThreadInfoGl* const tInfo = RenderThreadInfoGl::get();
+ if (!tInfo) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "Render thread GL not available.";
+ }
+
FrameBuffer *fb = FrameBuffer::getFB();
EGLSYNC_DPRINT("handle=0x%lx flags=0x%x timeout=%" PRIu64,
@@ -1232,7 +1242,12 @@
static void rcWaitSyncKHR(uint64_t handle,
EGLint flags) {
- RenderThreadInfo *tInfo = RenderThreadInfo::get();
+ RenderThreadInfoGl* const tInfo = RenderThreadInfoGl::get();
+ if (!tInfo) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "Render thread GL not available.";
+ }
+
FrameBuffer *fb = FrameBuffer::getFB();
EGLSYNC_DPRINT("handle=0x%lx flags=0x%x", handle, flags);
diff --git a/stream-servers/RenderThread.cpp b/stream-servers/RenderThread.cpp
index 88eb3b8..f3eb05a 100644
--- a/stream-servers/RenderThread.cpp
+++ b/stream-servers/RenderThread.cpp
@@ -268,8 +268,8 @@
//
// initialize decoders
//
- tInfo.m_glDec.initGL(gles1_dispatch_get_proc_func, nullptr);
- tInfo.m_gl2Dec.initGL(gles2_dispatch_get_proc_func, nullptr);
+ tInfo.initGl();
+
initRenderControlContext(&tInfo.m_rcDec);
if (!mChannel && !mRingStream) {
@@ -380,16 +380,7 @@
// restores the contexts from the handles, so check again here.
tInfo.postLoadRefreshCurrentContextSurfacePtrs();
- // We just loaded from a snapshot, need to initialize / bind
- // the contexts.
needRestoreFromSnapshot = false;
- HandleType ctx = tInfo.currContext ? tInfo.currContext->getHndl()
- : 0;
- HandleType draw = tInfo.currDrawSurf ? tInfo.currDrawSurf->getHndl()
- : 0;
- HandleType read = tInfo.currReadSurf ? tInfo.currReadSurf->getHndl()
- : 0;
- FrameBuffer::getFB()->bindContext(ctx, draw, read);
}
}
@@ -482,26 +473,28 @@
FrameBuffer::getFB()->lockContextStructureRead();
}
- {
- last = tInfo.m_glDec.decode(
- readBuf.buf(), readBuf.validData(), ioStream, &checksumCalc);
- if (last > 0) {
- progress = true;
- readBuf.consume(last);
+ if (tInfo.m_glInfo) {
+ {
+ last = tInfo.m_glInfo->m_glDec.decode(
+ readBuf.buf(), readBuf.validData(), ioStream, &checksumCalc);
+ if (last > 0) {
+ progress = true;
+ readBuf.consume(last);
+ }
}
- }
- //
- // try to process some of the command buffer using the GLESv2
- // decoder
- //
- {
- last = tInfo.m_gl2Dec.decode(readBuf.buf(), readBuf.validData(),
- ioStream, &checksumCalc);
+ //
+ // try to process some of the command buffer using the GLESv2
+ // decoder
+ //
+ {
+ last = tInfo.m_glInfo->m_gl2Dec.decode(readBuf.buf(), readBuf.validData(),
+ ioStream, &checksumCalc);
- if (last > 0) {
- progress = true;
- readBuf.consume(last);
+ if (last > 0) {
+ progress = true;
+ readBuf.consume(last);
+ }
}
}
@@ -530,22 +523,7 @@
fclose(dumpFP);
}
- // Don't check for snapshots here: if we're already exiting then snapshot
- // should not contain this thread information at all.
- if (!FrameBuffer::getFB()->isShuttingDown()) {
- // Release references to the current thread's context/surfaces if any
- FrameBuffer::getFB()->bindContext(0, 0, 0);
- if (tInfo.currContext || tInfo.currDrawSurf || tInfo.currReadSurf) {
- ERR("ERROR: RenderThread exiting with current context/surfaces");
- }
-
- FrameBuffer::getFB()->drainWindowSurface();
- FrameBuffer::getFB()->drainRenderContext();
- }
-
- if (!s_egl.eglReleaseThread()) {
- ERR("Error: RenderThread @%p failed to eglReleaseThread()", this);
- }
+ FrameBuffer::getFB()->drainRenderThreadResources();
setFinished();
diff --git a/stream-servers/RenderThreadInfo.cpp b/stream-servers/RenderThreadInfo.cpp
index 2e753bf..4bf8dad 100644
--- a/stream-servers/RenderThreadInfo.cpp
+++ b/stream-servers/RenderThreadInfo.cpp
@@ -16,12 +16,8 @@
#include "RenderThreadInfo.h"
-#include "base/Lookup.h"
-#include "base/StreamSerializing.h"
#include "base/Lock.h"
-#include "FrameBuffer.h"
-
#include <unordered_map>
#include <unordered_set>
@@ -62,76 +58,18 @@
}
}
+void RenderThreadInfo::initGl() {
+ m_glInfo.emplace();
+}
+
void RenderThreadInfo::onSave(Stream* stream) {
- if (currContext) {
- stream->putBe32(currContext->getHndl());
- } else {
- stream->putBe32(0);
- }
- if (currDrawSurf) {
- stream->putBe32(currDrawSurf->getHndl());
- } else {
- stream->putBe32(0);
- }
- if (currReadSurf) {
- stream->putBe32(currReadSurf->getHndl());
- } else {
- stream->putBe32(0);
- }
-
- saveCollection(stream, m_contextSet, [](Stream* stream, HandleType val) {
- stream->putBe32(val);
- });
- saveCollection(stream, m_windowSet, [](Stream* stream, HandleType val) {
- stream->putBe32(val);
- });
-
- stream->putBe64(m_puid);
-
- // No need to associate render threads with sync threads
- // if there is a global sync thread. This is only needed
- // to maintain backward compatibility with snapshot file format.
- // (Used to be: stream->putBe64(syncThreadAlias))
- stream->putBe64(0);
+ m_glInfo->onSave(stream);
}
bool RenderThreadInfo::onLoad(Stream* stream) {
- FrameBuffer* fb = FrameBuffer::getFB();
- assert(fb);
- HandleType ctxHndl = stream->getBe32();
- HandleType drawSurf = stream->getBe32();
- HandleType readSurf = stream->getBe32();
- currContextHandleFromLoad = ctxHndl;
- currDrawSurfHandleFromLoad = drawSurf;
- currReadSurfHandleFromLoad = readSurf;
-
- fb->lock();
- currContext = fb->getContext_locked(ctxHndl);
- currDrawSurf = fb->getWindowSurface_locked(drawSurf);
- currReadSurf = fb->getWindowSurface_locked(readSurf);
- fb->unlock();
-
- loadCollection(stream, &m_contextSet, [](Stream* stream) {
- return stream->getBe32();
- });
- loadCollection(stream, &m_windowSet, [](Stream* stream) {
- return stream->getBe32();
- });
-
- m_puid = stream->getBe64();
-
- // (Used to be: syncThreadAlias = stream->getBe64())
- stream->getBe64();
-
- return true;
+ return m_glInfo->onLoad(stream);
}
void RenderThreadInfo::postLoadRefreshCurrentContextSurfacePtrs() {
- FrameBuffer* fb = FrameBuffer::getFB();
- assert(fb);
- fb->lock();
- currContext = fb->getContext_locked(currContextHandleFromLoad);
- currDrawSurf = fb->getWindowSurface_locked(currDrawSurfHandleFromLoad);
- currReadSurf = fb->getWindowSurface_locked(currReadSurfHandleFromLoad);
- fb->unlock();
+ return m_glInfo->postLoadRefreshCurrentContextSurfacePtrs();
}
diff --git a/stream-servers/RenderThreadInfo.h b/stream-servers/RenderThreadInfo.h
index b291c17..bd45c21 100644
--- a/stream-servers/RenderThreadInfo.h
+++ b/stream-servers/RenderThreadInfo.h
@@ -20,19 +20,10 @@
#include <memory>
#include <unordered_set>
-#include "RenderContext.h"
-#include "StalePtrRegistry.h"
-#include "SyncThread.h"
-#include "RenderThreadInfoVk.h"
-#include "WindowSurface.h"
#include "base/Stream.h"
-#include "gles1_dec/GLESv1Decoder.h"
-#include "gles2_dec/GLESv2Decoder.h"
#include "renderControl_dec/renderControl_dec.h"
-
-typedef uint32_t HandleType;
-typedef std::unordered_set<HandleType> ThreadContextSet;
-typedef std::unordered_set<HandleType> WindowSurfaceSet;
+#include "RenderThreadInfoGl.h"
+#include "RenderThreadInfoVk.h"
// A class used to model the state of each RenderThread related
struct RenderThreadInfo {
@@ -50,32 +41,15 @@
// Loop over all active render thread infos
static void forAllRenderThreadInfos(std::function<void(RenderThreadInfo*)>);
- // Current EGL context, draw surface and read surface.
- HandleType currContextHandleFromLoad;
- HandleType currDrawSurfHandleFromLoad;
- HandleType currReadSurfHandleFromLoad;
+ void initGl();
- RenderContextPtr currContext;
- WindowSurfacePtr currDrawSurf;
- WindowSurfacePtr currReadSurf;
-
- // Decoder states.
- GLESv1Decoder m_glDec;
- GLESv2Decoder m_gl2Dec;
renderControl_decoder_context_t m_rcDec;
- // All the contexts that are created by this render thread.
- // New emulator manages contexts in guest process level,
- // m_contextSet should be deprecated. It is only kept for
- // backward compatibility reason.
- ThreadContextSet m_contextSet;
- // all the window surfaces that are created by this render thread
- WindowSurfaceSet m_windowSet;
-
// The unique id of owner guest process of this render thread
uint64_t m_puid = 0;
std::optional<std::string> m_processName;
+ std::optional<RenderThreadInfoGl> m_glInfo;
std::optional<goldfish_vk::RenderThreadInfoVk> m_vkInfo;
// Functions to save / load a snapshot
diff --git a/stream-servers/RenderThreadInfoGl.cpp b/stream-servers/RenderThreadInfoGl.cpp
new file mode 100644
index 0000000..8f47f17
--- /dev/null
+++ b/stream-servers/RenderThreadInfoGl.cpp
@@ -0,0 +1,130 @@
+// Copyright 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either expresso or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "RenderThreadInfoGl.h"
+
+#include <unordered_set>
+
+#include "FrameBuffer.h"
+#include "OpenGLESDispatch/GLESv1Dispatch.h"
+#include "OpenGLESDispatch/GLESv2Dispatch.h"
+#include "base/Lock.h"
+#include "base/Lookup.h"
+#include "base/StreamSerializing.h"
+#include "host-common/GfxstreamFatalError.h"
+
+using android::base::AutoLock;
+using android::base::Lock;
+using android::base::Stream;
+using emugl::ABORT_REASON_OTHER;
+using emugl::FatalError;
+
+static thread_local RenderThreadInfoGl* tlThreadInfo = nullptr;
+
+RenderThreadInfoGl::RenderThreadInfoGl() {
+ m_glDec.initGL(gles1_dispatch_get_proc_func, nullptr);
+ m_gl2Dec.initGL(gles2_dispatch_get_proc_func, nullptr);
+
+ if (tlThreadInfo != nullptr) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "Attempted to set thread local GL render thread info twice.";
+ }
+ tlThreadInfo = this;
+}
+
+RenderThreadInfoGl::~RenderThreadInfoGl() {
+ tlThreadInfo = nullptr;
+}
+
+RenderThreadInfoGl* RenderThreadInfoGl::get() { return tlThreadInfo; }
+
+void RenderThreadInfoGl::onSave(Stream* stream) {
+ if (currContext) {
+ stream->putBe32(currContext->getHndl());
+ } else {
+ stream->putBe32(0);
+ }
+ if (currDrawSurf) {
+ stream->putBe32(currDrawSurf->getHndl());
+ } else {
+ stream->putBe32(0);
+ }
+ if (currReadSurf) {
+ stream->putBe32(currReadSurf->getHndl());
+ } else {
+ stream->putBe32(0);
+ }
+
+ saveCollection(stream, m_contextSet, [](Stream* stream, HandleType val) {
+ stream->putBe32(val);
+ });
+ saveCollection(stream, m_windowSet, [](Stream* stream, HandleType val) {
+ stream->putBe32(val);
+ });
+
+ stream->putBe64(m_puid);
+
+ // No need to associate render threads with sync threads
+ // if there is a global sync thread. This is only needed
+ // to maintain backward compatibility with snapshot file format.
+ // (Used to be: stream->putBe64(syncThreadAlias))
+ stream->putBe64(0);
+}
+
+bool RenderThreadInfoGl::onLoad(Stream* stream) {
+ FrameBuffer* fb = FrameBuffer::getFB();
+ assert(fb);
+ HandleType ctxHndl = stream->getBe32();
+ HandleType drawSurf = stream->getBe32();
+ HandleType readSurf = stream->getBe32();
+ currContextHandleFromLoad = ctxHndl;
+ currDrawSurfHandleFromLoad = drawSurf;
+ currReadSurfHandleFromLoad = readSurf;
+
+ fb->lock();
+ currContext = fb->getContext_locked(ctxHndl);
+ currDrawSurf = fb->getWindowSurface_locked(drawSurf);
+ currReadSurf = fb->getWindowSurface_locked(readSurf);
+ fb->unlock();
+
+ loadCollection(stream, &m_contextSet, [](Stream* stream) {
+ return stream->getBe32();
+ });
+ loadCollection(stream, &m_windowSet, [](Stream* stream) {
+ return stream->getBe32();
+ });
+
+ m_puid = stream->getBe64();
+
+ // (Used to be: syncThreadAlias = stream->getBe64())
+ stream->getBe64();
+
+ return true;
+}
+
+void RenderThreadInfoGl::postLoadRefreshCurrentContextSurfacePtrs() {
+ FrameBuffer* fb = FrameBuffer::getFB();
+ assert(fb);
+
+ fb->lock();
+ currContext = fb->getContext_locked(currContextHandleFromLoad);
+ currDrawSurf = fb->getWindowSurface_locked(currDrawSurfHandleFromLoad);
+ currReadSurf = fb->getWindowSurface_locked(currReadSurfHandleFromLoad);
+ fb->unlock();
+
+ const HandleType ctx = currContext ? currContext->getHndl() : 0;
+ const HandleType draw = currDrawSurf ? currDrawSurf->getHndl() : 0;
+ const HandleType read = currReadSurf ? currReadSurf->getHndl() : 0;
+ fb->bindContext(ctx, draw, read);
+}
diff --git a/stream-servers/RenderThreadInfoGl.h b/stream-servers/RenderThreadInfoGl.h
new file mode 100644
index 0000000..c1d671b
--- /dev/null
+++ b/stream-servers/RenderThreadInfoGl.h
@@ -0,0 +1,75 @@
+// Copyright 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either expresso or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#include <optional>
+#include <string>
+
+#include "base/Stream.h"
+#include "gles1_dec/GLESv1Decoder.h"
+#include "gles2_dec/GLESv2Decoder.h"
+#include "RenderContext.h"
+#include "WindowSurface.h"
+#include "StalePtrRegistry.h"
+
+typedef uint32_t HandleType;
+typedef std::unordered_set<HandleType> ThreadContextSet;
+typedef std::unordered_set<HandleType> WindowSurfaceSet;
+
+struct RenderThreadInfoGl {
+ // Create new instance. Only call this once per thread.
+ // Future calls to get() will return this instance until
+ // it is destroyed.
+ RenderThreadInfoGl();
+
+ // Destructor.
+ ~RenderThreadInfoGl();
+
+ // Return the current thread's instance, if any, or NULL.
+ static RenderThreadInfoGl* get();
+
+ // Functions to save / load a snapshot
+ // They must be called after Framebuffer snapshot
+ void onSave(android::base::Stream* stream);
+ bool onLoad(android::base::Stream* stream);
+
+ // Sometimes we can load render thread info before
+ // FrameBuffer repopulates the contexts.
+ void postLoadRefreshCurrentContextSurfacePtrs();
+
+ // The unique id of owner guest process of this render thread
+ uint64_t m_puid = 0;
+
+ // All the contexts that are created by this render thread.
+ // New emulator manages contexts in guest process level,
+ // m_contextSet should be deprecated. It is only kept for
+ // backward compatibility reason.
+ ThreadContextSet m_contextSet;
+ // all the window surfaces that are created by this render thread
+ WindowSurfaceSet m_windowSet;
+
+ // Current EGL context, draw surface and read surface.
+ HandleType currContextHandleFromLoad;
+ HandleType currDrawSurfHandleFromLoad;
+ HandleType currReadSurfHandleFromLoad;
+
+ RenderContextPtr currContext;
+ WindowSurfacePtr currDrawSurf;
+ WindowSurfacePtr currReadSurf;
+
+ // Decoder states.
+ GLESv1Decoder m_glDec;
+ GLESv2Decoder m_gl2Dec;
+};
diff --git a/stream-servers/tests/FrameBuffer_unittest.cpp b/stream-servers/tests/FrameBuffer_unittest.cpp
index d858e43..a3ddec8 100644
--- a/stream-servers/tests/FrameBuffer_unittest.cpp
+++ b/stream-servers/tests/FrameBuffer_unittest.cpp
@@ -104,6 +104,7 @@
EXPECT_EQ(EGL_SUCCESS, egl->eglGetError());
mRenderThreadInfo = new RenderThreadInfo();
+ mRenderThreadInfo->initGl();
// Snapshots
mTestSystem.getTempRoot()->makeSubDir("Snapshots");
diff --git a/stream-servers/tests/GLSnapshotTestDispatch.cpp b/stream-servers/tests/GLSnapshotTestDispatch.cpp
index 1e9c192..1b5ed28 100644
--- a/stream-servers/tests/GLSnapshotTestDispatch.cpp
+++ b/stream-servers/tests/GLSnapshotTestDispatch.cpp
@@ -99,11 +99,11 @@
threadInfo->onLoad(m_stream.get());
// rebind to context
fb->bindContext(
- threadInfo->currContext ? threadInfo->currContext->getHndl()
+ threadInfo->m_glInfo->currContext ? threadInfo->m_glInfo->currContext->getHndl()
: 0,
- threadInfo->currDrawSurf ? threadInfo->currDrawSurf->getHndl()
+ threadInfo->m_glInfo->currDrawSurf ? threadInfo->m_glInfo->currDrawSurf->getHndl()
: 0,
- threadInfo->currReadSurf ? threadInfo->currReadSurf->getHndl()
+ threadInfo->m_glInfo->currReadSurf ? threadInfo->m_glInfo->currReadSurf->getHndl()
: 0);
}
diff --git a/stream-servers/tests/SampleApplication.cpp b/stream-servers/tests/SampleApplication.cpp
index e30a5ac..149ffd6 100644
--- a/stream-servers/tests/SampleApplication.cpp
+++ b/stream-servers/tests/SampleApplication.cpp
@@ -263,6 +263,7 @@
}
mRenderThreadInfo.reset(new RenderThreadInfo());
+ mRenderThreadInfo->initGl();
mColorBuffer = mFb->createColorBuffer(mWidth, mHeight, GL_RGBA, FRAMEWORK_FORMAT_GL_COMPATIBLE);
mContext = mFb->createRenderContext(0, 0, glVersion);