Resizable emulator: enable multiple display configs in framebuffer

Bug: 196986384
Bug: 265182971
Change-Id: I0af1be86f131bd5dad4292652f7d5be80d860299
diff --git a/gl-host-common/include/host-common/opengles.h b/gl-host-common/include/host-common/opengles.h
index e51faec..500cd5f 100644
--- a/gl-host-common/include/host-common/opengles.h
+++ b/gl-host-common/include/host-common/opengles.h
@@ -154,6 +154,10 @@
 /* Set vsync rate at runtime */
 AEMU_EXPORT void android_setVsyncHz(int vsyncHz);
 
+AEMU_EXPORT void android_setOpenglesDisplayConfigs(int configId, int w, int h,
+                                                   int dpiX, int dpiY);
+AEMU_EXPORT void android_setOpenglesDisplayActiveConfig(int configId);
+
 #ifndef USING_ANDROID_BP
 ANDROID_END_HEADER
 #endif
diff --git a/gl-host-common/opengles.cpp b/gl-host-common/opengles.cpp
index ede2bf1..faca808 100644
--- a/gl-host-common/opengles.cpp
+++ b/gl-host-common/opengles.cpp
@@ -709,3 +709,16 @@
         sRenderer->setVsyncHz(vsyncHz);
     }
 }
