Revert "Add DisplayGl and DisplaySurfaceGl"

This reverts commit cb8d1e4f237be8d58e26de57ee0b67245a63a34f.

Reason for revert: Seeing issues with potential concurrent usage of the pbuffer context.

Bug: b/251366833
Bug: b/250847245
Change-Id: I39ba968339009ba8086b5f0c989aa5ba50f5a9aa
diff --git a/stream-servers/Android.bp b/stream-servers/Android.bp
index 2484f6a..b425bc6 100644
--- a/stream-servers/Android.bp
+++ b/stream-servers/Android.bp
@@ -59,8 +59,8 @@
         "ChannelStream.cpp",
         "ColorBuffer.cpp",
         "Debug.cpp",
+        "Display.cpp",
         "DisplaySurface.cpp",
-        "DisplaySurfaceUser.cpp",
         "FenceSync.cpp",
         "Hwc2.cpp",
         "PostWorker.cpp",
diff --git a/stream-servers/CMakeLists.txt b/stream-servers/CMakeLists.txt
index eb07d6b..53fe3f9 100644
--- a/stream-servers/CMakeLists.txt
+++ b/stream-servers/CMakeLists.txt
@@ -21,8 +21,8 @@
     ChannelStream.cpp
     ColorBuffer.cpp
     Debug.cpp
+    Display.cpp
     DisplaySurface.cpp
-    DisplaySurfaceUser.cpp
     FenceSync.cpp
     Hwc2.cpp
     PostWorker.cpp
diff --git a/stream-servers/ColorBuffer.cpp b/stream-servers/ColorBuffer.cpp
index 2a8303c..d3ca129 100644
--- a/stream-servers/ColorBuffer.cpp
+++ b/stream-servers/ColorBuffer.cpp
@@ -216,7 +216,6 @@
                                  FrameworkFormat p_frameworkFormat,
                                  HandleType hndl,
                                  ContextHelper* helper,
-                                 TextureDraw* textureDraw,
                                  bool fastBlitSupported,
                                  bool vulkanOnly) {
     GLenum texFormat = 0;
@@ -236,7 +235,7 @@
             * p_height;
 
     // This constructor is private, so std::make_unique can't be used.
-    std::unique_ptr<ColorBuffer> cb{new ColorBuffer(p_display, hndl, helper, textureDraw)};
+    std::unique_ptr<ColorBuffer> cb{new ColorBuffer(p_display, hndl, helper)};
     cb->m_width = p_width;
     cb->m_height = p_height;
     cb->m_internalFormat = p_internalFormat;
@@ -331,9 +330,8 @@
     return cb.release();
 }
 
