Remove FrameBuffer teardownVkColorBuffer() calls

... as these are no longer needed after aosp/2452176 which ties
the VK backing directly to the lifetime of ColorBuffer.

Bug: b/233939967
Bug: b/271904841
Test: android build
Test: cmake build
Test: cvd start --gpu_mode=gfxstream
Test: cvd start --gpu_mode=gfxstream --enable_gpu_angle=true
Test: gfxstream unit tests
Change-Id: I3828071491ea0eeadd612838402d6b7a75d826e1
diff --git a/stream-servers/FrameBuffer.cpp b/stream-servers/FrameBuffer.cpp
index 7103903..d209e29 100644
--- a/stream-servers/FrameBuffer.cpp
+++ b/stream-servers/FrameBuffer.cpp
@@ -1264,49 +1264,49 @@
     if (m_shuttingDown) {
         return;
     }
-    AutoLock mutex(m_lock);
-    auto colorBuffersToCleanup = destroyEmulatedEglWindowSurfaceLocked(p_surface);
 
-    mutex.unlock();
+    std::vector<ColorBufferPtr> colorBuffersToCleanup;
 
-    for (auto handle : colorBuffersToCleanup) {
-        goldfish_vk::teardownVkColorBuffer(handle);
+    {
+        AutoLock mutex(m_lock);
+        destroyEmulatedEglWindowSurfaceLocked(p_surface, &colorBuffersToCleanup);
     }
+
+    // Avoid holding the global lock during potentially slow ColorBuffer
+    // destruction (during `colorBuffersToCleanup` destruction).
 }
 