+
+void android_setOpenglesDisplayConfigs(int configId, int w, int h, int dpiX,
+                                       int dpiY) {
+    if (sRenderer) {
+        sRenderer->setDisplayConfigs(configId, w, h, dpiX, dpiY);
+    }
+}
+
+void android_setOpenglesDisplayActiveConfig(int configId) {
+    if (sRenderer) {
+        sRenderer->setDisplayActiveConfig(configId);
+    }
+}
diff --git a/stream-servers/FrameBuffer.cpp b/stream-servers/FrameBuffer.cpp
index 8cb6584..3f66769 100644
--- a/stream-servers/FrameBuffer.cpp
+++ b/stream-servers/FrameBuffer.cpp
@@ -522,6 +522,8 @@
       m_postThread([this](Post&& post) { return postWorkerFunc(post); }),
       m_logger(CreateMetricsLogger()),
       m_healthMonitor(CreateHealthMonitor(*m_logger)) {
+    mDisplayActiveConfigId = 0;
+    mDisplayConfigs[0] = {p_width, p_height, 160, 160};
     uint32_t displayId = 0;
     if (createDisplay(&displayId) < 0) {
         fprintf(stderr, "Failed to create default display\n");
@@ -2981,6 +2983,15 @@
     stream->putBe32(m_framebufferWidth);
     stream->putBe32(m_framebufferHeight);
     stream->putFloat(m_dpr);
+    stream->putBe32(mDisplayActiveConfigId);
+    saveCollection(stream, mDisplayConfigs,
+                   [](Stream* s, const std::map<int, DisplayConfig>::value_type& pair) {
+                       s->putBe32(pair.first);
+                       s->putBe32(pair.second.w);
+                       s->putBe32(pair.second.h);
+                       s->putBe32(pair.second.dpiX);
+                       s->putBe32(pair.second.dpiY);
+                   });
 
     stream->putBe32(m_useSubWindow);
     stream->putBe32(/*Obsolete m_eglContextInitialized =*/1);
@@ -3157,6 +3168,17 @@
     m_framebufferWidth = stream->getBe32();
     m_framebufferHeight = stream->getBe32();
     m_dpr = stream->getFloat();
+    mDisplayActiveConfigId = stream->getBe32();
+    loadCollection(stream, &mDisplayConfigs,
+                   [](Stream* s) -> std::map<int, DisplayConfig>::value_type {
+                       int idx = static_cast<int>(s->getBe32());
+                       int w = static_cast<int>(s->getBe32());
+                       int h = static_cast<int>(s->getBe32());
+                       int dpiX =  static_cast<int>(s->getBe32());
+                       int dpiY = static_cast<int>(s->getBe32());
+                       return {idx, {w, h, dpiX, dpiY}};
+                   });
+
     // TODO: resize the window
     //
     m_useSubWindow = stream->getBe32();
@@ -3694,3 +3716,58 @@
 
     m_vsyncThread->schedule(task);
 }
+
+void FrameBuffer::setDisplayConfigs(int configId, int w, int h,
+                                    int dpiX, int dpiY) {
+    AutoLock mutex(m_lock);
+    mDisplayConfigs[configId] = {w, h, dpiX, dpiY};
+    INFO("setDisplayConfigs w %d h %d dpiX %d dpiY %d", w, h, dpiX, dpiY);
+}
+
+void FrameBuffer::setDisplayActiveConfig(int configId) {
+    AutoLock mutex(m_lock);
+    if (mDisplayConfigs.find(configId) == mDisplayConfigs.end()) {
+        ERR("config %d not set", configId);
+        return;
+    }
+    mDisplayActiveConfigId = configId;
+    m_framebufferWidth = mDisplayConfigs[configId].w;
+    m_framebufferHeight = mDisplayConfigs[configId].h;
+    setDisplayPose(0, 0, 0, getWidth(), getHeight(), 0);
+    INFO("setDisplayActiveConfig %d", configId);
+}
+
+const int FrameBuffer::getDisplayConfigsCount() {
+    AutoLock mutex(m_lock);
+    return mDisplayConfigs.size();
+}
+
+const int FrameBuffer::getDisplayConfigsParam(int configId, EGLint param) {
+    AutoLock mutex(m_lock);
+    if (mDisplayConfigs.find(configId) == mDisplayConfigs.end()) {
+        return -1;
+    }
+    switch (param) {
+        case FB_WIDTH:
+            return mDisplayConfigs[configId].w;
+        case FB_HEIGHT:
+            return mDisplayConfigs[configId].h;
+        case FB_XDPI:
+            return mDisplayConfigs[configId].dpiX;
+        case FB_YDPI:
+            return mDisplayConfigs[configId].dpiY;
+        case FB_FPS:
+            return 60;
+        case FB_MIN_SWAP_INTERVAL:
+            return -1;
+        case FB_MAX_SWAP_INTERVAL:
+            return -1;
+        default:
+            return -1;
+    }
+}
+
+const int FrameBuffer::getDisplayActiveConfig() {
+    AutoLock mutex(m_lock);
+    return mDisplayActiveConfigId >= 0 ? mDisplayActiveConfigId : -1;
+}
diff --git a/stream-servers/FrameBuffer.h b/stream-servers/FrameBuffer.h
index 3e9aea8..75971f0 100644
--- a/stream-servers/FrameBuffer.h
+++ b/stream-servers/FrameBuffer.h
@@ -656,6 +656,11 @@
 
     void setVsyncHz(int vsyncHz);
     void scheduleVsyncTask(VsyncThread::VsyncTask task);
+    void setDisplayConfigs(int configId, int w, int h, int dpiX, int dpiY);
+    void setDisplayActiveConfig(int configId);
+    const int getDisplayConfigsCount();
+    const int getDisplayConfigsParam(int configId, EGLint param);
+    const int getDisplayActiveConfig();
 
    private:
     FrameBuffer(int p_width, int p_height, bool useSubWindow);
@@ -883,5 +888,17 @@
 
     // Vsync thread.
     std::unique_ptr<VsyncThread> m_vsyncThread = {};
+
+    struct DisplayConfig{
+        int w;
+        int h;
+        int dpiX;
+        int dpiY;
+        DisplayConfig() {}
+        DisplayConfig(int w, int h, int x, int y)
+        : w(w), h(h), dpiX(x), dpiY(y) {}
+    };
+    std::map<int, DisplayConfig> mDisplayConfigs;
+    int mDisplayActiveConfigId = -1;
 };
 #endif
diff --git a/stream-servers/RenderWindow.cpp b/stream-servers/RenderWindow.cpp
index fc242ae..92da684 100644
--- a/stream-servers/RenderWindow.cpp
+++ b/stream-servers/RenderWindow.cpp
@@ -63,6 +63,8 @@
     CMD_HAS_GUEST_POSTED_A_FRAME,
     CMD_RESET_GUEST_POSTED_A_FRAME,
     CMD_SET_VSYNC_HZ,
+    CMD_SET_DISPLAY_CONFIGS,
+    CMD_SET_DISPLAY_ACTIVE_CONFIG,
     CMD_FINALIZE,
 };
 
@@ -116,6 +118,17 @@
         // CMD_SET_VSYNC_HZ
         int vsyncHz;
 
+        // CMD_SET_COMPOSE_DIMENSIONS
+        struct {
+            int configId;
+            int width;
+            int height;
+            int dpiX;
+            int dpiY;
+        } displayConfigs;
+
+        int displayActiveConfig;
+
         // result of operations.
         bool result;
     };