-ColorBuffer::ColorBuffer(EGLDisplay display, HandleType hndl, ContextHelper* helper,
-                         TextureDraw* textureDraw)
-    : m_display(display), m_helper(helper), m_textureDraw(textureDraw), mHndl(hndl) {}
+ColorBuffer::ColorBuffer(EGLDisplay display, HandleType hndl, ContextHelper* helper)
+    : m_display(display), m_helper(helper), mHndl(hndl) {}
 
 ColorBuffer::~ColorBuffer() {
     if (m_vulkanOnly) {
@@ -801,7 +799,7 @@
         s_gles2.glViewport(0, 0, m_width, m_height);
 
         // render m_blitTex
-        m_textureDraw->draw(m_blitTex, 0., 0, 0);
+        m_helper->getTextureDraw()->draw(m_blitTex, 0., 0, 0);
 
         // Restore previous viewport.
         s_gles2.glViewport(vport[0], vport[1], vport[2], vport[3]);
@@ -888,13 +886,13 @@
 bool ColorBuffer::post(GLuint tex, float rotation, float dx, float dy) {
     // NOTE: Do not call m_helper->setupContext() here!
     waitSync();
-    return m_textureDraw->draw(tex, rotation, dx, dy);
+    return m_helper->getTextureDraw()->draw(tex, rotation, dx, dy);
 }
 
 bool ColorBuffer::postWithOverlay(GLuint tex, float rotation, float dx, float dy) {
     // NOTE: Do not call m_helper->setupContext() here!
     waitSync();
-    return m_textureDraw->drawWithOverlay(tex, rotation, dx, dy);
+    return m_helper->getTextureDraw()->drawWithOverlay(tex, rotation, dx, dy);
 }
 
 void ColorBuffer::readback(unsigned char* img, bool readbackBgra) {
@@ -955,7 +953,6 @@
 ColorBuffer* ColorBuffer::onLoad(android::base::Stream* stream,
                                  EGLDisplay p_display,
                                  ContextHelper* helper,
-                                 TextureDraw* textureDraw,
                                  bool fastBlitSupported) {
     HandleType hndl = static_cast<HandleType>(stream->getBe32());
     GLuint width = static_cast<GLuint>(stream->getBe32());
@@ -969,9 +966,9 @@
 
     if (!eglImage) {
         return create(p_display, width, height, internalFormat, frameworkFormat,
-                      hndl, helper, textureDraw, fastBlitSupported);
+                      hndl, helper, fastBlitSupported);
     }
-    ColorBuffer* cb = new ColorBuffer(p_display, hndl, helper, textureDraw);
+    ColorBuffer* cb = new ColorBuffer(p_display, hndl, helper);
     cb->mNeedRestore = true;
     cb->m_eglImage = eglImage;
     cb->m_blitEGLImage = blitEGLImage;
@@ -1015,7 +1012,7 @@
 void ColorBuffer::postLayer(const ComposeLayer& l, int frameWidth, int frameHeight) {
     if (m_inUse) fprintf(stderr, "%s: cb in use\n", __func__);
     waitSync();
-    m_textureDraw->drawLayer(l, frameWidth, frameHeight, m_width, m_height, m_tex);
+    m_helper->getTextureDraw()->drawLayer(l, frameWidth, frameHeight, m_width, m_height, m_tex);
 }
 
 bool ColorBuffer::importMemory(ManagedDescriptor externalDescriptor, uint64_t size, bool dedicated,
diff --git a/stream-servers/ColorBuffer.h b/stream-servers/ColorBuffer.h
index 1ee5d34..10649d8 100644
--- a/stream-servers/ColorBuffer.h
+++ b/stream-servers/ColorBuffer.h
@@ -25,6 +25,7 @@
 
 #include "BorrowedImage.h"
 #include "ContextHelper.h"
+#include "DisplayVk.h"
 #include "FrameworkFormats.h"
 #include "Handle.h"
 #include "Hwc2.h"
@@ -94,7 +95,6 @@
                                FrameworkFormat p_frameworkFormat,
                                HandleType hndl,
                                ContextHelper* helper,
-                               TextureDraw* textureDraw,
                                bool fastBlitSupported,
                                bool vulkanOnly = false);
 
@@ -202,7 +202,6 @@
     static ColorBuffer* onLoad(android::base::Stream* stream,
                                EGLDisplay p_display,
                                ContextHelper* helper,
-                               TextureDraw* textureDraw,
                                bool fastBlitSupported);
 
     HandleType getHndl() const;
@@ -238,8 +237,7 @@
     void restore();
 
 private:
-    ColorBuffer(EGLDisplay display, HandleType hndl, ContextHelper* helper,
-                TextureDraw* textureDraw);
+    ColorBuffer(EGLDisplay display, HandleType hndl, ContextHelper* helper);
     // Helper function to get contents.
     std::vector<uint8_t> getContents();
     // Helper function to clear current EGL image.
@@ -278,7 +276,6 @@
 
     EGLDisplay m_display = nullptr;
     ContextHelper* m_helper = nullptr;
-    TextureDraw* m_textureDraw = nullptr;
     TextureResize* m_resizer = nullptr;
     FrameworkFormat m_frameworkFormat;
     GLuint m_yuv_conversion_fbo = 0;  // FBO to offscreen-convert YUV to RGB
diff --git a/stream-servers/ContextHelper.h b/stream-servers/ContextHelper.h
index b4d0a22..3f14735 100644
--- a/stream-servers/ContextHelper.h
+++ b/stream-servers/ContextHelper.h
@@ -25,6 +25,7 @@
     virtual ~ContextHelper() = default;
     virtual bool setupContext() = 0;
     virtual void teardownContext() = 0;
+    virtual TextureDraw* getTextureDraw() const = 0;
     virtual bool isBound() const = 0;
 };
 
diff --git a/stream-servers/DisplaySurfaceUser.cpp b/stream-servers/Display.cpp
similarity index 83%
rename from stream-servers/DisplaySurfaceUser.cpp
rename to stream-servers/Display.cpp
index 4abc885..a89f82d 100644
--- a/stream-servers/DisplaySurfaceUser.cpp
+++ b/stream-servers/Display.cpp
@@ -23,27 +23,27 @@
 using emugl::ABORT_REASON_OTHER;
 using emugl::FatalError;
 
-DisplaySurfaceUser::~DisplaySurfaceUser() {
+Display::~Display() {
     if (mBoundSurface != nullptr) {
         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
-            << "Failed to unbind a DisplaySurface before DisplaySurfaceUser destruction.";
+            << "Failed to unbind a DisplaySurface before Display destruction.";
     }
 }
 
-void DisplaySurfaceUser::bindToSurface(DisplaySurface* surface) {
+void Display::bindToSurface(DisplaySurface* surface) {
     if (mBoundSurface != nullptr) {
         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
             << "Attempting to bind a DisplaySurface while another is already bound.";
     }
 
     this->bindToSurfaceImpl(surface);
-    surface->registerUser(this);
+    surface->registerBoundDisplay(this);
     mBoundSurface = surface;
 }
 
-void DisplaySurfaceUser::unbindFromSurface() {
+void Display::unbindFromSurface() {
     this->unbindFromSurfaceImpl();
-    mBoundSurface->unregisterUser(this);
+    mBoundSurface->unregisterBoundDisplay(this);
     mBoundSurface = nullptr;
 }
 
diff --git a/stream-servers/Display.h b/stream-servers/Display.h
index 9a26223..4ed3062 100644
--- a/stream-servers/Display.h
+++ b/stream-servers/Display.h
@@ -14,13 +14,30 @@
 
 #pragma once
 
-#include "DisplaySurfaceUser.h"
-
 namespace gfxstream {
 
-class Display : public DisplaySurfaceUser {
+class Display;
+class DisplaySurface;
+
+class Display {
   public:
-    // TODO(b/233939967): move post()/viewport()/clear() interface here.
+    virtual ~Display();
+
+  public:
+    void bindToSurface(DisplaySurface* surface);
+
+    void unbindFromSurface();
+
+  protected:
+    virtual void bindToSurfaceImpl(DisplaySurface* surface) = 0;
+
+    virtual void unbindFromSurfaceImpl() = 0;
+
+    const DisplaySurface* getBoundSurface() const { return mBoundSurface; }
+
+  private:
+    friend class DisplaySurface;
+    DisplaySurface* mBoundSurface = nullptr;
 };
 
-}  // namespace gfxstream
\ No newline at end of file
+}  // namespace gfxstream
diff --git a/stream-servers/DisplaySurface.cpp b/stream-servers/DisplaySurface.cpp
index 0c84b80..6a62a70 100644
--- a/stream-servers/DisplaySurface.cpp
+++ b/stream-servers/DisplaySurface.cpp
@@ -31,9 +31,9 @@
       mImpl(std::move(impl)) {}
 
 DisplaySurface::~DisplaySurface() {
-    if (!mBoundUsers.empty()) {
+    if (mBoundDisplay) {
         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
-            << "DisplaySurface destroyed while there are still users!";
+            << "DisplaySurface destroyed while still bound to a Display!";
     }
 }
 
@@ -53,12 +53,14 @@
     mHeight = newHeight;
 }
 
-void DisplaySurface::registerUser(DisplaySurfaceUser* user) {
-    mBoundUsers.insert(user);
+void DisplaySurface::registerBoundDisplay(Display* display) {
+    mBoundDisplay = display;
 }
 
-void DisplaySurface::unregisterUser(DisplaySurfaceUser* user) {
-    mBoundUsers.erase(user);
+void DisplaySurface::unregisterBoundDisplay(Display* display) {
+    if (display == mBoundDisplay) {
+        mBoundDisplay = nullptr;
+    }
 }
 
 }  // namespace gfxstream
diff --git a/stream-servers/DisplaySurface.h b/stream-servers/DisplaySurface.h
index 394bbdc..49bfd98 100644
--- a/stream-servers/DisplaySurface.h
+++ b/stream-servers/DisplaySurface.h
@@ -17,12 +17,11 @@
 #include <cstdint>
 #include <memory>
 #include <mutex>
-#include <unordered_set>
 
 namespace gfxstream {
 
+class Display;
 class DisplaySurface;
-class DisplaySurfaceUser;
 
 // Base class used for controlling the lifetime of a particular surface
 // used for a display (e.g. EGLSurface or VkSurfaceKHR).
@@ -52,13 +51,13 @@
     void updateSize(uint32_t newWidth, uint32_t newHeight);
 
   private:
-    friend class DisplaySurfaceUser;
+    friend class Display;
 
-    void registerUser(DisplaySurfaceUser* user);
-    void unregisterUser(DisplaySurfaceUser* user);
+    void registerBoundDisplay(Display* display);
+    void unregisterBoundDisplay(Display* display);
 
     std::unique_ptr<DisplaySurfaceImpl> mImpl;
-    std::unordered_set<DisplaySurfaceUser*> mBoundUsers;
+    Display* mBoundDisplay = nullptr;
 
     mutable std::mutex mParamsMutex;
     uint32_t mWidth = 0;
diff --git a/stream-servers/DisplaySurfaceUser.h b/stream-servers/DisplaySurfaceUser.h
deleted file mode 100644
index 0065709..0000000
--- a/stream-servers/DisplaySurfaceUser.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (C) 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 express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#pragma once
-
-namespace gfxstream {
-
-class DisplaySurface;
-class DisplaySurfaceUser;
-
-class DisplaySurfaceUser {
-  public:
-    virtual ~DisplaySurfaceUser();
-
-  public:
-    void bindToSurface(DisplaySurface* surface);
-
-    void unbindFromSurface();
-
-  protected:
-    virtual void bindToSurfaceImpl(DisplaySurface* surface) = 0;
-
-    virtual void unbindFromSurfaceImpl() = 0;
-
-    const DisplaySurface* getBoundSurface() const { return mBoundSurface; }
-
-  private:
-    friend class DisplaySurface;
-    DisplaySurface* mBoundSurface = nullptr;
-};
-
-}  // namespace gfxstream
diff --git a/stream-servers/FrameBuffer.cpp b/stream-servers/FrameBuffer.cpp
index 503824b..a72d42b 100644
--- a/stream-servers/FrameBuffer.cpp
+++ b/stream-servers/FrameBuffer.cpp
@@ -49,7 +49,6 @@
 #include "host-common/logging.h"
 #include "host-common/misc.h"
 #include "host-common/vm_operations.h"
-#include "vulkan/DisplayVk.h"
 #include "vulkan/VkCommonOperations.h"
 #include "vulkan/VkDecoderGlobalState.h"
 
@@ -82,6 +81,33 @@
     GL_LOG("message:%s", message);
 }
 
+// Implementation of a ColorBuffer::Helper instance that redirects calls
+// to a FrameBuffer instance.
+class FrameBufferContextHelper : public ContextHelper {
+   public:
+    FrameBufferContextHelper(FrameBuffer* fb) : mFb(fb) {}
+
+    virtual bool setupContext() override {
+        mIsBound = mFb->bind_locked();
+        return mIsBound;
+    }
+
+    virtual void teardownContext() override {
+        mFb->unbind_locked();
+        mIsBound = false;
+    }
+
+    virtual TextureDraw* getTextureDraw() const override {
+        return mFb->getTextureDraw();
+    }
+
+    virtual bool isBound() const override { return mIsBound; }
+
+   private:
+    FrameBuffer* mFb;
+    bool mIsBound = false;
+};
+
 }  // namespace
 
 // static std::string getTimeStampString() {
@@ -283,15 +309,6 @@
         // will get cleaned when the process exits.
         if (m_useSubWindow) {
             m_postWorker.reset();
-            if (m_displayVk) {
-                m_displayVk->unbindFromSurface();
-            }
-            if (m_displayGl) {
-                m_displayGl->unbindFromSurface();
-            }
-            if (m_compositorGl) {
-                m_compositorGl->unbindFromSurface();
-            }
             removeSubWindow_locked();
         }
         return;
@@ -310,25 +327,24 @@
     }
     m_windows.clear();
     m_contexts.clear();
-
     if (m_eglDisplay != EGL_NO_DISPLAY) {
         s_egl.eglMakeCurrent(m_eglDisplay, NULL, NULL, NULL);
-
-        m_pbufferSurface.reset();
-        if (m_displayVk) {
-            m_displayVk->unbindFromSurface();
-        }
-        if (m_displayGl) {
-            m_displayGl->unbindFromSurface();
-        }
-        if (m_compositorGl) {
-            m_compositorGl->unbindFromSurface();
-        }
-        m_fakeWindowSurface.reset();
         if (m_eglContext != EGL_NO_CONTEXT) {
             s_egl.eglDestroyContext(m_eglDisplay, m_eglContext);
             m_eglContext = EGL_NO_CONTEXT;
         }
+        if (m_pbufContext != EGL_NO_CONTEXT) {
+            s_egl.eglDestroyContext(m_eglDisplay, m_pbufContext);
+            m_pbufContext = EGL_NO_CONTEXT;
+        }
+        if (m_pbufSurface != EGL_NO_SURFACE) {
+            s_egl.eglDestroySurface(m_eglDisplay, m_pbufSurface);
+            m_pbufSurface = EGL_NO_SURFACE;
+        }
+        if (m_eglSurface != EGL_NO_SURFACE) {
+            s_egl.eglDestroySurface(m_eglDisplay, m_eglSurface);
+            m_eglSurface = EGL_NO_SURFACE;
+        }
         m_eglDisplay = EGL_NO_DISPLAY;
     }
 
@@ -355,6 +371,8 @@
         return false;
     }
 
+    std::unique_ptr<RecursiveScopedContextBind> eglColorBufferBind;
+
     std::unique_ptr<emugl::RenderDocWithMultipleVkInstances> renderDocMultipleVkInstances = nullptr;
     if (!android::base::getEnvironmentVariable("ANDROID_EMU_RENDERDOC").empty()) {
         SharedLibrary* renderdocLib = nullptr;
@@ -594,44 +612,38 @@
     // on Mac platform when switching binded drawable for a context however
     // it is more efficient on other platforms as well.
     //
-    auto pbufferSurfaceGl = DisplaySurfaceGl::createPbufferSurface(fb->m_eglDisplay,
-                                                                   fb->m_eglConfig,
-                                                                   fb->m_eglContext,
-                                                                   getGlesMaxContextAttribs(),
-                                                                   /*width=*/1,
-                                                                   /*height=*/1);
-    if (!pbufferSurfaceGl) {
-        ERR("Failed to create pbuffer display surface.");
+    fb->m_pbufContext =
+            s_egl.eglCreateContext(fb->m_eglDisplay, fb->m_eglConfig,
+                                   fb->m_eglContext, getGlesMaxContextAttribs());
+    if (fb->m_pbufContext == EGL_NO_CONTEXT) {
+        ERR("Failed to create Pbuffer Context 0x%x", s_egl.eglGetError());
         return false;
     }
-    fb->m_pbufferSurface = std::make_unique<gfxstream::DisplaySurface>(
-        /*width=*/1,
-        /*height=*/1,
-        std::move(pbufferSurfaceGl));
 
-    auto fakeWindowSurfaceGl = DisplaySurfaceGl::createPbufferSurface(fb->m_eglDisplay,
-                                                                      fb->m_eglConfig,
-                                                                      fb->m_eglContext,
-                                                                      getGlesMaxContextAttribs(),
-                                                                      fb->m_framebufferWidth,
-                                                                      fb->m_framebufferHeight);
-    if (!fakeWindowSurfaceGl) {
-        ERR("Failed to create fake window display surface.");
+    GL_LOG("context creation successful");
+
+    //
+    // create a 1x1 pbuffer surface which will be used for binding
+    // the FB context.
+    // The FB output will go to a subwindow, if one exist.
+    //
+    static const EGLint pbufAttribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
+
+    fb->m_pbufSurface = s_egl.eglCreatePbufferSurface(
+            fb->m_eglDisplay, fb->m_eglConfig, pbufAttribs);
+    if (fb->m_pbufSurface == EGL_NO_SURFACE) {
+        ERR("Failed to create pbuf surface for FB 0x%x", s_egl.eglGetError());
         return false;
     }
-    fb->m_fakeWindowSurface = std::make_unique<gfxstream::DisplaySurface>(
-        fb->m_framebufferWidth,
-        fb->m_framebufferHeight,
-        std::move(fakeWindowSurfaceGl));
 
-
-    GL_LOG("Attempting to make pbuffer context and surface current");
-    RecursiveScopedContextBind contextBind(fb->getPbufferSurfaceContextHelper());
-    if (!contextBind.isOk()) {
-        ERR("Failed to make pbuffer context and surface current");
+    GL_LOG("attempting to make context current");
+    // Make the context current
+    eglColorBufferBind = std::make_unique<RecursiveScopedContextBind>(fb->m_colorBufferHelper);
+    if (!eglColorBufferBind->isOk()) {
+        ERR("Failed to make current");
         return false;
     }
-    GL_LOG("Succeeded making pbuffer context and surface current");
+    GL_LOG("context-current successful");
 
     //
     // Initilize framebuffer capabilities
@@ -868,9 +880,6 @@
         }
     }
 
-    fb->m_displayGl = std::make_unique<DisplayGl>();
-    fb->m_displayGl->bindToSurface(fb->m_fakeWindowSurface.get());
-
     if (fb->m_useVulkanComposition) {
         if (!vkEmu->compositorVk) {
             ERR("Failed to get CompositorVk from VkEmulation.");
@@ -881,8 +890,6 @@
     } else {
         GL_LOG("Performing composition using CompositorGl.");
         fb->m_compositorGl = std::make_unique<CompositorGl>(fb->m_textureDraw);
-        fb->m_compositorGl->bindToSurface(fb->m_fakeWindowSurface.get());
-
         fb->m_compositor = fb->m_compositorGl.get();
     }
 
@@ -976,6 +983,7 @@
       m_fpsStats(getenv("SHOW_FPS_STATS") != nullptr),
       m_perfStats(!android::base::getEnvironmentVariable("SHOW_PERF_STATS").empty()),
       m_perfThread(new PerfStatThread(&m_perfStats)),
+      m_colorBufferHelper(new FrameBufferContextHelper(this)),
       m_readbackThread(
           [this](FrameBuffer::Readback&& readback) { return sendReadbackWorkerCmd(readback); }),
       m_refCountPipeEnabled(feature_is_enabled(kFeature_RefCountPipe)),
@@ -1007,6 +1015,7 @@
 
     delete m_textureDraw;
     delete m_configs;
+    delete m_colorBufferHelper;
     delete m_perfThread;
 
     if (s_theFrameBuffer) {
@@ -1131,17 +1140,34 @@
 #endif
 
     if (!m_postThread.isStarted()) {
-        if (m_displayGl) {
-            m_displayGl->setUseBoundSurfaceContext(!postOnlyOnMainThread);
+        if (postOnlyOnMainThread) {
+            EGLContext prevContext = s_egl.eglGetCurrentContext();
+            EGLSurface prevReadSurf = s_egl.eglGetCurrentSurface(EGL_READ);
+            EGLSurface prevDrawSurf = s_egl.eglGetCurrentSurface(EGL_DRAW);
+            m_prevContext = prevContext;
+            m_prevReadSurf = prevReadSurf;
+            m_prevDrawSurf = prevDrawSurf;
         }
-        if (m_compositorGl) {
-            m_displayGl->setUseBoundSurfaceContext(!postOnlyOnMainThread);
-        }
-
-        m_postWorker.reset(new PostWorker(postOnlyOnMainThread,
-                                          m_compositor,
-                                          m_displayGl.get(),
-                                          m_displayVk));
+        m_postWorker.reset(new PostWorker(
+            [this]() {
+                if (m_displayVk) {
+                    return true;
+                }
+                if (m_subWin) {
+                    if (!bindSubwin_locked()) {
+                        return false;
+                    }
+                } else {
+                    if (!bindFakeWindow_locked()) {
+                        return false;
+                    }
+                }
+                if (m_compositorGl) {
+                    m_compositorGl->bindToWindow();
+                }
+                return true;
+            },
+            postOnlyOnMainThread, m_compositor, m_displayVk));
         m_postThread.start();
     }
 
@@ -1324,16 +1350,9 @@
 #endif
 
     if (deleteExisting) {
-        if (m_displayVk) {
-            m_displayVk->unbindFromSurface();
-        }
-        if (m_displayGl) {
-            m_displayGl->unbindFromSurface();
-        }
-        if (m_compositorGl) {
-            m_compositorGl->unbindFromSurface();
-        }
+        m_displayVk->unbindFromSurface();
         m_displaySurface.reset();
+        // TODO: look into reusing the existing native window when possible.
         removeSubWindow_locked();
     }
 
@@ -1371,13 +1390,11 @@
                                       reinterpret_cast<RENDERDOC_WindowHandle>(m_subWin));
                 }
             } else {
-                // TODO(Bug: b/233939967): move to EmulationGl->createDisplaySurface().
-                auto surfaceGl = DisplaySurfaceGl::createWindowSurface(m_eglDisplay,
-                                                                       m_eglConfig,
-                                                                       m_eglContext,
-                                                                       getGlesMaxContextAttribs(),
-                                                                       m_subWin);
-                if (!surfaceGl) {
+                // create EGLSurface from the generated subwindow
+                m_eglSurface = s_egl.eglCreateWindowSurface(
+                        m_eglDisplay, m_eglConfig, m_subWin, NULL);
+
+                if (m_eglSurface == EGL_NO_SURFACE) {
                     // NOTE: This can typically happen with software-only renderers
                     // like OSMesa.
                     destroySubWindow(m_subWin);
@@ -1385,17 +1402,8 @@
                 } else {
                     m_px = 0;
                     m_py = 0;
+
                     success = true;
-                    m_displaySurface =
-                        std::make_unique<gfxstream::DisplaySurface>(m_windowWidth,
-                                                                    m_windowHeight,
-                                                                    std::move(surfaceGl));
-                    if (m_displayGl) {
-                        m_displayGl->bindToSurface(m_displaySurface.get());
-                    }
-                    if (m_compositorGl) {
-                        m_compositorGl->bindToSurface(m_displaySurface.get());
-                    }
                 }
             }
         }
@@ -1464,9 +1472,11 @@
     }
 
     if (success && redrawSubwindow) {
-        RecursiveScopedContextBind bind(getPbufferSurfaceContextHelper());
-        assert(bind.isOk());
+        bool bindSuccess = bind_locked();
+        assert(bindSuccess);
+        (void)bindSuccess;
         s_gles2.glViewport(0, 0, fbw * dpr, fbh * dpr);
+        unbind_locked();
     }
     mutex.unlock();
 
@@ -1508,20 +1518,10 @@
     bool removed = false;
     if (m_subWin) {
         s_egl.eglMakeCurrent(m_eglDisplay, NULL, NULL, NULL);
-
-        if (m_displayVk) {
-            m_displayVk->unbindFromSurface();
-        }
-        if (m_displayGl) {
-            m_displayGl->unbindFromSurface();
-        }
-        if (m_compositorGl) {
-            m_compositorGl->unbindFromSurface();
-        }
-
-        m_windowSurface.reset();
+        s_egl.eglDestroySurface(m_eglDisplay, m_eglSurface);
         destroySubWindow(m_subWin);
 
+        m_eglSurface = EGL_NO_SURFACE;
         m_subWin = (EGLNativeWindowType)0;
         removed = true;
     }
@@ -1595,8 +1595,7 @@
 
     ColorBufferPtr cb(ColorBuffer::create(getDisplay(), p_width, p_height,
                                           p_internalFormat, p_frameworkFormat,
-                                          handle, getPbufferSurfaceContextHelper(),
-                                          m_textureDraw,
+                                          handle, m_colorBufferHelper,
                                           m_fastBlitSupported, m_guestUsesAngle));
     if (cb.get() != NULL) {
         assert(m_colorbuffers.count(handle) == 0);
@@ -1683,7 +1682,7 @@
             << "Buffer already exists with handle " << handle;
     }
 
-    BufferPtr buffer(Buffer::create(p_size, handle, getPbufferSurfaceContextHelper()));
+    BufferPtr buffer(Buffer::create(p_size, handle, m_colorBufferHelper));
 
     if (buffer) {
         m_buffers[handle] = {std::move(buffer)};
@@ -1839,7 +1838,7 @@
     std::vector<HandleType> colorBuffersToCleanup;
 
     AutoLock mutex(m_lock);
-    RecursiveScopedContextBind bind(getPbufferSurfaceContextHelper());
+    RecursiveScopedContextBind bind(m_colorBufferHelper);
     for (const HandleType winHandle : tinfo->m_windowSet) {
         const auto winIt = m_windows.find(winHandle);
         if (winIt != m_windows.end()) {
@@ -1911,7 +1910,7 @@
     std::vector<HandleType> colorBuffersToCleanUp;
     const auto w = m_windows.find(p_surface);
     if (w != m_windows.end()) {
-        RecursiveScopedContextBind bind(getPbufferSurfaceContextHelper());
+        RecursiveScopedContextBind bind(m_colorBufferHelper);
         if (!m_guestManagedColorBufferLifetime) {
             if (m_refCountPipeEnabled) {
                 if (decColorBufferRefCountLocked(w->second.second)) {
@@ -2168,7 +2167,7 @@
 std::vector<HandleType> FrameBuffer::cleanupProcGLObjects_locked(uint64_t puid, bool forced) {
     std::vector<HandleType> colorBuffersToCleanup;
     {
-        RecursiveScopedContextBind bind(getPbufferSurfaceContextHelper());
+        RecursiveScopedContextBind bind(m_colorBufferHelper);
         // Clean up window surfaces
         {
             auto procIte = m_procOwnedWindowSurfaces.find(puid);
@@ -2393,7 +2392,7 @@
                                     uint32_t* output) {
     FrameworkFormat format = static_cast<FrameworkFormat>(type);
     AutoLock mutex(m_lock);
-    RecursiveScopedContextBind bind(getPbufferSurfaceContextHelper());
+    RecursiveScopedContextBind bind(m_colorBufferHelper);
     for (uint32_t i = 0; i < count; ++i) {
         if (format == FRAMEWORK_FORMAT_NV12) {
             YUVConverter::createYUVGLTex(GL_TEXTURE0, width, height,
@@ -2415,7 +2414,7 @@
                                      uint32_t count,
                                      uint32_t* textures) {
     AutoLock mutex(m_lock);
-    RecursiveScopedContextBind bind(getPbufferSurfaceContextHelper());
+    RecursiveScopedContextBind bind(m_colorBufferHelper);
     if (type == FRAMEWORK_FORMAT_NV12) {
         s_gles2.glDeleteTextures(2 * count, textures);
     } else if (type == FRAMEWORK_FORMAT_YUV_420_888) {
@@ -2434,7 +2433,7 @@
                                     void* privData,
                                     void* func) {
     AutoLock mutex(m_lock);
-    RecursiveScopedContextBind bind(getPbufferSurfaceContextHelper());
+    RecursiveScopedContextBind bind(m_colorBufferHelper);
 
     yuv_updater_t updater = (yuv_updater_t)func;
     uint32_t gtextures[3] = {0, 0, 0};
@@ -2771,6 +2770,102 @@
     return true;
 }
 
+//
+// The framebuffer lock should be held when calling this function !
+//
+bool FrameBuffer::bind_locked() {
+    EGLContext prevContext = s_egl.eglGetCurrentContext();
+    EGLSurface prevReadSurf = s_egl.eglGetCurrentSurface(EGL_READ);
+    EGLSurface prevDrawSurf = s_egl.eglGetCurrentSurface(EGL_DRAW);
+
+    if (prevContext != m_pbufContext || prevReadSurf != m_pbufSurface ||
+        prevDrawSurf != m_pbufSurface) {
+        if (!s_egl.eglMakeCurrent(m_eglDisplay, m_pbufSurface, m_pbufSurface,
+                                  m_pbufContext)) {
+            if (!m_shuttingDown)
+                ERR("eglMakeCurrent failed");
+            return false;
+        }
+    } else {
+        ERR("Nested %s call detected, should never happen\n", __func__);
+    }
+
+    m_prevContext = prevContext;
+    m_prevReadSurf = prevReadSurf;
+    m_prevDrawSurf = prevDrawSurf;
+    return true;
+}
+
+bool FrameBuffer::bindSubwin_locked() {
+    EGLContext prevContext = s_egl.eglGetCurrentContext();
+    EGLSurface prevReadSurf = s_egl.eglGetCurrentSurface(EGL_READ);
+    EGLSurface prevDrawSurf = s_egl.eglGetCurrentSurface(EGL_DRAW);
+
+    if (prevContext != m_eglContext || prevReadSurf != m_eglSurface ||
+        prevDrawSurf != m_eglSurface) {
+        if (!s_egl.eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface,
+                                  m_eglContext)) {
+            ERR("eglMakeCurrent failed in binding subwindow!");
+            return false;
+        }
+    }
+
+    //
+    // initialize GL state in eglContext if not yet initilaized
+    //
+    if (!m_eglContextInitialized) {
+        m_eglContextInitialized = true;
+    }
+
+    m_prevContext = prevContext;
+    m_prevReadSurf = prevReadSurf;
+    m_prevDrawSurf = prevDrawSurf;
+    return true;
+}
+
+bool FrameBuffer::bindFakeWindow_locked() {
+    if (m_eglFakeWindowSurface == EGL_NO_SURFACE) {
+        // initialize here
+        m_eglFakeWindowContext = s_egl.eglCreateContext(
+                m_eglDisplay, m_eglConfig, m_eglContext,
+                getGlesMaxContextAttribs());
+
+        static const EGLint kFakeWindowPbufAttribs[] = {
+                EGL_WIDTH,          m_framebufferWidth, EGL_HEIGHT,
+                m_framebufferWidth, EGL_NONE,
+        };
+
+        m_eglFakeWindowSurface = s_egl.eglCreatePbufferSurface(
+                m_eglDisplay, m_eglConfig, kFakeWindowPbufAttribs);
+    }
+
+    if (!s_egl.eglMakeCurrent(m_eglDisplay, m_eglFakeWindowSurface,
+                              m_eglFakeWindowSurface, m_eglFakeWindowContext)) {
+        ERR("eglMakeCurrent failed in binding fake window!");
+        return false;
+    }
+    return true;
+}
+
+bool FrameBuffer::unbind_locked() {
+    EGLContext curContext = s_egl.eglGetCurrentContext();
+    EGLSurface curReadSurf = s_egl.eglGetCurrentSurface(EGL_READ);
+    EGLSurface curDrawSurf = s_egl.eglGetCurrentSurface(EGL_DRAW);
+
+    if (m_prevContext != curContext || m_prevReadSurf != curReadSurf ||
+        m_prevDrawSurf != curDrawSurf) {
+        if (!s_egl.eglMakeCurrent(m_eglDisplay, m_prevDrawSurf, m_prevReadSurf,
+                                  m_prevContext)) {
+            return false;
+        }
+    }
+
+    m_prevContext = EGL_NO_CONTEXT;
+    m_prevReadSurf = EGL_NO_SURFACE;
+    m_prevDrawSurf = EGL_NO_SURFACE;
+    return true;
+}
+
 void FrameBuffer::createTrivialContext(HandleType shared,
                                        HandleType* contextOut,
                                        HandleType* surfOut) {
@@ -2800,7 +2895,7 @@
         EGL_NONE };
 
     *contextOut = s_egl.eglCreateContext(
-            m_eglDisplay, config->getHostEglConfig(), getGlobalEGLContext(), contextAttribs);
+            m_eglDisplay, config->getHostEglConfig(), m_pbufContext, contextAttribs);
 
     const EGLint pbufAttribs[] = {
         EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE };
@@ -3173,14 +3268,14 @@
 
         switch (composeDevice->version) {
             case 1: {
-                RecursiveScopedContextBind scopedBind(getPbufferSurfaceContextHelper());
+                RecursiveScopedContextBind scopedBind(m_colorBufferHelper);
                 post(composeDevice->targetHandle, false);
                 break;
             }
             case 2: {
                 ComposeDevice_v2* composeDeviceV2 = (ComposeDevice_v2*)buffer;
                 if (composeDeviceV2->displayId == 0) {
-                    RecursiveScopedContextBind scopedBind(getPbufferSurfaceContextHelper());
+                    RecursiveScopedContextBind scopedBind(m_colorBufferHelper);
                     post(composeDeviceV2->targetHandle, false);
                 }
                 break;
@@ -3246,7 +3341,7 @@
     //     m_prevDrawSurf
     AutoLock mutex(m_lock);
     // set up a context because some snapshot commands try using GL
-    RecursiveScopedContextBind scopedBind(getPbufferSurfaceContextHelper());
+    RecursiveScopedContextBind scopedBind(m_colorBufferHelper);
     // eglPreSaveContext labels all guest context textures to be saved
     // (textures created by the host are not saved!)
     // eglSaveAllImages labels all EGLImages (both host and guest) to be saved
@@ -3265,6 +3360,7 @@
     stream->putFloat(m_dpr);
 
     stream->putBe32(m_useSubWindow);
+    stream->putBe32(m_eglContextInitialized);
 
     stream->putBe32(m_fpsStats);
     stream->putBe32(m_statsNumFrames);
@@ -3319,11 +3415,14 @@
             s_egl.eglPostSaveContext(m_eglDisplay, ctx.second->getEGLContext(),
                     stream);
         }
-        // We need to run the post save step for m_eglContext
+        // We need to run the post save step for m_eglContext and m_pbufContext
         // to mark their texture handles dirty
         if (m_eglContext != EGL_NO_CONTEXT) {
             s_egl.eglPostSaveContext(m_eglDisplay, m_eglContext, stream);
         }
+        if (m_pbufContext != EGL_NO_CONTEXT) {
+            s_egl.eglPostSaveContext(m_eglDisplay, m_pbufContext, stream);
+        }
     }
 
 }
@@ -3335,7 +3434,7 @@
     {
         sweepColorBuffersLocked();
 
-        RecursiveScopedContextBind scopedBind(getPbufferSurfaceContextHelper());
+        RecursiveScopedContextBind scopedBind(m_colorBufferHelper);
         bool cleanupComplete = false;
         {
             AutoLock colorBufferMapLock(m_colorBufferMapLock);
@@ -3444,6 +3543,7 @@
     // TODO: resize the window
     //
     m_useSubWindow = stream->getBe32();
+    m_eglContextInitialized = stream->getBe32();
 
     m_fpsStats = stream->getBe32();
     m_statsNumFrames = stream->getBe32();
@@ -3462,8 +3562,8 @@
         m_guestManagedColorBufferLifetime = stream->getByte();
         loadCollection(
             stream, &m_colorbuffers, [this, now](Stream* stream) -> ColorBufferMap::value_type {
-                ColorBufferPtr cb(ColorBuffer::onLoad(stream, m_eglDisplay, getPbufferSurfaceContextHelper(),
-                                                      m_textureDraw, m_fastBlitSupported));
+                ColorBufferPtr cb(ColorBuffer::onLoad(stream, m_eglDisplay, m_colorBufferHelper,
+                                                      m_fastBlitSupported));
                 const HandleType handle = cb->getHndl();
                 const unsigned refCount = stream->getBe32();
                 const bool opened = stream->getByte();
@@ -3497,7 +3597,7 @@
     registerTriggerWait();
 
     {
-        RecursiveScopedContextBind scopedBind(getPbufferSurfaceContextHelper());
+        RecursiveScopedContextBind scopedBind(m_colorBufferHelper);
         AutoLock colorBufferMapLock(m_colorBufferMapLock);
         for (auto& it : m_colorbuffers) {
             if (it.second.cb) {
@@ -3815,38 +3915,3 @@
     }
     return colorBufferPtr->getBorrowedImageInfo();
 }
-
-EGLSurface FrameBuffer::getWindowSurface() const {
-    if (!m_windowSurface) {
-        return EGL_NO_SURFACE;
-    }
-
-    const auto* displaySurfaceGl =
-        reinterpret_cast<const DisplaySurfaceGl*>(m_windowSurface->getImpl());
-
-    return displaySurfaceGl->getSurface();
-}
-
-EGLContext FrameBuffer::getGlobalEGLContext() const {
-    if (!m_pbufferSurface) {
-        GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
-            << "FrameBuffer pbuffer surface not available.";
-    }
-
-    const auto* displaySurfaceGl =
-        reinterpret_cast<const DisplaySurfaceGl*>(m_pbufferSurface->getImpl());
-
-    return displaySurfaceGl->getContextForShareContext();
-}
-
-ContextHelper* FrameBuffer::getPbufferSurfaceContextHelper() const {
-    if (!m_pbufferSurface) {
-        GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
-            << "FrameBuffer pbuffer surface not available.";
-    }
-
-    const auto* displaySurfaceGl =
-        reinterpret_cast<const DisplaySurfaceGl*>(m_pbufferSurface->getImpl());
-
-    return displaySurfaceGl->getContextHelper();
-}
diff --git a/stream-servers/FrameBuffer.h b/stream-servers/FrameBuffer.h
index 1404463..a740177 100644
--- a/stream-servers/FrameBuffer.h
+++ b/stream-servers/FrameBuffer.h
@@ -33,6 +33,7 @@
 #include "Compositor.h"
 #include "Display.h"
 #include "DisplaySurface.h"
+#include "DisplayVk.h"
 #include "Hwc2.h"
 #include "PostCommands.h"
 #include "PostWorker.h"
@@ -48,7 +49,6 @@
 #include "aemu/base/threads/Thread.h"
 #include "aemu/base/threads/WorkerThread.h"
 #include "gl/CompositorGl.h"
-#include "gl/DisplaySurfaceGl.h"
 #include "gl/EmulatedEglConfig.h"
 #include "gl/GLESVersionDetector.h"
 #include "gl/RenderContext.h"
@@ -64,8 +64,6 @@
 using emugl::HealthMonitor;
 using emugl::MetricsLogger;
 
-class DisplayVk;
-
 struct ColorBufferRef {
     ColorBufferPtr cb;
     uint32_t refcount;  // number of client-side references
@@ -464,10 +462,9 @@
 
     // Return the host EGLDisplay used by this instance.
     EGLDisplay getDisplay() const { return m_eglDisplay; }
-    EGLSurface getWindowSurface() const;
+    EGLSurface getWindowSurface() const { return m_eglSurface; }
     EGLContext getContext() const { return m_eglContext; }
     EGLConfig getConfig() const { return m_eglConfig; }
-    ContextHelper* getPbufferSurfaceContextHelper() const;
 
     // Change the rotation of the displayed GPU sub-window.
     void setDisplayRotation(float zRot) {
@@ -507,6 +504,10 @@
     // https://www.khronos.org/registry/egl/extensions/KHR/EGL_KHR_image_base.txt
     EGLBoolean destroyClientImage(HandleType image);
 
+    // Used internally.
+    bool bind_locked();
+    bool unbind_locked();
+
     void lockContextStructureRead() { m_contextStructureLock.lockRead(); }
     void unlockContextStructureRead() { m_contextStructureLock.unlockRead(); }
 
@@ -572,6 +573,7 @@
                        int displayId, int desiredWidth, int desiredHeight,
                        int desiredRotation);
     void onLastColorBufferRef(uint32_t handle);
+    ContextHelper* getColorBufferHelper() { return m_colorBufferHelper; }
     ColorBufferPtr findColorBuffer(HandleType p_colorbuffer);
     BufferPtr findBuffer(HandleType p_buffer);
 
@@ -610,7 +612,7 @@
     static const uint32_t s_invalidIdMultiDisplay = 0xFFFFFFAB;
     static const uint32_t s_maxNumMultiDisplay = 11;
 
-    EGLContext getGlobalEGLContext() const;
+    EGLContext getGlobalEGLContext() { return m_pbufContext; }
     HandleType getLastPostedColorBuffer() { return m_lastPostedColorBuffer; }
     void waitForGpu(uint64_t eglsync);
     void waitForGpuVulkan(uint64_t deviceHandle, uint64_t fenceHandle);
@@ -640,6 +642,8 @@
     // the object handle maps.
     HandleType genHandle_locked();
 
+    bool bindSubwin_locked();
+    bool bindFakeWindow_locked();
     bool removeSubWindow_locked();
     // Returns the set of ColorBuffers destroyed (for further cleanup)
     std::vector<HandleType> cleanupProcGLObjects_locked(uint64_t puid,
@@ -683,6 +687,7 @@
     float m_dpr = 0;
 
     bool m_useSubWindow = false;
+    bool m_eglContextInitialized = false;
 
     bool m_fpsStats = false;
     bool m_perfStats = false;
@@ -720,16 +725,19 @@
     using ColorBufferDelayedClose = std::vector<ColorBufferCloseInfo>;
     ColorBufferDelayedClose m_colorBufferDelayedCloseList;
 
+    ContextHelper* m_colorBufferHelper = nullptr;
+
+    EGLSurface m_eglSurface = EGL_NO_SURFACE;
     EGLContext m_eglContext = EGL_NO_CONTEXT;
+    EGLSurface m_pbufSurface = EGL_NO_SURFACE;
+    EGLContext m_pbufContext = EGL_NO_CONTEXT;
 
-    // TODO(b/233939967): move to EmulationGl
-    // Used for ColorBuffer ops.
-    std::unique_ptr<gfxstream::DisplaySurface> m_pbufferSurface;
-    // TODO(b/233939967): move to EmulationGl
-    // Used for Composition and Display ops.
-    std::unique_ptr<gfxstream::DisplaySurface> m_windowSurface;
-    std::unique_ptr<gfxstream::DisplaySurface> m_fakeWindowSurface;
+    EGLSurface m_eglFakeWindowSurface = EGL_NO_SURFACE;
+    EGLContext m_eglFakeWindowContext = EGL_NO_CONTEXT;
 
+    EGLContext m_prevContext = EGL_NO_CONTEXT;
+    EGLSurface m_prevReadSurf = EGL_NO_SURFACE;
+    EGLSurface m_prevDrawSurf = EGL_NO_SURFACE;
     EGLNativeWindowType m_subWin = {};
     TextureDraw* m_textureDraw = nullptr;
     EGLConfig m_eglConfig = nullptr;
@@ -833,8 +841,6 @@
     std::unique_ptr<CompositorGl> m_compositorGl;
     bool m_useVulkanComposition = false;
 
-    // TODO(b/233939967): move to EmulationGl.
-    std::unique_ptr<DisplayGl> m_displayGl;
     // The implementation for Vulkan native swapchain. Only initialized when useVulkan is set when
     // calling FrameBuffer::initialize(). DisplayVk is actually owned by VkEmulation.
     DisplayVk *m_displayVk = nullptr;
diff --git a/stream-servers/PostWorker.cpp b/stream-servers/PostWorker.cpp
index 2147fc1..c145984 100644
--- a/stream-servers/PostWorker.cpp
+++ b/stream-servers/PostWorker.cpp
@@ -20,15 +20,17 @@
 #include <chrono>
 
 #include "ColorBuffer.h"
+#include "CompositorGl.h"
 #include "Debug.h"
 #include "FrameBuffer.h"
+#include "OpenGLESDispatch/DispatchTables.h"
+#include "OpenGLESDispatch/EGLDispatch.h"
+#include "OpenGLESDispatch/GLESv2Dispatch.h"
 #include "RenderThreadInfo.h"
 #include "aemu/base/Tracing.h"
-#include "gl/DisplayGl.h"
 #include "host-common/GfxstreamFatalError.h"
 #include "host-common/logging.h"
 #include "host-common/misc.h"
-#include "vulkan/DisplayVk.h"
 #include "vulkan/VkCommonOperations.h"
 
 using emugl::ABORT_REASON_OTHER;
@@ -55,172 +57,137 @@
     (void)wait;
 }
 
-namespace {
-
-hwc_transform_t getTransformFromRotation(int rotation) {
-    switch (static_cast<int>(rotation / 90)) {
-        case 1:
-            return HWC_TRANSFORM_ROT_270;
-        case 2:
-            return HWC_TRANSFORM_ROT_180;
-        case 3:
-            return HWC_TRANSFORM_ROT_90;
-        default:
-            return HWC_TRANSFORM_NONE;
-    }
-}
-
-}  // namespace
-
-PostWorker::PostWorker(bool mainThreadPostingOnly, Compositor* compositor,
-                       DisplayGl* displayGl, DisplayVk* displayVk)
+PostWorker::PostWorker(PostWorker::BindSubwinCallback&& cb, bool mainThreadPostingOnly,
+                       Compositor* compositor, DisplayVk* displayVk)
     : mFb(FrameBuffer::getFB()),
+      mBindSubwin(cb),
       m_mainThreadPostingOnly(mainThreadPostingOnly),
       m_runOnUiThread(m_mainThreadPostingOnly ? emugl::get_emugl_window_operations().runOnUiThread
                                               : sDefaultRunOnUiThread),
       m_compositor(compositor),
-      m_displayGl(displayGl),
       m_displayVk(displayVk) {}
 
+void PostWorker::fillMultiDisplayPostStruct(ComposeLayer* l,
+                                            hwc_rect_t displayArea,
+                                            hwc_frect_t cropArea,
+                                            hwc_transform_t transform) {
+    l->composeMode = HWC2_COMPOSITION_DEVICE;
+    l->blendMode = HWC2_BLEND_MODE_NONE;
+    l->transform = transform;
+    l->alpha = 1.0;
+    l->displayFrame = displayArea;
+    l->crop = cropArea;
+}
+
 std::shared_future<void> PostWorker::postImpl(ColorBuffer* cb) {
+    std::shared_future<void> completedFuture =
+        std::async(std::launch::deferred, [] {}).share();
+    completedFuture.wait();
+    // bind the subwindow eglSurface
+    if (!m_mainThreadPostingOnly && m_needsToRebindWindow) {
+        m_needsToRebindWindow = !mBindSubwin();
+        if (m_needsToRebindWindow) {
+            // Do not proceed if fail to bind to the window.
+            return completedFuture;
+        }
+    }
+
     if (m_displayVk) {
         const auto imageInfo = mFb->borrowColorBufferForDisplay(cb->getHndl());
         return m_displayVk->post(imageInfo.get());
     }
 
-    if (!m_displayGl) {
-        GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
-            << "PostWorker missing DisplayGl.";
-    }
+    float dpr = mFb->getDpr();
+    int windowWidth = mFb->windowWidth();
+    int windowHeight = mFb->windowHeight();
+    float px = mFb->getPx();
+    float py = mFb->getPy();
+    int zRot = mFb->getZrot();
+    hwc_transform_t rotation = (hwc_transform_t)0;
 
-    DisplayGl::Post post = {};
+    // Find the x and y values at the origin when "fully scrolled."
+    // Multiply by 2 because the texture goes from -1 to 1, not 0 to 1.
+    // Multiply the windowing coordinates by DPR because they ignore
+    // DPR, but the viewport includes DPR.
+    float fx = 2.f * (m_viewportWidth  - windowWidth  * dpr) / (float)m_viewportWidth;
+    float fy = 2.f * (m_viewportHeight - windowHeight * dpr) / (float)m_viewportHeight;
 
-    ComposeLayer postLayerOptions = {
-        .composeMode = HWC2_COMPOSITION_DEVICE,
-        .blendMode = HWC2_BLEND_MODE_NONE,
-        .transform = HWC_TRANSFORM_NONE,
-    };
+    // finally, compute translation values
+    float dx = px * fx;
+    float dy = py * fy;
 
-    const auto& multiDisplay = emugl::get_emugl_multi_display_operations();
-    if (multiDisplay.isMultiDisplayEnabled()) {
-        uint32_t combinedDisplayW = 0;
-        uint32_t combinedDisplayH = 0;
-        multiDisplay.getCombinedDisplaySize(&combinedDisplayW, &combinedDisplayH);
-
-        post.frameWidth = combinedDisplayW;
-        post.frameHeight = combinedDisplayH;
-
-        int32_t previousDisplayId = -1;
-        uint32_t currentDisplayId;
-        int32_t currentDisplayOffsetX;
-        int32_t currentDisplayOffsetY;
-        uint32_t currentDisplayW;
-        uint32_t currentDisplayH;
-        uint32_t currentDisplayColorBufferHandle;
-        while (multiDisplay.getNextMultiDisplay(previousDisplayId,
-                                                &currentDisplayId,
-                                                &currentDisplayOffsetX,
-                                                &currentDisplayOffsetY,
-                                                &currentDisplayW,
-                                                &currentDisplayH,
-                                                /*dpi=*/nullptr,
-                                                /*flags=*/nullptr,
-                                                &currentDisplayColorBufferHandle)) {
-            previousDisplayId = currentDisplayId;
-
-            if (currentDisplayW == 0 ||
-                currentDisplayH == 0 ||
-                currentDisplayColorBufferHandle == 0) {
+    if (emugl::get_emugl_multi_display_operations().isMultiDisplayEnabled()) {
+        uint32_t combinedW, combinedH;
+        emugl::get_emugl_multi_display_operations().getCombinedDisplaySize(&combinedW, &combinedH);
+        mFb->getTextureDraw()->prepareForDrawLayer();
+        int32_t start_id = -1, x, y;
+        uint32_t id, w, h, c;
+        while(emugl::get_emugl_multi_display_operations().getNextMultiDisplay(start_id, &id,
+                                                                              &x, &y, &w, &h,
+                                                                              nullptr, nullptr,
+                                                                              &c)) {
+            if ((id != 0) && (w == 0 || h == 0 || c == 0)) {
+                start_id = id;
                 continue;
             }
-
-            ColorBuffer* cb = mFb->findColorBuffer(currentDisplayColorBufferHandle).get();
-            if (!cb) {
+            ColorBuffer* multiDisplayCb = id == 0 ? cb : mFb->findColorBuffer(c).get();
+            if (multiDisplayCb == nullptr) {
+                start_id = id;
                 continue;
             }
-
-            postLayerOptions.displayFrame = {
-                .left = static_cast<int>(currentDisplayOffsetX),
-                .top = static_cast<int>(currentDisplayOffsetY),
-                .right = static_cast<int>(currentDisplayOffsetX + currentDisplayW),
-                .bottom = static_cast<int>(currentDisplayOffsetY + currentDisplayH),
-            };
-            postLayerOptions.crop = {
-                .left = 0.0f,
-                .top = static_cast<float>(cb->getHeight()),
-                .right = static_cast<float>(cb->getWidth()),
-                .bottom = 0.0f,
-            };
-
-            post.layers.push_back(DisplayGl::PostLayer{
-                .colorBuffer = cb,
-                .layerOptions = postLayerOptions,
-            });
+            ComposeLayer l;
+            hwc_rect_t displayArea = { .left = (int)x,
+                                       .top = (int)y,
+                                       .right = (int)(x + w),
+                                       .bottom = (int)(y + h) };
+            hwc_frect_t cropArea = { .left = 0.0,
+                                     .top = (float)multiDisplayCb->getHeight(),
+                                     .right = (float)multiDisplayCb->getWidth(),
+                                     .bottom = 0.0 };
+            fillMultiDisplayPostStruct(&l, displayArea, cropArea, rotation);
+            multiDisplayCb->postLayer(l, combinedW, combinedH);
+            start_id = id;
         }
-    } else if (emugl::get_emugl_window_operations().isFolded()) {
-        const float dpr = mFb->getDpr();
+        mFb->getTextureDraw()->cleanupForDrawLayer();
+    }
+    else if (emugl::get_emugl_window_operations().isFolded()) {
+        mFb->getTextureDraw()->prepareForDrawLayer();
+        ComposeLayer l;
+        int x, y, w, h;
+        emugl::get_emugl_window_operations().getFoldedArea(&x, &y, &w, &h);
+        hwc_rect_t displayArea = { .left = 0,
+                                   .top = 0,
+                                   .right = windowWidth,
+                                   .bottom = windowHeight };
+        hwc_frect_t cropArea = { .left = (float)x,
+                                 .top = (float)(y + h),
+                                 .right = (float)(x + w),
+                                 .bottom = (float)y };
+        switch ((int)zRot/90) {
+            case 1:
+                rotation = HWC_TRANSFORM_ROT_270;
+                break;
+            case 2:
+                rotation = HWC_TRANSFORM_ROT_180;
+                break;
+            case 3:
+                rotation = HWC_TRANSFORM_ROT_90;
+                break;
+            default: ;
+        }
 
-        post.frameWidth = m_viewportWidth;
-        post.frameHeight = m_viewportHeight;
-
-        int displayOffsetX;
-        int displayOffsetY;
-        int displayW;
-        int displayH;
-        emugl::get_emugl_window_operations().getFoldedArea(&displayOffsetX,
-                                                           &displayOffsetY,
-                                                           &displayW,
-                                                           &displayH);
-
-        postLayerOptions.displayFrame = {
-            .left = 0,
-            .top = 0,
-            .right = mFb->windowWidth(),
-            .bottom = mFb->windowHeight(),
-        };
-        postLayerOptions.crop = {
-            .left = static_cast<float>(displayOffsetX),
-            .top = static_cast<float>(displayOffsetY + displayH),
-            .right = static_cast<float>(displayOffsetX + displayW),
-            .bottom = static_cast<float>(displayOffsetY),
-        };
-        postLayerOptions.transform = getTransformFromRotation(mFb->getZrot());
-
-        post.layers.push_back(DisplayGl::PostLayer{
-            .colorBuffer = cb,
-            .layerOptions = postLayerOptions,
-        });
-    } else {
-        float dpr = mFb->getDpr();
-        int windowWidth = mFb->windowWidth();
-        int windowHeight = mFb->windowHeight();
-        float px = mFb->getPx();
-        float py = mFb->getPy();
-        int zRot = mFb->getZrot();
-        hwc_transform_t rotation = (hwc_transform_t)0;
-
-        // Find the x and y values at the origin when "fully scrolled."
-        // Multiply by 2 because the texture goes from -1 to 1, not 0 to 1.
-        // Multiply the windowing coordinates by DPR because they ignore
-        // DPR, but the viewport includes DPR.
-        float fx = 2.f * (m_viewportWidth  - windowWidth  * dpr) / (float)m_viewportWidth;
-        float fy = 2.f * (m_viewportHeight - windowHeight * dpr) / (float)m_viewportHeight;
-
-        // finally, compute translation values
-        float dx = px * fx;
-        float dy = py * fy;
-
-        post.layers.push_back(DisplayGl::PostLayer{
-            .colorBuffer = cb,
-            .overlayOptions = DisplayGl::PostLayer::OverlayOptions{
-                .rotation = static_cast<float>(zRot),
-                .dx = dx,
-                .dy = dy,
-            },
-        });
+        fillMultiDisplayPostStruct(&l, displayArea, cropArea, rotation);
+        cb->postLayer(l, m_viewportWidth/dpr, m_viewportHeight/dpr);
+        mFb->getTextureDraw()->cleanupForDrawLayer();
+    }
+    else {
+        // render the color buffer to the window and apply the overlay
+        GLuint tex = cb->getViewportScaledTexture();
+        cb->postWithOverlay(tex, zRot, dx, dy);
     }
 
-    return m_displayGl->post(post);
+    s_egl.eglSwapBuffers(mFb->getDisplay(), mFb->getWindowSurface());
+    return completedFuture;
 }
 
 // Called whenever the subwindow needs a refresh (FrameBuffer::setupSubWindow).
@@ -228,19 +195,27 @@
 // when the refresh is a display change, for instance)
 // and resets the posting viewport.
 void PostWorker::viewportImpl(int width, int height) {
+    if (!m_mainThreadPostingOnly) {
+        // For GLES, we rebind the subwindow eglSurface unconditionally: this
+        // could be from a display change, but we want to avoid binding
+        // VkSurfaceKHR too frequently, because that's too expensive.
+        if (!m_displayVk || m_needsToRebindWindow) {
+            m_needsToRebindWindow = !mBindSubwin();
+            if (m_needsToRebindWindow) {
+                // Do not proceed if fail to bind to the window.
+                return;
+            }
+        }
+    }
+
     if (m_displayVk) {
         return;
     }
 
-    const float dpr = mFb->getDpr();
+    float dpr = mFb->getDpr();
     m_viewportWidth = width * dpr;
     m_viewportHeight = height * dpr;
-
-    if (!m_displayGl) {
-        GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
-            << "PostWorker missing DisplayGl.";
-    }
-    m_displayGl->viewport(m_viewportWidth, m_viewportHeight);
+    s_gles2.glViewport(0, 0, m_viewportWidth, m_viewportHeight);
 }
 
 // Called when the subwindow refreshes, but there is no
@@ -252,12 +227,11 @@
         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
             << "PostWorker with Vulkan doesn't support clear";
     }
-
-    if (!m_displayGl) {
-        GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
-            << "PostWorker missing DisplayGl.";
-    }
-    m_displayGl->clear();
+#ifndef __linux__
+    s_gles2.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT |
+                    GL_STENCIL_BUFFER_BIT);
+    s_egl.eglSwapBuffers(mFb->getDisplay(), mFb->getWindowSurface());
+#endif
 }
 
 std::shared_future<void> PostWorker::composeImpl(const FlatComposeRequest& composeRequest) {
@@ -265,6 +239,19 @@
         ERR("The last composition on the target buffer hasn't completed.");
     }
 
+    std::shared_future<void> completedFuture =
+        std::async(std::launch::deferred, [] {}).share();
+    completedFuture.wait();
+
+    // bind the subwindow eglSurface
+    if (!m_mainThreadPostingOnly && m_needsToRebindWindow) {
+        m_needsToRebindWindow = !mBindSubwin();
+        if (m_needsToRebindWindow) {
+            // Do not proceed if fail to bind to the window.
+            return completedFuture;
+        }
+    }
+
     Compositor::CompositionRequest compositorRequest = {};
     compositorRequest.target = mFb->borrowColorBufferForComposition(composeRequest.targetHandle,
                                                                     /*colorBufferIsTarget=*/true);
@@ -312,7 +299,12 @@
     }));
 }
 
-PostWorker::~PostWorker() {}
+PostWorker::~PostWorker() {
+    if (mFb->getDisplay() != EGL_NO_DISPLAY) {
+        s_egl.eglMakeCurrent(mFb->getDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE,
+                             EGL_NO_CONTEXT);
+    }
+}
 
 void PostWorker::post(ColorBuffer* cb, std::unique_ptr<Post::CompletionCallback> postCallback) {
     auto packagedPostCallback = std::shared_ptr<Post::CompletionCallback>(std::move(postCallback));
diff --git a/stream-servers/PostWorker.h b/stream-servers/PostWorker.h
index af5ab76..aa68864 100644
--- a/stream-servers/PostWorker.h
+++ b/stream-servers/PostWorker.h
@@ -15,32 +15,35 @@
  */
 #pragma once
 
+#include <EGL/egl.h>
+#include <GLES/gl.h>
+#include <GLES3/gl3.h>
+#include <vulkan/vulkan.h>
+
 #include <functional>
 #include <future>
 #include <optional>
-#include <unordered_map>
 #include <vector>
 
 #include "Compositor.h"
-#include "ContextHelper.h"
+#include "DisplayVk.h"
 #include "Hwc2.h"
 #include "PostCommands.h"
 #include "aemu/base/Compiler.h"
 #include "aemu/base/synchronization/Lock.h"
 #include "aemu/base/synchronization/MessageChannel.h"
-#include "gl/DisplayGl.h"
 #include "host-common/window_agent.h"
 
 class ColorBuffer;
-class DisplayGl;
-class DisplayVk;
 class FrameBuffer;
 struct RenderThreadInfo;
 
 class PostWorker {
    public:
-    PostWorker(bool mainThreadPostingOnly, Compositor* compositor,
-               DisplayGl* displayGl, DisplayVk* displayVk);
+    using BindSubwinCallback = std::function<bool(void)>;
+
+    PostWorker(BindSubwinCallback&& cb, bool mainThreadPostingOnly, Compositor* compositor,
+               DisplayVk* display);
     ~PostWorker();
 
     // post: posts the next color buffer.
@@ -77,6 +80,10 @@
     std::shared_future<void> composeImpl(const FlatComposeRequest& composeRequest);
     void clearImpl();
 
+    void fillMultiDisplayPostStruct(ComposeLayer* l, hwc_rect_t displayArea,
+                                    hwc_frect_t cropArea,
+                                    hwc_transform_t transform);
+
     // If m_mainThreadPostingOnly is true, schedule the task to UI thread by
     // using m_runOnUiThread. Otherwise, execute the task on the current thread.
     void runTask(std::packaged_task<void()>);
@@ -88,15 +95,15 @@
 
     Compositor* m_compositor = nullptr;
 
+    std::function<bool(void)> mBindSubwin;
+
+    bool m_needsToRebindWindow = true;
     int m_viewportWidth = 0;
     int m_viewportHeight = 0;
 
     bool m_mainThreadPostingOnly = false;
     UiThreadRunner m_runOnUiThread = 0;
 
-    // TODO(b/233939967): conslidate DisplayGl and DisplayVk into
-    // `Display* const m_display`.
-    DisplayGl* const m_displayGl;
     // The implementation for Vulkan native swapchain. Only initialized when
     // useVulkan is set when calling FrameBuffer::initialize(). PostWorker
     // doesn't take the ownership of this DisplayVk object.
diff --git a/stream-servers/gl/Android.bp b/stream-servers/gl/Android.bp
index 941152c..9771e96 100644
--- a/stream-servers/gl/Android.bp
+++ b/stream-servers/gl/Android.bp
@@ -13,8 +13,6 @@
     defaults: [ "gfxstream_defaults" ],
     srcs: [
         "CompositorGl.cpp",
-        "DisplayGl.cpp",
-        "DisplaySurfaceGl.cpp",
         "EmulatedEglConfig.cpp",
         "GLESVersionDetector.cpp",
         "RenderContext.cpp",
diff --git a/stream-servers/gl/CMakeLists.txt b/stream-servers/gl/CMakeLists.txt
index 8043164..822d61d 100644
--- a/stream-servers/gl/CMakeLists.txt
+++ b/stream-servers/gl/CMakeLists.txt
@@ -10,8 +10,6 @@
 
 add_library(gfxstream-gl-server
             CompositorGl.cpp
-            DisplayGl.cpp
-            DisplaySurfaceGl.cpp
             EmulatedEglConfig.cpp
             GLESVersionDetector.cpp
             RenderContext.cpp
diff --git a/stream-servers/gl/CompositorGl.cpp b/stream-servers/gl/CompositorGl.cpp
index f0e0fd5..df2da14 100644
--- a/stream-servers/gl/CompositorGl.cpp
+++ b/stream-servers/gl/CompositorGl.cpp
@@ -16,7 +16,6 @@
 
 #include "BorrowedImageGl.h"
 #include "Debug.h"
-#include "DisplaySurfaceGl.h"
 #include "OpenGLESDispatch/DispatchTables.h"
 #include "TextureDraw.h"
 #include "host-common/GfxstreamFatalError.h"
@@ -35,68 +34,27 @@
     return nullptr;
 }
 
-std::shared_future<void> getCompletedFuture() {
-    std::shared_future<void> completedFuture = std::async(std::launch::deferred, [] {}).share();
-    completedFuture.wait();
-    return completedFuture;
-}
-
 }  // namespace
 
 CompositorGl::CompositorGl(TextureDraw* textureDraw) : m_textureDraw(textureDraw) {}
 
-CompositorGl::~CompositorGl() {}
-
-void CompositorGl::bindToSurfaceImpl(gfxstream::DisplaySurface* surface) {
-    const auto* surfaceGl = static_cast<const DisplaySurfaceGl*>(surface->getImpl());
-
-    std::optional<RecursiveScopedContextBind> contextBind;
-    if (mUseBoundSurfaceContext) {
-        contextBind.emplace(surfaceGl->getContextHelper());
-        if (!contextBind->isOk()) {
-            return;
-        }
+CompositorGl::~CompositorGl() {
+    if (m_composeFbo) {
+        s_gles2.glDeleteFramebuffers(1, &m_composeFbo);
     }
+}
 
+void CompositorGl::bindToWindow() {
+    if (m_composeFbo) {
+        s_gles2.glDeleteFramebuffers(1, &m_composeFbo);
+    }
     s_gles2.glGenFramebuffers(1, &m_composeFbo);
 }
 
-void CompositorGl::unbindFromSurfaceImpl() {
-    const auto* surface = getBoundSurface();
-    if (!surface) {
-        return;
-    }
-    const auto* surfaceGl = static_cast<const DisplaySurfaceGl*>(surface->getImpl());
-
-    std::optional<RecursiveScopedContextBind> contextBind;
-    if (mUseBoundSurfaceContext) {
-        contextBind.emplace(surfaceGl->getContextHelper());
-        if (!contextBind->isOk()) {
-            return;
-        }
-    }
-
-    if (m_composeFbo) {
-        s_gles2.glDeleteFramebuffers(1, &m_composeFbo);
-        m_composeFbo = 0;
-    }
-}
-
 Compositor::CompositionFinishedWaitable CompositorGl::compose(
-        const CompositionRequest& composeRequest) {
-    const auto* surface = getBoundSurface();
-    if (!surface) {
-        return getCompletedFuture();
-    }
-    const auto* surfaceGl = static_cast<const DisplaySurfaceGl*>(surface->getImpl());
-
-    std::optional<RecursiveScopedContextBind> contextBind;
-    if (mUseBoundSurfaceContext) {
-        contextBind.emplace(surfaceGl->getContextHelper());
-        if (!contextBind->isOk()) {
-            return getCompletedFuture();
-        }
-    }
+    const CompositionRequest& composeRequest) {
+    std::shared_future<void> completedFuture = std::async(std::launch::deferred, [] {}).share();
+    completedFuture.wait();
 
     const auto* targetImage = getInfoOrAbort(composeRequest.target);
     const uint32_t targetWidth = targetImage->width;
@@ -139,5 +97,5 @@
     // complete but is currently only returning a future when all CPU work is completed.
     // In the future, CompositionFinishedWaitable should be replaced with something that
     // passes along a GL fence or VK fence.
-    return getCompletedFuture();
+    return completedFuture;
 }
diff --git a/stream-servers/gl/CompositorGl.h b/stream-servers/gl/CompositorGl.h
index 62b59fd..526e200 100644
--- a/stream-servers/gl/CompositorGl.h
+++ b/stream-servers/gl/CompositorGl.h
@@ -14,36 +14,25 @@
 
 #pragma once
 
-#include <atomic>
-
 #include <EGL/egl.h>
 #include <GLES/gl.h>
 #include <GLES/glext.h>
 #include <GLES3/gl3.h>
 
 #include "Compositor.h"
-#include "DisplaySurfaceUser.h"
 #include "TextureDraw.h"
 
-class CompositorGl : public Compositor, public gfxstream::DisplaySurfaceUser {
+class CompositorGl : public Compositor {
   public:
     CompositorGl(TextureDraw* textureDraw);
     virtual ~CompositorGl();
 
-    // If false, this display will use the existing bound context when performing compositions.
-    void setUseBoundSurfaceContext(bool use) { mUseBoundSurfaceContext = use; }
+    void bindToWindow();
 
     CompositionFinishedWaitable compose(const CompositionRequest& compositionRequest) override;
 
-  protected:
-    void bindToSurfaceImpl(gfxstream::DisplaySurface* surface) override;
-    void unbindFromSurfaceImpl() override;
-
   private:
     GLuint m_composeFbo = 0;
- 
     // Owned by FrameBuffer.
     TextureDraw* m_textureDraw = nullptr;
-
-    std::atomic_bool mUseBoundSurfaceContext{true};
 };
diff --git a/stream-servers/gl/DisplayGl.cpp b/stream-servers/gl/DisplayGl.cpp
deleted file mode 100644
index c9541e1..0000000
--- a/stream-servers/gl/DisplayGl.cpp
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright (C) 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 express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "DisplayGl.h"
-
-#include "DisplaySurfaceGl.h"
-#include "OpenGLESDispatch/DispatchTables.h"
-#include "OpenGLESDispatch/EGLDispatch.h"
-
-namespace {
-
-std::shared_future<void> getCompletedFuture() {
-    std::shared_future<void> completedFuture =
-        std::async(std::launch::deferred, [] {}).share();
-    completedFuture.wait();
-    return completedFuture;
-}
-
-}  // namespace
-
-std::shared_future<void> DisplayGl::post(const Post& post) {
-    const auto* surface = getBoundSurface();
-    if (!surface) {
-        return getCompletedFuture();
-    }
-    const auto* surfaceGl = static_cast<const DisplaySurfaceGl*>(surface->getImpl());
-
-    std::optional<RecursiveScopedContextBind> contextBind;
-    if (mUseBoundSurfaceContext) {
-        contextBind.emplace(surfaceGl->getContextHelper());
-        if (!contextBind->isOk()) {
-            return getCompletedFuture();
-        }
-    }
-
-    for (const PostLayer& layer : post.layers) {
-        if (layer.layerOptions) {
-            layer.colorBuffer->postLayer(*layer.layerOptions,
-                                         post.frameWidth,
-                                         post.frameHeight);
-        } else if (layer.overlayOptions) {
-            layer.colorBuffer->postWithOverlay(layer.colorBuffer->getViewportScaledTexture(),
-                                               layer.overlayOptions->rotation,
-                                               layer.overlayOptions->dx,
-                                               layer.overlayOptions->dy);
-        }
-    }
-
-    s_egl.eglSwapBuffers(surfaceGl->mDisplay, surfaceGl->mSurface);
-
-    return getCompletedFuture();
-}
-
-void DisplayGl::viewport(int width, int height) {
-    mViewportWidth = width;
-    mViewportHeight = height;
-
-    const auto* surface = getBoundSurface();
-    if (!surface) {
-        return;
-    }
-
-    std::optional<RecursiveScopedContextBind> contextBind;
-    if (mUseBoundSurfaceContext) {
-        const auto* surfaceGl = static_cast<const DisplaySurfaceGl*>(surface->getImpl());
-        contextBind.emplace(surfaceGl->getContextHelper());
-        if (!contextBind->isOk()) {
-            return;
-        }
-    }
-
-    s_gles2.glViewport(0, 0, mViewportWidth, mViewportHeight);
-}
-
-void DisplayGl::clear() {
-    const auto* surface = getBoundSurface();
-    if (!surface) {
-        return;
-    }
-    const auto* surfaceGl = static_cast<const DisplaySurfaceGl*>(surface->getImpl());
-
-    std::optional<RecursiveScopedContextBind> contextBind;
-    if (mUseBoundSurfaceContext) {
-        contextBind.emplace(surfaceGl->getContextHelper());
-        if (!contextBind->isOk()) {
-            return;
-        }
-    }
-
-#ifndef __linux__
-    s_gles2.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-    s_egl.eglSwapBuffers(surfaceGl->mDisplay, surfaceGl->mSurface);
-#endif
-}
diff --git a/stream-servers/gl/DisplayGl.h b/stream-servers/gl/DisplayGl.h
deleted file mode 100644
index a59d036..0000000
--- a/stream-servers/gl/DisplayGl.h
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright (C) 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 express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#pragma once
-
-#include <atomic>
-#include <future>
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-
-#include "ColorBuffer.h"
-#include "Display.h"
-#include "Hwc2.h"
-
-class DisplayGl : public gfxstream::Display {
-  public:
-    DisplayGl() {}
-    ~DisplayGl() {}
-
-    // If false, this display will use the existing bound context when
-    // performing display ops.
-    void setUseBoundSurfaceContext(bool use) { mUseBoundSurfaceContext = use; }
-
-    struct PostLayer {
-      ColorBuffer* colorBuffer = nullptr;
-
-      std::optional<ComposeLayer> layerOptions;
-
-      // TODO: This should probably be removed and TextureDraw should
-      // only use drawLayer() but this is currently needed to support
-      // existing draw paths without depending on FrameBuffer directly.
-      struct OverlayOptions {
-        float rotation;
-        float dx;
-        float dy;
-      };
-      std::optional<OverlayOptions> overlayOptions;
-    };
-
-    // TODO(b/233939967): move to generic Display.
-    struct Post {
-      uint32_t frameWidth = 0;
-      uint32_t frameHeight = 0;
-      std::vector<PostLayer> layers;
-    };
-
-    std::shared_future<void> post(const Post& request);
-
-    void viewport(int width, int height);
-
-    void clear();
-
-  protected:
-    void bindToSurfaceImpl(gfxstream::DisplaySurface* surface) override {}
-    void unbindFromSurfaceImpl() override {}
-
-  private:
-    int mViewportWidth = 0;
-    int mViewportHeight = 0;
-
-    std::atomic_bool mUseBoundSurfaceContext{true};
-};
\ No newline at end of file
diff --git a/stream-servers/gl/DisplaySurfaceGl.cpp b/stream-servers/gl/DisplaySurfaceGl.cpp
deleted file mode 100644
index 70b0695..0000000
--- a/stream-servers/gl/DisplaySurfaceGl.cpp
+++ /dev/null
@@ -1,178 +0,0 @@
-// Copyright (C) 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 express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "DisplaySurfaceGl.h"
-
-#include "OpenGLESDispatch/DispatchTables.h"
-#include "OpenGLESDispatch/EGLDispatch.h"
-#include "host-common/GfxstreamFatalError.h"
-#include "host-common/logging.h"
-
-namespace {
-
-using emugl::ABORT_REASON_OTHER;
-using emugl::FatalError;
-
-class DisplaySurfaceGlContextHelper : public ContextHelper {
-  public:
-    DisplaySurfaceGlContextHelper(EGLDisplay display,
-                                  EGLSurface surface,
-                                  EGLContext context)
-        : mDisplay(display),
-          mSurface(surface),
-          mContext(context) {
-        if (mDisplay == EGL_NO_DISPLAY) {
-            GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
-                << "DisplaySurfaceGlContextHelper created with no display?";
-        }
-        if (mSurface == EGL_NO_SURFACE) {
-            GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
-                << "DisplaySurfaceGlContextHelper created with no surface?";
-        }
-        if (mContext == EGL_NO_CONTEXT) {
-            GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
-                << "DisplaySurfaceGlContextHelper created with no context?";
-        }
-    }
-
-    bool setupContext() override {
-        EGLContext currentContext = s_egl.eglGetCurrentContext();
-        EGLSurface currentDrawSurface = s_egl.eglGetCurrentSurface(EGL_DRAW);
-        EGLSurface currentReadSurface = s_egl.eglGetCurrentSurface(EGL_READ);
-
-        if (currentContext != mContext ||
-            currentDrawSurface != mSurface ||
-            currentReadSurface != mSurface) {
-            if (!s_egl.eglMakeCurrent(mDisplay, mSurface, mSurface, mContext)) {
-                ERR("Failed to make display surface context current: %d", s_egl.eglGetError());
-                return false;
-            }
-        }
-
-        mPreviousContext = currentContext;
-        mPreviousDrawSurface = currentDrawSurface;
-        mPreviousReadSurface = currentReadSurface;
-
-        mIsBound = true;
-
-        return mIsBound;
-    }
-
-    void teardownContext() override {
-        EGLContext currentContext = s_egl.eglGetCurrentContext();
-        EGLSurface currentDrawSurface = s_egl.eglGetCurrentSurface(EGL_DRAW);
-        EGLSurface currentReadSurface = s_egl.eglGetCurrentSurface(EGL_READ);
-
-        if (currentContext != mPreviousContext ||
-            currentDrawSurface != mPreviousDrawSurface ||
-            currentReadSurface != mPreviousReadSurface) {
-            if (!s_egl.eglMakeCurrent(mDisplay,
-                                      mPreviousDrawSurface,
-                                      mPreviousReadSurface,
-                                      mPreviousContext)) {
-                ERR("Failed to make restore previous context: %d", s_egl.eglGetError());
-                return;
-            }
-        }
-
-        mPreviousContext = EGL_NO_CONTEXT;
-        mPreviousDrawSurface = EGL_NO_SURFACE;
-        mPreviousReadSurface = EGL_NO_SURFACE;
-        mIsBound = false;
-    }
-
-    bool isBound() const override { return mIsBound; }
-
-  private:
-    EGLDisplay mDisplay = EGL_NO_DISPLAY;
-    EGLSurface mSurface = EGL_NO_SURFACE;
-    EGLContext mContext = EGL_NO_CONTEXT;
-
-    EGLContext mPreviousContext = EGL_NO_CONTEXT;
-    EGLSurface mPreviousReadSurface = EGL_NO_SURFACE;
-    EGLSurface mPreviousDrawSurface = EGL_NO_SURFACE;
-
-    bool mIsBound = false;
-};
-
-}  // namespace
-
-/*static*/
-std::unique_ptr<DisplaySurfaceGl> DisplaySurfaceGl::createPbufferSurface(
-        EGLDisplay display,
-        EGLConfig config,
-        EGLContext shareContext,
-        const EGLint* contextAttribs,
-        EGLint width,
-        EGLint height) {
-    EGLContext context = s_egl.eglCreateContext(display, config, shareContext, contextAttribs);
-    if (context == EGL_NO_CONTEXT) {
-        ERR("Failed to create context for DisplaySurfaceGl.");
-        return nullptr;
-    }
-
-    const EGLint surfaceAttribs[] = {
-        EGL_WIDTH, width,   //
-        EGL_HEIGHT, height, //
-        EGL_NONE,           //
-    };
-    EGLSurface surface = s_egl.eglCreatePbufferSurface(display, config, surfaceAttribs);
-    if (surface == EGL_NO_SURFACE) {
-        ERR("Failed to create pbuffer surface for DisplaySurfaceGl.");
-        return nullptr;
-    }
-
-    return std::unique_ptr<DisplaySurfaceGl>(new DisplaySurfaceGl(display, surface, context));
-}
-
-/*static*/
-std::unique_ptr<DisplaySurfaceGl> DisplaySurfaceGl::createWindowSurface(
-        EGLDisplay display,
-        EGLConfig config,
-        EGLContext shareContext,
-        const GLint* contextAttribs,
-        FBNativeWindowType window) {
-    EGLContext context = s_egl.eglCreateContext(display, config, shareContext, contextAttribs);
-    if (context == EGL_NO_CONTEXT) {
-        ERR("Failed to create context for DisplaySurfaceGl.");
-        return nullptr;
-    }
-
-    EGLSurface surface = s_egl.eglCreateWindowSurface(display, config, window, nullptr);
-    if (surface == EGL_NO_SURFACE) {
-        ERR("Failed to create window surface for DisplaySurfaceGl.");
-        return nullptr;
-    }
-
-    return std::unique_ptr<DisplaySurfaceGl>(new DisplaySurfaceGl(display, surface, context));
-}
-
-DisplaySurfaceGl::DisplaySurfaceGl(EGLDisplay display,
-                                   EGLSurface surface,
-                                   EGLContext context)
-    : mDisplay(display),
-      mSurface(surface),
-      mContext(context),
-      mContextHelper(new DisplaySurfaceGlContextHelper(display, surface, context)) {}
-
-DisplaySurfaceGl::~DisplaySurfaceGl() {
-    if (mDisplay != EGL_NO_DISPLAY) {
-        if (mSurface) {
-            s_egl.eglDestroySurface(mDisplay, mSurface);
-        }
-        if (mContext) {
-            s_egl.eglDestroyContext(mDisplay, mContext);
-        }
-    }
-}
diff --git a/stream-servers/gl/DisplaySurfaceGl.h b/stream-servers/gl/DisplaySurfaceGl.h
deleted file mode 100644
index e682053..0000000
--- a/stream-servers/gl/DisplaySurfaceGl.h
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright (C) 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 express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#pragma once
-
-#include <cstdint>
-#include <memory>
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-
-#include "ContextHelper.h"
-#include "DisplaySurface.h"
-#include "render-utils/render_api_platform_types.h"
-
-class DisplaySurfaceGl : public gfxstream::DisplaySurfaceImpl {
-  public:
-    static std::unique_ptr<DisplaySurfaceGl> createPbufferSurface(EGLDisplay display,
-                                                                  EGLConfig config,
-                                                                  EGLContext shareContext,
-                                                                  const EGLint* contextAttribs,
-                                                                  EGLint width,
-                                                                  EGLint height);
-
-    static std::unique_ptr<DisplaySurfaceGl> createWindowSurface(EGLDisplay display,
-                                                                 EGLConfig config,
-                                                                 EGLContext shareContext,
-                                                                 const GLint* contextAttribs,
-                                                                 FBNativeWindowType window);
-
-    ~DisplaySurfaceGl();
-
-    ContextHelper* getContextHelper() const { return mContextHelper.get(); }
-
-    EGLContext getContextForShareContext() const { return mContext; }
-
-    EGLSurface getSurface() const { return mSurface; }
-
-  private:
-    friend class DisplayGl;
-
-    DisplaySurfaceGl(EGLDisplay display,
-                     EGLSurface surface,
-                     EGLContext context);
-
-    EGLDisplay mDisplay = EGL_NO_DISPLAY;
-    EGLSurface mSurface = EGL_NO_SURFACE;
-    EGLContext mContext = EGL_NO_CONTEXT;
-
-    std::unique_ptr<ContextHelper> mContextHelper;
-};