-std::vector<HandleType> FrameBuffer::destroyEmulatedEglWindowSurfaceLocked(HandleType p_surface) {
-    std::vector<HandleType> colorBuffersToCleanUp;
-    const auto w = m_windows.find(p_surface);
-    if (w != m_windows.end()) {
-        RecursiveScopedContextBind bind(getPbufferSurfaceContextHelper());
-        if (!m_guestManagedColorBufferLifetime) {
-            if (m_refCountPipeEnabled) {
-                if (decColorBufferRefCountLocked(w->second.second)) {
-                    colorBuffersToCleanUp.push_back(w->second.second);
-                }
-            } else {
-                if (closeColorBufferLocked(w->second.second)) {
-                    colorBuffersToCleanUp.push_back(w->second.second);
-                }
-            }
-        }
-        m_windows.erase(w);
-        RenderThreadInfo* tinfo = RenderThreadInfo::get();
-        uint64_t puid = tinfo->m_puid;
-        if (puid) {
-            auto ite = m_procOwnedEmulatedEglWindowSurfaces.find(puid);
-            if (ite != m_procOwnedEmulatedEglWindowSurfaces.end()) {
-                ite->second.erase(p_surface);
-            }
+void FrameBuffer::destroyEmulatedEglWindowSurfaceLocked(
+    HandleType p_surface, std::vector<ColorBufferPtr>* colorBuffersToCleanup) {
+    auto it = m_windows.find(p_surface);
+    if (it == m_windows.end()) {
+        return;
+    }
+    auto& surfaceAndBackingColorBuffer = it->second;
+
+    RecursiveScopedContextBind bind(getPbufferSurfaceContextHelper());
+    if (!m_guestManagedColorBufferLifetime) {
+        if (m_refCountPipeEnabled) {
+            decColorBufferRefCountLocked(surfaceAndBackingColorBuffer.second,
+                                         colorBuffersToCleanup);
         } else {
-            if (!tinfo->m_glInfo) {
-                GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
-                    << "Render thread GL not available.";
-            }
-            tinfo->m_glInfo->m_windowSet.erase(p_surface);
+            closeColorBufferLocked(surfaceAndBackingColorBuffer.second, colorBuffersToCleanup);
         }
     }
-    return colorBuffersToCleanUp;
+    m_windows.erase(it);
+    RenderThreadInfo* tinfo = RenderThreadInfo::get();
+    uint64_t puid = tinfo->m_puid;
+    if (puid) {
+        auto ite = m_procOwnedEmulatedEglWindowSurfaces.find(puid);
+        if (ite != m_procOwnedEmulatedEglWindowSurfaces.end()) {
+            ite->second.erase(p_surface);
+        }
+    } else {
+        if (!tinfo->m_glInfo) {
+            GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Render thread GL not available.";
+        }
+        tinfo->m_glInfo->m_windowSet.erase(p_surface);
+    }
 }
 
 void FrameBuffer::createEmulatedEglFenceSync(EGLenum type,
@@ -1406,36 +1406,32 @@
         return;
     }
 
-    std::vector<HandleType> colorBuffersToCleanup;
+    std::vector<ColorBufferPtr> colorBuffersToCleanup;
 
-    AutoLock mutex(m_lock);
-    RecursiveScopedContextBind bind(getPbufferSurfaceContextHelper());
-    for (const HandleType winHandle : tinfo->m_windowSet) {
-        const auto winIt = m_windows.find(winHandle);
-        if (winIt != m_windows.end()) {
-            if (const HandleType oldColorBufferHandle = winIt->second.second) {
-                if (!m_guestManagedColorBufferLifetime) {
-                    if (m_refCountPipeEnabled) {
-                        if (decColorBufferRefCountLocked(oldColorBufferHandle)) {
-                            colorBuffersToCleanup.push_back(oldColorBufferHandle);
-                        }
-                    } else {
-                        if (closeColorBufferLocked(oldColorBufferHandle)) {
-                            colorBuffersToCleanup.push_back(oldColorBufferHandle);
+    {
+        AutoLock mutex(m_lock);
+        RecursiveScopedContextBind bind(getPbufferSurfaceContextHelper());
+        for (const HandleType winHandle : tinfo->m_windowSet) {
+            const auto winIt = m_windows.find(winHandle);
+            if (winIt != m_windows.end()) {
+                if (const HandleType oldColorBufferHandle = winIt->second.second) {
+                    if (!m_guestManagedColorBufferLifetime) {
+                        if (m_refCountPipeEnabled) {
+                            decColorBufferRefCountLocked(oldColorBufferHandle,
+                                                         &colorBuffersToCleanup);
+                        } else {
+                            closeColorBufferLocked(oldColorBufferHandle, &colorBuffersToCleanup);
                         }
                     }
+                    m_windows.erase(winIt);
                 }
-                m_windows.erase(winIt);
             }
         }
+        tinfo->m_windowSet.clear();
     }
-    tinfo->m_windowSet.clear();
 
-    m_lock.unlock();
-
-    for (auto handle: colorBuffersToCleanup) {
-        goldfish_vk::teardownVkColorBuffer(handle);
-    }
+    // Avoid holding the global lock during potentially slow ColorBuffer
+    // destruction (during `colorBuffersToCleanup` destruction).
 }
 
 int FrameBuffer::openColorBuffer(HandleType p_colorbuffer) {
@@ -1468,7 +1464,7 @@
     return 0;
 }
 
-void FrameBuffer::closeColorBuffer(HandleType p_colorbuffer) {
+void FrameBuffer::closeColorBuffer(HandleType colorBufferHandle) {
     // When guest feature flag RefCountPipe is on, no reference counting is
     // needed.
     if (m_refCountPipeEnabled) {
@@ -1477,32 +1473,30 @@
 
     RenderThreadInfo* tInfo = RenderThreadInfo::get();
 
-    std::vector<HandleType> toCleanup;
+    std::vector<ColorBufferPtr> colorBuffersToCleanup;
 
-    AutoLock mutex(m_lock);
-    uint64_t puid = tInfo ? tInfo->m_puid : 0;
-    if (puid) {
-        auto ite = m_procOwnedColorBuffers.find(puid);
-        if (ite != m_procOwnedColorBuffers.end()) {
-            const auto& cb = ite->second.find(p_colorbuffer);
-            if (cb != ite->second.end()) {
-                ite->second.erase(cb);
-                if (closeColorBufferLocked(p_colorbuffer)) {
-                    toCleanup.push_back(p_colorbuffer);
-                }
+    {
+        AutoLock mutex(m_lock);
+        uint64_t puid = tInfo ? tInfo->m_puid : 0;
+        if (puid) {
+            auto processOwnedColorBuffersIt = m_procOwnedColorBuffers.find(puid);
+            if (processOwnedColorBuffersIt == m_procOwnedColorBuffers.end()) {
+                return;
             }
-        }
-    } else {
-        if (closeColorBufferLocked(p_colorbuffer)) {
-            toCleanup.push_back(p_colorbuffer);
+            auto& processOwnedColorBuffers = processOwnedColorBuffersIt->second;
+
+            auto colorBufferIt = processOwnedColorBuffers.find(colorBufferHandle);
+            if (colorBufferIt != processOwnedColorBuffers.end()) {
+                processOwnedColorBuffers.erase(colorBufferIt);
+                closeColorBufferLocked(colorBufferHandle, &colorBuffersToCleanup);
+            }
+        } else {
+            closeColorBufferLocked(colorBufferHandle, &colorBuffersToCleanup);
         }
     }
 
-    mutex.unlock();
-
-    for (auto handle : toCleanup) {
-        goldfish_vk::teardownVkColorBuffer(handle);
-    }
+    // Avoid holding the global lock during potentially slow ColorBuffer
+    // destruction (during `colorBuffersToCleanup` destruction).
 }
 
 void FrameBuffer::closeBuffer(HandleType p_buffer) {
@@ -1517,7 +1511,8 @@
     m_buffers.erase(it);
 }
 
-bool FrameBuffer::closeColorBufferLocked(HandleType p_colorbuffer,
+bool FrameBuffer::closeColorBufferLocked(HandleType colorBufferHandle,
+                                         std::vector<ColorBufferPtr>* colorBuffersToCleanup,
                                          bool forced) {
     // When guest feature flag RefCountPipe is on, no reference counting is
     // needed.
@@ -1530,14 +1525,15 @@
 
         if (m_noDelayCloseColorBufferEnabled) forced = true;
 
-        ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer));
-        if (c == m_colorbuffers.end()) {
+        auto it = m_colorbuffers.find(colorBufferHandle);
+        if (it == m_colorbuffers.end()) {
             // This is harmless: it is normal for guest system to issue
             // closeColorBuffer command when the color buffer is already
             // garbage collected on the host. (we don't have a mechanism
             // to give guest a notice yet)
             return false;
         }
+        ColorBufferRef& colorBufferRef = it->second;
 
         // The guest can and will gralloc_alloc/gralloc_free and then
         // gralloc_register a buffer, due to API level (O+) or
@@ -1545,19 +1541,20 @@
         // So, we don't actually close the color buffer when refcount
         // reached zero, unless it has been opened at least once already.
         // Instead, put it on a 'delayed close' list to return to it later.
-        if (--c->second.refcount == 0) {
+        if (--colorBufferRef.refcount == 0) {
             if (forced) {
-                eraseDelayedCloseColorBufferLocked(c->first, c->second.closedTs);
-                m_colorbuffers.erase(c);
+                eraseDelayedCloseColorBufferLocked(colorBufferHandle, colorBufferRef.closedTs);
+                m_colorbuffers.erase(it);
                 deleted = true;
             } else {
-                c->second.closedTs = android::base::getUnixTimeUs();
-                m_colorBufferDelayedCloseList.push_back({c->second.closedTs, p_colorbuffer});
+                colorBufferRef.closedTs = android::base::getUnixTimeUs();
+                m_colorBufferDelayedCloseList.push_back(
+                    {colorBufferRef.closedTs, colorBufferHandle});
             }
         }
     }
 
-    performDelayedColorBufferCloseLocked(false);
+    performDelayedColorBufferCloseLocked(colorBuffersToCleanup, false);
 
     return deleted;
 }
@@ -1576,7 +1573,8 @@
     }
 }
 
-void FrameBuffer::performDelayedColorBufferCloseLocked(bool forced) {
+void FrameBuffer::performDelayedColorBufferCloseLocked(
+    std::vector<ColorBufferPtr>* colorBuffersToCleanup, bool forced) {
     // Let's wait just long enough to make sure it's not because of instant
     // timestamp change (end of previous second -> beginning of a next one),
     // but not for long - this is a workaround for race conditions, and they
@@ -1590,9 +1588,11 @@
            it->ts + kColorBufferClosingDelaySec <= now)) {
         if (it->cbHandle != 0) {
             AutoLock colorBufferMapLock(m_colorBufferMapLock);
-            const auto& cb = m_colorbuffers.find(it->cbHandle);
-            if (cb != m_colorbuffers.end()) {
-                m_colorbuffers.erase(cb);
+            auto colorBufferIt = m_colorbuffers.find(it->cbHandle);
+            if (colorBufferIt != m_colorbuffers.end()) {
+                ColorBufferRef& colorBufferRef = colorBufferIt->second;
+                colorBuffersToCleanup->push_back(std::move(colorBufferRef.cb));
+                m_colorbuffers.erase(colorBufferIt);
             }
         }
         ++it;
@@ -1658,41 +1658,41 @@
         android::base::sleepUs(10000);
     } while (renderThreadWithThisPuidExists);
 
-
-    AutoLock mutex(m_lock);
-    if (!hasEmulationGl() || !getDisplay()) {
-        return;
-    }
-
-    auto colorBuffersToCleanup = cleanupProcGLObjects_locked(puid);
-
-    // Run other cleanup callbacks
-    // Avoid deadlock by first storing a separate list of callbacks
+    std::vector<ColorBufferPtr> colorBuffersToCleanup;
     std::vector<std::function<void()>> callbacks;
 
     {
-        auto procIte = m_procOwnedCleanupCallbacks.find(puid);
-        if (procIte != m_procOwnedCleanupCallbacks.end()) {
-            for (auto it : procIte->second) {
-                callbacks.push_back(it.second);
+        AutoLock mutex(m_lock);
+        if (!hasEmulationGl() || !getDisplay()) {
+            return;
+        }
+
+        cleanupProcGLObjects_locked(puid, &colorBuffersToCleanup);
+
+        // Gather other cleanup callbacks.
+        {
+            auto procIte = m_procOwnedCleanupCallbacks.find(puid);
+            if (procIte != m_procOwnedCleanupCallbacks.end()) {
+                for (auto it : procIte->second) {
+                    callbacks.push_back(it.second);
+                }
+                m_procOwnedCleanupCallbacks.erase(procIte);
             }
-            m_procOwnedCleanupCallbacks.erase(procIte);
         }
     }
 
-    mutex.unlock();
+    // Avoid holding the global lock during potentially slow ColorBuffer destruction
+    colorBuffersToCleanup.clear();
 
-    for (auto handle : colorBuffersToCleanup) {
-        goldfish_vk::teardownVkColorBuffer(handle);
-    }
-
+    // Avoid deadlock
     for (auto cb : callbacks) {
         cb();
     }
 }
 
-std::vector<HandleType> FrameBuffer::cleanupProcGLObjects_locked(uint64_t puid, bool forced) {
-    std::vector<HandleType> colorBuffersToCleanup;
+void FrameBuffer::cleanupProcGLObjects_locked(uint64_t puid,
+                                              std::vector<ColorBufferPtr>* colorBuffersToCleanup,
+                                              bool forced) {
     {
         std::unique_ptr<RecursiveScopedContextBind> bind = nullptr;
         if (m_emulationGl) {
@@ -1710,13 +1710,9 @@
                     }
                     if (!m_guestManagedColorBufferLifetime) {
                         if (m_refCountPipeEnabled) {
-                            if (decColorBufferRefCountLocked(w->second.second)) {
-                                colorBuffersToCleanup.push_back(w->second.second);
-                            }
+                            decColorBufferRefCountLocked(w->second.second, colorBuffersToCleanup);
                         } else {
-                            if (closeColorBufferLocked(w->second.second, forced)) {
-                                colorBuffersToCleanup.push_back(w->second.second);
-                            }
+                            closeColorBufferLocked(w->second.second, colorBuffersToCleanup, forced);
                         }
                     }
                     m_windows.erase(w);
@@ -1733,9 +1729,7 @@
                 auto procIte = m_procOwnedColorBuffers.find(puid);
                 if (procIte != m_procOwnedColorBuffers.end()) {
                     for (auto cb : procIte->second) {
-                        if (closeColorBufferLocked(cb, forced)) {
-                            colorBuffersToCleanup.push_back(cb);
-                        }
+                        closeColorBufferLocked(cb, colorBuffersToCleanup, forced);
                     }
                     m_procOwnedColorBuffers.erase(procIte);
                 }
@@ -1764,8 +1758,6 @@
             m_procOwnedEmulatedEglContexts.erase(procIte);
         }
     }
-
-    return colorBuffersToCleanup;
 }
 
 void FrameBuffer::markOpened(ColorBufferRef* cbRef) {
@@ -1804,44 +1796,55 @@
 
 bool FrameBuffer::setEmulatedEglWindowSurfaceColorBuffer(HandleType p_surface,
                                                          HandleType p_colorbuffer) {
+    std::vector<ColorBufferPtr> colorBuffersToCleanup;
+
     AutoLock mutex(m_lock);
 
-    EmulatedEglWindowSurfaceMap::iterator w(m_windows.find(p_surface));
-    if (w == m_windows.end()) {
-        // bad surface handle
-        ERR("bad window surface handle %#x", p_surface);
+    auto surfaceIt = m_windows.find(p_surface);
+    if (surfaceIt == m_windows.end()) {
+        ERR("Failed to find window surface %#x", p_surface);
         return false;
     }
+    auto& surfaceAndBackingColorBuffer = surfaceIt->second;
 
     {
         AutoLock colorBufferMapLock(m_colorBufferMapLock);
-        ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer));
-        if (c == m_colorbuffers.end()) {
-            ERR("bad color buffer handle %#x", p_colorbuffer);
-            // bad colorbuffer handle
+
+        auto colorBufferIt = m_colorbuffers.find(p_colorbuffer);
+        if (colorBufferIt == m_colorbuffers.end()) {
+            ERR("Failed to find ColorBuffer:%#x", p_colorbuffer);
             return false;
         }
+        auto& colorBufferRef = colorBufferIt->second;
 
-        (*w).second.first->setColorBuffer((*c).second.cb);
-        markOpened(&c->second);
+        auto& surface = surfaceAndBackingColorBuffer.first;
+        surface->setColorBuffer(colorBufferRef.cb);
+
+        markOpened(&colorBufferRef);
+
         if (!m_guestManagedColorBufferLifetime) {
-            c->second.refcount++;
+            colorBufferRef.refcount++;
         }
     }
-    if (w->second.second) {
+
+    auto previousBackingColorBuffer = surfaceAndBackingColorBuffer.second;
+    if (previousBackingColorBuffer) {
         if (!m_guestManagedColorBufferLifetime) {
             if (m_refCountPipeEnabled) {
-                decColorBufferRefCountLocked(w->second.second);
+                decColorBufferRefCountLocked(previousBackingColorBuffer, &colorBuffersToCleanup);
             } else {
-                closeColorBufferLocked(w->second.second);
+                closeColorBufferLocked(previousBackingColorBuffer, &colorBuffersToCleanup);
             }
         }
     }
 
-    (*w).second.second = p_colorbuffer;
-
+    surfaceAndBackingColorBuffer.second = p_colorbuffer;
     m_EmulatedEglWindowSurfaceToColorBuffer[p_surface] = p_colorbuffer;
 
+    // Avoid holding the global lock during potentially slow ColorBuffer
+    // destruction (during `colorBuffersToCleanup` destruction).
+    m_lock.unlock();
+
     return true;
 }
 
@@ -2488,7 +2491,8 @@
         }
     }
     if (!m_subWin) { // m_subWin is supposed to be false
-        decColorBufferRefCountLocked(p_colorbuffer);
+        std::vector<ColorBufferPtr> colorBuffersToCleanup;
+        decColorBufferRefCountLocked(p_colorbuffer, &colorBuffersToCleanup);
     }
 
 EXIT:
@@ -2747,17 +2751,22 @@
     }
 }
 
-bool FrameBuffer::decColorBufferRefCountLocked(HandleType p_colorbuffer) {
+void FrameBuffer::decColorBufferRefCountLocked(HandleType p_colorbuffer,
+                                               std::vector<ColorBufferPtr>* toDestroy) {
     AutoLock colorBufferMapLock(m_colorBufferMapLock);
-    const auto& it = m_colorbuffers.find(p_colorbuffer);
-    if (it != m_colorbuffers.end()) {
-        it->second.refcount -= 1;
-        if (it->second.refcount == 0) {
-            m_colorbuffers.erase(p_colorbuffer);
-            return true;
-        }
+
+    auto it = m_colorbuffers.find(p_colorbuffer);
+    if (it == m_colorbuffers.end()) {
+        return;
     }
-    return false;
+
+    ColorBufferRef& ref = it->second;
+
+    ref.refcount -= 1;
+    if (ref.refcount == 0) {
+        toDestroy->push_back(std::move(ref.cb));
+        m_colorbuffers.erase(it);
+    }
 }
 
 bool FrameBuffer::compose(uint32_t bufferSize, void* buffer, bool needPost) {
@@ -2995,31 +3004,23 @@
             }
         }
         if (!cleanupComplete) {
-            std::vector<HandleType> colorBuffersToCleanup;
+            std::vector<ColorBufferPtr> colorBuffersToCleanup;
 
             while (m_procOwnedEmulatedEglWindowSurfaces.size()) {
-                auto cleanupHandles = cleanupProcGLObjects_locked(
-                        m_procOwnedEmulatedEglWindowSurfaces.begin()->first, true);
-                colorBuffersToCleanup.insert(colorBuffersToCleanup.end(),
-                    cleanupHandles.begin(), cleanupHandles.end());
+                cleanupProcGLObjects_locked(m_procOwnedEmulatedEglWindowSurfaces.begin()->first,
+                                            &colorBuffersToCleanup, true);
             }
             while (m_procOwnedColorBuffers.size()) {
-                auto cleanupHandles = cleanupProcGLObjects_locked(
-                        m_procOwnedColorBuffers.begin()->first, true);
-                colorBuffersToCleanup.insert(colorBuffersToCleanup.end(),
-                    cleanupHandles.begin(), cleanupHandles.end());
+                cleanupProcGLObjects_locked(m_procOwnedColorBuffers.begin()->first,
+                                            &colorBuffersToCleanup, true);
             }
             while (m_procOwnedEmulatedEglImages.size()) {
-                auto cleanupHandles = cleanupProcGLObjects_locked(
-                        m_procOwnedEmulatedEglImages.begin()->first, true);
-                colorBuffersToCleanup.insert(colorBuffersToCleanup.end(),
-                    cleanupHandles.begin(), cleanupHandles.end());
+                cleanupProcGLObjects_locked(m_procOwnedEmulatedEglImages.begin()->first,
+                                            &colorBuffersToCleanup, true);
             }
             while (m_procOwnedEmulatedEglContexts.size()) {
-                auto cleanupHandles = cleanupProcGLObjects_locked(
-                        m_procOwnedEmulatedEglContexts.begin()->first, true);
-                colorBuffersToCleanup.insert(colorBuffersToCleanup.end(),
-                    cleanupHandles.begin(), cleanupHandles.end());
+                cleanupProcGLObjects_locked(m_procOwnedEmulatedEglContexts.begin()->first,
+                                            &colorBuffersToCleanup, true);
             }
 
             std::vector<std::function<void()>> cleanupCallbacks;
@@ -3036,13 +3037,12 @@
 
             m_procOwnedResources.clear();
 
-            performDelayedColorBufferCloseLocked(true);
+            performDelayedColorBufferCloseLocked(&colorBuffersToCleanup, true);
 
             lock.unlock();
 
-            for (auto colorBufferHandle : colorBuffersToCleanup) {
-                goldfish_vk::teardownVkColorBuffer(colorBufferHandle);
-            }
+            // Avoid holding the global lock during potentially slow ColorBuffer destruction.
+            colorBuffersToCleanup.clear();
 
             for (auto cb : cleanupCallbacks) {
                 cb();
@@ -3320,15 +3320,17 @@
 }
 
 void FrameBuffer::sweepColorBuffersLocked() {
+    std::vector<ColorBufferPtr> colorBuffersToDestroy;
+
     HandleType handleToDestroy;
     while (mOutstandingColorBufferDestroys.tryReceive(&handleToDestroy)) {
-        bool needCleanup = decColorBufferRefCountLocked(handleToDestroy);
-        if (needCleanup) {
-            m_lock.unlock();
-            goldfish_vk::teardownVkColorBuffer(handleToDestroy);
-            m_lock.lock();
-        }
+        decColorBufferRefCountLocked(handleToDestroy, &colorBuffersToDestroy);
     }
+
+    // Avoid holding the global lock during potentially slow destruction.
+    m_lock.unlock();
+    colorBuffersToDestroy.clear();
+    m_lock.lock();
 }
 
 std::future<void> FrameBuffer::blockPostWorker(std::future<void> continueSignal) {
diff --git a/stream-servers/FrameBuffer.h b/stream-servers/FrameBuffer.h
index 563a6c3..9952621 100644
--- a/stream-servers/FrameBuffer.h
+++ b/stream-servers/FrameBuffer.h
@@ -218,8 +218,10 @@
     // handle value as returned by createEmulatedEglWindowSurface().
     void destroyEmulatedEglWindowSurface(HandleType p_surface);
 
-    // Returns the set of ColorBuffers destroyed (for further cleanup)
-    std::vector<HandleType> destroyEmulatedEglWindowSurfaceLocked(HandleType p_surface);
+    // Destroy a given EmulatedEglWindowSurface instance and moves any references to
+    // backing ColorBuffers to the `toDestroy`.
+    void destroyEmulatedEglWindowSurfaceLocked(HandleType p_surface,
+                                               std::vector<ColorBufferPtr>* toDestroy);
 
     void createEmulatedEglFenceSync(EGLenum type,
                                     int destroyWhenSignaled,
@@ -294,6 +296,8 @@
     std::unique_ptr<ProcessResources> removeGraphicsProcessResources(uint64_t puid);
     // TODO(kaiyili): retire cleanupProcGLObjects in favor of removeGraphicsProcessResources.
     void cleanupProcGLObjects(uint64_t puid);
+    void cleanupProcGLObjects_locked(uint64_t puid, std::vector<ColorBufferPtr>* toDestroy,
+                                     bool forced = false);
 
     // Equivalent for eglMakeCurrent() for the current display.
     // |p_context|, |p_drawSurface| and |p_readSurface| are the handle values
@@ -671,21 +675,22 @@
     HandleType genHandle_locked();
 
     bool removeSubWindow_locked();
-    // Returns the set of ColorBuffers destroyed (for further cleanup)
-    std::vector<HandleType> cleanupProcGLObjects_locked(uint64_t puid,
-                                                        bool forced = false);
 
     void markOpened(ColorBufferRef* cbRef);
     // Returns true if the color buffer was erased.
-    bool closeColorBufferLocked(HandleType p_colorbuffer, bool forced = false);
-    // Returns true if this was the last ref and we need to destroy stuff.
-    bool decColorBufferRefCountLocked(HandleType p_colorbuffer);
+    bool closeColorBufferLocked(HandleType p_colorbuffer, std::vector<ColorBufferPtr>* toDestroy,
+                                bool forced = false);
+    // Decrements the color buffer's reference count and adds the color buffer to the given
+    // `toDestroy` list if this was the last reference to the color buffer.
+    void decColorBufferRefCountLocked(HandleType p_colorbuffer,
+                                      std::vector<ColorBufferPtr>* toDestroy);
     // Decrease refcount but not destroy the object.
     // Mainly used in post thread, when we need to destroy the object but cannot in post thread.
     void decColorBufferRefCountNoDestroy(HandleType p_colorbuffer);
     // Close all expired color buffers for real.
     // Treat all delayed color buffers as expired if forced=true
-    void performDelayedColorBufferCloseLocked(bool forced = false);
+    void performDelayedColorBufferCloseLocked(std::vector<ColorBufferPtr>* toDestroy,
+                                              bool forced = false);
     void eraseDelayedCloseColorBufferLocked(HandleType cb, uint64_t ts);
 
     AsyncResult postImpl(HandleType p_colorbuffer, Post::CompletionCallback callback,