@@ -267,6 +280,34 @@
                 }
                 break;
 
+            case CMD_SET_DISPLAY_CONFIGS:
+                GL_LOG("CMD_SET_DISPLAY_CONFIGS");
+                D("CMD_SET_DISPLAY_CONFIGS");
+                fb = FrameBuffer::getFB();
+                if (fb) {
+                    fb->setDisplayConfigs(msg.displayConfigs.configId,
+                                          msg.displayConfigs.width,
+                                          msg.displayConfigs.height,
+                                          msg.displayConfigs.dpiX,
+                                          msg.displayConfigs.dpiY);
+                    result = true;
+                } else {
+                    GL_LOG("CMD_SET_DISPLAY_CONFIGS: no FrameBuffer");
+                }
+                break;
+
+            case CMD_SET_DISPLAY_ACTIVE_CONFIG:
+                GL_LOG("CMD_SET_DISPLAY_ACTIVE_CONFIG");
+                D("CMD_SET_DISPLAY_ACTIVE_CONFIG");
+                fb = FrameBuffer::getFB();
+                if (fb) {
+                    fb->setDisplayActiveConfig(msg.displayActiveConfig);
+                    result = true;
+                } else {
+                    GL_LOG("CMD_SET_DISPLAY_ACTIVE_CONFIG: no FrameBuffer");
+                }
+                break;
+
             default:
                 ;
         }
@@ -614,6 +655,29 @@
     D("Exiting\n");
 }
 
+void RenderWindow::setDisplayConfigs(int configId, int w, int h,
+                                     int dpiX, int dpiY) {
+    D("Entering\n");
+    RenderWindowMessage msg = {};
+    msg.cmd = CMD_SET_DISPLAY_CONFIGS;
+    msg.displayConfigs.configId = configId;
+    msg.displayConfigs.width = w;
+    msg.displayConfigs.height= h;
+    msg.displayConfigs.dpiX= dpiX;
+    msg.displayConfigs.dpiY = dpiY;
+    (void) processMessage(msg);
+    D("Exiting\n");
+}
+
+void RenderWindow::setDisplayActiveConfig(int configId) {
+    D("Entering\n");
+    RenderWindowMessage msg = {};
+    msg.cmd = CMD_SET_DISPLAY_ACTIVE_CONFIG;
+    msg.displayActiveConfig = configId;
+    (void) processMessage(msg);
+    D("Exiting\n");
+}
+
 bool RenderWindow::processMessage(const RenderWindowMessage& msg) {
     if (useThread()) {
         if (msg.cmd == CMD_REPAINT) {
diff --git a/stream-servers/RenderWindow.h b/stream-servers/RenderWindow.h
index a3b59a9..68e7ca1 100644
--- a/stream-servers/RenderWindow.h
+++ b/stream-servers/RenderWindow.h
@@ -148,6 +148,8 @@
     void removeListener(emugl::Renderer::FrameBufferChangeEventListener* listener);
 
     void setVsyncHz(int vsyncHz);
+    void setDisplayConfigs(int configId, int w, int h, int dpiX, int dpiY);
+    void setDisplayActiveConfig(int configId);
 private:
     bool processMessage(const RenderWindowMessage& msg);
     bool useThread() const { return mThread != nullptr; }
diff --git a/stream-servers/RendererImpl.cpp b/stream-servers/RendererImpl.cpp
index a52ad29..602dea9 100644
--- a/stream-servers/RendererImpl.cpp
+++ b/stream-servers/RendererImpl.cpp
@@ -677,17 +677,15 @@
 
 void RendererImpl::setDisplayConfigs(int configId, int w, int h,
                                      int dpiX, int dpiY) {
-    // TODO: need CP
-    (void)configId;
-    (void)w;
-    (void)h;
-    (void)dpiX;
-    (void)dpiY;
+    if (mRenderWindow) {
+        mRenderWindow->setDisplayConfigs(configId, w, h, dpiX, dpiY);
+    }
 }
 
 void RendererImpl::setDisplayActiveConfig(int configId) {
-    // TODO: need CP
-    (void)configId;
+    if (mRenderWindow) {
+        mRenderWindow->setDisplayActiveConfig(configId);
+    }
 }
 
 }  // namespace emugl